Page MenuHome

Stretchy IK stretches when unnecessary even with extremely small stretch threshholds
Closed, ArchivedPublic

Description

When rigging characters it is extremely useful to have IK chains "stretch" when and only when the IK target is unreachable. In Blender this is accomplished by setting the "Stretch" bone property to a very small value. However, ik chains will still stretch noticably even when the target is reachable, and even with extremely small (0.00001) stretch values.

The attached file presents an example. The nature of this example is slightly confusing, but I will try to explain.

If you toggle into edit mode on the armature you can see the rest pose of the armature, with a very slightly (almost unnoticeable) bent knee. If you toggle back into pose mode, however, you can see that the knee is bent noticeably more, indicating that the leg lengthened.

The reason this happens is because the shin's fk position is posed differently than the edit-mode rest pose, which gives the IK solver a slightly different starting pose to solve from (this is a common and useful technique/trick for getting an IK chain to bend the correct direction even when the edit-mode position of the bone is straight or bent differently). You can see the FK adjustment either by disabling the IK constraint, or by observing the rotation values of the shin bone.

The point is that instead of the chain simply being rotated back into place by the IK solver, the IK solver instead stretches it unnecessarily. The "stretch" property on both leg bones is 0.00001. With such a tiny value, one would expect stretching to only be noticeable when the leg is beyond full extension. Setting the value even smaller and smaller has no effect (unless one sets it to zero, disabling stretching entirely). In fact, there is no notable effect of setting the value smaller than 0.001. Users expect the IK solution to approach the solution one gets with a value of 0.0 as the value approaches 0.0, but this does not seem to happen.

Details

Type
To Do

Event Timeline

A simpler example occurred to me, which is in the file "stretchy_ik_bend_2.blend"

In this case it is just a plain ik chain (no weird setup). I have precisely placed the ik target to almost-but-not-quite fully extend the leg. If you set the stretch value on the two leg bones to zero, you see that the bend in the knee is noticeably different, indicating unnecessary stretching. Again, no matter how small you set the stretch values, you cannot make this behave appropriately. The issue is the same as the previous example, although the previous example is more the use-case that makes this problematic.

Had a look into this after talking with Beorn,

See:
intern/iksolver/extern/IK_solver.h

/home/ideasman42/blender/blender/intern/iksolver/extern/IK_solver.h

#define IK_STRETCH_STIFF_EPS 0.001f
#define IK_STRETCH_STIFF_MIN 0.001f
#define IK_STRETCH_STIFF_MAX 1e10

Try change both 0.001f to 0.000001f

This stops the problem reported but introduces a new problem where the joint jitters when stretched.

need to look into this further...

Such small stretch values gives numerical instability in the solver, multiplied with other small values you get rounding errors. I've looked into this before a few years ago, and I think the priority would need to be handled explicitly somewhere, by first solving without the stretch, and then solving a second time with stretch. Probably would need a UI option "only stretch if necessary" to control this.

An "only stretch if necessary" option sounds perfect to me.

I discover that my puppet arms does not stretch as before... now, they can double the original size, but not more. I think something is different in the code.

I attached a stretchy_ik_blend_3.blend. The bones from the first (and third) has stretch 0.001 and, the ones from the second chain: 1. The second one (and the forth) seems that it work better than the first (the first shakes when moving the IK target bone far away). But, when I move the target bone close the chain root, the bones shrink until 0 (like the third and forth show).

I think about an option like "only stretch, not shrink"... then, we can put 1 as stretch value.

I want to add that, in stable version, for example, when my character (digital puppet) stretchs its arms, he can do it to where I want without problems. In new versions (50532), the arms don't reach to where I want, and the FPS gets slower. It's like a overprocess.

The file to test it is the one I uploaded (stretchy_ik_blend_3.blend), but I don't know if it is noticeable the FPS change.

Brecht: is this an active todo item for you or someone? To me it seems to be more part of active maintenance than open bug report!
Either let's find time to handle it, or make a note on the wiki todo with link to this report for future reference.

It's a todo item yes, to improve the IK solver, but was a known limitation in the implementation, so putting it on the todo list:
http://wiki.blender.org/index.php/Dev:2.5/Source/Development/Todo/Animation#Rigging

I have to say that the last comment I wrote, is about some kind of regression. I don't know the changes that IK code suffered, but now it is not possible to do something that it was possible in a previous version.

[quote]
I want to add that, in stable version, for example, when my character (digital puppet) stretchs its arms, he can do it to where I want without problems. In new versions (50532), the arms don't reach to where I want, and the FPS gets slower. It's like a overprocess.
[/quote]

The example file is stretchy_ik_blend_3.blend. I upladed 2 screenshots, 2.63 and 2.65 stables.

Mario, sorry, I missed that. Fix in svn for that now.

I realize this is closed, but just for reference:
I've figured out a rigging solution to this, which makes a code solution unnecessary, and I'd like to briefly document it here.

It's based on what Brecht said above regarding doing a solve without stretch, and then a solve with stretch. This can be accomplished by using two IK chains: one without stretch, and one with stretch. The chain with stretch copies the transforms of the one without stretch, and then does its IK solve. This gives perfect results.

Example blend file is attached ("stretchy_ik.blend").