Dismiss Notice
Join Physics Forums Today!
The friendliest, high quality science and math community on the planet! Everyone who loves science is here!

Averaging Quaternions

  1. Nov 28, 2014 #1
    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 (Text):

    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?
     
  2. jcsd
  3. Nov 28, 2014 #2

    jedishrfu

    Staff: Mentor

    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?
     
  4. Nov 28, 2014 #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?
     
  5. Nov 29, 2014 #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!
     
  6. Nov 29, 2014 #5
    This seems like a step in the right direction.

    Code (Text):

    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.
     
  7. Nov 29, 2014 #6

    jedishrfu

    Staff: Mentor

    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. Nov 29, 2014 #7

    jedishrfu

    Staff: Mentor

  9. Nov 29, 2014 #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.
     
  10. Nov 29, 2014 #9

    Stephen Tashi

    User Avatar
    Science Advisor

    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?
     
  11. Nov 29, 2014 #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?
     
  12. Nov 30, 2014 #11

    Stephen Tashi

    User Avatar
    Science Advisor

    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?
     
  13. Nov 30, 2014 #12
    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.
     
  14. Nov 30, 2014 #13

    Stephen Tashi

    User Avatar
    Science Advisor

    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?
     
  15. Nov 30, 2014 #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.
     
  16. Nov 30, 2014 #15

    Stephen Tashi

    User Avatar
    Science Advisor

    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?
     
  17. Nov 30, 2014 #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.
     
Know someone interested in this topic? Share this thread via Reddit, Google+, Twitter, or Facebook




Similar Discussions: Averaging Quaternions
  1. Quaternion confusion (Replies: 3)

Loading...