Thursday, December 29, 2022

The quaternion

I had occasion to transform an angle recently. This to find the velocity of a body on Kepler's ellipse. Therefore: the unit tangent, multiplied by vis-viva. If I'm pretty sure that the body is at, let's orient it like a computer clockwise, {-1, 0} and that the eccentricity is zero then I should be looking at {0, -1}. So {y,x} right? But {0,1} behind it slides into {-1,0}. That's {-y,x}; this defines the right-angle transform. Obviously orienting the page so that y increments upward doesn't change this.

What has happened is matrix-multiplication. Luckily 90° is easy. For anything else, unless I am certain of my x,y quadrant: a lot of sin-theta awaits. Luckily, computer-science has resurrected one of Sir William Rowan Hamilton's less-favoured mechanics - the Quaternion.

As of the early 1990s pure mathematicians (like me, then) used vector analysis. At some point, though, I'd caught wind from the comp-sci department that we weren't quite done with Hamilton. I'd even seen a book about quaternions in 2010ish - but I didn't pick it up. Now, 'tis time, with the System.Numerics Vector3.

What we do is to define our transform, Quaternion.CreateFromAxisAngle(Vector3.UnitZ, (float)Math.PI / 2F) for the right-angle in radians. Vector3.Normalize(Vector3.Transform(xy, TurnwiseRightAngle)) will get the job done, returning a unit angle of velocity to which I'll apply my speed.

TurnwiseRightAngle looks like a unit-z vector, with a similarly-unit floating point "w" which represents the angle. Although w is not the angle; it's 0.707. Square-root of one half; the cosine (and sine) of the right-triangle. It turns out that the "unit-z" was 0.707 too. Do I know why?

I don't know if I care. I got some small floating-point deviations. new Quaternion(Vector3.UnitZ, 1) * (float)Math.Sqrt(.5) will do for a quicker TurnwiseRightAngle. C# doesn't let this be commutative; there's no overload in case I want this in reverse. Oh and I got errors here too. Probably due to the usual CPU follies.

Anyway as noted all I needed today was {-y,x} which doesn't introduce errors. At least we have this lore in case I need it later. Like .CreateFromAxisAngle(Vector3.UnitZ, (float)Math.PI / 6F).

No comments:

Post a Comment