1
\$\begingroup\$

Project description: 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 (Link to video):

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)

Thank you for reading this and I hope that you can help me.

\$\endgroup\$
1
  • \$\begingroup\$ I’m voting to close this question because it is a cross-post of stack overflow. Crossposting question on StackExchange sites is not allowed. Please select the site you think you'll get the most/best answers and post only there. \$\endgroup\$ – Vaillancourt Aug 10 '20 at 15:40
2
\$\begingroup\$

It turns out that the above code is correct. The issue resided in the OpennGL shader, where I forgot that matrix calculations are non commutive, i.e. numpy.matmul(Mat4(Rotation), Vec4(position)) is not the same as numpy.matmul(Vec4(position), Mat4(Rotation)).

After updating my shader code from:

vec4 aRPos = vec4(aRotation * aVertex); 

To:

vec4 aRPos = vec4(aVertex * aRotation);

It worked perfectly. Thank you.

\$\endgroup\$

Not the answer you're looking for? Browse other questions tagged or ask your own question.