Integrating Bullet with a Z-axis-up System

Post Reply
allsey87
Posts: 33
Joined: Fri Oct 26, 2012 1:50 pm

Integrating Bullet with a Z-axis-up System

Post by allsey87 »

Hi All,

I am integrating Bullet into a multi-physics-engine simulator that uses a right angle coordinate system with +Z as the 'up-axis'. As I understand, for implementation purposes Bullet can be seen as using a right angle coordinate system with +Y as the 'up-axis'. This problem is demonstrated visually as follows:
contrasting the bullet and simulator coordinate systems
contrasting the bullet and simulator coordinate systems
rhcs.png (3.84 KiB) Viewed 6488 times
I have found scattered information on this issue, and what appears to be an adhoc solution in the RayCastVehicle class and demo example (see: btRaycastVehicle::setCoordinateSystem). However I have been unable to find any recommendations on the best way adapt/convert the coordinate system in bullet, into the coordinate system that is inside the simulator.

My solution at the moment is to leave everything in Bullet as is, and attempt to simply rotate the coordinate system on the interface between Bullet and the simulator. Since the simulator has it's own sets of classes for quaternions and 3D vectors, I have tried to use the type conversion interface to also add the appropriate transformations (see the following code).

Code: Select all

static const CQuaternion SIMULATOR_TO_BULLET = 
   CQuaternion(CVector3(0.0, 1.0, 0.0), CVector3(0.0, 0.0, 1.0));

static const CQuaternion BULLET_TO_SIMULATOR =
   CQuaternion(CVector3(0.0, 0.0, 1.0), CVector3(0.0, 1.0, 0.0));

inline CVector3 BulletToSimulator(const btVector3& c_bt_vector) {
   return CVector3(c_bt_vector.getX(), -c_bt_vector.getZ(), c_bt_vector.getY());
}

inline btVector3 SimulatorToBullet(const CVector3& c_a_vector) {
   return btVector3(c_a_vector.GetX(), c_a_vector.GetZ(), -c_a_vector.GetY());
}

inline CQuaternion BulletToSimulator(const btQuaternion& c_bt_quaternion) {
   return CQuaternion(c_bt_quaternion.getW(), c_bt_quaternion.getX(),
                      c_bt_quaternion.getY(), c_bt_quaternion.getZ()) * BULLET_TO_SIMULATOR;
}

inline btQuaternion SimulatorToBullet(const CQuaternion& c_a_quaternion_in) {
   CQuaternion c_a_quaternion(c_a_quaternion_in * SIMULATOR_TO_BULLET);
   return btQuaternion(c_a_quaternion.GetX(), c_a_quaternion.GetY(),
                       c_a_quaternion.GetZ(), c_a_quaternion.GetW());
}
However this still has some bugs (see below - objects are coming to rest at 45 degrees, despite only multiples of 90 degree rotations) and it isn't really all that efficient to be applying these quaternion rotations on every simulation step if unnecessary.
screenshot of the simulator showing entities resting at 45 degrees...
screenshot of the simulator showing entities resting at 45 degrees...
frame.png (36.64 KiB) Viewed 6488 times
So my question to all readers would be, how have you tackled this problem before and what recommendations can you make?

All the best,

allsey87
allsey87
Posts: 33
Joined: Fri Oct 26, 2012 1:50 pm

Re: Integrating Bullet with a Z-axis-up System

Post by allsey87 »

Actually this solution does work nicely and can also avoid rotations (relatively costly compared to simple negations), the bug before was that I had forgotten to negate and switch the Z and Y axes in the Quaternion helper functions.

Code: Select all

inline CVector3 BulletToSimulator(const btVector3& c_bt_vector) {
   return CVector3(c_bt_vector.getX(), -c_bt_vector.getZ(), c_bt_vector.getY());
}

inline btVector3 SimulatorToBullet(const CVector3& c_a_vector) {
   return btVector3(c_a_vector.GetX(), c_a_vector.GetZ(), -c_a_vector.GetY());
}

inline CQuaternion BulletToSimulator(const btQuaternion& c_bt_quaternion) {
   return CQuaternion(c_bt_quaternion.getW(), c_bt_quaternion.getX(),
                         -c_bt_quaternion.getZ(), c_bt_quaternion.getY());
}

inline btQuaternion SimulatorToBullet(const CQuaternion& c_a_quaternion) {
   return btQuaternion(c_a_quaternion.GetX(), c_a_quaternion.GetZ(), 
                       -c_a_quaternion.GetY(), c_a_quaternion.GetW());
}
Post Reply