There are 3 parts. 1) covers the basic idea and some rudimentary vector math 2) covers the python scipting of those concepts in Maya and 3) introduces "message attributes" which are nifty little attrs that can be really useful to bump up functionality of your rigs/scripts.
Maya/Rigging: IK to FK snapping, part 1 from zeth willie on Vimeo.
Maya/Rigging: IK to FK snapping, part 2 from zeth willie on Vimeo.
Maya/Rigging: IK to FK snapping, part 3 from zeth willie on Vimeo.
Oh, yeah. Here is the code for the basic version of the IK/FK script in python (the script using the message attrs will depend on your specific attr names):
import maya.cmds as cmds import maya.OpenMaya as om #select the joints we need sel = cmds.ls(sl=True) #assign selection fkWrist = sel[0] fkShldr = sel[1] fkElbow = sel[2] ikWrist = sel[3] ikPv = sel[4] #get positions from fk fkwRaw = cmds.xform(fkwrist, ws=True, q=True, t=True) fkwPos = om.MVector(fkwRaw[0], fkwRaw[1], fkwRaw[2]) fkeRaw = cmds.xform(fkelbow, ws=True, q=True, t=True) fkePos = om.MVector(fkeRaw[0], fkeRaw[1], fkeRaw[2]) fksRaw = cmds.xform(fkshldr, ws=True, q=True, t=True) fksPos = om.MVector(fksRaw[0], fksRaw[1], fksRaw[2]) #set position of IK wrist ctrl cmds.move(fkwPos.x, fkwPos.y, fkwPos.z, ikwrist) #start figuring out pole vector pos #find avg (midpoint) of shoulder and wrist midpoint = (fkwPos + fksPos) / 2 #find pv direction pvOrigin = fkePos - midpoint #extend that length pvRaw = pvOrigin * 2 #position pvRaw at midpoint pvPos = pvRaw + midpoint #stick pole vector at pvPos cmds.move(pvPos.x, pvPos.y, pvPos.z, ikpv)
Once I get the little things hammered out in the zbw_messageMapper script that I showed in the video, I'll post that up too. . .
EDIT: One more thing! Here's the link to Ryan Trowbridge's site. http://www.rtrowbridge.com/blog/ Not sure how to access individual posts, but the post from March 09 has the video of the MasterClass on Vector Math in Maya. Good stuff. Also just bought his book on Python for Games and Film. Can't wait to read it!
Great Stuff! :-)
ReplyDeleteCan I vote for a SapceSwitching demo while I'm here?
Hi
ReplyDeletethanks for very good tutorial.
can you comment or post for fstretch plugin and download??!
I think very useful.
thank you very much for special tutorial
@Craig:
ReplyDeleteConsider your secret vote counted!
@Saman:
Haven't used it myself. Seen the video, looks a lot like Stretchmesh, a plug in Rob O'Neil(a TD I know) helped create. But as I said, don't know how it works.
This comment has been removed by the author.
ReplyDeleteI can't seem to get the pole vector to snap.
ReplyDeleteDo you have any suggestions for why this may occur?
hey zeth - i've been following your vids for about a year and have enjoyed them all - very helpful stuff. i recently tried setting up the switch system outlined here, but for the life of me can't get the elbow to line up. if you have a minute or two to help, i have scripted the whole process (arm setup with the msg attrs and then the code to switch). is there a way i can get these scripts to you for checking out my math?
ReplyDeleteYou can email it to me. . . I'll take a look when I get a sec.
Deletehey zeth,
Deletethanks for the quick re:. i can't find your email address on this site, google+ or the vimeo site. could you IM or email your contact info. on gmail\gchat i am beautifulrobot.
thx!
If this hasn't been resolved yet, I may have found the solution.
DeleteDouble check the name of the variable where we assigned it from the selection (line 12 - ikPv = sel[4] from the code Zeth posted for us) and make sure that exact name is being referenced in the line where it's supposed to be moved, line 43 of this code.
If you straight up copy/pasted from this, there is a small error between those lines. the variable is called ikPv while the "object" to be moved is called ikpv. The missing capital letter is throwing this code off.
Thanks for the tutorials. All of them are awesome.
ReplyDeleteHey Zeth ! How can I get transformations with rotations from IK-joints to set them FK-joints with python to make feedback for IK to FK switch ? and can I put this script to attribute in control to easy snaping in the animation process?
ReplyDeleteHey Daria-
DeleteYeah, I didnt' get into that too much, cuz a lot of it depends on how you set things up with the controls. But IK to FK is pretty easy assuming you have identical joints on the Fk/IK chains. Just get the rotation from the world space of the IK joints and apply them to the world space of the FK controls (cause the controls should match the joints).
FK to IK can be harder because the ankle joint MAY not line up with the IK control (the IK control may be left at the default world space which won't correspond to the joint orientation). So the gist is to just get the difference between the zeroed out IK control and the zeroed out ankle joint. Does that make sense? So the IK control at zero rots will be in world space (in many setups). The FK (or IK) ankle joint will be at zero rotation, but might oriented differently (i.e. bent at 20 deg to create the foot angle). So you can get the rotation of that by using some matrix code from the api or, more conveniently, the "xform" command using the "ws" (worldspace) flag. Or you can get it manually by looking at the "joint Orient" box in the attr editor of the joint. Then you use that value to OFFSET the rotation of the IK control.
So in the example I gave above, to orient the IK control to the FK ankle you'd subtract 20 deg from the correct axis when you use the "ws" flags in the "xform" command. The ankle at rot values (0,0,0) would yield (20, 0, 0) in the xform and the IK handle would yield (0,0,0). So to line then up you'd make sure to subtract (20, 0, 0) from whatever the FK gives you. Got it? It gets more complicated depending on the how you set up the joint orientations initially, so it'd be different for joints oriented in y than for joints oriented in x.
I often make it easier for myself by figuring it out the rotation difference and then putting that on the IK control (or something else) as an extra hidden attribute. Then I can just tell controls to generically use the "orientOffset" attr or whatever when doing the conversion.
That help at all?
hai zeth i tried your script in my ctrls but when i run the script i got this message
ReplyDelete# Error: line 1: NameError: file line 15: name 'fkwrist' is not defined #
how can i solve it ,i will be very much thank full for your help
I'm getting the same problem? any ideas out there please?
Deletecould use some feedback. The script works snapping ikwrist to fkwrist, but ik elbow doesnt move as in tutorial on 1st attempt at snapping wrist . almost like its locked in place . Then executing entire script ikwrist doesnt snap but ikPv moves . So in parts it seems to work but as a whole its not working correctly ...Any ideas
ReplyDeleteSo instead of picking actual ikwrist joint I select ikhandle, which will be ikCtrl eventually and that worked in moving elbow . Now the ikPv is not snapping into place, its close but not an exact match . I noticed if i changed pvRaw = pvOrigin * 2 to a higher number it would get closer, but thats not the correct way either is it ?
ReplyDeletealso how difficult would it be to setup an ik/fk snap with a mechanical arm ?? consisting of 4 joints, 2 of those being elbow joints . For the most part your tutorial works great with 3 joints , but 4 i got lost and also had trouble matching ik to fk rotations .....any help would be appreciated . thanks so much
ReplyDeletefirst off thanks,
ReplyDeletereally clear explanation of what turned out to not be very difficult math.
This works for me if my arm is on the origin.
if its not i had to add the fk elbows position to the cooridinates in the move command.
like this
cmds.move(pv_pos.x + fk_elbow_pos.x, pv_pos.y + fk_elbow_pos.y, pv_pos.z + fk_elbow_pos.z, ik_pv)
There are errors in your script. All your variables are case sensitive and your script calls lower case letters, so all the people saying it cannot work, are correct.
ReplyDelete#assign selection
#the below var
#fkWrist = sel[0]
#should be
fkwrist = sel[0]
So the below script will now work:
import maya.cmds as cmds
import maya.OpenMaya as om
#select the joints we need
sel = cmds.ls(sl=True)
#assign selection
fkwrist = sel[0]
fkshldr = sel[1]
fkelbow = sel[2]
ikwrist = sel[3]
ikPv = sel[4]
#get positions from fk
fkwRaw = cmds.xform(fkwrist, ws=True, q=True, t=True)
fkwPos = om.MVector(fkwRaw[0], fkwRaw[1], fkwRaw[2])
fkeRaw = cmds.xform(fkelbow, ws=True, q=True, t=True)
fkePos = om.MVector(fkeRaw[0], fkeRaw[1], fkeRaw[2])
fksRaw = cmds.xform(fkshldr, ws=True, q=True, t=True)
fksPos = om.MVector(fksRaw[0], fksRaw[1], fksRaw[2])
#set position of IK wrist ctrl
cmds.move(fkwPos.x, fkwPos.y, fkwPos.z, ikwrist)
#start figuring out pole vector pos
#find avg (midpoint) of shoulder and wrist
midpoint = (fkwPos + fksPos) / 2
#find pv direction
pvOrigin = fkePos - midpoint
#extend that length
pvRaw = pvOrigin * 2
#position pvRaw at midpoint
pvPos = pvRaw + midpoint
#stick pole vector at pvPos
cmds.move(pvPos.x, pvPos.y, pvPos.z, ikpv)
Hi Zeth and all,
ReplyDeleteRyan trowbridges class is now here.
https://area.autodesk.com/learning/class3_q1_2012/