This project has moved and is read-only. For the latest updates, please go here.

Create indefinitely oscillating pendulum in Farseer Physics 3.3.1

Apr 15, 2012 at 6:37 AM
Edited Apr 15, 2012 at 6:38 AM

Hi Guys,

After a lot of tinkering around I have managed to produce a thin vertical rectangle shape on the screen and I wish this to swing back and forth pinned at the top up to an angle I set (90 degrees would be fine for this sample).

When it is approaching the top I wish it to slow down, then fall back the way it just came, increase speed then obviously slow to a stop at the top again. Almost how a swinging pirate ship would work at a theme park.

This is the code I have so far which swings the shape, but it is seeming to lose speed on each swing eventually grinding to a halt:

float playerWidth = ConvertUnits.ToSimUnits(5), playerHeight = ConvertUnits.ToSimUnits(68);
playerPosition = ConvertUnits.ToSimUnits(-350, 0);
playerBody = BodyFactory.CreateRectangle(World, playerWidth, playerHeight, 2f, playerPosition);
playerBody.BodyType = BodyType.Dynamic;
// create player sprite based on player body
_rectangleSprite = new Sprite(ScreenManager.Assets.TextureFromShape(playerBody.FixtureList[0].Shape, MaterialType.Player, Color.Orange, 1f));
// Create swinging joint
var joint = JointFactory.CreateFixedRevoluteJoint(World, playerBody, ConvertUnits.ToSimUnits(0, -34), playerBody.Position);

If somebody could also provide the command I would need to pause the shape on a mouse click or keyboard command at it's current angle and then continue when I let go of the mouse click that would be super fantastic!


Apr 15, 2012 at 12:27 PM
Edited Apr 15, 2012 at 12:34 PM

Hi fascinating experiment. Your rappresentation of a pendulum is not completely correct, though. The problem is the mass. For the engine the body's mass is "concentrated" on a point (the body's center of mass) which for a rectangle will be half-way. A pendulum, of course, works quite differently - in the perfect case all the mass is on one end of the hand and the hand's mass is negligible (a rope?). I don't know if you are trying to realistically simulate a real pendulum (it won't be so easy anyways).

As for the other issues - Euler integration for the motion inherently  loses energy so it's normal that your pendulum will stop. First set the friction of the body to 0. Then you can use motors on the joint to drive the pendulum according to some equation each time step based on the angle since the motors will regulate the total energy on their own. As a last resort you can make the pendulum kinematic and calculate the velocities according to the pendulum equations.

To pause the simulation on a body you can set a flag on mouse click and then: 

1. Not step the world - this will pause everything.


2. Disable the body - this will effectively pause the body.


3. Make the body static - forces will have no effect on the body but other bodies will still collide with it.

4. Clear all forces on the body and set the velocities and accelerations to 0 - same as above.

Some more info:

Apr 15, 2012 at 1:51 PM

Hi Jerry,

Firstly, thanks for the swift reply! I had read the first article actually, thanks, and understand some of the theory, but being novice to physics engines I don't really know how to get started in code applying this. I've programmed in .NET for about 10 years so my programming skill is proficient, just very new to game dev and physics.

I understand the theory of making the body static and that should be satisfactory choosing that option actually, as I'm fine if no forces can be applied. However as for using motors on the joint to drive the pendulum etc (smoothly I assume, and then slow to a stop once the designated angle is hit) and/or make the pendulum kinematic I wouldn't have an idea on where to start, are you able to elaborate with some basic code or even pseudo-code I might use in Farseer as I'm not familiar with a lot of the classes yet. How would I drive the pendulum with motors on each time step? As in, what functions and values would I give my motor to boost it just enough to reach the inverse angle keeping it accurate? I have briefly played with MotorEnabled, MaxMotorTorque and MotorSpeed on the revolute joint, so at least I'm in the same ball park as what you're talking about I think :)


Apr 15, 2012 at 3:59 PM

Hi, I can give you some pointers but my math is not really up to par for the actual equations :)

Basically you enable the motor of the joint to drive the pendulum. The motor works on its own according to its parameters. Afterwards in each Update() before calling World.Step() you modify its speed to get the behaviour you want.

To sum up: you can take several approaches:

- calculate it according to the laws

For example since your pendulum is compound you can find the equations here:

I think it won't be hard starting with the joint angle RevoluteJoint.JointAngle and substitute to find the angular acceleration and from there the angular velocity (that you can set directly to the body.AngularVelocity).

- another way is to use the equation of a pendulum as a function of time, find the angle and just set body.rotation to that angle or use a more sophisticated method to smooth it out:

- finally what i think is the simplest: motors. You can find brief description in the box2d manual. Note that one of the examples will exactly make a pendulum-like (i.e. swing back-and-forth) motion: 

myJoint->SetMotorSpeed(cosf(0.5f * time));

Here's the link

This might be no more than what you need.

Btw check the RopeTest in the test bed for a pendulum like contraption that uses the rope joint and gravity.

Jul 1, 2012 at 2:11 PM
Edited Jul 1, 2012 at 2:15 PM

Hey Jerry,

Long time no speak :) I finally had a chance to get back onto this project today and I finally conquered the infinitely oscilliating pendulum and freezing of the body with your help, I ended up going with nudging the linear velocity every time the line did a 90° pass on the swing, however I am just nudging it a finite amount each time at the moment for testing to ensure it always reaches the same top Y coodinates on the left and the right, which it is (to a few variable fractions each time!) so that's sweet. I also just set the body static when I wish to freeze it, it also works a treat.

However now I am not sure on..

1) If there is any way to, on left mouse click (along with freezing the body, which currently does work on mouse click) swap out the fixed testing velocity of 1.5f each time, (which is the same one set every time my line does a pass) for the real one I need which is a linear velocity determined by at which angle the line happens to be in a point of time when you click; In other words, if you left click and the line is rising to a 70° angle, the line should then fall and swing all the way toa mirror -70° with the joint being at the top like a true pendulum, then alternatively if you click at an angle of a mere 20° it will just set a smaller linear velocity ensuring a little push and swing only to a -20° on the opposing side. Again, these should swing indefinitely to these angles until I left click and shortern the angle even further. Hope that makes sense?

2) My second problem is, I want to be able to "move" my joint anchor (or at least that's what I think I have to do) from -0.34f on the Y axis to 0.34f, effectively swapping which end effectively is "pinned", however when I do this (using the below code) my body jumps around; the entire body actually moves position up 0.34f, (not just the joint), I want my body to stay still. Supposing end A is "pinned" and end B is loose, I now want end B "pinned" and end A loose :) Apologises on my lack of technical terms ;)

Initialisation of the joint:

playerJoint = JointFactory.CreateFixedRevoluteJoint(World, playerBody, ConvertUnits.ToSimUnits(0, -34), playerBody.Position);

Joint anchor reconfigured on mouse click:

// Left MouseClick
if (mouseStateCurrent.LeftButton == ButtonState.Pressed)
   playerJoint.LocalAnchorA = ConvertUnits.ToSimUnits(0, -34);
   //swingVelocity = playerBody.LinearVelocity;
   //swingVelocity = new Vector2(val, 0); // I thought maybe something like this? This variable was used every pass through 90� and I thought capturing the linear velocity at the point in which we click the mouse might work, but I really need to encorporate the actual angle in it somehow I think :S
   //playerBody.BodyType = BodyType.Static;
// Right MouseClick
if (mouseStateCurrent.RightButton == ButtonState.Pressed)
   playerJoint.LocalAnchorA = ConvertUnits.ToSimUnits(0, 34);
   //playerBody.BodyType = BodyType.Static;

Maybe I'm not supposed to move the anchor like this to achieve what I need? I have no idea, this engine and game dev. in general is really new to me. After 10 years in line-of-business .NET development, game dev is really stretching my skills (and vocabulary lol) ;) It's very annoying as I feel these are probably such basic questions! Again apologies for having to ask so many questions, thanks again.


Jul 1, 2012 at 3:00 PM

Actually Jerry I've just had a breakthrough on pinning the appropriate end to the world by utilising two joints and enabling them on left and right click respectively, however again, they seem to keep jumping to their original set world location, I have uploaded a quick video for you below to see what I'm talking about!)

(I obviously want the appropriately enabled joint to pin at the current X,Y location and not reset the position to where it was when the game started; I am left and right clicking lots in this vid, but you can see the closest way to explain the effect I want is a grappling hook I suppose, so my line continues to move along the level but that pins on either end appropriately)

You can also see at the end of this video the line can be infinitely oscillating in the pendulum effect :)

Jul 2, 2012 at 11:13 PM

I noticed you use FixedRevoluteJoints. I have no experience with those since they are an extension of Farseer with regards to Box2D. I know they were removed from the latest svn - might be because there were issues? I've always had problems visualizing how a fixed joint would work when bodies move, what happens to the anchors...

I could suggest you try a normal revolute joint attached to a static body (that would be invisible graphically). Might get you further.

Jul 11, 2012 at 3:12 PM

Hi Jerry,

I now have my joint position setting correctly now in conjunction with the standard revolute joint and static body you suggested, it's working great! So nice to see that operational as it should be. I can't thank you enough.

I seem to just have one minor problem, or well, confusion now-- It appears when my object [player] drops through the world and then becomes frozen in the world by setting a top and bottom joint to enabled (effectively 'pinning' it to the world; a better approach I found than setting the BodyType to Static) it seems if I pin the body to the world for too long (eg, >2 secs) the player then continues to be pinned and does not proceed to drop as usual due to gravity, however if I left click and hold (as my left click is bound to set the joint to Enabled=False, effectively releasing it and dropping it through the world vertically) for say 1 second or less it drops down and pins again as it should on click again.

So any idea why it would 'pin' indefinitely on the greater mouse hold timings?

I found a work around, I give the body a nudge every time and it seems to 'unlock' it (so to speak) each and every time, even on long mouse holds.

else if (mouseStatePrevious.LeftButton == ButtonState.Pressed && mouseStateCurrent.LeftButton == ButtonState.Released)
    playerJointA.Enabled = false;
    // Just enough force to get the player moving again - Don't know why I have to do this?
    playerBody.ApplyForce(new Vector2(0, 0.01f));

What do you think could be causing this, is this expected behavior?

Thanks, and feel free to say you have to stop helping me at any time :)

Jul 11, 2012 at 10:27 PM

I've had a somewhat similar issue and it was because the body went to sleep and only applying a force would wake it up (not gravity or joint forces). I had to set SleepingAllowed=false and this solved it.

Jul 12, 2012 at 12:27 AM

Ah, interesting, thanks Jerry, will try when I get home from work.

You're a wealth of knowledge!