Arm Rig Setup For Seamless FK/IK Switching

October 13th, 2007 Leave a comment Go to comments

This tutorial assumes that you have the following simple skeleton:

  • A joint named L_shoulder_JNT
  • A joint named L_elbow_JNT
  • An arm IK control object called L_armIk_CON (to which the IK handle is going to be point-constrained)
  • A pole-vector control object called L_armPole_CON

You can download the Maya (6.0) scene here: armRig_001.ma.

The purpose of this tutorial is to detail the setup of a simple arm rig that will allow you to switch from FK to IK and vice-versa without the joints popping, which is very useful to pose a character (among other things). Please note that this method uses a single skeleton (no blending between multiple arms/skeletons).

In this example, the arm IK and pole vector control objects are Nurbs curves, but they could be any type of object you’d like. You can download the basic setup with this (maya 6.0) scene: armRig_001.ma.

Please note that it is indispensable that those joints form a perfectly flat plane. Bending the elbow is OK, but no twisting!

1) Building the Rig using MEL:

Now that we’ve got a basic skeleton and some controls, time to setup the arm rig itself. The following code is basically a scripted “tweaking” of the above Maya file to allow for the FK / IK switching:

// 1) First lock the Y and Z rotations on the elbow joint (it will only bend like a real elbow).
setAttr "L_elbow_JNT.jointTypeY" 0;
setAttr "L_elbow_JNT.jointTypeZ" 0;
setAttr -lock true -keyable false "L_elbow_JNT.ry";
setAttr -lock true -keyable false "L_elbow_JNT.rz";
//
// 2) Create the IK handle.
ikHandle -sol ikRPsolver -sj L_shoulder_JNT -ee L_wrist_JNT -n L_arm_IK;
//
// 3) Set the armIk control in world space (default values won't be 0, but we don't care).
move -rpr 0 0 0 L_armIk_CON;
makeIdentity -a 1 -r 1 -t 1 -s 1 L_armIk_CON;
vector $wristPos = `xform -query -a -worldSpace -rp L_wrist_JNT`;
move -worldSpace -a ($wristPos.x) ($wristPos.y) ($wristPos.z) L_armIk_CON;
makeIdentity -a 1 -r 1 -t 1 -s 1 L_armIk_CON;
pointConstraint -w 1 -o 0 0 0 L_armIk_CON L_arm_IK;
//
// 4) Create the default position locator for the arm pole vector
// (we'll use it to position the pole-vector when switching from FK to IK).
spaceLocator -p 0 0 0 -n "L_armPoleDefault_LOC";
vector $elbowPos = `xform -query -a -worldSpace -rp L_elbow_JNT`;
move -a ($elbowPos.x) ($elbowPos.y) ($elbowPos.z) L_armPoleDefault_LOC;
//
// 5) Parent the locator to the shoulder joint and put the locator behind the elbow.
parent L_armPoleDefault_LOC L_shoulder_JNT;
move -r -ws -wd 0 0 -10 "L_armPoleDefault_LOC";
setAttr "L_armPoleDefault_LOC.visibility" 0;
//
// 6) Match the position between the pole vector and the locator.
pointConstraint -w 1 -o 0 0 0 L_armPoleDefault_LOC L_armPole_CON;
delete L_armPole_CON_pointConstraint1;
makeIdentity -apply true -t 1 -r 1 -s 1 -n 0 "L_armPole_CON";
//
// 7) Pole-constraint the IK handle to the pole-vector control.
poleVectorConstraint -w 1 L_armPole_CON L_arm_IK;
//
// 8) Connect the IK handle visibility to the wrist IK enable attribute.
addAttr -ln enableIk -at bool -k on -dv 0 L_armIk_CON;
connectAttr -f L_armIk_CON.enableIk L_arm_IK.ikBlend;
connectAttr -f L_armIk_CON.enableIk L_arm_IK.visibility;
connectAttr -f L_armIk_CON.enableIk L_armIk_CON.visibility;
//
// 9) Put the arm in FK by default.
setAttr "L_armIk_CON.enableIk" 0;

2) IK/FK switching:

Now we have a rig ready for some switching. If everything went well, the Ik control object just disappeared (!). That’s normal, since the rig is currently in FK. So you can animate the elbow and shoulder joints by selecting and rotating them.

The whole idea behind this simple rig is to only use one skeleton for the arm, both in FK and IK. The trick is achieved by parenting a locator to L_shoulder_JNT that will serve as a ‘solid’ reference anchor point to which we snap the L_armPole_CON each time we switch to IK.

One advantage is that the locator will always be at the ‘right place’ for the plane of the arm to be respected (since it IS part of the arm skeleton); Therefore there won’t be ANY wobbling/popping at all when switching.

The other advantage for the animators is that they won’t have to look for the pole vector object every time they switch to IK, since it will ALWAYS appear at the same place/distance from the elbow.
When you want to switch to IK, use the following script: IkFk_switch_002.mel. You can source it, or copy and paste it into the script editor, and then make a button out of it. To run the script, just type:
IkFk_switch( "", "L_", "arm" );
The switch procedure itself is a command which takes 3 arguments; the first being the namespace (since the rig’s not referenced we’ll use “”), the second being the arm’s side (“L_” or “R_”) and finally the limb (“arm” or “leg”; in this case the arm). The code is abundantly commented, so please have a look to see what happens under the hood.

You should now see the Ik control object, neatly placed on the wrist. Now you can move it (as well as the pole vector object) and the arm should follow along.

To toggle back to FK, simply call the same procedure again (with the same arguments).

There you go!

As always, drop me a line if something explodes that shouldn’t…

  1. animator.k
    October 22nd, 2007 at 21:44 | #1

    thanks your tutorial

  2. November 1st, 2007 at 00:51 | #2

    wow. So much work. Can you animate and rig? That’s a lot of knowledge there.

  3. Jeison
    February 1st, 2012 at 23:34 | #3

    hello
    first. thank you very much for the tutorial is very good ..

    but there is something I do not work well ..

    when switching to fk. (Arm maintains its position.).

    but when will rotate the shoulder or elbow.
    completely lost position ..
    it is this?? ..
    thank you very much ..
    I would like you can help me in this part ..
    I hope and lies been as clear as possible …

  4. sasys
    March 7th, 2012 at 19:51 | #4

    Hi there, I have a question that I would like to ask as I don’t seem to be able to find it online. For example, as I am rigging a simple human arm construction – Shoulder Joint, elbow Joint and wrist Joint.

    Before I insert a iKhandle from the wrist to the shoulder, does the joints need to be align in the same level (while previewing it in the Front panel), suppose all the Joint axis are in the same/ correct direction?

    Waiting to hear from you soon

  5. Seith
    March 9th, 2012 at 14:12 | #5

    Yes, it’s best to have the joints aligned in a plane. And to do a “Set Preferred Angle” on them as well, before you create the IK handle.

  6. Innerg
    March 13th, 2012 at 03:51 | #6

    I came across this and so far, so good. I have added both arms with slight modding of the script. If it works the way I have in mind, it will be a godsend!

  7. April 16th, 2012 at 20:27 | #7

    Sim, é melhor ter as articulações alinhadas em um avião. E para fazer um “Angle conjunto preferido” sobre eles, bem como, antes de criar a alça IK.

  8. Amin
    July 9th, 2013 at 17:46 | #8

    very very cool tutorial :)
    but , no work NameSpace or Refrance ???
    Please Help Me !

  9. admin
    July 22nd, 2013 at 09:34 | #9

    @Amin
    Well, support for referenced characters would just mean adding the namespace (plus “:”) before each joint/control name in the script. It shouldn’t be too complicated, but that’s slightly beyond the purpose of that very old tutorial.

    I should expect that rigging has come a long way since I posted this thing, and hopefully it isn’t really relevant anymore…

  10. Pradeep
    November 12th, 2014 at 07:20 | #10

    Thanks for the Tutorial, it is working fine for Left Arm.
    Can you please help me out for similar setup for Right Arm.
    Thanks

  11. Seith
    November 12th, 2014 at 07:47 | #11

    Well, it should just be a matter of creating a mirrored skeleton, renaming the joints and doing the same for the script (replacing all “L_” with “R_” to match the right arm). It should be pretty self-explanatory.

  12. Pradeep
    November 12th, 2014 at 12:07 | #12

    @Seith
    Thanks for quick reply.
    Got, the fix where I was wrong. I missed mirroring armIk_CON and armPole_CON in my version of Rig.
    Thanks for your time.

  13. Kai
    January 6th, 2017 at 11:10 | #13

    Hi! thanks for the tutorial! Everything works well for me but I would like to ask, is it possible to set the “IkFk_switch( “”, “L_”, “arm” );” command to an object attribute?

    so when that attribute changes, it runs the script?

    Thanks!

  14. Seith
    January 7th, 2017 at 13:23 | #14

    Hi Kai. That’s a good question. I’m not sure actually. I usually proceed the other way around; I usually have a proc that’s called when the user does something, and that proc centralizes everything that needs to happen (in that case calling the switch). So there is no need to “link” behaviors like this.

  15. Kai
    January 9th, 2017 at 04:47 | #15

    @Seith
    oh i see! i’ll try that way! thank you so much!

  1. October 27th, 2007 at 19:49 | #1
  2. January 21st, 2009 at 23:15 | #2
  3. February 26th, 2012 at 17:27 | #3
  4. November 1st, 2014 at 22:55 | #4