calculating angles of joints ?

i wanna be able to calculate the angle between two bones inside the game and store it in a database i know how to make and insert into the database the angles part that i don’t quite know how

Get the vector between the tail and the head of each bone then use the vector builtin method ‘angle’ to get the angle between those two vectors. ie. angle = vector1.angle(vector2)

what if i want to track the angle during the game ?

This can be done in a script at runtime.

i tried a script before and it keep on giving me the same angle even if the bones moves

ah bone tail and head positions might need to be converted into armature or world space.

cont = G.getCurrentController()
own = cont.owner
target=own["Targets"]
path = logic.expandPath("//")

while True:

controller = bge.logic.getCurrentController()
scene=bge.logic.getCurrentScene()


own = controller.owner


target=own.actuators["level"]
v1=bge.data.objects["Armature"].pose.bones['Elbow_L'].vector
v2=bge.data.objects["Armature"].pose.bones['Shoulder_L'].vector
v3=bpy.data.objects["Armature"].pose.bones['Hand_L'].vector
v4=bpy.data.objects["Armature"].pose.bones['Neck'].vector

def dotproduct(v1, v2):
return sum((a*b) for a, b in zip(v1, v2))
def length(v):
return math.sqrt(dotproduct(v, v))
def angle(v1, v2):
return math.acos(dotproduct(v1, v2) / (length(v1) * length(v2)))* 180/ math.pi

elbow=int(180-angle(v1,v2))
shoulder=int(angle(v2,v4))
wrist= int(180-angle(v3,v1))



def save():
info1 = str(elbow)+" "
file1= open(path+"angle_elbow"+".txt",'a') 
file1.write(info1)
file1.close()
info2 = str(wrist)+" "
file2 = open(path+"angle_wrist"+".txt",'a') 
file2.write(info2)
file2.close() 
info3 = str(shoulder)+" "
file3 = open(path+"angle_shoulder"+".txt",'a') 
file3.write(info3)
file3.close()

print(elbow)

if int(target.body)==0:
break

this is my code and it dont get updated through the game

While loops can be incredibly volatile when used with the blender game engine. I would recommend against using them if possible.
Also, many of those functions that you have defined are already included in the mathutils module. (i.e the dot product) There are many useful vector functions which you can find here.

okay still the same problem the angles still the same through the game


 import os
import GameLogic as G
import bge
from bge import logic
import Load
import time 
import math 
import bpy
import mathutils

scene=bge.logic.getCurrentScene()
cont = G.getCurrentController()
own = cont.owner

v1=bpy.data.objects["Armature"].pose.bones['Elbow_L'].vector
v2=bpy.data.objects["Armature"].pose.bones['Shoulder_L'].vector
v3=bpy.data.objects["Armature"].pose.bones['Hand_L'].vector
v4=bpy.data.objects["Armature"].pose.bones['Neck'].vector

def dotproduct(v1, v2):
return sum((a*b) for a, b in zip(v1, v2))

def length(v):
return math.sqrt(dotproduct(v, v))

def angle(v1, v2):
return math.acos(dotproduct(v1, v2) / (length(v1) * length(v2)))

elbow=int(180-angle(v1,v2))
shoulder=int(angle(v2,v4))
wrist= int(180-angle(v3,v1))

print(elbow +","+shoulder+","+wrist)

Although the code gets the correct bone angle at the beginning of the game … it Keeps printing the same angle although the armature moves during the game

note: the script is attached to “always sensor” running on "true edge triggered frequency "

dont use bpy its not meant for game engine and the data does not change within runtime as all objects are converted to game objects and only the game objects attributes change during runtime, to access bones use something like armature_object.channels[0].bone[0]

can i get the bone vector form channels or only the positions ?

I gave it a try and this seems to work though I don’t think its a signed angle there are many different ways to go about getting the angle difference I suggest you just do some experimentation.


from bge import logicfrom math import degrees


def get_bone_angle_diff(arm, bone1, bone2):
    scene = logic.getCurrentScene()
    bone1_ch = scene.objects[arm].channels[bone1]
    bone2_ch = scene.objects[arm].channels[bone2]
    bone1_vec = bone1_ch.pose_tail-bone1_ch.pose_head
    bone2_vec = bone2_ch.pose_tail-bone2_ch.pose_head
    print(degrees(bone1_vec.angle(bone2_vec)))


def bone_info():
    get_bone_angle_diff('Armature', 'Bone', 'Bone.001')

@Siegel, getting the vector between bone head and tail will override the Z rotation value, instead use bone.pose_matrix * armature.worldTransform.
Here’s something I’ve been doing recently that involves getting the full transforms of bones. I’m not on PC so sorry can’t just extract that only code part.

(that blend file simply adds rigid cubes with bone positions and orientations and adds joints between them, basically constructing a ragdoll out of armature)

Attachments

bonetransforms.blend (528 KB)

I tried doing this, but ened up parenting empties to each bone(I needed them anyway) and then
diff =empty1.worldOrientation-empty2.worldOrientation