# Align pose bone to axis

Hey,
I am trying to make a small function that “straightens” a bone to a world axis (for testing I am simply using the x-axis). The rest pose has been applied, so I cannot simply “zero out” the rotation values. The function below is very unstable; sometimes it is correct on first try, sometimes it is correct after several tries, sometimes it is wildly off all the times and sometimes it does nothing. I will admit that vector and quaternion maths are not my strong suit, but I feel that the vector calculations done here is correct, but that the issue lies with how I apply the quaternion rotations.
Anyone here that has done something similar before with success, or sees an issue with my method below? Any and all feedback is appreciated, thanks

``````def rotate_bone_to_axis():

if bpy.context.mode != 'POSE':
print(f'ERROR! You are not in pose mode, aborting')
return

# setting vars
armature = bpy.context.active_object
active_bone = bpy.context.active_pose_bone

if active_bone is None:
print(f'ERROR! No bone is selected, aborting')
return

# World space calculation of vectors
bone_vector = (armature.matrix_world @ active_bone.tail - armature.matrix_world @ active_bone.head).normalized()
axis_vector = Vector((1, 0, 0))

# Calculate Quaternion difference between the bone and desired axis
rotation_delta = bone_vector.rotation_difference(axis_vector)
# Apply rotation to bone
active_bone.rotation_mode = 'QUATERNION'
active_bone.rotation_quaternion = rotation_delta @ active_bone.rotation_quaternion

bpy.context.view_layer.update()
``````

Did not find a good solution to do the math myself, however I found that the constraint “Copy Rotation” basicly does the same thing (even on bones where rest pose has been applied). Ended up with a script that adds a temporary bone oriented in the user defined axis and applied the constraint to the pose bone from this. Here is a snippet from the function adding the temp bone and aligning:

``````    #add new reference bone
bpy.ops.object.mode_set(mode='EDIT', toggle=False)
edit_bones = armature.data.edit_bones

temp_bone = edit_bones.new('tmp_bone')
#in case there already exists a 'tmp_bone' and the new bone gets an altered name
temp_bone_name = temp_bone.name

active_bone = edit_bones[active_bone_name]

# set orientation of temp bone

# set rotation constraint
bpy.ops.object.mode_set(mode='POSE')
active_bone = armature.pose.bones[active_bone_name]

constraint = active_bone.constraints.new(type='COPY_ROTATION')
constraint.target = armature
constraint.subtarget = temp_bone_name
``````