Bone rotation axis order issue

Before anything, take a look at the below code:

head_b_rot = self.parts_dict['body'].channels[5].rotation_quaternion
self.parts_dict['head'].localOrientation = ( -head_b_rot[1], head_b_rot[3], head_b_rot[2] )

I find it strange which the rotation_quaternion obtained from the bone cannot be used as self.parts_dict[‘head’].localOrientation = head_b_rot, otherwise the head rotation gets all wrong. By trial and error I found the correct disposition was (-head_b_rot[1], head_b_rot[3], head_b_rot[2]).

Is there anything at the mathutils bge module which already arrange correctly the head_b_rot result? Is there other command to retrieve the bone rotation in a format which I can simply do self.parts_dict[‘head’].localOrientation = head_b_rot?

Thanks in advance for any help


I managed to do something with Euler.

(must change the option in the UI if want using euler)

with quaternion nothing happen

You say which using Euler can make the use of head_b_parts more efficient? I will take a look at it.

I already messed with Eulers with good results, but at other part of the code and with other purposes.

i think to underastand the reason of your issue ,when you get
this return as Vector[4], not as quaternion.

(and when you put it in localOrientation , I think is read as Euler…sure which return correct, just with order inverted? i not know quaternion but seem different to euler)

so, have to convert this in quaternion :

import mathutils

q = mathutils.Quaternion(self.parts_dict[‘body’].channels[5].rotation_quaternion)
self.parts_dict[‘head’].localOrientation = q

anyway seem a bug.

Hi once more, I have now managed to have a working and somehow efficient fully python object to bone tracking system(no emptys) it operates on quaternions(a small part of it is as suggested on the post above), I have further investigated on the axis order things above and I guess I can explain better the problem:

If we have a vertical direction bone(tail right above the head), the rotation axis of the quaternion must be arranged into a given order(sometimes inverting rotation with - is required) to work correctly; if the bone is horizontal (tail at the side of the head), there is another axis order required(different from the previous case). Is there a good logic for me to apply only one set of ordered axis to both types of bones?

For example, in the case I needed for an object to attach to a given position in relation to a bone, and this object position must rotate in relation the bone center(ex: rotate as the hand rotates), I used LocalTransform manipulation for that ; I suspect there is a way in BGE to rotate both bone types correctly using a single axis order(.bone_mat?).

The obvious thing which comes to my mind is to compare the bones being tracked tail and head positions, to know if it is horizontal or vertical and apply the right set of ordered axis to the detected case; but I would like a more efficient and straightforward alternative; does one of the community members have a solution for that?

Thanks in advance.

Hi , i worked on this in the last week , i know pretty weel now how work the bone.
i not know how you can manipulate manually the quaternion (is possible?)
what you use to align the bone ?

also , you make the transformation from armature space in the world space before?

Got a fully working, efficient, simplified/easy and without axis order worries system. A hint for you which need to make such a system:

1 - Do not go quaternions way, use matrices, they are more eficient, also do not have gimbal lock issues, and are the base of any system, so quaternions and euler probably get converted to matrices along the path under BGE hood anyway.

2 - For correct positioning, you must take in account both the position and rotation

3 - Use the correct bone matrix, channel_matrix(no bone_mat, arm_mat or pose_mat). It gives you the bone rotation taking in account parent bones rotations also, so you do not need to get each parent bones and their rotation and multiply them. The bones axis are correct also, avoiding manual axis switch. Actually I know bone_mat doesn’t works as it never changes(tested only 1 axis movement thought); can’t remember arm_mat and pose_matrix results, but I remember channel_matrix was the first one to work right away.

Obs: Answered MarcoIT throught Private message

mhh, if you use the bone as imput(read data) you can use directly the matrices .(agree,much better as performances and as “mess code”)

but if you instead want move / rotate the bone , i not think you can use matrices directly (pose_matrix,channel_matrix here read-only)
since this is the only way to rotate the bone from python

bone.rotation_quaternion >> Quaternion
bone.rotation_euler >> Euler
bone.joint_rotation >> Euler

(and is not even local, but a sort of local+local)

if i not missing something