I am definitely not qualified to be discussing the topic of geometric algebra.
This post is likely to have mistakes, but it has been incredibly useful for
improving my understanding on things that previously felt disconnected,
unintuitive and full of exceptions. I am aware that geometric algebra is a
Clifford algebra which dates back to the 1800s, but the framing is valuable for
me. Throughout this post, I am able to derive and build up a construct which
allows me to perform rotations in 3D. Quaternions, on the other hand, are
significantly more complicated to understand and derive (from my perspective).
This post is not unique, but actually just documents the order in which I was
able to understand and derive this. You can jump straight to the references at
the bottom of this post which take a number of different approaches. This
mostly serves as a reference for myself.
Wait, it’s just multiplication?
Firstly, we begin with a simple definition (we define this, it is not some
universal truth1) for any vector, v:
v2=∥v∥2
Simply, this new product of a vector with itself gives us the magnitude of that
vector squared. Next, we’re going to multiply two vectors a and
b. We’ll use x^, y^ and z^ as our basis
vectors – you may see these represented as i^, j^, and
k^ or even e1^, e2^, and e3^, elsewhere.
We could easily eliminate the basis vectors multiplied by themselves with our
definition from the beginning as we know that they have magnitude one (i.e.
x^2=∥x^∥2=12=1). We’ve also managed to pull the dot
product out of the result. However, we’re now stuck with these products of two
orthogonal bases. Let’s see how far we can get without reducing these values
but rather treating them as their own new unique type, we’ll call them
“bivectors”. You can think of them as oriented planes. Moving forward, I may
choose to annotate x^x^ as xx.
We don’t have enough tricks to reduce this just yet, so let’s see what we can do
with these bases. Let’s take x^ and y^:
That’s a useful result. We know that our basis bivectors anti-commute! We’ll
use the bivectors yz, zx, and xy.
zx is flipped so that the cross product of the vectors that make
up the basis bivector points in the positive direction of another basis
vector2. You can think of these as planes in the corresponding axes oriented
in the direction of the axis that is not involved. So, yz exists
in the yz-plane and it points in the direction of the positive x-axis.
So, continuing with the geoemtric product from above:
We pulled out a new product called the wedge (∧) product, but you may
have noticed that its components are the same as the cross product! The wedge
product represents a bivector, which corresponds to an oriented plane. The cross
product represents the vector which is perpendicular to its inputs. That
essentially encodes the same detail, but allows for the wedge product to exist
in any number of dimensions. The cross product doesn’t exist in 2D, for example.
The result of this geometric product corresponds to a rotor, which is similar
but not identical to a quaternion. A quaternion focus on the rotation axis, or
the normal to the bivector plane.
R=realrw+bivectorryzyz+rzxzx+rxyxy
This differs from the common interpretation of using the three imaginary
components i, j, and k as seen in quaternions.
A Complex Detour
If you apply the geometric product to two 2D vectors, you’ll arrive at the following:
To convince you, let’s multiply this number (as a scalar and bivector) with a
bivector that represents a rotation by 90°. Typically, this just
means multiplying by i, but for us it means multiplying by
xy.
Same result, but not a −1 in sight! While I’m not opposed to the use
of −1, it does feel like an unnecessary reduction. Treating these as
a standalone type with the anti-commutative property gives us the same result,
without breaking the rules of real numbers.
Back to Rotors
Inverse of a vector
All vectors have an inverse. We can determine this under the geometric product.
Given a vector v and a potential inverse, v′=∥v∥2v, we have:
Now, given the above, we can represent a vector, a, as the components of
another vector, b.
a=abb−1=∥b2∥1(ab)b=∥b2∥a⋅bb+∥b2∥a∧bb
It turns out that this is equivalent to:
a=a∥b+a⊥b
Since the dot product is greatest when the two vectors are parallel, and the
wedge product (similar to the cross product) is greatest when the two vectors
are perpendicular.
Reflections
In a previous post,
we showed that a reflection v′ of a vector v can be represented as:
v′=v⊥−v∥
However, that was for a physical representation of a ray reflecting off of a
surface represented by its normal. The definition for a reflection about a
vector is given as:
v′=v∥−v⊥
So, for two vectors a and v, we can write the reflection as:
This is referred to as the sandwich product. We see it outputs a vector,
which is a valuable insight as we move towards a derivation for rotation.
Rotations
We can perform a rotation by performing two consecutive reflections, as seen
below, from v→v′→v′′. First by a and then by
b.
This works in 3D too. You can imagine that a reflection would “invert” an
image, so another reflection would remove that inversion. We get to keep the
side-effect that is the rotation, however.
Since we defined our reflection in terms of the sandwich product, it means we
can define rotations in terms of two applications of the sandwich product! You
may have noticed the one deficiency is that the angle between a and
b is θ, but the rotation of the original vector,
v, is double that. In a practical implementation, you may want to
correct the angles in advance, so that when constructing a rotor as the
geometric product of two vectors, you pick a vector halfway between them and
then multiply them. This gives us an object in which the rotation always
represents exactly the angle between the two input vectors.
Since we will often want to hold onto a rotor instead of the two vectors that
represent the orientation, we can calculate the sandwich product directly.
First, we define the rotor and vector, respectively:
We get our first trivector in xyz, which represents an oriented
volume, however we’ll see this is quickly resolved in the rest of the proof.
Moving on, we’ll define the following:
Rv=L=lxx^+lyy^+lzz^+lxyzxyz
We know that we’re trying to perform two applications of some vectors,
a and b, respectively. So, we are really looking for
(ba)v(ba)−1.
From some of the previous definitions, we can show the following:
RvR−1====(ba)v(ba)−1(ba)v(a−1b−1)∥a∥∥b∥1(ba)v(ab)∥a∥∥b∥1L(ab)(notice the two sandwich products)
ab is the result of commuting ba, so we could
imagine this means that since the dot product commutes and the wedge product
anti-commutes that this means the following is true
ab=rw−ryzyz−rzxzx−rxyxy
You can verify this more formally by flipping the vectors in the Multiplying
Rotors section below. So, we have:
Finally, it can be shown that the trivector is zero by substituting in the components of L and simplifying. If we do this, and assume that our rotor is made of two vectors of unit length, then we have our final vector, v′, as:
It can be substituted further, but we can stop here, as there is no further
simplification of the type. We have produced a vector.
Rotor to matrix
Rotors represent a rotation, not an orientation, but we can build up a matrix
which represents a change of
basis to feed
into some transformation matrix3. So, assuming we have the basis vectors
i^, j^ and k^, as well as a rotor R, we can
calculate the rotation matrix, M, as:
You can calculate the sandwich product once per basis vector. You can even take
it a step further and calculate the z-axis column as the cross product of
the first two to reduce some of the computation involved.
Multiplying rotors
For two rotors, A and B, we can derive their product. Note that this is
just the same application as for the 2D case at the start, there’s just a lot
more algebra. This is useful for the composition of rotors, which may be useful
for some applications.
AB====(aw+ayzyz+azxzx+axyxy)(bw+byzyz+bzxzx+bxyxy)awbw+awbyzyz+awbzxzx+awbxyxy+bwayzyz+bwazxzx+bwaxyxy+ayzbyzyzyz+ayzbzxyzzx+ayzbxyyzxy+azxbyzzxyz+azxbzxzxzx+azxbxyzxxy+axybyzxyyz+axybzxxyzx+axybxyxyxyawbw+awbyzyz+awbzxzx+awbxyxy+bwayzyz+bwazxzx+bwaxyxy−ayzbyz−ayzbzxxy+ayzbxyzx+azxbyzxy−azxbzx−azxbxyyz−axybyzzx+axybzxyz−axybxyawbw−aB⋅bB+(awbyz+bwayz−azxbxy+axybzx)yz+(awbzx+bwazx+ayzbxy−axybyz)zx+(awbxy+bwaxy−ayzbzx+azxbyz)xy(with aB and bB made up of the bivector components of the rotors)
This is like the Hamilton
product,
except the signs of the last two coefficients for each basis is flipped. I
assume it’s because they’re isomorphic, but not identical objects.
Rotor from plane-angle
Quaternions represent an axis-angle, but for rotors we consider the bivector
plane and an angle, so I’ve personally dubbed this the “plane-angle”
representation.
Firstly, we have to recall the following equations from their definition:
a⋅b∥a×b∥=∥a∥∥b∥cosθ=∥a∥∥b∥sinθ
And with a bit of a leap of faith, we’ll assume that
You’ll note that the last bivector component represents a unit bivector (or
plane), B, instead of an oriented vector. Additionally, assuming
a and b are unit vectors, we have ∥a∥∥b∥=1. Given
this, and the fact that rotors produce a rotation that is twice the angle
between the two vectors that make up the rotor, we can summarize this equation
as:
R=cos2θ+sin2θB
Links
The following links were referenced before and while I made this post. I tried
to tackle it in the direction that made most sense to me, but each of these are
invaluable resources for the intuition and understanding of geometric algebra.
An incredible aid for the approach to the algebra concerning the sandwich product in this post. I was stumped for a few sections, and this helped me through it. There are a bunch more proofs and applications in this post for those interested.