I am trying to track the rotation of a sphere by tracking surface features on the sphere.
TL;DR: Am I wrong averaging quaternions?
Introduction
Let's skip over the feature detection and matching, it's just ORB+FLANN from OpenCV. This gives me two sets of (matched) keypoints for two successive frames.
I project the keypoints into 3d by placing them on the sphere according to their distance to the spheres center 1. This gives me the keypoints in the spheres coordinate system.
(never mind the big vectors for now)
From the matched keypoints as vectors I calculate a set of quaternions that represent the rotation since the last frame (algorithm used).
a = np.cross(v1,v2)
w = np.sqrt(np.linalg.norm(v1)**2 * np.linalg.norm(v2)**2) + np.dot(v1,v2)
return quaternion(w, a[0], a[1], a[2]).normalized()
Problem
So at this point my idea is that all of those quaternions represent the same rotation (plus/minus noise). So in theory I should be able to calculate the mean quaternion of my quaternion set and have a good idea of how my sphere moved since the last frame (algorithm used).
np.linalg.eig(np.mean(np.array([np.outer(q,q) for q in quats]), axis=0))[0]
Thing is that this results in unit quaternions for all frames (or close by, like e^-06 close):
quaternion(0.999999999865224, -4.24742027709118e-06, 1.4799762763963e-05, 5.69900765792268e-06)
("naive" averaging over all quaternions actually produces a results that kind of looks like it might fit with the original rotation, but I would rather use a proven method)
So, I have two theories:
- Having several thousand quaternions in this leads to catastrophic cancellation in the summation and eigen vector calculations. Or, (more probable):
- I have an error in my thinking.
Thoughts?
1 I am aware that I have to deal with the cameras projection, but for a proof of concept I chose to ignore that.