Transformation constraint popping (local)

While trying to add an elevated protraction (raised forward movement) to my shoulder rig with Transformation Constraint, I can’t seem to find a way around the sudden “popping”, even with rigorous setting fiddlings

These are the constraint settings in local transformation with XYZ euler and Mix: Add

The settings for the Source are meant to keep the constraint from activating unless the clavicle is raised in the abduction pose (raising the arm), because I don’t want it interfering with the Action Constraint I have to enable proper tilting of the scapula in neutral forward movement.

Pink scapula is reference bone so I know the constraint isn’t ruining my Action Constraint for abduction.

Also, any suggestions to do this double variable activation movement (X and Z rotation of clav bone) would be very much appreciated.

I’ve already tried doing another Action Constraint using the Z or Y rotation of the clav bone so it doesn’t interrupt the protraction Action Constraint using the X rotation of clav.
This results in my start and end poses of my abduction Action Constraint for the scapula being corrupted despite testing changing the Action Constraint stack order.

Also tried my hand at Drivers but my math/equational thinking is too weak despite trying to find other tutorials that I could modify to either to drive the Y rotation of the scapula bone with double variables or simply to have my protraction Action Constraint be reduced from 1.0 to 0.5 to reduce influence over my elevated protraction Action Constraint.

Drivers are going to be better.

So there are two potential issues happening:

  1. Your X and Z are evaluated separately. That means, a Z less than 0 is not going to stop your X->X mapping.

  2. Here’s how bones get transformed: fcurve->driver->matrix->constraint->matrix. What does “matrix” mean? It means that the bones’ transforms aren’t stored as separate loc/rot/scale triplets-- to evaluate the constraints, the matrices need to be decomposed back into triplets. But that involves some loss of data-- eg, a rotation of 190 degrees turns into a rotation of -170 degrees. But also, Euler angles are a weird abstraction of actual orientations, because 3D orientations can not be decomposed into 3 separate, equal values. -180,180 eulers are overbroad-- there’s more than one set of eulers describing any particular orientation. (Think about 3 triplets for a ship’s orientation on the globe: latitude, longitude, heading. Why do longitude and heading have 360 degrees while latitude only has 180 degrees?) So when you go euler->matrix->euler, the eulers you get out aren’t necessarily the eulers you put in.

So, drivers, for which the eulers you put in, are the eulers you get out.

For me, I haven’t made a perfect auto-shoulder. However, my favorite “close enough” version, for an IK arm, uses two, 2-bone IK chains, both tracking the same target-- but the first one’s bone starts slightly above the shoulder, and the shoulder bone damped tracks a marker parented to that first bone:

Not demo’d, but better to give pole targets to keep the same elbow position, and it may be necessary to limit the rotation of the clavicle. (But I don’t limit rotation with a simple limit rotation constraint, because of 2 above; I damped track a marker bone that has a limited position.)

1 Like

Thanks for the bone transform breakdown!

And alas, how my little lizard brain hisses at drivers

Is there a specific keyword I’ve been missing to look for a better explanation of driver expressions? I’ve looked at a good majority of “demystifying” and driver series on youtube to no avail. I’m aware it’s a BEDMAS format, the equation logic just keeps going over my head.

I don’t know. I haven’t had that much trouble with it. For me, I use right click in a field, copy as driver, right click in a field, paste as driver, open the driver editor and change to scripting expression. The rest is just math-- in the case of your transformation constraint, adding and multiplying, + and *.

I’m good with constraints, and sometimes I’ll use constraints to get a bone in the position I want, and then use a transform channel instead of single property driver. Single property drivers are pre-constraint; transform channels are post constraint (and so, again, the eulers you get out are not what you put in, not in that case.)

Drivers on/from quaternion values are generally not a good idea. A quaternion is in no way a set of 4 independent values. Drivers on eulers make much more sense.

1 Like

I’ve been trying to fiddle with how you’ve described but the actual math is still beating me in mortal combat. If I manage to make the math rotate my scap’s Y axis when I try to put the min at 0 for the action’s end frame it breaks :confused:

Thank you for reminding me copy as driver was a thing though! I had completely blanked on that :dizzy_face:

i guess it’s more than * and +, there are mins and maxes. And you need to convert to radians.

If your Z axis rotates -10.5 degrees, your Y rotates 24.2 degrees. So your Y is Z * (24.2/-10.5). Let’s simplify that a bit: Y=-Z * 24.2/10.5.

But then, you want to clamp the rotation. If Z axis rotates more than -10.5, we still want the same rotation. So Y = min((-Z * 24.2/10.5), 24.2). Except-- rotation here is measured in degrees, and we want radians. So, Y = min((-Z * 24.2/10.5), 24.2 * (pi/180) ). Because there are pi radians in 180 degrees.

That clamps one end of it. We want the other end clamped to, to 0. So Y = max(min((Z * 24.2/10.5),24.2 * (pi/180)),0). 0 degrees is also 0 radians so we don’t have to worry about that one :slight_smile:

How did I know “min” and “max” do that? They’re built-in Python operators: .

1 Like

Thanks so much for the indepth explanation!
I ended up also having to add a driver to reduce the protraction Action Constraint, but your expression worked great!