Matrices
The rotation difference returns how much to rotate from direction to direction. The result needs to be applied to current direction.
Setting the direction absolutely from the rotation difference result will only work for the case when initial value is 0.
By using matrices, will work for whatever rotation type the pose bone has.
Test script. Rotates the context pose bone to point to the head of the pose bone named "Target".
import bpy
from bpy import context
from mathutils import Matrix
rig = context.object
target = rig.pose.bones.get("Target")
pb = context.active_pose_bone
v = target.head - pb.head
bv = pb.tail - pb.head
rd = bv.rotation_difference(v)
M = (
Matrix.Translation(pb.head) @
rd.to_matrix().to_4x4() @
Matrix.Translation(-pb.head)
)
pb.matrix = M @ pb.matrix
Emulating the constraint.
Can roll the bone around its Y axis in result above and it will still point to target.
POSE space is one of the more "tricky" spaces since it is defined by the head, tail and roll of each bone as set in edit mode.
To get but one roll result
q = v.to_track_quat('Y', 'Z')
makes a quaternion from vector v
that points its $Y$ direction to vector with $X$ axis up.
There is a handy convert_space
method available on all objects.
>>> rig
bpy.data.objects['Armature']
>>> rig.convert_space(
convert_space()
Object.convert_space(pose_bone=None, matrix=((0, 0, 0, 0), (0, 0, 0, 0), (0, 0, 0, 0), (0, 0, 0, 0)), from_space='WORLD', to_space='WORLD')
Convert (transform) the given matrix from one space to another