What is the best way to do FK/IK snapping?

No probs. Done.

(edited, sorry i meant the ā€œSnap IK to FKā€ Button )
Hi guys, iā€™ve been working with this topic for some days, and after using the files you posted, specially the last FK_IK_Snapping_Symmetry2.blend and FK_IK_Snapping.blend i was getting crazy with it, because as soon as i rotate the FK_LowerArm_L on pose mode, the ā€œSnap IK to FKā€ Button doest work, it just snaps incorrectly. Maybe its just me, but what solved my day is to set the IK_LowerArm_R rotation to the FK_LowerArm_R before doing the snap, now iā€™ve been testing it for a while and it seems to work like a charm. Just write this before the snap (in my case having all the pose bones in rotation mode quaternion):
bpy.context.object.pose.bones[ā€˜IK_LowerArm_Rā€™].rotation_quaternion = bpy.context.object.pose.bones[ā€˜FK_LowerArm_Rā€™].rotation_quaternion
bpy.ops.pose.snapik_to_fk()

Idk in your case but verify that the fk or ik chain matches bone roll of the other (I think is required to iirc)

Hello and welcome aboardā€¦

The FK_IK_Snapping.blend file included in my last post here doesnā€™t have the problems you mentioned.

Iā€™m currently using this code with my current character that Iā€™ve been animating, and havenā€™t had any problems.

What version of blender are you using? Iā€™m on 3.6.5 and donā€™t know if changes are needed for 4.0.

Care to post a .blend file showing the problem?

Since youā€™re new here, you probably canā€™t attach files to posts, so use a file hosting site and post a link, please.

Randy

1 Like

do the same but clicking on the other button ā€œSnap IK to FKā€ after rotating FK_LowerArm_R

I just checked again, rotating FK-LowerArm_R and then ā€˜Snap IK to FKā€™ -

And itā€™s working on my end, so Iā€™m wondering where the problem is. I really want to find out if there is a problem with this.

Randy

Edit: I just downloaded my file posted above and checked it, and itā€™s working the same as the file on my HD. Just wanted to make sure there was no difference in my reference file and the one I posted.

Edit #2: I stand corrected - I just got it to screw up! If FK_LowerArm_R is set to quaternion rotations and IK_LowerArm_R is set to XYZ euler rotations then it fails. Also noticed in my example some bones are set to eulers and some to quaternions. Obviously, all bones should be set to the same rotation mode. Iā€™ll correct my file and upload another example soon.

I also noticed this thread has been viewed over 4,200 times! Perhaps I should document the code a little more, to make it easier to use.

1 Like

So I was going thru this file (the last one I posted - FK_IK_Snapping.blend) the other night, fixing up the python code a bit, adding in remarks, to make it more user friendly.

While doing that, I noticed there was a function that is missing from that example. I also remembered I had rotational problems when snapping IK to FK, which is one of the reasons why I started this thread. I thought it had to do with changes in blender & python API because the code I was using was from blender 2.76. Basically it was this:

On the IK_LowerArm, you have to have 2 of the rotations channels locked down on that bone. That bone can only rotate on one axis, just like your lower arm does, or it messes things up. If that bone can rotate on more than one axis, it screws up the calculation of the pole target location. So it kind of snaps correctly, but not quite.

@AresSancho can you check your troubled files to see if this corrects your issue?

I will be posting a more complete example of how this works in the coming days, with better documentation.

Thanks,
Randy

As promised, hereā€™s an up to date complete example of how to do FK/IK snapping with python. Works with blender 4.0.2

See below

Iā€™ve spent some time add in remarks in the code, explaining how things work and added in a couple of code examples. There are also a couple of notes at the end of the code that need to be read before using.

There are 2 ways to make this example fail:

1st - All the boneā€™s rotation modes needs to be the same. If using quaternions, all bones should use quaternions, having some set to euler will cause incorrect snapping.

2nd - The lower limb bone in the IK chain of bones needs to have 2 of itā€™s rotation axis locked, so the bone can rotate on only 1 axis.

Feel free to ask questions,
Randy

1 Like

Thank you very much for this script.
Unfortunately, Iā€™m not a programmerā€¦ so I have a question.
How can I use this script in case, when I have to create IK-FK legs? I should copy the script somehow? Or I should make any changes in the script itself?

I tried to make a copy of the script with a different limb names (for legs) and to run both of them. Unfortunately, it didnā€™t work. You can run only one script at a timeā€¦ So I got only one pair of limb workingā€¦
Please, someone help me please to make a script for 2 pair of limbs.

Hi @pekareff

Sorry not to get back to you sooner, Iā€™ve been out of townā€¦

Basically, you duplicate and edit only parts of the code that deal with the specific bones. Like this:

# define fk_bones - a list of FK bones - the order of the bones matter
#             upper limb       lower limb       limb end
fk_bones_L = ['FK_UpperArm_L', 'FK_LowerArm_L', 'FK_Hand_L']
fk_bones_R = ['FK_UpperArm_R', 'FK_LowerArm_R', 'FK_Hand_R']

# define ik_bones - a list of IK bones - the order of the bones matter
#             upper limb       lower limb       limb end     pole target
ik_bones_L = ['IK_UpperArm_L', 'IK_LowerArm_L', 'IK_Hand_L', 'IK_Elbow_L']
ik_bones_R = ['IK_UpperArm_R', 'IK_LowerArm_R', 'IK_Hand_R', 'IK_Elbow_R']

would become this:

# define fk_bones - a list of FK bones - the order of the bones matter
#             upper limb       lower limb       limb end
fk_bones_L = ['FK_UpperArm_L', 'FK_LowerArm_L', 'FK_Hand_L']
fk_bones_R = ['FK_UpperArm_R', 'FK_LowerArm_R', 'FK_Hand_R']
fk_leg_bones_L =['FK_UpperLeg_L', 'FK_LowerLeg_L', 'FK_Foot_L']

# define ik_bones - a list of IK bones - the order of the bones matter
#             upper limb       lower limb       limb end     pole target
ik_bones_L = ['IK_UpperArm_L', 'IK_LowerArm_L', 'IK_Hand_L', 'IK_Elbow_L']
ik_bones_R = ['IK_UpperArm_R', 'IK_LowerArm_R', 'IK_Hand_R', 'IK_Elbow_R']
ik_leg_bones_L = ['IK_UpperLeg_L', 'IK_LowerLeg_L', 'IK_Foot_L', 'IK_Knee_L']

Then, further down in the code, this:

class SnapFKtoIK(bpy.types.Operator):
    """Snap FK bones to IK bones."""
    bl_idname = "pose.snapfk_to_ik"
    bl_label = "Snap FK to IK"
    bl_options = {'UNDO'}

    @classmethod
    def poll(cls, context):
        return (context.active_object != None and context.mode == 'POSE')    

    def execute(self, context):
                
        obj = bpy.context.active_object
        bone = bpy.context.active_bone.name

        # call the snapping function - fk_2_ik() - passing in the bone lists
        if bone in (fk_bones_L + ik_bones_L):
            fk_2_ik(obj, fk_bones_L, ik_bones_L)
        elif bone in (fk_bones_R + ik_bones_R):
            fk_2_ik(obj, fk_bones_R, ik_bones_R)
        
        # repeat the above code for legs like this:
        '''
        if bone in (leg_fk_bones_L + leg_ik_bones_L):
            fk_2_ik(obj, leg_fk_bones_L, leg_ik_bones_L)
        elif bone in (leg_fk_bones_R + leg_ik_bones_R):
            fk_2_ik(obj, leg_fk_bones_R, leg_ik_bones_R)  
        '''          
        
        return {'FINISHED'}

Would have this added to it:

class SnapFKtoIK(bpy.types.Operator):
    """Snap FK bones to IK bones."""
    bl_idname = "pose.snapfk_to_ik"
    bl_label = "Snap FK to IK"
    bl_options = {'UNDO'}

    @classmethod
    def poll(cls, context):
        return (context.active_object != None and context.mode == 'POSE')    

    def execute(self, context):
                
        obj = bpy.context.active_object
        bone = bpy.context.active_bone.name

        # call the snapping function - fk_2_ik() - passing in the bone lists
        if bone in (fk_bones_L + ik_bones_L):
            fk_2_ik(obj, fk_bones_L, ik_bones_L)
        elif bone in (fk_bones_R + ik_bones_R):
            fk_2_ik(obj, fk_bones_R, ik_bones_R)
        elif bone in (fk_leg_bones_L + ik_leg_bones_L):
            fk_2_ik(obj, fk_leg_bones_L, ik_leg_bones_L)
        
        # repeat the above code for legs like this:
        '''
        if bone in (leg_fk_bones_L + leg_ik_bones_L):
            fk_2_ik(obj, leg_fk_bones_L, leg_ik_bones_L)
        elif bone in (leg_fk_bones_R + leg_ik_bones_R):
            fk_2_ik(obj, leg_fk_bones_R, leg_ik_bones_R)  
        '''          
        
        return {'FINISHED'}

and thereā€™s a template there, the part of the code in the triple single quotes (ā€˜ā€™')

Same goes for this code too:

class SnapIKtoFK(bpy.types.Operator):
    """Snap IK bones to FK bones."""
    bl_idname = "pose.snapik_to_fk"
    bl_label = "Snap IK to FK"
    bl_options = {'UNDO'}

    @classmethod
    def poll(cls, context):
        return (context.active_object != None and context.mode == 'POSE')    

    def execute(self, context):
                
        obj = bpy.context.active_object
        bone = bpy.context.active_bone.name

        # call the snapping function - ik_2_fk() - passing in the bone lists
        if bone in (fk_bones_L + ik_bones_L):
            ik_2_fk(obj, ik_bones_L, fk_bones_L)        
        elif bone in (fk_bones_R + ik_bones_R):
            ik_2_fk(obj, ik_bones_R, fk_bones_R)
        
        # see notes in SnapFKtoIK above for using with legs
               
        return {'FINISHED'}

I worked on updating my example file to have a chain of leg bones in it to show exactly how it works, but I ran out of time today. Will post a new example file up tomorrow!

Stay Tuned!
Randy

Thanks! Iļl wate for the update.

Hereā€™s an updated example for FK/IK Snapping that includes a leg. I only created a left leg, but should be able to follow the example to get it to work for the right leg as well.

FK_IK_Snapping_4_0.blend (698.6 KB)

Iā€™ve been meaning to create a website for my blender work and this example with a text tutorial will be included when I get around to it!

Randy

1 Like

Thanks!
Iā€™m trying to copy-paste your script into my file. Changed all the object names I could find to the names specified in your script.
And I got that:
image
Couldnā€™t get ā€œFK/IK Switchā€ slider. So I can not get a path for a driverā€¦ :frowning:

All other functions works very well.

This is likely caused by this bit of code:

        if selected_bone(context, fk_bones_R + ik_bones_R):
            col.label(text="Arm_R  FK/IK Switch:")
            col.prop(pose_bones["FK_Hand_R"], '["FK_IK_Switch_R"]', text="IK", slider=False)
            col.label(text="Arm_R  FK/IK Snapping:")
            col.operator('pose.snapfk_to_ik')
            col.operator('pose.snapik_to_fk')

That code checks to see if the currently selected bone is in the fk_bones_R & ik_bones_R python lists created at the beginning of the code. If the selected bone is in those lists, (which it is because part of the panel is displayed), then display the panel. Since the switch isnā€™t showing up, the problem is this line of code:

col.prop(pose_bones["FK_Hand_R"], '["FK_IK_Switch_R"]', text="IK", slider=False)

All that line of code does is display the custom property called ā€œFK_IK_Switch_Rā€ that is on the bone 'FK_Hand_R". So check that the FK_Hand_R bone has a custom property called FK_IK_Switch_R.

Opening blenderā€™s console window will display python error messages just like you can find rigging error messages there.

Alternately, you could just change all the names in the script to match those of your file. You donā€™t have to name your hand bones to be FK_Hand_R, if they are called something else. If you called your FK hand bones to be just Hand.R, then change the name in the script to be Hand.R.

Hope this helps!
Randy

Ha-ha! The right answer was so near and I couldnā€™t find it. And it wasnā€™t difficult )))
Thanks a lot!

1 Like

Hello, first thanks for the script, it has been really usefull so far.

Iā€™m trying to make an armature for my videogame character that uses both ik and fk systems to animate, i used the first file as reference and then chaged to the second one because of the problem you mentioned bellow but i found out that thereā€™s still a problem when you rotate the fk bone equivalent to the one thatā€™s responsible for the ik chain and do ā€œSnap IK To FKā€, i do not know if this is only a problem for me because i do want to use both systems and i would need to rotate that bone in fk mode, but i was wodering if you could help me with the issue because you said you wanted to leave the example working as perfect as you could.

I would leave a video as reference but iā€™m a new user so it seems i canā€™t, but iā€™d further explain if needed.

Thanks Again.

Hello and welcome to the forum!

I know this thread is kind of long, but if you back up to this post and read thru those few posts, I explain 2 ways the IK snapping can fail. Basically, all the boneā€™s rotation modes must be the same, and the lower arm/leg bone can only rotate on 1 axis (like a human lower arm/leg does) or it screws up the pole target calculations.

If this doesnā€™t solve your problem, post up a .blend file and Iā€™ll take a look at it. Since you are new here, youā€™ll need to use a file hosting site to host the file and paste the link to the file here.

Randy

1 Like

Thanks, glad to be here!

Iā€™ve already read through the thread multiple times because iā€™ve been trying to solve this issue for a bit now, but i didnā€™t really understand what you meant by limiting the rig rotations on both bone groups.

Wouldnā€™t that make the fk system unusable in the first place? Or am i just lost and you are reffering to a totally different thing? (Very possible)

Anyways thanks for the rapid response, I was testing the script with this arm cause it shares the same system that my character and i thought it would be easier to make it work here first, so if you could look it up as you said i would aprecciate it a lot.
Hereā€™s the link to my file: https://drive.google.com/file/d/1IuBs07ONfqz5tOn1253N05OHRtPVP3YL/view?usp=sharing

Mario

Thanks for the file.

I looked thru it, noticed you are using one more bone than my example file. Looked thru the code and it looks like you corrected the code for the extra bone. Also noticed the IK_to_FK isnā€™t working correctly.

TBH, Iā€™ll have to look into this further. It will be a day or two before I can look at this.

Stay tuned, more to comeā€¦
Randy