1
$\begingroup$

I want to get angles of joints in armature in pose mode, see the picture below. I tried to get local rotation of bones, but I can't find a way to do this.

enter image description here

I tried:

bone.rotation_euler()   # everytime returns [0, 0, 0] 
bone.matrix.to_euler()  # everytime returns some constant value e.g. [2, 0, 0]

I can rotate bone, but values don't change. How can I get actual rotations of the bone?

Also I find out a strange thing:

  1. If bone has Rotation Constrait I can rotate it to constraint and it stops, but in Transform panel I see that angle is stil growing
  2. If I use IK and move bone, location and translation in Transform window doesn't change.

Maybe this is relating to my problem. What is actually displays the Transform panel?

$\endgroup$
  • 1
    $\begingroup$ The bone.rotation_euler property is only used if the rotation_mode is set to use euler. The rotation from the matrix property should update with any rotation that is within constraint limits. Are you sure you are looking at the right bone? context.active_bone is not the same as context.active_pose_bone $\endgroup$ – sambler Jun 17 '17 at 9:51
  • $\begingroup$ I figured out that matrix works well. I was testing using console and values don't change when I move bone and call it, but when I add this code to scene_update_post handler it's works, but returns bone rotation in global coordinates. Thanks to your commetn, rotation_euler with rotation_mode is works. Can you write answer so I can accept it? $\endgroup$ – Alexey Markov Jun 17 '17 at 11:35
  • $\begingroup$ UPD: I test It with IK and rotation_euler doesn't change when IK-driven bone is moving. $\endgroup$ – Alexey Markov Jun 17 '17 at 11:51
4
$\begingroup$

First note that bones have two representations within blender, the EditBone data represents it's static rest position within the armature while the PoseBone is the animated bone data that you would be moving around. The edit bones are stored in obj.data.edit_bones while the pose bones are in obj.pose.bones.

The rotation_mode value of a pose bone is used to switch between using rotation_euler, rotation_axis_angle or rotation_quaternion. These three rotation values can be seen in the bones properties and will show values without any constraints being applied. Note that euler values are stored as radians so you may want to use math.degrees() for the display value. Also the W in axis angle is radians.

The pose bones matrix value should give you the world position of the bone after constraints and drivers have been applied. You can get the bones euler rotation with bone.matrix.to_euler(). If using bpy.context to get the bone, you will find that bpy.context.active_bone.matrix will give you a matrix of zeros and ones while bpy.context.active_pose_bone.matrix will give you the matrix that you are after.

You can use a panel to watch the rotation of a bone -

import bpy
from math import degrees

class SimpleBoneAnglesPanel(bpy.types.Panel):
    bl_label = "Bone Angles"
    bl_space_type = 'VIEW_3D'
    bl_region_type = 'UI'

    def draw(self, context):
        arm = context.scene.objects['Armature']
        bone = arm.pose.bones['Bone']

        mat = bone.matrix.to_euler()
        row = self.layout.row()
        row.label(text='X: {:.3}'.format(degrees(mat.x)))
        row.label(text='Y: {:.3}'.format(degrees(mat.y)))
        row.label(text='Z: {:.3}'.format(degrees(mat.z)))

bpy.utils.register_class(SimpleBoneAnglesPanel)
$\endgroup$

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.