# Python, How to Roll a Pose Bone along a Vector in PoseMode?

I'm stuck, Trying to roll a pose bone while staying in the Head and Tail vector. When I use axis angle or any other rotation, it doesn't stay in place and it goes off its vector.

Vector shouldn't change and rolling angle is the variable. Rolling a pose bone.

Using python, how do you get the "roll" of a pose_bone?

IMO this is simply a case of rotating the bone around any pivot point that is on a line parallel to y axis vector passing thru points head and tail.

Matrix math to translate, rotate, scale with respect to a pivot point in Object mode

import bpy
from mathutils import Matrix

def rollposebone(pb, roll):
R = (
Matrix.Rotation(roll, 4, pb.y_axis) @
)
pb.matrix = R @ pb.matrix

# test call, roll 3 degrees.
context = bpy.context



Please also note that blender natively uses radians, as does math and numpy. Recommend using as above, ie if you wish to pass a value like 90 degrees pass via radians(90) rather than converting to and fro in code. If making a UI give any angle property a unit = 'ROTATION and it will be displayed in the chosen rotation unit, which is by default degrees.

import bpy
import math
import numpy as np
from mathutils import Vector

context = bpy.context
scene = context.scene
RobloxRig = bpy.context.scene.objects['__Rig']
UpperRightArm_bone = RobloxRig.pose.bones["RightUpperArm"]

def angle(v1, v2, acute):
# v1 is your first vector
# v2 is your second vector
angle = np.arccos(np.dot(v1, v2) / (np.linalg.norm(v1) * np.linalg.norm(v2)))
if (acute == True):
return angle
else:
return 2 * np.pi - angle

def RollBone(bone,Degrees):
BoneXVec = Vector((0,vdir.y,vdir.z))
Xangle = math.degrees(angle(Vector((0, 0, 1)), BoneXVec, True))

xAbs = vdir.y
xsign = 0

if xAbs > 0:

if xAbs < 0:

#Center X
bpy.ops.transform.rotate(value= xsign, orient_axis='X', orient_type='GLOBAL')

bpy.context.view_layer.update()

BoneXVec = Vector((vdir.x,0,vdir.z))
Yangle = math.degrees(angle(Vector((1, 0, 0)), BoneXVec, True))
yAbs = vdir.z
ysign = 0

if yAbs > 0:

if yAbs < 0:

#Center Y
bpy.ops.transform.rotate(value=ysign, orient_axis='Y', orient_type='GLOBAL')
bpy.context.view_layer.update()

#Roll on Z
bpy.context.view_layer.update()

#Return Rotation
bpy.ops.transform.rotate(value=-ysign, orient_axis='Y', orient_type='GLOBAL')
bpy.ops.transform.rotate(value= -xsign, orient_axis='X', orient_type='GLOBAL')

if __name__ == "__main__":
RollBone(UpperRightArm_bone,90)
`

I used bpy.ops.transform.rotate to rotate the bone to its normal x and y vector, then I rotate z to the desired angle. Lastly I use the inverse of x and y rotations to set it back to the space it was at.