Constant rotational speed

1 view
Skip to first unread message

Bobby5808

unread,
May 25, 2009, 6:35:11 AM5/25/09
to Physics2D.Net
Hi

Id like to rotate an object around a joint at a certain speed. How
would I calculate the force to apply?

At the moment what I do is apply a certain force every timestep, and
if the speed of the object gets above a certain point I dont apply the
force. This keeps it pretty constant but I dont think its the best
way, plus the values are really wild and random depending on the mass
and size of the object, and I always have to keep trying till I find
the perfect value.

Ive seen some other physics engines have a motor-joint, but I havent
looked at any code yet.

Thanks
Cheers

Bobby5808

unread,
May 26, 2009, 11:40:10 PM5/26/09
to Physics2D.Net
I found this: http://code.google.com/p/box2dx/source/browse/trunk/src/Dynamics/Joints/RevoluteJoint.cs

Its from a C# port of Box2D.

Basically its a normal Hinge joint but with the added ability of
enabling a motor on it. You can then adjust the speed and strength of
the motor, which is what I was really looking for.

Im gonna try put it into the Physics2D code, and if I manage il put it
up.

:D Cheers

Bobby5808

unread,
May 27, 2009, 5:25:46 AM5/27/09
to Physics2D.Net
Could someone help please? Ive integrated it into the FixedHingeJoint
Class, but had some problems applying the impulse. It works fine on
ordinary objects, but fixed objects(infinite mass) there are some
problems.

Heres the 2 functions Prestep and ApplyImpulse, if someone would
please look at them.
(ive got a feeling that I should use the Add/Subtract impulse
functions, but I dont know where to put the motors impulse into it)



void Solvers.ISequentialImpulsesJoint.PreStep(TimeStep step)
{

Scalar mass1Inv = body.Mass.MassInv;
Scalar inertia1Inv = body.Mass.MomentOfInertiaInv;

// Pre-compute anchors, mass matrix, and bias.

Vector2D.TransformNormal(ref body.Matrices.ToWorld, ref
localAnchor1, out r1);

// deltaV = deltaV0 + K * impulse
// invM = [(1/m1 + 1/m2) * eye(2) - skew(r1) * invI1 * skew
(r1) - skew(r2) * invI2 * skew(r2)]
// = [1/m1+1/m2 0 ] + invI1 * [r1.y*r1.y -
r1.x*r1.y] + invI2 * [r1.y*r1.y -r1.x*r1.y]
// [ 0 1/m1+1/m2] [-r1.x*r1.y
r1.x*r1.x] [-r1.x*r1.y r1.x*r1.x]

Matrix2x2 K;
K.m00 = mass1Inv;
K.m11 = mass1Inv;

K.m00 += inertia1Inv * r1.Y * r1.Y;
K.m01 = -inertia1Inv * r1.X * r1.Y;
K.m10 = -inertia1Inv * r1.X * r1.Y;
K.m11 += inertia1Inv * r1.X * r1.X;

K.m00 += softness;
K.m11 += softness;

Matrix2x2.Invert(ref K, out M);

//MOTOR
_motorMass = 1.0f / inertia1Inv ;
maxImpulse = step.Dt * _maxMotorTorque; //used in next
step - put it here cause no dt in next step
if (_enableMotor == false)
{
_motorImpulse = 0.0f;
}

Vector2D dp;
Vector2D.Add(ref body.State.Position.Linear, ref r1, out
dp);
Vector2D.Subtract(ref anchor, ref dp, out dp);

if (!Scalar.IsPositiveInfinity(distanceTolerance) &&
dp.MagnitudeSq > distanceTolerance *
distanceTolerance)
{
this.Lifetime.IsExpired = true;
}

if (solver.PositionCorrection)
{
//bias = -0.1f * dtInv * dp;
Scalar flt = -biasFactor * step.DtInv;
Vector2D.Multiply(ref dp, ref flt, out bias);
}
else
{
bias = Vector2D.Zero;
}
if (solver.WarmStarting)
{
_motorImpulse *= step.DtInv * step.Dt;

PhysicsHelper.SubtractImpulse(
ref body.State.Velocity, ref accumulatedImpulse,
ref r1, ref mass1Inv, ref inertia1Inv );
//Motor
body.State.Velocity.Angular += _motorImpulse;
}
else
{
accumulatedImpulse = Vector2D.Zero;
_motorImpulse = 0;
}
body.ApplyProxy();

}
void Solvers.ISequentialImpulsesJoint.ApplyImpulse()
{
Scalar mass1Inv = body.Mass.MassInv;
Scalar inertia1Inv = body.Mass.MomentOfInertiaInv;

Vector2D dv;
PhysicsHelper.GetRelativeVelocity(ref body.State.Velocity,
ref r1, out dv);
float w1 = 0;

//MOTOR
if (_enableMotor)
{
w1 = body.State.Velocity.Angular;
float Cdot = w1 - _motorSpeed;
float mimpulse = _motorMass * (-Cdot);
float oldImpulse = _motorImpulse;
//float maxImpulse = step.Dt * _maxMotorTorque;
_motorImpulse = MathHelper.Clamp(_motorImpulse +
mimpulse, -maxImpulse, maxImpulse);
mimpulse = _motorImpulse - oldImpulse;

w1 = inertia1Inv * mimpulse;
}


Vector2D impulse;
impulse.X = bias.X - dv.X - softness *
accumulatedImpulse.X;
impulse.Y = bias.Y - dv.Y - softness *
accumulatedImpulse.Y;
Vector2D.Transform(ref M, ref impulse, out impulse);
//impulse = M * (bias - dv - softness * P);


PhysicsHelper.SubtractImpulse(
ref body.State.Velocity, ref impulse,
ref r1, ref mass1Inv, ref inertia1Inv);
//Motor
body.State.Velocity.Angular += w1;


Vector2D.Add(ref accumulatedImpulse, ref impulse, out
accumulatedImpulse);
body.ApplyProxy();

}

JonoPorter

unread,
May 27, 2009, 11:09:16 AM5/27/09
to Physics2D.Net
I remember running into something similar when I tried to port the
most recent Box2D code as well. For someof the equations The
infinities have to be zero.

Bobby If you want SVN access I can grant it too you.

Bobby5808

unread,
May 27, 2009, 11:28:36 PM5/27/09
to Physics2D.Net
Yep, it was an infinite problem :) Thanks for that Jono.

_motorMass = 1.0f / inertia1Inv ;
if (Scalar.IsInfinity(_motorMass) )
{
_motorMass = 0.0f;
}

Does SVN access mean I can modify the source download? That would be
great if thats so, cause then I can put in those extra classes Ive
done.

Bobby5808

unread,
May 28, 2009, 5:47:18 AM5/28/09
to Physics2D.Net
Hi Jono could you please have a look at the Fixedhingejoint and
Hingejoint classes I uploaded in the files section?

I got the motor in Fixedhingejoint working perfectly, but theres
something wrong with the one in Hingejoint. You need to pass a really
large value for Maxtorque for it to begin working, way out of
proportion to what you pass for a Fixedhingejoint. eg:

Fixedhingejoint:
_enableMotor = true;
_maxMotorTorque = 100;
_motorSpeed = -8;
works fine

Hingejoint:
_enableMotor = true;
_maxMotorTorque = 100000;
_motorSpeed = -8;

Applying the impulse the way I did with the Fixedhingejoint didnt
work, so I used a way closer to the original code, which didnt work
with the Fixedhingejoint (this is the code in
ISequentialImpulsesJoint.PreStep - solver.WarmStarting, the code in
ISequentialImpulsesJoint.ApplyImpulse worked fine)

Anyway if you get some time please have a look, I really want this
motor! :D

Bobby5808

unread,
Jun 5, 2009, 5:28:59 AM6/5/09
to Physics2D.Net
I fixed it!

I think it had something to do with using dt instead of inverseDT, but
there mightve been something else, I was just changing any variable
that caught my eye after a while so Im not too sure what did it ;D

Anyway I put both Joints in the files section.

They are exactly exactly like a normal hinge/fixed hinge joint, but if
you want to make them spin, set:
Joint.Motor_Enabled = true;
Joint.Motor_Speed = 2.0f;
Joint.Motor_MaxTorque = 10.0f;
with your own values, and it should spin!

:)
Reply all
Reply to author
Forward
0 new messages