The hind leg of a quadruped is quite a bit different from a standard biped leg. Technically the anatomy is similar, but for a dog, unlike a biped, their “heel” doesn’t rest on the ground. For riggers and animators, this is kind of like having an extra knee to deal with. Most rigs, I’ve generally found, just treat this setup the same as an inverse foot, locking the orientation of that last joint to the ik control and supplying an attribute to rotate it manually. That’s not a bad solution, because for animators it’s consistent with other types of rigs, and for riggers it can usually be built quickly with existing tools. So it works, but I’ve never been completely happy with that type of setup because the ankle requires a lot of attention just to get it moving properly with the rest of the leg. Many running quadrupeds, including dogs, have a pretty tight relationship between the knee and ankle, and I wanted a setup which automated that motion as much as possible, without sacrificing control.
So I laid out some goals for how I would want a hind leg to behave:
- Effects of the IK should be evenly distributed between both the knee and ankle.
- Pulling the IK control away should result in a perfectly straight leg before breaking, stretching or pulling away from the foot.
- Pole Vector twists the whole leg, not just the knee, which is another byproduct of a standard inverse foot setup.
- The ratio between the knee and the ankle, which I’m calling “pitch,” should be controllable as an attribute.
- Possibly other attributes for twisting non-uniformly, or breaking the plane of the leg to bow it in and out.
One of the key component in getting all of this to work is the ikSpringSolver, which for some reason is a super secret IK solver in Maya. It doesn’t have a front-end, so you have to create it from the command line. But basically it’s a nice solver for chains longer than 2 bones, which need to collapse evenly and alternately, kind of like a spring, but more like a long strip of folded paper or something.
Anyway, best just to jump right into it. Here’s a basic joint chain for a hind leg, the hip, knee, ankle, foot:
Assigning just a regular IK handle to the whole chain might be the first instinct, and it’s worth trying out. At first glance you standard IK will appear to work fine, but when you compress this chain, you may begin to see its limitations as the joints rotate past eachother:
Furthermore, there’s nothing we can to do in the ik system to fix this pose.
This is where the ikSpringSolver comes in. To use the ikSpringSolver, you first have to initialize it by typing:
into the MEL command line. Then you create an ik handle by using the ikHandle command with “ikSpringSolver” as the -solver argument. Select the first and last joint, and then run this:
ikHandle -solver ikSpringSolver;
Now for some reason that I haven’t really narrowed down yet (maybe someone else has some insight on this), sometimes the chain will flip when you create this solver. I think it’s just a case of the pole vector being in the wrong spot, so assigning a pole vector constraint seems like it might be the only thing you need to do to fix it. I’m not sure if that will turn into a bigger issue or not.
So the ikSpringSolver is half of it. If you go into the ikSpringSolver attributes, you’ll find it has its own section where you can adjust the weighting of the joints in the system using a ramp, but while this is a cool feature, it doesn’t give you quite enough control. If you play around with it, you’ll find that it only has a subtle affect, and only when it’s not in the default pose:
It’s cool, but not quite the solution we’re looking for. But what you can do is nest another ik system underneath this one. Nesting IK systems is a very simple and useful technique, all it means is building another chain and IK handle that is a child of this system.
So we’re going to make a new rig to control the pitch of the leg. Duplicate the whole chain, and then create a regular ikRPSolver from the knee to the foot creating a basic two-joint ik chain. The result would look something like this when you move the new handle by itself:
Parent the duplicated chain under the hip of the primary chain, so that the top joint inherits the hip motion from the ikSpringSolver. Finally parent that new ikHandle under the ikSpringSolver handle. Now when you move the parent handle, the secondary chain follows the primary one exactly.
The benefit is now is that there’s one joint which isn’t being directly controlled by an IKhandle: the secondary hip. Rotate it and you’ll be changing the pitch of the leg:
This is the most basic example. Depending on the functionality you want, you can also do the same thing but with an inverse IK setup for the secondary chain. In either case, the rotation can be hooked up to an attribute to control pitch from the foot control. For additional clean-up, create a pole vector control for the spring chain, and then make the secondary chain follow along by setting its pole vector to the be the corresponding joint in the primary chain.
So here’s a short clip of the hind leg as I have it currently set up. In this example there’s another fancy thing going on. I’ve created a distance node, set up like you would for a stretchy system, but instead it’s hooked up to a remap value node to feather off the influence of the pitch effect as the leg gets stretched or compressed. That way you can’t pitch the leg when it’s completely straight, and a pitched leg will still stretch and compress evenly.
So, I hope that was interesting! I’ve been working on a foreleg as well, hopefully post that one soon.
As the resourceful commenters discovered, the ikSpringSolver behaves a bit differently from the ik solvers that we’re used to. Whereas a regular ik handle will respect a pole vector constraint regardless of where they each are in the hierarchy, the spring solver inherits twist from its chain’s local space, which can lead to double transforms. A solution is to keep the ikSpringSolver chain (not the handle) outside of the local hierarchy, in worldspace, and point constrain it so that it doesn’t inherit rotation.
Here’s an example file: