# Setting Angles Between Bones

I have 2 different hand objects in separate files that have bones identically named. I want to set the angles between the bones of hand 2 same as the angles in hand 1 so that they have the same posture.

I have tried getting the bones' positions from hand 1 as normalized vectors, then do the same for hand 2 and find the angles between two vectors along X, Y and Z axes. Then, rotate the bones with those angles. However, the result is not at all what I want. The rotate_euler.rotate_axis() function rotates the bone over its local axes, not the global ones.

How should I approach this problem? Any help would be appreciated.

Here are some screenshots for better visualizing the situation.

Bone 1

[![enter image description here][1]][1]

Bone 2

[![enter image description here][2]][2]

Script that saves normalized vectors from Bone 1

import bpy
import json
from math import *
from mathutils import *
import numpy as np

obj = bpy.data.objects["Armature"]
bones = obj.pose.bones

with open("vectors.json","w") as outfile:
outfile.write("[")
i = 0
for bone in bones:
u = (bone.tail - bone.head).normalized()
outfile.write(json.dumps({bone.name:list(u)},indent = 2))
if(i != len(bones.keys())-1):
outfile.write(",\n")
i += 1
outfile.write("]")


Script that finds the angles and rotates the bones of Hand 2

import json
import numpy as np
import bpy
from math import *
from mathutils import *

arm = bpy.data.objects["Armature"]

with open("vectors.json","r") as infile:

counter = 1
for vector in vectors:
v1 = vector
key = list(v1.keys())[0]
print(key)
v1 = Vector(vector[key])
bone = arm.pose.bones[key]
v2 = bone.tail - bone.head
v2 = v2.normalized()

angleyz = acos(np.dot(v1.yz,v2.yz))
anglexy = acos(np.dot(v1.xy,v2.xy))
anglexz = acos(np.dot(v1.xz,v2.xz))

bone.rotation_mode = 'XYZ'

bone.rotation_euler.rotate_axis("X", angleyz)
bone.rotation_euler.rotate_axis("Y", anglexz)
bone.rotation_euler.rotate_axis("Z", anglexy)


Result [![enter image description here][3]][3]

The Files I am working on

I am trying to make the hand in the abnormal.blend to have the same pose as the hand in neutral.blend [1]: https://i.stack.imgur.com/BxpqC.png [2]: https://i.stack.imgur.com/Q0ctQ.png [3]: https://i.stack.imgur.com/G4yjy.png

Use matrices.

In Python, How to get pose bone to rotate with another pose bone from a different armature? Finding Rotational difference have shown how to snap a bone to another using world space matrices of each. The example snaps one bone to the world space rotation of another.

Similarly here could look at local space. Have simply converted the local space matrix back to pose and applied to bone. Bit hard to test without two rigs, but as shown in linked answer, and Python How to make pose bone rotation toward a point? can make matrix to adjust the rotation of the target pose bone to the source. Basically the rotation part of a pose matrix is pointing the Y axis of the bone (head - tail). If a bone is connected it will ignore the location part of its matrix

import bpy
from bpy import context
from mathutils import Matrix
import json

# WRITE

def pose2local(pb):
M = pb.id_data.convert_space(
pose_bone=pb,
matrix=pb.matrix,
from_space='POSE',
to_space='LOCAL'
)
return [row[:] for row in M]

scene = context.scene
rig1 = scene.objects.get("Armature")

output = {pb.name : pose2local(pb)
for pb in rig1.pose.bones}

with open("matrices.json", "w") as fp:
json.dump(output, fp)

rig2 = scene.objects.get("Armature.001")

with open("matrices.json", "r") as fp:

def local2pose(pb, matrix):
return pb.id_data.convert_space(
pose_bone=pb,
matrix=Matrix(matrix),
from_space='LOCAL',
to_space='POSE'
)

for name, matrix in data.items():
pb = rig2.pose.bones.get(name)
if pb:
pb.matrix = local2pose(pb, matrix)

• Thanks for the comprehensive answer. This script applies the transform changes of one hand to other; however, it does not change the original position of hand 2. I am adding the links of my blend files to original post if you want to look Mar 21 '21 at 10:47
• As in the linked answer can decompose & recompose a matrix to keep any or all components of the source -> to make the matrix of the transform target . Was unsure, as if the bones are connected AFAIK the location doesn't matter and gets dealt with for us. The linked example only changes the rotation of matrix world of target. Mar 21 '21 at 11:58

The simplest way would probably be to create a Pose Library for the source file and save the pose to it, then later append that Pose library to the destination file, then link to it, and then assign the pose to the new hand.

Select your source hand armature in Object Mode, then go into Pose Mode and select every bone of the hand. The reason for selecting all bones is that poses are saved on a selected bone basis. Any bone not selected won't have its position saved to the pose. Click the Object Data tab in the Properties Panel (Skeleton Icon) and expand the section titled Pose Library. Click New to create a new library. Give it a name. Now click the "+" icon to add a new pose, based on your current selection, and then name it also.