## 2D Angle Joint Limits (Box2D-Style)

Please don't post Bullet support questions here, use the above forums instead.
crashlander
Posts: 41
Joined: Sat Apr 08, 2006 11:20 am

### 2D Angle Joint Limits (Box2D-Style)

I have a physics engine that uses the concepts in Box2D at it's core.

I'm trying to implement 2D JointLimits.

I already implemented an Angle joint that constrains two bodies to remain at some fixed angle. For this I used the equations:

difference = (_body2.TotalRotation - _body1.TotalRotation) - targetAngle;
_bias = -_biasFactor * inverseDt * difference;

All is good with this joint.

For the joint limit constraint, I'd like to provide and Lower Limit and an Upper Limit and constrain the angle between 2 bodies to remain between these 2 angles.

Should I just implement this as 2 in equality constraints, one for each limit, all within a single LimitedAngleJoint class

I'd also need to allow for slop, similar to the contact constraints.

Anything else I need to take into consideration?

For reference, here is the key code from my regular AngleJoint:

Code: Select all

``````        public override void PreStep(float inverseDt) {
float difference;
difference = (_body2.TotalRotation - _body1.TotalRotation) - _targetAngle;

_bias = -_biasFactor * inverseDt * difference;

_accumulatedAngularImpulse *= _relaxation;

_body1.AngularVelocity -= _body1.InverseMomentOfInertia * _accumulatedAngularImpulse;
_body2.AngularVelocity += _body2.InverseMomentOfInertia * _accumulatedAngularImpulse;
}

public override void Update() {
float angularImpulse;
angularImpulse = (_bias - _body2.AngularVelocity + _body1.AngularVelocity) / (_body1.InverseMomentOfInertia  + _body2.InverseMomentOfInertia);
_accumulatedAngularImpulse += angularImpulse;

_body1.AngularVelocity -= _body1.InverseMomentOfInertia * angularImpulse;
_body2.AngularVelocity += _body2.InverseMomentOfInertia * angularImpulse;
}``````

Dirk Gregorius
Posts: 874
Joined: Sun Jul 03, 2005 4:06 pm
Location: Kirkland, WA
The only other thing you might need to take into consideration is to reset the accumulated impulse, when either the constraint is no more violated or when in the last frame the lower limit was exceeded and now in the next frame the upper limit is exceeded.

Dirk Gregorius
Posts: 874
Joined: Sun Jul 03, 2005 4:06 pm
Location: Kirkland, WA
I would also remove the relaxation...

crashlander
Posts: 41
Joined: Sat Apr 08, 2006 11:20 am
Thanks Dirk, that helped.

I have my angle limits working (sort of). They work fine for certain configurations, but are very unstable in others. Things seem to become more unstable the further the anchor is from the involved bodies.

I'm wondering if this is just the nature of the beast or if I have something that isn't implemented quite correct.

Here is what I have:

Code: Select all

``````        float max;
float difference;
float error;
public override void PreStep(float inverseDt) {
if (isDisposed) { return; }
difference = (body2.totalRotation - body1.totalRotation);

if (difference > upperLimit) {
upperLimitViolated = true;
if (lowerLimitViolated) { _accumulatedAngularImpulse = 0; lowerLimitViolated = false; }
error =  difference - upperLimit;
max = Math.Max(0, error - _slop); //error and slop are both positive
_bias = -_biasFactor * inverseDt * max;
}
else
if (difference < lowerLimit) {
lowerLimitViolated = true;
if (upperLimitViolated) { _accumulatedAngularImpulse = 0; upperLimitViolated = false; }
error = lowerLimit - difference;
max = Math.Max(0, error - _slop);
_bias = _biasFactor * inverseDt * max;
}
else {
upperLimitViolated = false;
lowerLimitViolated = false;
_accumulatedAngularImpulse = 0;
_bias = 0;
}
}

public override void Update() {
if (isDisposed) { return; }

if (upperLimitViolated || lowerLimitViolated) {

float angularImpulse = 0;
angularImpulse = (_bias-(body2.angularVelocity - body1.angularVelocity)) / (body1.inverseMomentOfInertia + body2.inverseMomentOfInertia);

_accumulatedAngularImpulse += angularImpulse;

body1.angularVelocity -= body1.inverseMomentOfInertia * _accumulatedAngularImpulse; //angularImpulse;
body2.angularVelocity += body2.inverseMomentOfInertia * _accumulatedAngularImpulse; //angularImpulse;
}
}``````

crashlander
Posts: 41
Joined: Sat Apr 08, 2006 11:20 am
I thought this had been discussed before:

http://www.continuousphysics.com/Bullet ... .php?t=517

Looks like I'm missing the clamping!