Joint problem Farseer 3.0

Jul 22, 2010 at 9:20 PM
Edited Jul 22, 2010 at 9:23 PM
Hi, I'm fairly new to Farseer but I've been working on a vehicle that uses prismatic joints for suspension and revolute joints to attach wheels to the ends of these. When I drive it left and right and maybe the vehicle bounces a little sometimes the joints sometimes stretch all out of place, the prismatic gets left behind the chasis and wheel then gets left behind as well, both pulled out of position. The prismatic motor is being driven proportional to it's translation so it has a restoring motion on it so it acts like a hydraulic suspension. Not sure if there's something else I need to set up? I've kept the values fairly realistic I think. I've set a common collision group on all these parts. I've tweaked the masses, the friction, the amount of travel in the prismatic joints etc, but I can't seem to make them 'fixed'. They're ok when the vehicle moves slowly. This happens on 73518. Thanks.
Jul 24, 2010 at 5:25 AM

Do you have both the PrismaticJoint and RevoluteJoint between the Wheel to the Car? If so that won't work, as they will pull against each other. Rather than that use a small block on the PrismaticJoint, and connect the wheel to that.

Jul 24, 2010 at 6:43 AM
Edited Jul 24, 2010 at 8:51 AM

Hi, I think that's what I have. Although when stationary it does seem to bounce a bit, that might be the motor on the prismatic. Anyway I took a few screenshots in case it helps. The top is the object at rest and the second shows the problem when you move. In the bottom pic the car is traveling to the right, it always seems to be the trailing wheel/joint that has the problem. It's probably something stupid I've done as it's the first jointed thing I've made. http://img638.imageshack.us/img638/5968/farseerjointproblem.jpg I got a better screenshot that shows the revolute being pulled as well http://img514.imageshack.us/img514/7207/farseerjointproblem2.jpg 

 I roughly based it on the following example (bottom one), just for the body/joint setup. http://www.emanueleferonato.com/2009/04/06/two-ways-to-make-box2d-cars

Jul 24, 2010 at 9:29 AM

I didn't know you had other bodies between the car and the wheel, so it's probably not the problem I thought it was.

Here's a couple of things I can think of trying:

  • Joint.CollideConnected = false;
  • Make sure you are creating the PrismaticJoint correctly, look at the testbed samples.
  • Use CollisionCategories and make sure none of the bodies can collide with each other.
  • The PrismaticJoint must only be between the two Piston bodies, not the Wheel body.

Thats all I can think of off the top of my head. The picture looks like it's either a collision problem or a prismatic joint problem though.

Try those, and if you still can't get it post some of your code and someone might be able to see what the problem is.

Jul 24, 2010 at 4:17 PM

Ok I had a go at that and still can't fix it. Here's the set up code from the constructor, sorry it's long. There's a couple of lines at the bottom that are used during update to apply the restoring motion to the prismatic joints too and some lines from the keyboard update where I try and turn the back wheel.

 

            ////////////////////////////////////////////////////////////////////////////////////////////////
            // Chasis - consist of the main body and two forks (front and rear)
            ////////////////////////////////////////////////////////////////////////////////////////////////
            float chasisDensity = 0.5f;
            float chasisWidth = 2.0f;
            float chasisHeight = 1.0f;
            Vector2 chasisInitialPosition = new Vector2(0.0f, 12.0f);

            Body chasisBody = BodyFactory.CreateBody(World);
            chasisBody.BodyType = BodyType.Dynamic;
            chasisBody.Position = chasisInitialPosition;

            PolygonShape chasisShape = new PolygonShape();
            chasisShape.SetAsBox(chasisWidth / 2, chasisHeight / 2);

            PolygonShape chasisRearStrut = new PolygonShape();
            chasisRearStrut.SetAsBox(0.4f, 0.15f, new Vector2(-1.0f, -0.3f), MathHelper.Pi/3);

            PolygonShape chasisFrontStrut = new PolygonShape();
            chasisFrontStrut.SetAsBox(0.4f, 0.15f, new Vector2(1.0f, -0.3f), -MathHelper.Pi / 3);

            Fixture chasisFixture = chasisBody.CreateFixture(chasisShape, chasisDensity);
            Fixture chasisFixtureRear = chasisBody.CreateFixture(chasisRearStrut, chasisDensity);
            Fixture chasisFixtureFront = chasisBody.CreateFixture(chasisFrontStrut, chasisDensity);
            chasisFixture.CollisionGroup = chasisFixtureRear.CollisionGroup = chasisFixtureFront.CollisionGroup = 100;


            ////////////////////////////////////////////////////////////////////////////////////////////////
            // Rear suspension - the suspension body that moves up and down
            ////////////////////////////////////////////////////////////////////////////////////////////////
            float rearSusDensity = chasisDensity;
            Body rearSusBody = BodyFactory.CreateBody(World);
            rearSusBody.BodyType = BodyType.Dynamic;
            rearSusBody.Position = chasisInitialPosition;

            PolygonShape rearSusShape = new PolygonShape();
            rearSusShape.SetAsBox(0.4f, 0.1f, new Vector2(-1.0f - 0.6f * (float)Math.Cos(MathHelper.Pi / 3), -0.3f - 0.6f * (float)Math.Sin(MathHelper.Pi / 3.0)), (float)(MathHelper.Pi / 3.0) );

            Fixture rearSusFixture = rearSusBody.CreateFixture(rearSusShape, rearSusDensity);
            rearSusFixture.CollisionGroup = 100;

            ////////////////////////////////////////////////////////////////////////////////////////////////
            // Rear suspension Spring joint - holds the suspension to the chasis
            ////////////////////////////////////////////////////////////////////////////////////////////////
            rearPrismatic = new PrismaticJoint(chasisBody, rearSusBody, Vector2.Zero, new Vector2((float)Math.Cos(MathHelper.Pi / 3.0), (float)Math.Sin(MathHelper.Pi / 3.0)));
            rearPrismatic.LowerLimit = -0.5f;
            rearPrismatic.UpperLimit = 0.5f;
            rearPrismatic.LimitEnabled = true;
            rearPrismatic.MotorEnabled = true;
            rearPrismatic.MotorSpeed = 0.0f;
            rearPrismatic.CollideConnected = false;
            World.AddJoint(rearPrismatic);

            ////////////////////////////////////////////////////////////////////////////////////////////////
            // Front suspension - the suspension body that moves up and down
            ////////////////////////////////////////////////////////////////////////////////////////////////
            float frontSusDensity = chasisDensity;
            Body frontSusBody = BodyFactory.CreateBody(World);
            frontSusBody.BodyType = BodyType.Dynamic;
            frontSusBody.Position = chasisInitialPosition;

            PolygonShape frontSusShape = new PolygonShape();
            frontSusShape.SetAsBox(0.4f, 0.1f, new Vector2(1.0f + 0.6f * (float)Math.Cos(-MathHelper.Pi / 3), -0.3f + 0.6f * (float)Math.Sin(-MathHelper.Pi / 3.0)), (float)(-MathHelper.Pi / 3.0));

            Fixture frontSusFixture = frontSusBody.CreateFixture(frontSusShape, frontSusDensity);
            frontSusFixture.CollisionGroup = 100;

            ////////////////////////////////////////////////////////////////////////////////////////////////
            // Front suspension Spring joint  - holds the suspension to the chasis
            ////////////////////////////////////////////////////////////////////////////////////////////////
            frontPrismatic = new PrismaticJoint(chasisBody, frontSusBody, Vector2.Zero, new Vector2((float)-Math.Cos(MathHelper.Pi / 3.0), (float)Math.Sin(MathHelper.Pi / 3.0)));
            frontPrismatic.LowerLimit = -0.5f;
            frontPrismatic.UpperLimit = 0.5f;
            frontPrismatic.LimitEnabled = true;
            frontPrismatic.MotorEnabled = true;
            frontPrismatic.MotorSpeed = 0.0f;
            frontPrismatic.CollideConnected = false;
            World.AddJoint(frontPrismatic);


            ////////////////////////////////////////////////////////////////////////////////////////////////
            // Back Wheel
            ////////////////////////////////////////////////////////////////////////////////////////////////
            float backWheelDensity = 0.1f;
            float backWeelRadius = 0.4f;
            // World pos of wheel - also the position the RJ locks it to.
            Vector2 backWheelInitialPosition = new Vector2(chasisInitialPosition.X - 1.45f, chasisInitialPosition.Y - 1.05f);

            Body backWheelBody = BodyFactory.CreateBody(World);
            backWheelBody.BodyType = BodyType.Dynamic;
            backWheelBody.Position = backWheelInitialPosition;

            CircleShape backWheelShape = new CircleShape(backWeelRadius);

            Fixture backWheelFixture = backWheelBody.CreateFixture(backWheelShape, backWheelDensity);
            backWheelFixture.CollisionGroup = 100;
            backWheelFixture.Friction = 5.0f;                // Grippy back wheel

            // Back Wheel Joint
            rearRevolute = new RevoluteJoint(rearSusBody, backWheelBody, Vector2.Zero);
            rearRevolute.MotorEnabled = true;
            rearRevolute.MaxMotorTorque = 10.0f;
            rearRevolute.CollideConnected = false;
            World.AddJoint(rearRevolute);

            ////////////////////////////////////////////////////////////////////////////////////////////////
            // Front Wheel
            ////////////////////////////////////////////////////////////////////////////////////////////////
            float frontWheelDensity = 0.1f;
            float frontWeelRadius = 0.4f;
            // World pos of wheel - also the position the RJ locks it to.
            Vector2 frontWheelInitialPosition = new Vector2(chasisInitialPosition.X + 1.45f, chasisInitialPosition.Y - 1.05f);

            Body frontWheelBody = BodyFactory.CreateBody(World);
            frontWheelBody.BodyType = BodyType.Dynamic;
            frontWheelBody.Position = frontWheelInitialPosition;

            CircleShape frontWheelShape = new CircleShape(frontWeelRadius);

            Fixture frontWheelFixture = frontWheelBody.CreateFixture(frontWheelShape, frontWheelDensity);
            frontWheelFixture.Friction = 5.0f;
            frontWheelFixture.CollisionGroup = 100;

            // front Wheel Joint
            RevoluteJoint frontRevolute = new RevoluteJoint(frontSusBody, frontWheelBody, Vector2.Zero);
            frontRevolute.MaxMotorTorque = 10.0f;
            frontRevolute.CollideConnected = false;
            World.AddJoint(frontRevolute);

 

And in my update I have:

            const float stiffness = 30.0f;

            rearPrismatic.MaxMotorForce = (float)(stiffness + Math.Abs(800 * Math.Pow(rearPrismatic.JointTranslation, 2)));
            rearPrismatic.MotorSpeed = (float)((rearPrismatic.MotorSpeed - 10 * rearPrismatic.JointTranslation) * 0.4);

            frontPrismatic.MaxMotorForce = (float)(stiffness + Math.Abs(800 * Math.Pow(frontPrismatic.JointTranslation, 2)));
            frontPrismatic.MotorSpeed = (float)((frontPrismatic.MotorSpeed - 10 * frontPrismatic.JointTranslation) * 0.4);

 

And in Keyboad I have:

            bool bDriveL = state.IsKeyDown(Microsoft.Xna.Framework.Input.Keys.N);
            bool bDriveR = state.IsKeyDown(Microsoft.Xna.Framework.Input.Keys.M);

            if (bDriveL)
            {
                rearRevolute.MotorSpeed = (float)(15 * Math.PI);
                rearRevolute.MaxMotorTorque = 10;
            }
            else if (bDriveR)
            {
                rearRevolute.MotorSpeed = (float)(-15 * Math.PI);
                rearRevolute.MaxMotorTorque = 10;
            }
            else
            {
                rearRevolute.MaxMotorTorque = 0.5f;
            }

 

Jul 25, 2010 at 4:00 AM

I'm not sure, but I think for the collision categories to work you need to set the "CollidesWith" field as well. I think by default it is set to "All". As a test comment out the "World.AddJoint" lines, and only add the bodies to the engine and see whether they collide or not.

If that is working the next thing you could try is to make sure the update for the PrismaticJoints is working correctly. It might be easier to make a sample with just the 2 suspension bodies and the joint, and drag them around to see if it adjusts correctly. And also check that the prismaticjoint's axis is correct.

Anyway, see if you can narrow it down a bit. Your code looked fine (although I only browsed it), but it'll be easier to figure out what's wrong if you know whether its a joint problem or a collision problem; or something else.

Jul 25, 2010 at 6:30 PM
Edited Jul 25, 2010 at 6:30 PM

Hi,
 Thanks for the suggestions. I tried all that and more, I've been stepping through the prismaticjoint code etc, eventually out of desperation I tried changing some values in Settings.cs and I've no idea what it is or why it has an effect but I found that setting ContinuousPhysics = false; seems to fix it!? I wonder why that improves it, is it a safe thing to to?