Skip to content

Angle constraints #71

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
automata opened this issue Mar 18, 2015 · 23 comments
Open

Angle constraints #71

automata opened this issue Mar 18, 2015 · 23 comments

Comments

@automata
Copy link

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

@liabru
Copy link
Owner

liabru commented Mar 21, 2015

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

@gamecubate
Copy link

+1

1 similar comment
@Misiur
Copy link
Contributor

Misiur commented Oct 21, 2015

+1

@jstoeffler
Copy link

+1

1 similar comment
@iamjoshua
Copy link
Contributor

+1

@iamjoshua
Copy link
Contributor

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

@davearel
Copy link

+1

@greenSnot
Copy link

+1111111111

@babyzone2004
Copy link

+1

1 similar comment
@omegahacker
Copy link

+1

@Twosies
Copy link

Twosies commented Nov 11, 2017

@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.

@forresto
Copy link

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

@AndrewBrownK
Copy link

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

@davearel
Copy link

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

@joel-simon
Copy link

+1

@flukeout
Copy link

flukeout commented Feb 11, 2019

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.

@SillyFreak
Copy link

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".

@liabru
Copy link
Owner

liabru commented Mar 11, 2020

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)

@ulfaslak
Copy link

ulfaslak commented May 4, 2021

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 !

@liabru
Copy link
Owner

liabru commented May 24, 2021

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.

@joel-simon
Copy link

@liabru any updates on this? Thanks!

@ProgrammingLife
Copy link

ProgrammingLife commented Mar 13, 2023

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

@mreinstein
Copy link

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests