3

I am currently trying to get the rotation of an object. I am using C++ and Bullet Physics. This is my code:

btScalar x, y, z;
body[0]->getCenterOfMassTransform().getBasis().getEulerZYX(z, y, x);

However, as I rotate the object around clockwise the number I get from the y (y is vertical in Bullet) axis goes from 0 to -90 to 0 to 90 and finally back to 0 for every quarter rotation. It is close but what I need is for it to go all the way from 0 to 360.

Ciro Santilli OurBigBook.com
  • 347,512
  • 102
  • 1,199
  • 985
  • Possible duplicate of [Converting yaw Euler angles in range \[-90, 90\] to \[0, 360\]](http://stackoverflow.com/questions/11165556/converting-yaw-euler-angles-in-range-90-90-to-0-360) – Ciro Santilli OurBigBook.com May 03 '16 at 06:56

2 Answers2

1

Bullet documentation says:

void    getEulerZYX (btScalar &yaw, btScalar &pitch, btScalar &roll, unsigned int solution_number=1) const 

and

solution_number Which solution of two possible solutions ( 1 or 2) are possible values 

this is because euler angles are ambigous. have you tried solution 2?

stefan
  • 3,681
  • 15
  • 25
  • Thanks for the fast response. I tried solution 2 and it is closer but still not perfect. Now what I get as I turn it is 180 to 270 to 180 to 90 for each quarter rotation of the object.. It would be perfect if the first value was 360 or 0 rather than 180. As it is now I still can't distinguish between 0/360 and 180. Any other ideas? – gsparrowpepin Apr 26 '15 at 16:14
  • Something that may of may not be helpful. I am looking at the y value returned. However, when the simulation starts and the y value is 180 the z and x values are -180 and 180 respectively. After a half turn when the y value again reads 180 the x and z are both 0. I realize I could most likely use this to hack the solution but I would really like to understand how this is working rather than just hacking it together. Is there an equation that is used to get the rotation which uses the 3 values rather than just the y? – gsparrowpepin Apr 26 '15 at 16:21
  • there are two solutions. with that function you can get both and select by your criteria which solution you like more. technically they are identical. if you want to rotate your body to look back you could simply turn by 180°. or you might want to do half a forward roll and then rotate around your belly point to stand upright again. I'd favor the first but in terms of the result the latter is identical. :-) – stefan Apr 26 '15 at 20:07
  • Right, that makes sense. But the question still remains, is it possible to get the rotation around the vertical axis from 0-360 degrees? – gsparrowpepin Apr 27 '15 at 02:02
  • Of course you are free to alter both solutions by adding 360° to any (negative) angle. – stefan Apr 27 '15 at 04:51
1

I had the same problem. I using LibGDX with Bullet engine, so my code sample on Java, but I'm sure, that it will works on C++ too. Here is my solution (for Z axis):

body.getWorldTransform().getRotation(mRotation);

// That gives you an angle in all range but excluding (85, 95) and (-95, 85). For other axis you can try to get Pitch or Yaw.
float roll = mRotation.getRoll();

// That gives you an angle in range [0, 240). Clockwise and counterclockwise directions isn't detected. 
float angle = mRotation.getAngleAround(0, 0, 1);

// Usually 0, but on (85, 95) and (-95, 85) becomes 1 and -1. 
int gimbalPole = mRotation.getGimbalPole();

// Using roll (pitch/yaw for other axis) if it's defined, and using angle with gimble pole otherwise.
float rotation = (gimbalPole == 0) ? roll : angle * gimbalPole;

Obtained rotation will be in range (-180, 180). It can be easily converted to [0, 360) range:

if (rotation < 0) rotation += 360;
Andrew
  • 161
  • 2
  • 14