Wednesday, 9 February 2011

Developer Journal 55

Argh! How do I detect when you've tipped over? Argh!

4:10 PM
I felt very tired this morning. I got about nine hours sleep last night.

5:41 PM
I added controls to manually rotate a robot around yaw, pitch, and roll. Makes working out the numbers to help me set limits easier.

The valid range for pitch will be from -85 degrees to 85 degrees.
The valid range will be the same for roll.
Luckily, only yaw is the tricky one and I don't need to look at that to write the code to help robots get back up.

6:17 PM
The problem is that roll changes when I change yaw.
The same with pitch.

7:33 PM
Rotating right.
When yaw is 0 degrees, pitch is 0 degrees and roll is 0 degrees.
When yaw is -90 degrees, pitch is 180 degrees and roll is -180 degrees.
5 degrees more and yaw is -85, pitch -180, roll is 180.

8:14 PM
There's got to be an easier to way to tell when a robot has tipped over and then reset it.

8:24 PM
I could cheat. I could reset any robots that haven't moved for a while or disable vertical movement...

10:34 PM
I wish my teachers had put mathematics in context for when I was a kid. I would have paid much more attention and learned a whole bunch more.

I remember something about how you can put the end of two vectors together and calculate the angle between them. I think you can do the same thing with quaternions. I can get a quaternion representing a robot's orientation and another quaternion that points straight up. Then I can calculate the angle between then and if it is more than 85 degrees, I can reset the position of the robot. I'll give it a go tomorrow.

Through doing game and simulation programming, I've come across more and more situations that have put the maths that I barely learned in use. One of the things I'm going to do is keep track of these situations. I have a hunch they'll become useful. Especially as my little brother starts to complain about learning maths.



  1. I am surprised that you are helping them up! Mind if I ask why? lol :D

    That aside, I do not understand why pitch, yaw, and roll are affecting each other. Is that expected behavior? Are you setting angles, or adding them relatively? (That would result in the behavior you describe in some instances since the three dimensions are not independent w.r.t. addition...)

    In general, I think tipping over should be indicated by an absolute pitch of +/- 90 degrees (fully back/forward) or an absolute roll of +/- 90 degrees (fully right/left).

    I mean, it might depend on your how your system deals with the values... But generally that should hold, shouldn't it? (Esp once it has settled, since it's a square?)

    Also, it sounds like what you are wanting to do is treat the two angles as vectors projected onto a plane so that you can calculate the angle between them using trig. However, I think there might be a better solution here, especially if your system stores absolute angles anywhere.

    Maybe some code snippets/examples would help me understand what's going on better?

  2. Just an addendum re: calculating the angle.

    If you do actually need to calculate the angle, I think that trig would yield a very simple closed form given how basic the up angle is (90, 0, 0).

    Despite this, I think there must be an easier way to calculate the angle than either trig or quaternions.

    Did you code the spatial orientations/etc, or is that all OGRE?

  3. Hi Anonymous,

    I'm helping them up because I need to get a self perpetuating population going again to get some interim milestone results. The robots currently can only move forwards, backwards, turn left, and right. When a robot falls over, it has no way to get up so it will starve and die. I'll take away the assistance as the robots become more sophisticated.

    The starting orientation is yaw 0, pitch 0, and roll 0. Positive x is right, positive y is up, and positive z is out of the screen. My robot is facing negative z, into the screen. If I only change pitch, the range is between -90 and 90 degrees as expected. Similar with roll.

    However, when I change yaw, then pitch is no longer between -90 and 90. Things get even more complicated when I also change roll at the same time. I'll put up some screen-shots, values, and code tomorrow :)

    The behavior I got is not what I expected. I'm using Bullet Physics, so I apply a force and Bullet calculates the resulting positions and orientations.

    I tried disabling Bullet and rotated the robots manually. I tried getting yaw, pitch, and roll and incremented them to rotated in one direction and decremented them to go in the other direction. Yaw, pitch, and roll changed from positive to negative so it was difficult to even just rotate in one direction. This is kind of like adding to them relatively.

    I then tried a different method. I created a rotation matrix with the increment I wanted and applied it to the matrix in the robot. This allowed me to rotate the robot smoothly in all directions.

    The next challenge was to determine how far the robot had rotated in the pitch and yaw directions. I can keep track of them when I rotated manually, but I couldn't when I turned things over to the physics engine.

    So I had to get the values from the robot's matrices. However, the pitch, yaw, and roll values were unpredictable in some orientations.

    I finally stumbled across how to do it today.

    1) Create 2 up vectors, (0,1,0). Call them Alpha and Bravo.
    2) Rotate Bravo by the rotation matrix of the robot.
    3) Calculate then angle between the two vectors.

    Does not work if Bravo is not an up vector and I could not work out how to do this with quaternions.

    The affect of doing this is that the ends of the vectors are touching and I'm getting the angle between them.

    The math involved a little more than trig but that little bit was beyond what I was comfortable doing. So all the calculations were done by Bullet.

    I originally thought that this part wouldn't be too hard and it wouldn't take me too long :)