News Mar 20: R.U.B.E v1.7 released. Instanciable objects!
Feb 21: Added RUBE sample loader for Cocos2d-X v3.4.
Feb 17: Funny Fists released in iOS App store and Google Play store. (YouTube video)
May 25: R.U.B.E v1.6 released. Samplers!
May 12: "On-the-fly" resource updating for Cocos2d-x
Apr 22: New blog post: Inverted pendulum control
Apr 7: On-screen logging class for Cocos2d-x
Mar 22: Downhill Supreme 2 released for iOS and Android
Jan 2: YouTube video: Making soft-body wheels in RUBE
Oct 6: Check out Supplyfront RTS, my 7dRTS entry continued.
Sep 26: R.U.B.E v1.5 released. Customizable item labels, snap-to-grid, export filtering, full-text help search.
Sep 18: Added RUBE sample loader for Cocos2d-X.
Sep 16: Updated RUBE sample loader for Cocos2d v2.
Aug 12: RUBE loader for Nape by Zeh Fernando
Aug 7: Added RUBE sample loader for SFML.
Jul 30: Try my MiniLD 7dRTS entry.
Jul 24: Added physics-driven particles tutorial.
Jul 20: New blog post: rendering solid ground (as in Downhill Supreme)
Jul 18: R.U.B.E v1.4 released. Command-line interface for batch jobs, hotkeys for scripts, better script management.
May 22: Downhill Supreme is out now! (iOS)
Apr 2: R.U.B.E v1.3 released. Collision bitplane editing, Cocos2d-iphone loader, usability improvements.
Mar 11: R.U.B.E v1.2 released. Now supports weld, friction, motor joints and automatic image reloading.
Mar 10: RUBE loader for libGDX by Tim Scott
Jan 28: New blog post: a functional combustion engine!
Jan 22: New blog post: wind tunnel
Jan 20: Added explosions tutorial.
Jan 16: Added buoyancy tutorial.
Jan 16: AndEngine sample project to load RUBE scene by Bart Hirst
Jan 14: R.U.B.E v1.1 released, now supports custom properties.
Jan 1: All basic tutorials are now available in Chinese at Huge thankyou to @OhCoder!
Dec 23: Discussion forums have been set up
Dec 4: R.U.B.E v1.0 is ready !
Dec 2: YouTube video: Box2D pendulum clock
Nov 26: New blog post: rocket platform thingy
Nov 25: Video of R.U.B.E scenes in Chipmunk.
Nov 23: A sample project to load R.U.B.E scenes into Chipmunk physics! Details here.
Nov 14: An XCode sample project to load R.U.B.E scenes on iOS is now available. Details here.
Nov 11: A Java version of b2dJson is now available, based on JBox2D.
Nov 6: A Javascript version of b2dJson based on box2dweb is now available. Demo here!
Nov 2: The full specification of the JSON format used by b2dJson can be found here: b2dJson file structure
Oct 28: YouTube video: 2-minute ragdoll in R.U.B.E Box2D editor
Sep 29: YouTube video: R.U.B.E Box2D editor usage example
Created: April 22 2014

Inverted pendulum control

Inverted pendulum is a fancy term for balancing something like a stick or a pole to keep it vertical, by supporting it only at the bottom. Inverted pendulum As you probably know if you've tried this, the vertical position is an unstable state and the natural result is for the stick to accelerate away from it. It can be stabilized with a fast enough controller, eg. your eye/brain/hand, or a computer, that can react in real-time and move the support point.

It seems like PID controllers are commonly used to keep this kind of situation stable. When using one for another project recently I found they are actually extremely simple, so thought I would also try using them for inverted pendulums in Box2D.

I made three variations, the first has the 'cart' on a prismatic joint, which allows for exact (and unrealistic) control by setting the motor speed to whatever is needed. The second two variations are carts on wheels, and are more limited in the control they have because they depend on friction between the wheels and the ground, and the torque of the wheels themselves spinning can interfere a little: Inverted pendulum A basic controller for a single variable can be written in a few dozen lines of code. Each time step, you tell it what the current error is, and 'step' it for a specific time length, similar to a Box2D step. The output value of the controller is then applied to whatever will affect the error - in this case The controller error is of course the angle deviation from vertical, which is easy to find.
  angleController.setError( targetAngle - pendulumBody->GetAngle() );
  angleController.step( 1 / 60.0 );
  float targetSpeed = angleController.getOutput();
The target speed here is the speed that the cart should move at. For the first case, this can be set directly as the motor speed of the prismatic joint. For the other two cases, dividing the speed by the circumference of the wheels will give the angular velocity that the wheels should turn at, which is given as the motor speed of the wheel joints.

The not-so-simple part of all this is deciding what the 'gain' values should be for the controller. There is a proper way to design these controllers so that they are optimal, and there is a huge amount of info around on the net about that. However the math made my head hurt, so I just played with the numbers for a while until I got a reasonable result. If the required speed exceeds a maximum limit, the controller will give up and do nothing instead of speeding off into the distance.

This simple controller works fairly well to keep the angle of the pendulum vertical, but the cart will usually move away from the position it started at. It should also be noted that the angle of the pendulum corresponds to an acceleration of the cart. For example, to hold the pendulum at a constant angle of 5 degrees the cart would need to accelerate at a constant rate - it would need to continuously get faster and faster. To hold the pendulum at a constant angle of zero means that the acceleration of the cart will be zero. Acceleration of zero means that speed is not changing... but it does not mean that speed is zero. The result of this situation is that when the pendulum stabilizes in a vertical position, the cart will have a constant speed. To stabilize the speed of the cart, or even better bring it to a specific position, another controller is needed.

Since the angle of the pendulum corresponds to an acceleration of the cart, changing the target angle of the pendulum from zero to something else will cause a change of speed of the cart. The question that stumped me for a while was the exact relationship between pendulum angle and cart acceleration. I finally found some math I could understand here (PDF), which points out that the angular acceleration of the pendulum can be written in two ways: Inverted pendulum ... where g is gravity. This can be rewritten and solved to find the angle required to produce a given acceleration: Inverted pendulum Okay it's not solved, but my head was still hurting from earlier, and I noticed that sin/cos is basically linear for the part of it that I'm interested in: Inverted pendulum The point of this graph probably seems quite obtuse, but since the other side of the equation is the cart acceleration over gravity, you could think of the vertical axis as 'g-force' and the horizontal axis is the angle of the pendulum away from vertical. The graph line shows how much g-force is required to maintain the pendulum constantly at a given angle. The important thing to see is that as the pendulum angle increases, the corresponding cart acceleration increases linearly up until about 0.5, which is roughly 30 degrees. This means the relationship between pendulum angle and cart acceleration can be considered as linear for the purposes of this little experiment (any angle over 30 degrees is a lost cause anyway).

(Side note: apparently Formula One cars can accelerate at about 1.4g until about 200km/h, which according to this graph would let them maintain a pendulum at about 55 degrees away from vertical during that time. That must be quite a ride!)

Since I had my PID controller class ready I used a second controller to adjust the desired angle based on the current position of the cart, to make it move left or right. This is probably not the best way but it does ok. The code is similar to above, with input error being the difference between current position and desired position, and the output being a target angle for the pendulum.

Turns out it was not really necessary to bother with the equations above since the controller can do an ok job as long as it's given decent gain settings, but it was nice to know the input and output are linear, and it makes me feel smart to have formula markup and graphs in my blog. In future if I make a more sophisticated controller, eg. maintain a target velocity, that formula could be used as part of a proper calculation for target angle.

Check out these links for some cool related things:

Source code:

Binaries for Win32, Mac, Linux64: