7
$\begingroup$

I use the below code to retrieve location of pose.bone, but it always give 0 (or -0).
It seems the pose.bone location is the relative position of its parent so it will not-zero value once I grab pose.bone to somewhere?!
Is there a way to get "global location(X, Y, Z)" of pose.bone??

for action in bpy.data.actions:
    print(action)
    for fcurve in action.fcurves:
         print("data_path:" + fcurve.data_path + ", channel " + str(fcurve.array_index))
         for keyframe in fcurve.keyframe_points:
              print(keyframe.co)

 

data_path:pose.bones["Bone.011"].location, channel 0 
Vector (13.0000, -0.0000) 
Vector (29.0000, -0.0000) 
Vector (40.0000, -0.0000) 
Vector (45.0000, -0.0000) 
Vector (83.0000, -0.0000) 
Vector (110.0000, -0.0000) 
data_path:pose.bones["Bone.011"].location, channel 1 
Vector (13.0000, 0.0000) 
Vector (29.0000, 0.0000) 
Vector (40.0000, 0.0000) 
Vector (45.0000, 0.0000) 
Vector (83.0000, 0.0000) 
Vector (110.0000, 0.0000) 
data_path:pose.bones["Bone.011"].location, channel 2 
Vector (13.0000, -0.0000) 
Vector (29.0000, -0.0000) 
Vector (40.0000, -0.0000) 
Vector (45.0000, -0.0000) 
Vector (83.0000, -0.0000) 
Vector (110.0000, -0.0000) 
data_path:location, channel 0 
Vector (13.0000, 0.0245) 
Vector (45.0000, -3.3037) 
Vector (83.0000, 0.0245) 
Vector (110.0000, 1.5101) 
data_path:location, channel 1 
Vector (13.0000, -0.0075) 
Vector (45.0000, -0.0075) 
Vector (83.0000, -0.0075) 
Vector (110.0000, -0.0075) 
data_path:location, channel 2 
Vector (13.0000, 3.0031) 
Vector (45.0000, 2.5048) 
Vector (83.0000, 1.8442) 
Vector (110.0000, 1.8442) 
$\endgroup$
7
$\begingroup$

This is a bit of a duplicate of this question, but just to complete the picture, to get the global location of your pose bone, you need to multiply the bone's location by the armature and the bone's transform matrices (sounds complicated, but is actually simple):

p = bpy.context.active_pose_bone  # Our pose bone
o = bpy.context.object            # Our armature object
global_location = o.matrix_world * p.matrix * p.location
$\endgroup$
4
  • $\begingroup$ but how if the p.location is 0? then the global_location is always 0? $\endgroup$ – Caxton Aug 20 '15 at 8:02
  • $\begingroup$ Not an expert in linear algebra, but from what I understand, not necessarily: mathinsight.org/matrix_vector_multiplication $\endgroup$ – TLousky Aug 20 '15 at 9:03
  • $\begingroup$ not sure about what "not necessarily" mean.. do you mean value of p.location is 0 will not result in global_location to 0? $\endgroup$ – Caxton Aug 21 '15 at 4:28
  • 2
    $\begingroup$ Yes, it depends on the transform matrices of the armature and the p's parent bones, both represented in the aforementioned code. $\endgroup$ – TLousky Aug 21 '15 at 5:49
1
$\begingroup$

If anyone is interested in a more declarative approach, the following did the trick for me. For a given animation, this snippet retrieves the global 3D position of each bone (head and tail) as well as the pixel+depth position with respect to the camera:

from bpy_extras.object_utils import world_to_camera_view

armature = ...
cam = ...

pose_bones = {pb.name: pb for pb in D.objects[armature.name].pose.bones}
for frame_i in range(C.scene.frame_start, C.scene.frame_end + 1):
    print("Collecting positions for frame >>>", frame_i)
    # C.scene.frame_current = frame_i
    bpy.context.scene.frame_set(frame_i)  # important: refresh scene between frames
    data = {"frame": frame_i}
    for ico_bone, ico in icospheres:
        # get PoseBone global position
        pb_tail = pose_bones[ico_bone].tail
        pb_head = pose_bones[ico_bone].head
        # get PoseBone cam-relative position (0,0)=bottom left, (1,1)=top right
        pb_tail_cam_xyz = world_to_camera_view(C.scene, cam, pb_tail)
        pb_head_cam_xyz = world_to_camera_view(C.scene, cam, pb_tail)

The approach is based on the following observation:

At a given frame,the head and tail fields of the D.objects[armature.name].pose.bones show the current global position in (x, y, z) coordinates.

I've tested it on 2.90 and seems to work fine, please correct me otherwise! Hope this helps.

Cheers,
Andres

$\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.