SplineIK Rotation jitter problem
-
Hi,
I found that IK_spline tag will cause joint rotation jitter when moving the controller under certain circumstances.
The picture(pic1) below shows this situation, showing the axes of the joint to make it easier to see.
pic1Is this a bug or a wrong way of using it?
I use the parallel transport method to expand to get a more stable rotational mixing. The picture(pic2) below is a comparison. The thicker coordinate axis shows the result of using parallel transfer mixing, which is more stable.
pic2Although the rotational jitter problem has been solved, I would like to understand the cause of the rotational jitter. The following is the c4d file where this problem occurs.
Thanks for any help!
-
Hello @chuanzhen,
Thank you for reaching out to us. When you say you are using Parallel Transport, which is just a subject of math, I assume you mean "the" parallel transport frame(s) algorithm we talked about for example here and not something more fancy like rotation minimizing frames (which also realizes parallel transport).
I would say you simply have a bug in your algorithm, because naive parallel transport is stable and its shortcoming is that it does not react to sudden changes in curvature very responsively (as you always drag the sum of the past banking values with you by carrying over the normals). I.e., its weakness is the exact opposite of what you show us. As declared in our forum guidelines, I cannot help you too much with debugging and general math subjects (I also do not see any code in your file or on the forum).
While it can be necessary in some cases to write your own parallel transport, specifically when you need more control over how changes in curvature translate into the banking of the frames, you can also just use
c4d.utils.SplineHelp
. It can construct frames on the vertices of a spline for you. We talked not too long ago about the subject in this thread, I also gave an explanation and a code example there. The problem was very similar to yours, aligning cones with a spline.In this case you simply construct a linear spline on your bones, and then use
c4d.utils.SplineHelp
to construct the frames. Afterwards you could swizzle the frames or do other post-processing if you do not like other aspects of the output.Cheers,
Ferdinand -
Hi @ferdinand
Thank you for your detailed reply. As you said 'bug', just direct parallel transport cannot directly obtain as stability control as in the picture. The working method I use is to perform parallel transport in segments(2 control is a segment), in both forward and reverse directions. After two time parallel transport, then mix the rotation.This can achieve flexible control by the controller. The bones also ensure his stability.I would like to know more about why the built-in IK_Spline Tag causes such jitter in c4d files and pic. Is the IK_Spline Tag not working stably enough, or is there another problem?
-
Hey @chuanzhen,
just direct parallel transport cannot directly obtain as stability control as in the picture
I strongly doubt that, the run of the mill parallel transport algorithm, aka PFT, has many flaws but it will pretty much smooth out everything out under the sun (which is also one of its flaws). Jitter is the last thing I would expect from PFT. I might be overlooking here an important detail in your setup, but this seems very unlikely to me, especially because my setup below works fine.
I do not see jitter in the file you have provided, can you be more specific?
Below I have provided a very quick and dirty setup for constructing the frames on a spline. It is unclear to me if you want to construct the frames of the spline input of a Spline-IK, or if you want to construct the frames on the bones. A chose the slightly more complicated case of first constructing spline for the bone chain.
I kept the example very loose, which is why the nulls are slightly offset, as I assume all bones always to have the same length, instead of doing the busy working of figuring out where the offsets for the bones must lie on the spline.
Cheers,
FerdinandFile:
splineik_rotation_problem.c4d
Result:
Code:
"""Constructs frames for a list of input objects interpreted as a spline. """ from typing import Optional import c4d doc: c4d.documents.BaseDocument # The document evaluating this tag op: c4d.BaseTag # The Python scripting tag def iter(node: c4d.GeListNode | None) -> c4d.GeListNode: """Yields all descendants of #node and #node itself. """ if not isinstance(node, c4d.GeListNode): return yield node for child in node.GetChildren(): for descendant in iter(child): yield descendant def ConstructSpline(offsets: list[c4d.Vector]) -> c4d.SplineObject: """Constructs a linear spline from the given offsets and builds its cache. """ spline: c4d.SplineObject = c4d.SplineObject(len(offsets), c4d.SPLINEOBJECT_TYPE_LINEAR) if not spline: raise MemoryError() spline.SetAllPoints(offsets) spline.Message(c4d.MSG_UPDATE) temp: c4d.documents.BaseDocument = c4d.documents.BaseDocument() if not temp: raise MemoryError() temp.InsertObject(spline) if not temp.ExecutePasses(c4d.threading.GeGetCurrentThread(), False, True, True, c4d.BUILDFLAGS_NONE): raise RuntimeError() spline.Remove() temp.Flush() return spline def main() -> None: """ """ # Get the user data inputs. boneRoot: c4d.BaseObject | None = op[c4d.ID_USERDATA, 2] frameRoot: c4d.BaseObject | None = op[c4d.ID_USERDATA, 3] # Get the list of global offsets from the bones and the list of null objects to set. offsets: list[c4d.Vector] = [n.GetMg().off for n in iter(boneRoot)] nulls: list[c4d.BaseObject] = [n for n in iter(frameRoot)] if len(offsets) != len(nulls): raise RuntimeError() # Construct the spline object and init the helper. spline: c4d.SplineObject = ConstructSpline(offsets) helper: c4d.utils.SplineHelp = c4d.utils.SplineHelp() helper.InitSplineWithUpVector(spline, upvector=c4d.Vector(0, 1, 0) ) count: int = spline.GetPointCount() # Iterate over all points and compute a transported frame for each of them. I am just blindly # assuming here that each bone will have the same length, which of course does not hold true. # I was too lazy to do all the busy work, but what you would have to do is compute/get the length # of all bones, then compute the sum of them, get the length of the spline, and with that # information compute the offsets #t. for i in range(spline.GetPointCount()): t: float = (i + 1.) / count mg: c4d.Matrix = helper.GetMatrix(t, realoffset=True) nulls[i].SetMg(mg)
-
Hey @ferdinand
Thanks for your reply!
The video shows that the new file(splineIK_rotation_problem.c4d ) has rotational jitter at frames 6-7 and 49-50.The python tag of the new file contains the solution code, you can see it in the file.
-
Hey @chuanzhen,
you mean the twisting motion of the bones aligned to the spline? That comes from the Twist of the IK-Spline being set to World. But with such questions you must go to our support center. We cannot provide support on end-user questions here; the problem/twisting happens with no code present in the scene.
Cheers,
Ferdinand -
@ferdinand Thanks