Question about RevoluteJoint

Discuss any questions about BEPUphysics or problems encountered.
Post Reply
grobi
Posts: 34
Joined: Wed Sep 23, 2009 5:47 pm

Question about RevoluteJoint

Post by grobi »

Hi,
I want try to use a RevoluteJoint with ServoMechanism Motor to connect a tank-vehicle with its turret.
So far so good, I got it positioned right, and its rotation is restricted to the up vector.
But the turrets orientation is not aligned to the vehicle chassis. When the chassis is inclined to any side, it looks like the turret tried to follow, but sometimes inclines to the opposite direction or it looks like its trying to stay upright or jut weired. I noticed that RevoluteJoint has a BallSocketJoint, I think this is causing the behavior. Is there a way to make it 100% stiff, so that the turrets orientation is aligned to the vehicle chassis but still remains turnable by servomotor?

thx Grobi
Norbo
Site Admin
Posts: 4929
Joined: Tue Jul 04, 2006 4:45 am

Re: Question about RevoluteJoint

Post by Norbo »

The BallSocketJoint removes 3 linear degrees of freedom. The RevoluteJoint removes 2 angular degrees of freedom. Provided that everything is configured right, that leaves only a single angular degree of freedom between the two bodies, which should do what you want. The problem probably lies in the configuration.

Constaints, particularly the SolverGroup combination constraints, make initial guesses to configure themselves. Sometimes they guess wrong and require additional work, which may be the case here.

However, in the following example, I attached a 'turret' to the default demos vehicle and it works as expected. Try comparing the configurations to see if anything is conceptually different.

Code: Select all

            Entity turret = new Box(body.InternalCenterPosition + new Vector3(0, 1f, -1), 1, .3f, 2, 5); 
            RevoluteJoint revoluteJoint = new RevoluteJoint(body, turret, body.InternalCenterPosition + new Vector3(0, .9f, -1), Vector3.Up);
            revoluteJoint.Motor.IsActive = true;
            revoluteJoint.Motor.Settings.Mode = MotorMode.Servomechanism;
            revoluteJoint.Motor.Settings.Servo.Goal = 0;
            Space.Add(turret);
            Space.Add(revoluteJoint);
grobi
Posts: 34
Joined: Wed Sep 23, 2009 5:47 pm

Re: Question about RevoluteJoint

Post by grobi »

my setup looks like this (nothing really different from yours) :

Code: Select all

            modelMatrix = (Matrix.CreateRotationX(MathHelper.ToRadians(modelRotation.X)) * Matrix.CreateRotationY(MathHelper.ToRadians(modelRotation.Y)) * Matrix.CreateRotationZ(MathHelper.ToRadians(modelRotation.Z))) * Matrix.CreateTranslation(modelPosition);
            modelBody = new CompoundBody(false);
            List<Vector3> vertices = new List<Vector3>();
            Matrix[] transforms = new Matrix[model.Bones.Count];
            model.CopyAbsoluteBoneTransformsTo(transforms);
            XNAutils.XNAutils.ExtractVectors(model.Meshes[0], vertices, transforms[model.Meshes[0].ParentBone.Index]);
            ConvexHull cHull = new ConvexHull(vertices);
            modelBody.AddBody(cHull);
            modelBody.Mass = 400f;
            modelVehicle = new Vehicle(modelBody);

... wheels...

            modelVehicle.Body.WorldTransform = modelMatrix;
            space.Add(modelVehicle);

            Vector3 turretPosition = modelPosition;
            turretPosition.Y += 4.0f;
            vertices.Clear();
            transforms = new Matrix[modelTurret.Bones.Count];
            modelTurret.CopyAbsoluteBoneTransformsTo(transforms);
            XNAutils.XNAutils.ExtractVectors(modelTurret.Meshes[0], vertices, transforms[modelTurret.Meshes[0].ParentBone.Index]);
            modelTurretBody = new ConvexHull(vertices);
            modelTurretBody.Mass = 10f;
            modelMatrix = modelVehicle.Body.OrientationMatrix * Matrix.CreateTranslation(turretPosition);
            modelTurretBody.WorldTransform = modelMatrix;
            space.Add(modelTurretBody);

            Vector3 turretRotationPoint = turretPosition;
            turretRotationPoint.Y -= 2.0f;
            turretJoint = new RevoluteJoint(modelVehicle.Body, modelTurretBody, turretRotationPoint, Vector3.Up);
            turretJoint.Motor.Settings.Mode = MotorMode.Servomechanism;
            turretJoint.Motor.IsActive = true;
            /*turretJoint.Motor.Settings.MaximumForce = 300f;
            turretJoint.Motor.Settings.Servo.BaseCorrectiveSpeed = 1f;
            turretJoint.Motor.Settings.Servo.MaxCorrectiveVelocity = 1f;*/
            turretJoint.Motor.Settings.Servo.Goal = 0f;
            space.Add(turretJoint);
            modelVehicle.Body.CollisionRules.SpecificEntities.Add(modelTurretBody, CollisionRule.NoPair);
            modelVehicle.Body.ForceCollisionRuleRecalculation();
and that looks like the turret is connected to the vehicle with a spring.

Grobi
grobi
Posts: 34
Joined: Wed Sep 23, 2009 5:47 pm

Re: Question about RevoluteJoint

Post by grobi »

...i forgot the servor motor isn't working at all if i don't set a maximumforce and basecorrectionspeed etc.
Norbo
Site Admin
Posts: 4929
Joined: Tue Jul 04, 2006 4:45 am

Re: Question about RevoluteJoint

Post by Norbo »

The one thing I notice is that your RevoluteJoint has a freed axis of Vector3.Up. If your vehicle isn't initially oriented in a certain way, that will not work. You could try to use your orientation.Up vector instead.

If that still doesn't work, I'd recommend just stepping through it and making sure all the relevant configuration values are what you expect them to be (relative positions, orientations, etc.).
grobi
Posts: 34
Joined: Wed Sep 23, 2009 5:47 pm

Re: Question about RevoluteJoint

Post by grobi »

I tried changing the RevoluteJoint :

Code: Select all

turretJoint = new RevoluteJoint(modelVehicle.Body, modelTurretBody, turretRotationPoint, modelVehicle.Body.OrientationMatrix.Up);
but still the same effect as :

Code: Select all

turretJoint = new RevoluteJoint(modelVehicle.Body, modelTurretBody, turretRotationPoint, Vector3.Up);
Post Reply