I am writing a basic game engine to help with my PhD topic on multi-agent learning. I am using PyBullet as the backend physics engine and OpenGL for visual display. I have OpenGL buffers set up to hold the object information such as position(vec3) and rotation(matrix4x4) with rotations being done using Quaternions, but are stored using Euler angles for convenience.
My problem is that when I rotate an object in the OpenGL game world (around any axis), the pyBullet rotation (as seen from the pyBullet GUI) is in the opposite direction and sometime completely off. I must be missing something quiet basic and I apologies if this is a simple fix. I have also provided a video to show the issue that I am having - link to video of error (https://youtu.be/4VpBUx5LBYQ):
When I extract the rotation from PyBullet using getBasePositionAndOrientation()
and convert the quaternion to Euler angles using pybullet.getEulerFromQuaternion()
, the result is the correct vec3, but upon conversion to the rotation matrix pybullet.getMatrixFromQuaternion()
, it seems to reverse the rotation direction.
Please see my code below:
'obj = Class BaseSceneObject'
'action = Euler rotation angle in degrees to apply vec3(x, y, z) e.g.(1., 0., 0.) apply +1 degree rotation to x-axis'
'Collect current position and rotation of object and update PyBullet'
# get the rotation - euler angles in degrees vec3(x,y,z)
rot = obj.get_rotation()
# add rotation action (e.g. +1 degree to x = vec3(1., 0., 0.)) and convert to radians
rot = math.radians(rot[0] + action[0]), math.radians(rot[1] + action[1]), math.radians(rot[2] + action[2])
# convert rotation from euler to quaternion
quat = pybullet.getQuaternionFromEuler(rot)
# update position and orientation
pybullet.resetBasePositionAndOrientation(bodyUniqueId=obj.get_rigid_body_id(),
posObj=obj.get_position(),
ornObj=quat)
'Collect PyBullet results and update OpenGL'
# get position and rotation from PyBullet
position, rotation = pybullet.getBasePositionAndOrientation(bodyUniqueId=obj.get_rigid_body_id())
# update object position
obj.set_position(position=position)
# convert rotation quaternion to euler angles
rot_r = pybullet.getEulerFromQuaternion(rotation)
# convert radians to degrees
rot_d = math.degrees(rot_r[0]), math.degrees(rot_r[1]), math.degrees(rot_r[2])
# construct OpenGL object rotation matrix
rot_m_final = numpy.identity(4)
rot_mr = numpy.array(pybullet.getMatrixFromQuaternion(rotation)).reshape(3, 3)
rot_m_final[:3, :3] = rot_mr
# update OpenGL rotation matrix
obj.set_rotation(rotation=rot_d,
rotation_matrix=rot_m_final)