The Karcher/Fréchet mean algorithm can be used, which for quaternions boils down to:
# initial guesscurr = Quat.identity()while True: # linearize samples at current guess and average mu = sum((curr.conjugate() * q).log() for q in qs) / len(qs) # convergence check if mu.norm() < eps: return curr # improve guess curr = curr * Quat.exp(mu)
where log/exp
are the quaternion logarithm/exponential.
If you can convert between rotation vectors (where the direction is the rotation axis and the magnitude is the angle) and quaternions you can use that as the exponential, and the logarithm is the reverse operation (both modulo a factor 2 that cancels out).
The above weighting scheme is uniform but other convex combinations can be used instead.