Sunday, 24 July 2011
Developer Journal 114 - On Bullet Physics Constraints
Over the past few days I've been driven nuts learning about Bullet Physics constraints. When I bent the right elbow, the right arm would start shaking uncontrollably and the whole arm would bend in angles and directions that human arms could not.
I found the shaking reduced when I decreased the weight of the right hand. (There was also a whole mess where I had to try a whole bunch of things to figure out that the right hand was what was causing the right elbow not to bend. I got so desperate that I converted my simple cube trial set up to a upper torso, right upper arm, right lower arm, and right hand set up to figure out what was the thing that was different that enabled my trial set up to work but not my humanoid robot.)
The shaking also decreased when I applied a high level of damping to the right upper arm, the right lower arm, and the right elbow joint. This eliminated the shaking and I was ecstatic. Later however, the humanoid robot got knocked by cube robot and the humanoid robot's legs hung in the air. I realised that with the high level of damping, that gravity was not being applied to the limbs.
I then programmed keys to allow me to control the rotation of the right elbow. Previously, I had programmed the right elbow to bend as soon as the simulation started.
Somewhere along the line I came across the hard limits in the Bullet Physics documentation. I suspected and confirmed that the shaking was due to the limb bumping against the hard limit of what constraint Y axis. The Y axis has the hard limit of -PI/2 and PI/2 (-1.53 and 1.53). So when I operated in the smaller limit of -1.4 and 1.4, the limb shaking diminished substantially.
Now due to my earlier realization that high damping turned off gravity, I reduced the damping.
Now suddenly, the keys could not activate movement. I tried a whole bunch of things for a long time and noticed that the elbow could bend when I programmed the elbow to bend when I started the simulation instead of using the keys to do so once the simulation had started.
Strangely the keys could activate X and Z rotation but not Y rotation.
Strangely, the cube shape test set up works. I created a simpler example. On a side note, the cube shape has trouble when I enable all three axis.
What if I just dampen the constraints? Nope. Only works when I set to full the damping for all rigid bodies. Does the motor not work when the constraint goes beyond a limit?
I tried adjusting the dozen or so parameters in the constraint motor over and over to no avail. This took up a lot of time.
The elbow works when the upper arm has an infinite mass. That's when I noticed it. Indeed the motor does not work when a joint goes far beyond its limit. When the upper arm is fixed the elbow joint goes only a little pass its limit. When the upper arm is not fixed, the elbow joint goes pass its limit by a greater amount. The limit error is 0.000660473 when the upper arm has an infinite mass and is
0.0173877 when the upper arm has a mass of 1.
Much to my frustration, it doesn't matter if I adjust the limits by small amounts. Only big ones. Limit -1.4 and 1.4 works well. This is because the arm is hanging down. -1.4 and 1.0 does not work. -1.4 and 1.2 works.
I realised that the elbow worked before when I had damping because the elbow joint did not go pass its limit because gravity was not acting on the arm.
I also realised that the elbow worked when I programmed the elbow to bend when the simulation started but not when I used my keys after the simulation started. It was because after the simulation started, the elbow had gone pass the limit, but if I programmed the elbow to bend when the simulation started, the elbow did not have time to go pass the limit.
I tried a whole bunch of ways to get around the motor not working when the elbow went beyond its limit. One of the ways that worked was applying a velocity when the joint approach a limit. The downside of this was that the arm wobbled.
I then found another clue on the Bullet Physics Library forum that confirmed my hunch. I can get the motor to work by temporarily changing the limit that was being breached!
The elbow joint now works really well.
However, I noticed that when I used keys and switched keys quickly the arm would not move quite right. For example, if I pressed down and then up quickly, the arm would not move up. I realised that it was due to pressing up and then releasing down. When I press up, I set the velocity to a certain number but when I release a key, I set the velocity to zero. The three possible target velocities were -1, 0, and 1. The solution was to check that I had not gone the opposite direction before setting the velocity to zero. For example, if the velocity is 1, before setting the velocity to 0, I check whether the velocity has changed to -1.
So far so good. I never want to program new things again. I am starting to crave more certainty in my work. Perhaps I should have finished my accounting degree?
My next hunch is that I'll have to use more than one motor because rotations in one axes affects other axes too much.
Can I have 3 separate constraints between 2 rigid bodies or do I need more rigid bodies?
For example instead of just upper and lower arm, adding two more rigid. The order would then be upper arm, constraint 1, rigid body alpha, constraint 2, rigid body bravo, constraint 3, lower arm.
Can I have 1 constraint responsible for rotation in 1 axis and another rotation responsible for rotation in 2 axis?
Is axis or axes plural or singular?
Enough questions for today.
Labels: developer journal