Can anyone help me fix quaternion rotation errors in Unity?

In summary, using an exponential moving average to smooth out keyframes can help with positional jitter, but when quaternions are used, it causes rotations to go in the wrong direction. converting quaternions to euler angles, averaging, and then converting back seems to work, but is not error-free.
  • #1
twoski
181
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
  • #2
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?
 
  • #3
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?
 
  • #4
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!
 
  • #5
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.
 
  • #6
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
 
  • #8
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.
 
  • #9
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.
 

What is the purpose of averaging quaternions?

The purpose of averaging quaternions is to find a single representative quaternion that best represents a set of multiple quaternions. This is useful for data fusion and orientation estimation in applications such as robotics, computer graphics, and motion tracking.

How is the average quaternion calculated?

The average quaternion is calculated using a mathematical formula known as the "mean of unit quaternions" or "SLERP (Spherical Linear Interpolation) mean". This involves taking the weighted average of the individual quaternions, where the weights are determined by the angle between each quaternion and the average quaternion.

What are some challenges in averaging quaternions?

One of the main challenges in averaging quaternions is dealing with the non-commutative nature of quaternion multiplication. Another challenge is handling cases where the quaternions have different orientations or are very close in angle, which can lead to numerical instability and inaccurate results.

What are the benefits of using quaternion averaging?

Quaternion averaging provides a more accurate and robust way of estimating orientation compared to using a single quaternion. It also allows for data fusion from multiple sensors and can handle cases where the data may be noisy or inconsistent.

Are there any alternative methods to averaging quaternions?

Yes, there are alternative methods such as taking the median quaternion or using a geometric mean. However, these methods may not always provide the most accurate results and may not be suitable for all applications. It is important to carefully consider the specific use case and choose the method that best fits the requirements.

Similar threads

Replies
2
Views
2K
  • Classical Physics
Replies
6
Views
512
  • Calculus and Beyond Homework Help
Replies
1
Views
4K
  • Programming and Computer Science
Replies
1
Views
1K
Replies
16
Views
1K
  • General Discussion
Replies
4
Views
605
Replies
8
Views
1K
  • Programming and Computer Science
Replies
4
Views
958
  • STEM Educators and Teaching
Replies
3
Views
2K
  • Sci-Fi Writing and World Building
Replies
9
Views
2K
Back
Top