I have about 30 control bones of a rig that I want to animate using mocap tracker empties.

I will be doing this many times for many models and each time, I need to set and calibrate the drivers for the bones. So I would like to automate the process as much as possible.

The empties are all parented to a reference empty and I need to use the local space coordinates in the drivers.

Specifically, I'd like to:

  1. Set coordinates of the location of each bone to be driven by local space coordinates of its related empty.
  2. For a specified frame, find the coordinates of the empty and set its keyed value to 0 on the f-curve

One thing that might help in this process is that the empties are mostly named the same as the bones with an added prefix; e.g. the bone "c_nose_02.x" is driven by the empty "mt.c_nose_02.x".

To make this clearer, this is what I am currently doing manually:

  1. Add drivers to the relevant coordinates of the bone.

enter image description here

  1. In the Drivers Editor, set the var object to the relevant empty,
  2. Choose the matching coordinate and select Local Space
  3. Note the value at the default frame

enter image description here 5. On the f-curve, set a keyframe of that value to 0.

enter image description here

I'm reasonably fluent in Python, but haven't used it much to automate Blender yet.

As always, any advice or pointers would be most appreciated.

  • $\begingroup$ Rather than changing the FCurve's key frame, I think it's smarter to change the python expression, like var-0.033. $\endgroup$
    – tetii
    Nov 20, 2022 at 6:45
  • $\begingroup$ Thanks @tetii - I didn't mention it in the question but the reason f-curves are necessary is because the movement is not linear. So yes, a simple formula in the expression would zero the bone in default position, but after that I will add max an min coordinates. And I've found that using a combination of formula and f-curve keys makes the process more complicated. $\endgroup$ Nov 20, 2022 at 11:40

1 Answer 1


Well I've worked it out, after a lot of research, trial and error...

pb = obj.pose.bones['c_nose_02.x'] #get pose_bone
pb.driver_remove('location') #remove old drivers

#Add drivers to the relevant coordinates of the bone.
driver_locx = pb.driver_add('location', 0) 
driver_locz = pb.driver_add('location', 2)

#For some reason, that causes f-curve modifiers to be inserted by default, which need to be removed
modx = driver_locx.modifiers[0] 
modz = driver_locz.modifiers[0]

#Set the variables to the relevant empties, choose the matching coordinate and select Local Space
varx = driver_locx.driver.variables.new()
varx.name = "varx"
varx.type = "TRANSFORMS"
tx = varx.targets[0]
tx.id = bpy.data.objects.get('mt.c_nose_02.x')
tx.transform_type = 'LOC_X'
tx.transform_space = 'LOCAL_SPACE'
driver_locx.driver.expression = "varx"

varz = driver_locz.driver.variables.new()
varz.name = "varz"
varz.type = "TRANSFORMS"
tz = varz.targets[0]
tz.id = bpy.data.objects.get('mt.c_nose_02.x')
tz.transform_type = 'LOC_Z'
tz.transform_space = 'LOCAL_SPACE' 
driver_locz.driver.expression = "varz" 

#Get the value of the default frame (actually had to get it from the empty)
#On the f-curve, set a keyframe of that value to 0.
offset_x = tx.id.location.x
driver_locx.keyframe_points.insert(offset_x, 0.0, keyframe_type='KEYFRAME' )

offset_z = tz.id.location.z
driver_locz.keyframe_points.insert(offset_z, 0.0, keyframe_type='KEYFRAME' )

After testing this code successfully, I set up an array of all bones that I wanted to control with mocap and used that to make a for loop.


You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .