matter-js icon indicating copy to clipboard operation
matter-js copied to clipboard

Angle constraints

Open automata opened this issue 9 years ago • 23 comments

Distance constraints are really nice, how about angle constraints?

That would make it possible to remove those two "diagonal constraints" from this example: http://jsbin.com/risahi/4/edit

automata avatar Mar 18 '15 22:03 automata

This is definitely on my list, I'll keep this thread updated, thanks!

liabru avatar Mar 21 '15 13:03 liabru

+1

gamecubate avatar Aug 03 '15 20:08 gamecubate

+1

Misiur avatar Oct 21 '15 15:10 Misiur

+1

jstoeffler avatar Dec 27 '15 15:12 jstoeffler

+1

iamjoshua avatar Apr 14 '16 00:04 iamjoshua

What are/were your thoughts on the best way to implement this @liabru? I really need this and would be willing to help.

iamjoshua avatar Apr 19 '16 00:04 iamjoshua

+1

davearel avatar May 17 '16 17:05 davearel

+1111111111

greenSnot avatar Aug 17 '16 06:08 greenSnot

+1

babyzone2004 avatar May 26 '17 07:05 babyzone2004

+1

omegahacker avatar Oct 16 '17 20:10 omegahacker

@liabru Is there any progress on this one? I need this for my project so much that I'm looking into hacking it in myself. But, I'm concerned I might not figure out how to do it in a way that conserves momentum, etc.

Twosies avatar Nov 11 '17 17:11 Twosies

FWIW, here's how I implemented angular constraints for another verlet lib: https://github.com/softfab/tshirt/blob/master/src/verlet-constraint-angle-2d.js

forresto avatar Nov 11 '17 17:11 forresto

I will bury a timecapsule with instructions for my great grandchildren on how to complete my project when angle constraints are finally added to this library in 2050

AndrewBrownK avatar May 22 '18 03:05 AndrewBrownK

Anyone wanna help @liabru out? It's an open source library, not a paid service ;)

davearel avatar May 23 '18 15:05 davearel

+1

joel-simon avatar Oct 15 '18 21:10 joel-simon

I've come up with a solution for this that seems like a good workaround until this is implemented. For my project I wanted to limit the extended and contracted angle between the upper arm and lower arm of a character to mimic normal elbow behavior. You can check it out below in action...

revolute

How it works

  • Create a constraint between the two bodies that are linked with a revolute constraint
    • Ie.. a 0 distance .7 stiffness regular constraint
    • Set the constraint stiffness to 0
    • The length doesn't matter yet
  • It seems like it works well if you offset the constraint from the bodies as seen in the gif
  • Every frame, measure the distance between the two attachment points of the constraint
    • Set some some minimum and & maximum rules around this distance
  • For my case, I am checking to see if the the distance is greater than 120
  • If it's greater than 120,
    • I set the stiffness of the constraint to 1
    • I set the length of the constraint to 120
  • For my case, this does enough to limit the angle for both an extended and contracted arm but you could layer a bunch of these together to get the constraints you want.

In general, I think this might be a good approach and can be adapted for other scenarios.

Some Code

This is the constraint setup

let testConstraint = Constraint.create({
  bodyA: upperArm,
  pointA: { x: 120, y: 0 },
  bodyB: lowerArm,
  pointB: { x: 120, y: 0 },
  stiffness : 0,
  length: 100
});

This gets the distance between the attachment points

let uX = 120; // This is the x offset of the constraint for the upper arm
let uY = 0;   // This is the y offset of the constraint for the upper arm
let uA = upperArm.angle;
let upperX = upperArm.position.x + uX * Math.cos(uA) - uY * Math.sin(uA);
let upperY = upperArm.position.y + uX * Math.sin(uA) + uY * Math.cos(uA);

let lX = 120; // This is the x offset of the constraint for the lower arm
let lY = 0;   // This is the x offset of the constraint for the lower arm
let lA = lowerArm.angle;
let lowerX = lowerArm.position.x + lX * Math.cos(lA) - lY * Math.sin(lA);
let lowerY = lowerArm.position.y + lX * Math.sin(lA) + lY * Math.cos(lA);

var xDelta = upperX - lowerX;
var yDelta = upperY - lowerY;
var distance = Math.sqrt( xDelta * xDelta + yDelta * yDelta );

if (distance > 120){
  testConstraint.length = 120;
  testConstraint.stiffness = 1;
} else {
  testConstraint.stiffness = 0;
}

cc @AndrewBrownK @Twosies @joel-simon @davearel in case this still matter to you haha.

flukeout avatar Feb 11 '19 03:02 flukeout

My use case was to implement a servo arm. What I ended up doing was to add two revolute constraints; one for the pivot point (like flukeout) and one farther out (unlike in flukeout's example, this is also a revolute constraint!). The constraint can be modified at runtime to change to which angle the dependent element should go.

const anchor = Matter.Bodies.rectangle(200, 350, 50, 50, {
  density: 1,
  frictionAir: 0.4,
});
const arm = Matter.Bodies.rectangle(200, 200, 10, 200, {
  // in this example I don't want the anchor to rotate too much when the arm moves
  density: 0.01,
  frictionAir: 0.1,
});
// this constraint remains constant
const pivot = Matter.Constraint.create({
  bodyA: anchor,
  pointA: { x: 0, y: -50 },
  bodyB: arm,
  pointB: { x: 0, y: 100 },
});
const control = Matter.Constraint.create({
  bodyA: anchor,
  // the pointA is modified to change the point to which the arm should be fixed
  pointA: { x: 0, y: -100 },
  bodyB: arm,
  pointB: { x: 0, y: 50 },
});

Matter.World.add(this.simulation.world, [anchor, arm, pivot, control]);

setTimeout(() => {
  // change the control point later
  // should use sine and cosine, this is fine for the demo
  control.pointA = { x: 20, y: -100 };
}, 1000);

I think by making the pivot constraint stiffer than the control constraint, you can ensure that the rotation point is at/closer to the pivot, and by adjusting the distance between pivot and control, you can control the "angular stiffness".

SillyFreak avatar Jan 12 '20 12:01 SillyFreak

I've opened PR #837 which adds angle constraints, those interested please take a look, try them out and let me know if you spot any issues or just if they work nicely for your use case.

Thanks for holding on here everyone!

(@AndrewBrownK get ready to dig up that time capsule)

liabru avatar Mar 11 '20 22:03 liabru

Phew! I really needed this feature. Was quite exciting reading through the comments starting 6 years ago and finding that it had finally happened by 2020. Good job @liabru !

ulfaslak avatar May 04 '21 22:05 ulfaslak

Yes! I need to come back to this though, it's not merged as there were a few cases that were not stable (chains). I could probably release it with some caveats I suppose.

liabru avatar May 24 '21 20:05 liabru

@liabru any updates on this? Thanks!

joel-simon avatar Dec 23 '22 04:12 joel-simon

So what about angularStiffness or something like this? 8 years passed since this topic has started 😀

ProgrammingLife avatar Mar 13 '23 21:03 ProgrammingLife

I'm trying to simulate some piston-like things and this angle constraint would make things significantly easier.

mreinstein avatar Sep 26 '23 22:09 mreinstein