I have an armature where Automatic IK is enabled. I want to move my bone in pose mode using python instead of grabbing it using mouse. I tried the below but it didn't work as it says tail location is a read only. How I can move the bone's tail to a certain location in the scene without stretching the bone and in pose mode not edit mode?

import bpy

ob = bpy.data.objects['Armature']

ob.pose.bones['Bone.002'].tail = bpy.context.scene.cursor_location

I've also tried selecting the bone in Pose Mode then using ops.transform.translate but it didn't move the bone to the cursor:

bpy.ops.transform.translate(value=bpy.context.scene.cursor_location, constraint_axis=(False, False, False), constraint_orientation='GLOBAL', mirror=False, proportional='DISABLED', proportional_edit_falloff='SMOOTH', proportional_size=1)

enter image description here

As shown below I can do this manually by selecting the bone and grabbing it to the correct position while auto-ik is enabled without resizing or stretching the bones:

enter image description here

  • $\begingroup$ As stated in Automatic IK it calculates the Inverse Kinematic for you. AFAIK there no link between scripting and translation in auto-IK mode. ( also suggest making your sample images landscape ) $\endgroup$ – batFINGER May 10 '17 at 12:02
  • $\begingroup$ @batFINGER thanks for your comment. I just mentioned auto-IK so that the bone doesn't stretch or get resized. The main question is how I can use python move the tail of the bone to a certain point in pose mode, or at least as close as possible if the point is far? $\endgroup$ – Tak May 10 '17 at 12:09
  • $\begingroup$ Rotate it to align with vector made by subtracting base from cursor (in same space ofcourse) . Here is how to do so for object. blender.stackexchange.com/questions/19533/… $\endgroup$ – batFINGER May 10 '17 at 12:17
  • $\begingroup$ @batFINGER is it possible to post an answer whenever you have time? As I'm not sure how this can be done in pose mode with bones. $\endgroup$ – Tak May 10 '17 at 12:22
  • $\begingroup$ The solution is not trivial for this one. Either you can calculate your own IK chain and rotate bones to follow it, or you could add some helper empty at cursor location and temporary IK constraint for the last bone of chain (target: empty), followed by bpy.ops.pose.visual_transform_apply(), then delete empty and constraint. $\endgroup$ – Jaroslav Jerryno Novotny May 10 '17 at 13:58

Here is a solution using a temporary IK constraint:

enter image description here

The principle is to:

  • Set an empty at cursor position
  • Add a IK constraint to the bone targeting the empty
  • Get the resulting transformation
  • Remove the constraint
  • Assign the previously obtained transformations

The commented code:

import bpy

#Bones and its parents
def BoneAndParents( bone ):
    yield bone
    while bone.parent:
        bone = bone.parent
        yield bone

arm = bpy.data.objects['Armature']


#Add a temporary empty
empty = bpy.context.scene.objects.active

bpy.context.scene.objects.active = arm


bone = arm.pose.bones['Bone.003']

#Add IK constraint and update
constraint = bone.constraints.new( 'IK' )
constraint.target = empty
bpy.context.scene.update() #Important: update the scene

#Get the bones and transformation due to the constraint
bones = [b for b in BoneAndParents( bone )]
transformations = [b.matrix.copy() for b in bones]

#Get rid of the temporary constraint and update
bone.constraints.remove( constraint )

#Assign transformation
for b, t in zip( bones, transformations ):
    b.matrix = t

#Remove temporary empty
bpy.context.scene.objects.active = empty

#Back to pose
bpy.context.scene.objects.active = arm
  • $\begingroup$ I don't know why you have to assign the transformation matrices after the updates. $\endgroup$ – robit Mar 6 '19 at 9:29

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.