Search code examples
geometryquaternionsaffinetransformrotational-matricespose-estimation

Average and Measure of Spread of 3D Rotations


I've seen several similar questions, and have some ideas of what I might try, but I don't remember seeing anything about spread.

So: I am working on a measurement system, ultimately computer vision based.

I take N captures, and process them using a library which outputs pose estimations in the form of 4x4 affine transformation matrices of translation and rotation.

There's some noise in these pose estimations. The standard deviation in Euler angles for each axis of rotation is less than 2.5 degrees, so all orientations are pretty close to each other (for a case where all Euler angles are close to 0 or 180). Standard errors of less than 0.25 degrees are important to me. But I have already run into the problems endemic to Euler angles.

I want to average all these pretty-close-together pose estimates to get a single final pose estimate. And I also want to find some measure of spread so that I can estimate accuracy.

I'm aware that "average" isn't actually well defined for rotations.

(For the record, my code is in Numpy-heavy Python.)

I also may want to weight this average, since some captures (and some axes) are known to be more accurate than others.

My impression is that I can just take the mean and standard deviation of the translation vector, and that for the rotation I can convert to quaternions, take the mean, and re-normalize with OK accuracy since these quaternions are pretty close together.

I've also heard mentions of least-squares across all the quaternions, but most of my research into how this would be implemented has been a dismal failure.

Is this workable? Is there a reasonably well-defined measure of spread in this context?


Solution

  • Without more info about your geometry setup is hard to answer. Anyway for rotations I would:

    1. create 3 unit vectors

      x=(1,0,0),y=(0,1,0),z=(0,0,1)
      

      and apply the rotation on them and call the output

      x(i),y(i),z(i)
      

      it is just applying the matrix(i) with position at (0,0,0)

    2. do this for all measurements you have

    3. now average all vectors

      X=avg(x(1),x(2),...x(n))
      Y=avg(y(1),y(2),...y(n))
      Z=avg(z(1),z(2),...z(n))
      
    4. correct the vector values

      so make each of the X,Y,Z unit vectors again and take the axis which is more closest to the rotation axis as main axis. It will stay as is and recompute the remaining two axises as cross product of main axis and the other vector to ensure orthogonality. Beware of the multiplication order (wrong order of operands will negate the output)

    5. construct averaged transform matrix

      see transform matrix anatomy as origin you can use averaged origin of the measurement matrices