I have the following information from an object: Rotation in degrees (absolute world coordinates) and position in absolute world coordinates.

My goal: to set the position and orientation of a pose bone via python.

My problem: How to rotate the bone by the X, Y, Z axis around it's head along the world X, Y, Z axis?

Here is my current approach: I take my bone's rest matrix (armatureObject.pose.bones["Arm1"].matrix), convert this to euler angles in degrees.

Here is my first assumption that may actually be wrong:

  1. This is not the rest matrix.
  2. The X Y Z angles I get out of this: are these angles relative to the world, or relative to something else?

Now in this process I add my rotation (as I want this bone to be rotated by X = 20°, Y = 30° and Z = 40°) and finally I apply these again to the pose bone.

However, this does not yield a correct result.

What I have in values:

  • Pose Bone Rest Matrix 4x4 converted to Euler (XYZ): -56.332200° , 27.38295°, 48.9299°
  • My input Offset Rotation: : 20°, 30°, 40°

By manually using the cursor and rotating the bone via this pivot in 3D View, I was able to get the correct position for the bone and read the values I need to get through calculation: - Should be (Euler XYZ): 3.082°, -29.799°, 38.67°

Simple enough I believe rotating my matrix by 20, 30 and 40 rotation matrices should have solved it, but it doesn't. :(

armatureBones = armatureObject.pose.bones
boneWP = armatureObject.matrix_world * armatureBones["Arm1"].matrix

rX = mathutils.Matrix.Rotation(radians(20), 4, 'X')
rY = mathutils.Matrix.Rotation(radians(30), 4, 'Y')
rZ = mathutils.Matrix.Rotation(radians(40), 4, 'Z')
newRotMat = rZ * rY * rX * boneWP
newRotMatDirs = newRotMat.to_euler()

# readout to compare
print ("is angle:", degrees(newRotMatDirs[0]),degrees(newRotMatDirs[1]),degrees(newRotMatDirs[2]))
print ("should be", 3.082, -29.799, 38.67)

For this I get: 8.900, 1.558, 144.03145

Where am I going wrong?


See this answer

def rotate_around_center(mat_rot, center):
    return ( mathutils.Matrix.Translation( center) * 
             mat_rot * 

eu = mathutils.Euler(map(radians, (20.0, 30.0, 40.0), 'XYZ').to_matrix().to_4x4()
newRotMat = rotate_around_center(eu, boneWP.location) * boneWP
  • $\begingroup$ This did the trick! There was a missing ) to close the "map" parameter, and boneWP.location didn't work for me, so I used boneWP.decompose()[0] $\endgroup$
    – Mondkalb
    Jan 20 '17 at 9:44

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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