Can anyone help me fix quaternion rotation errors in Unity?

  • Context: Undergrad 
  • Thread starter Thread starter twoski
  • Start date Start date
  • Tags Tags
    Quaternions
Click For Summary

Discussion Overview

The discussion revolves around issues related to quaternion rotation errors in Unity, specifically in the context of implementing animation smoothing for keyframes. Participants explore various methods for reducing jitter in animations, including the use of exponential moving averages and the challenges associated with converting between quaternions and Euler angles.

Discussion Character

  • Technical explanation
  • Debate/contested
  • Mathematical reasoning

Main Points Raised

  • One participant describes the implementation of animation smoothing using an exponential moving average, noting issues with jitter in keyframes and errors in rotation when converting quaternions to Euler angles.
  • Another participant suggests printing input and output values to diagnose potential averaging issues with angles.
  • A question is raised about whether it is appropriate to average Euler angles or if averaging quaternions directly would yield better results.
  • A participant illustrates a specific problem with angle averaging, highlighting how averaging can lead to incorrect rotation directions when angles wrap around (e.g., from 350 to 10 degrees).
  • One participant proposes a modified averaging function that attempts to account for angle wrapping, but still experiences issues with skeleton rotations.
  • Another participant provides references to resources discussing quaternion averaging and potential errors, indicating that they may be relevant to the problem at hand.
  • Clarification is sought regarding the meaning of "jitter" in the context of animation, with a participant relating it to unwanted vibrations in animated sequences.
  • A participant explains that the keyframes are derived from raw input from a Kinect, emphasizing the need to calculate the exponential moving average while considering the limitations of Euler angles.
  • Discussion includes the suggestion that quaternion interpolation may produce smoother results than Euler angle interpolation, raising questions about its relevance to the current problem.
  • One participant expresses the intention to showcase different smoothing methods, including quaternion lerping, while addressing the challenges posed by Euler angles.
  • Another participant questions whether the smoothed animation is intended to match the keyframes exactly or if slight deviations are acceptable.
  • Concerns are raised about the correctness of the exponential average implementation, with suggestions to perform sanity tests to verify the animation's behavior under constant conditions.
  • A participant shares their experience of observing incorrect joint rotations and sporadic flipping when angles transition from low to high values.

Areas of Agreement / Disagreement

Participants express various viewpoints on the best approach to averaging rotations and handling quaternion errors, with no consensus reached on a definitive solution. Multiple competing methods and ideas are presented, indicating ongoing debate and exploration of the topic.

Contextual Notes

Participants highlight limitations related to angle wrapping in Euler angles and the complexities of averaging quaternions versus Euler angles. The discussion reflects a range of assumptions and conditions that may affect the proposed solutions.

twoski
Messages
177
Reaction score
2
I am trying to implement animation smoothing for a given set of keyframes. Some keyframes have "jitter" which i have to remove through my own algorithms. I am using the Unity game engine which has its own quaternion classes and such.

I looked into it, and using an Exponential Moving Average seems like a good idea. This approach works well for removing positional jitter, however when i use it with quaternions it causes some errors with rotations.

I am currently converting quaternions to euler angles, averaging, then converting back. However this doesn't seem to work. It causes my models to rotate in the wrong directions.

Here is the code i use:

Code:
void UpdateRotationEMA(int i, Quaternion q)
    {
        if (transforms[i] != null)
        {
            if (frameList[i] != null)
            {
                Vector3 pos = AvgPos(frameList[i], q.eulerAngles); //T1

                transforms[i].rotation = Quaternion.Euler(pos);
                frameList[i] = pos;
            }
            else
            {
                transforms[i].rotation = q;
                frameList[i] = q.eulerAngles; 
            }
        }
    }
Vector3 AvgPos(Vector3 lastPos, Vector3 pos)
    {
        return (emaAlpha * pos + ((1f - emaAlpha) * lastPos));
    }

Can anyone spot any obvious bugs?
 
Physics news on Phys.org
Perhaps you can get it to print the input and the averaged output to see what's going on. Could the algorithm be averaging the angles too?
 
I wasn't sure if this was the proper method - should i be converting my quaternions to euler angles, then averaging those? Or am i meant to just average the quaternions?
 
I think my problems are stemming from a situation like this:

Angle 1: 10, 0, 0.
Angle 2: 350, 0, 0.

The distance between 10 and 350 is 20. This is pretty clear.

However, by doing:

(0.2 * Angle1 + ((0.8) * Angle2))

We get a new angle which is 282, 0, 0. This is totally wrong since it goes the wrong direction!
 
This seems like a step in the right direction.

Code:
Vector3 AvgPos(Vector3 lastPos, Vector3 pos)
    {
        Vector3 init = (emaAlpha * pos + ((1f - emaAlpha) * lastPos));

        if (init == pos)
        {
            return init;
        }

        Vector3 res = init;
        Vector3 delta = pos - init;

        if (Mathf.Abs(pos.x - lastPos.x) > 180f)
        {
            res.x = pos.x - delta.x;
        }

        if (Mathf.Abs(pos.y - lastPos.y) > 180f)
        {
            res.y = pos.y - delta.y;
        }

        if (Mathf.Abs(pos.z - lastPos.z) > 180f)
        {
            res.z = pos.z - delta.z;
        }

        res.x = res.x % 360f;
        res.y = res.y % 360f;
        res.z = res.z % 360f;

        return res;
    }

Still, my skeletons are rotating weirdly.
 
I don't know much about what you're trying to do but am talking from the experience of debugging programs.

So are you trying to move an object from once place to the next smoothly without changing it orientation? Or change it in a natural and smooth way?

I found this NASA pdf talking about how to average quaternions and also about subtle errors you may encounter:

http://ntrs.nasa.gov/archive/nasa/casi.ntrs.nasa.gov/20070017872.pdf

Here's another reference:

http://www.mathworks.com/matlabcentral/fileexchange/40098-tolgabirdal-averaging-quaternions
 
Hmm that looks correct, however i am trying to do an exponential moving average which is slightly different from the way they are doing it.
 
twoski said:
I am trying to implement animation smoothing for a given set of keyframes. Some keyframes have "jitter" which i have to remove through my own algorithms. I am using the Unity game engine which has its own quaternion classes and such.

Clarify the meaning of "jitter".

Thinking of hand drawn animation, I can imagine a sequence of keyframes that are supposed portray a globe turning. Perhaps some of them inadvertently show the globe moving a little from side to side, so the animation that interpolates images between the keyframes shows the globe vibrating as well as rotating.

How were the keyframes generated? Is a keyframe a set of parameters or an actual image?
 
  • #10
Ok keyframes was misleading as an example, I'm using raw input from a kinect. Essentially, i have the last frame, and the current frame. Both have a rotation value.

I want to calculate the exponential moving average of these values, however in order to do so i need to convert to euler i think. The problem with using an exponential moving average for this is that euler angles go from 0 to 360 then start at 0 again, so if 2 angles are, say, 350 and 10, the exponential moving average of these will be incorrect using the function i posted.

Intuitively, we know that the difference is 20 degrees. Given this value is there a way to find out the exponential moving average?
 
  • #11
I've glanced at pages about using quaternions for animation and seen interpolation recommended - something like a spline. Supposedly interpolation between quaternion values produces smoother results than interpolating between Euler angles. Is interpolation relevant to what you are doing?

I don't know what an "exponential moving average" is. The meaning of "moving average" is familiar, but what is being averaged? What is being exponentiated?
 
  • #12
Stephen Tashi said:
I've glanced at pages about using quaternions for animation and seen interpolation recommended - something like a spline. Supposedly interpolation between quaternion values produces smoother results than interpolating between Euler angles. Is interpolation relevant to what you are doing?

I don't know what an "exponential moving average" is. The meaning of "moving average" is familiar, but what is being averaged? What is being exponentiated?

I am showcasing different methods of animation smoothing, I've already implemented quaternion lerping so now I'm trying to show a different method.

Here is the definition: http://en.wikipedia.org/wiki/Moving_average#Exponential_moving_average

The exponential moving average is easy to implement for vectors, however in my case we need to account for the fact that the vectors are euler angles and can go from 0 to 350 in 10 degrees rather than 350 degrees.
 
  • #13
The way I think of moving averages computed from a sequence of data points is that they don't form a curve that goes through the points. So smoothing with moving average is not "interpolation". Is it your intention that your smoothed animation never exactly matches the keyframes?
 
  • #14
The main goal is to remove jitter, if the animation is slightly off then that just gives me one more talking point for when i showcase the different styles of smoothing.
 
  • #15
I second jedishfu's suggestion to check the code that does the exponential average, if you haven't done that yet.

Have you done any "sanity" tests? Does animation look right if you apply the method to something that just stays in the same constant position?
 
  • #16
I have done debug prints, however the easiest way to see what was going on was by looking at the raw data in action.



You can see that it's rotating joints in the wrong direction which results in the sporadic flipping of the middle girl.

It only happens when an angle goes from a low number to a very high number, like the scenarios i have described.
 

Similar threads

  • · Replies 1 ·
Replies
1
Views
3K
  • · Replies 6 ·
Replies
6
Views
2K
  • · Replies 10 ·
Replies
10
Views
9K
  • · Replies 1 ·
Replies
1
Views
4K
  • · Replies 1 ·
Replies
1
Views
4K
  • · Replies 3 ·
Replies
3
Views
2K
  • · Replies 1 ·
Replies
1
Views
3K
  • · Replies 0 ·
Replies
0
Views
6K
  • · Replies 5 ·
Replies
5
Views
2K
  • · Replies 4 ·
Replies
4
Views
2K