# How can I move a PoseBone to a specific world space position?

I have written some code that calculates the world space coordinate I want to move the bone to but i am having trouble figuring out how to get that back into the bones coordinates.

from bpy import context, data
from mathutils import Vector

def test_empty(matrix, name):
# view matrix by applying it to an object
obj_empty = data.objects.new(name, None)
obj_empty.matrix_world = matrix

armature = data.objects["Armature"]
pbones = armature.pose.bones
root = pbones["root"]
hips = pbones["hips"]
test = pbones["test"]

# calculate root
root_matrix = armature.matrix_world * root.matrix
test_empty(root_matrix, "Root")

# calculate hips
hips_matrix = armature.matrix_world * hips.matrix
test_empty(hips_matrix, "Hips")

# calculate bone
test_matrix = armature.matrix_world * test.matrix
test_empty(test_matrix, "Test")

# get offset of hips from root bone
offset = root_matrix.translation - hips_matrix.translation
print(offset)

# calculate new location in local space
new_position = test_matrix.translation + Vector((0,offset.y,0))

obj_empty = data.objects.new("TEST", None)
obj_empty.location = new_position

# obviously something wrong here
new_position = armature.matrix_world.inverted() * new_position

# move bone to new location
test.location = new_position


There is a handy method on the object to do this for you. Example below, adds an empty at each pose bone (to test pose to world) and then uses this to convert back to pose and checks against bones matrix.

import bpy
context = bpy.context
ob = context.object
scene = context.scene

for pb in ob.pose.bones:
# convert from pose to world
mw = ob.convert_space(pose_bone=pb,
matrix=pb.matrix,
from_space='POSE',
to_space='WORLD')
mt = bpy.data.objects.new(pb.name, None)
mt.name = pb.name
mt.matrix_world = mw
# now back from world to pose
mp = ob.convert_space(pose_bone=pb,
matrix=mw,
from_space = 'WORLD',
to_space = 'POSE')

print("Pose bone matrix", pb.matrix)
print("Matrix World to pb.matrix", mp)
print((mp - pb.matrix)) # zero matrix if all is good


To move a bone to the cursor

pb = ob.pose.bones.get("root")
mw = ob.convert_space(pose_bone=pb,
matrix=pb.matrix,
from_space='POSE',
to_space='WORLD')
mw.translation = scene.cursor_location
pb.matrix = ob.convert_space(pose_bone=pb,
matrix=mw,
from_space='WORLD',
to_space='POSE')


Note: If the pose bone has a joined parent bone this may not work as expected as it wont break that bond.