Help me python a tracking bone

hi, i’m just looking how i could possibly making a “Y”-up orientated bone tracking objects on its “Z” axis

import bge
from bge import render
from mathutils import Matrix, Vector, Quaternion

scene = bge.logic.getCurrentScene()
tracker = scene.objects['Armature']
cube = scene.objects['Cube']


### World Position of the tracker Bone 
boneloc = tracker.worldTransform * tracker.channels["tracker"].pose_matrix * tracker.channels["tracker"].location 

#### test :  with a red Ray display Global directional vector 
render.drawLine(cube.worldPosition  , boneloc , [255,0,0] ) 

##   convert to local orientation  ??
myVect = arm.worldOrientation * Vector(cube.worldPosition - boneloc)

## apply the tracking transformation on myVect and convert it to an euler
trkTsf = myVect.to_track_quat('Z','Y').to_euler()

## testing flip axis in case of .. , locking the X axis
eee = [0, trkTsf[2] , trkTsf[1]]

### BBaaah no bug, it reacts, but doesnt work right  
tracker.channels["tracker"].rotation_euler = eee

help ? :slight_smile:

putting the bone in quaternion mode

### Position of the tracker Bone 
boneloc = tracker.worldTransform * tracker.channels["tracker"].pose_matrix * tracker.channels["tracker"].location 

####   display Global directional vector with a red Ray
render.drawLine(cube.worldPosition  , boneloc , [255,0,0] ) 

##   the Vector
myVect = Vector(boneloc  -  cube.worldPosition)

## apply on the Orientation Matrix, the tracking transformation as a Matrix
trkTsf =  arm.worldOrientation * myVect.to_track_quat('Z','Y').to_matrix()

## convert the transformed Matrix to quaternion
eee = trkTsf.to_quaternion()     

### no more flipping issues thx to quaterion , behavior well when moving, but seems to require 1 more transformation to track well ?
tracker.channels["tracker"].rotation_quaternion = eee

still doesn’t work

sometimes things with tracking etc are sensitive to being .normalized()

here’s a set up.

bone_tracker.blend (580.0 KB)

i want to red cone to target the cube with its nose

You are missing the pose matrix of the parent of the tracking bone, but although it works, it is prone to spinning while tracking the target.

import bge
from bge import render
from mathutils import Matrix, Vector, Quaternion

scene = bge.logic.getCurrentScene()
tracker = scene.objects['Armature']
cube = scene.objects['Cube']

### Position of the tracker Bone 
boneloc = tracker.worldTransform * tracker.channels["tracker"].pose_matrix * tracker.channels["tracker"].location 

tracker.channels["tracker"].rotation_mode = 0
##   the Vector
myVect = Vector(cube.worldPosition - boneloc).normalized()

####   display Global directional vector with a red Ray
render.drawLine(cube.worldPosition, boneloc , [255,0,0] ) 

## apply on the Orientation Matrix, the tracking transformation as a Matrix
trackerParent = tracker.channels["Bone.001"]
# apply the parent's rotation to the direction vector
myVect = myVect * trackerParent.pose_matrix
trkTsf = tracker.worldOrientation * myVect.to_track_quat('Y','Z').to_matrix()

## convert the transformed Matrix to quaternion
eee = trkTsf.to_quaternion()

### no more flipping issues thx to quaterion , behavior well when moving, but seems to require 1 more transformation to track well ?
tracker.channels["tracker"].rotation_quaternion = eee

## useless option if an action is already playing ?
tracker.update()

1 Like

thank you very much !

you mean on its tracking Y axis itself. Yes, i see . I guess it’s possible to lock it.

I fail to understand this as there’s a Grand-Parent too (and with true human Armatures, there’s more than 3 bones) How limiting the integration to the direct parent solves the thing ? :thinking:

Once again, big thanks

The worldOrientation matrix of the armature transforms the direction vector to armature space, the pose_matrix of the parent transforms the vector to the local space of the bone.
Also, I made a mistake, the worldOrientation must be applied before the pose_matrix:

import bge
from bge import render
from mathutils import Matrix, Vector, Quaternion

scene = bge.logic.getCurrentScene()
tracker = scene.objects['Armature']
cube = scene.objects['Cube']


### Position of the tracker Bone 
boneloc = tracker.worldTransform * tracker.channels["tracker"].pose_matrix * tracker.channels["tracker"].location 

tracker.channels["tracker"].rotation_mode = 0
##   the Vector
myVect = Vector(cube.worldPosition - boneloc).normalized()

####   display Global directional vector with a red Ray
render.drawLine(cube.worldPosition, boneloc, [255,0,0] ) 

## apply on the Orientation Matrix, the tracking transformation as a Matrix
trackerParent = tracker.channels["Bone.001"]
# apply the armature and the parent's rotation to the direction vector
myVect = myVect * tracker.worldOrientation * trackerParent.pose_matrix

tracker.channels["tracker"].rotation_quaternion = myVect.to_track_quat('Y','Z')

## useless option if an action is already playing ?
tracker.update()

ok, this seems quite perfect. :slight_smile: In my game, it still doesn’t work because the tracker bone doesn’t share same inner Axis Orientation and even so, the result is buggy for some reason … maybe because the inner default pose has bones not completely world aligned ? Anyway…

But here, as you can see, even with the armature moving, it works perfect. Thx

ok