0
$\begingroup$

For a school project I need to calculate joint angle of an armature. I found some code that works with 2 bones, but I need to calculate the angle of every 2 adjacent bones (knees, elbows, back, etc). I'm not getting it to work for multiple bones. In a perfect situation I need a text output in the 3d viewer that shows a list of the angles.

#stock code
import bpy
import math  # we need this to get the anglein degrees
import numpy  # we need this for the Vector Math
cob = bpy.data.objects.get('Armature')

# remember, we are working on the Pose Bones in this example!
bones = cob.pose.bones

# get the bones
bone1 = bones['FirstBone']
bone2 = bones['LastBone']


# get the bone locations as Vectors in World Space
pointA = bone1.head
pointB = bone1.tail
pointC = bone2.tail


# find the two Vectors
# you retrieve the Vector by subtracting the intended Vector Root coordinate from the Tip coordinate
vecA = pointA - pointB
vecB = pointC - pointB


print(vecA, vecB)

# calculate the angle, formula taken from https://stackoverflow.com/questions/39497496/angle-between-two-vectors-3d-python
angle=numpy.arccos(numpy.dot(vecA,vecB)/(numpy.linalg.norm(vecA)*numpy.linalg.norm(vecB)))

# remember the angle is in RADIANS!
print(math.degrees(angle))
# remixed code
import bpy
import math  # we need this to get the anglein degrees
import numpy  # we need this for the Vector Math
cob = bpy.data.objects.get('Mannequin')

# remember, we are working on the Pose Bones in this example!
bones = cob.pose.bones

# get the bones
bone1 = bones['RightUpLeg']
bone2 = bones['RightLowLeg']
bone3 = bones['RightUpArm']
bone4 = bones['RightLowArm']



# get the bone locations as Vectors in World Space
pointA = bone1.head
pointB = bone1.tail
pointC = bone2.tail
pointD = bone3.head
pointE = bone3.tail
pointF = bone4.tail

# find the two Vectors
# you retrieve the Vector by subtracting the intended Vector Root coordinate from the Tip coordinate
vecA = pointA - pointB
vecB = pointC - pointB
vecD = pointD - pointE
vecE = pointF - pointE

print(vecA, vecB)
print(vecD, vecE)


# calculate the angle, formula taken from https://stackoverflow.com/questions/39497496/angle-between-two-vectors-3d-python
angle1=numpy.arccos(numpy.dot(vecA,vecB)/(numpy.linalg.norm(vecA)*numpy.linalg.norm(vecB)))
angle2=numpy.arccos(numpy.dot(vecD,vecE)/(numpy.linalg.norm(vecD)*numpy.linalg.norm(vecE)))

# remember the angle is in RADIANS!
print(math.degrees(angle1))
print(math.degrees(angle2))

# let's for the show assign the angle to a Text Object for display in the Viewport
bpy.data.objects.get('Output1').data.body = str(math.degrees(angle1))
bpy.data.objects.get('Output2').data.body = str(math.degrees(angle2))

Right now I got the code working for multiple joints but I can figure out how to loop the code so it runs on every frame.

$\endgroup$
3
  • $\begingroup$ What's wrong with the remixed code? Can you provide an example Mannequin? I think you need a list of bone pairs for which you want to calculate the angles (or loop over the whole armature) and then do the calculations. Where are you stuck? $\endgroup$
    – Blunder
    Dec 14, 2022 at 13:57
  • $\begingroup$ Right now I got the code working for multiple joints but I can figure out how to loop the code so it runs on every frame. $\endgroup$ Dec 15, 2022 at 9:46
  • $\begingroup$ This is a very important detail that should be added to your question. To do the calculation for every frame have a look at the so-called Application Handlers $\endgroup$
    – Blunder
    Dec 15, 2022 at 13:32

0

You must log in to answer this question.

Browse other questions tagged .