Browse Source

Merge pull request #1351 from tagcup/rot_fix

mhilbrunner 7 years ago
parent
commit
9332e20d01
1 changed files with 31 additions and 28 deletions
  1. 31 28
      tutorials/math/rotations.rst

+ 31 - 28
tutorials/math/rotations.rst

@@ -17,7 +17,7 @@ Lie groups is a branch of mathematics which deals with rotations in a systematic
 	:width: 400px
 	:align: center
 
-So let's start with small steps. Suppose that you want to make a really tiny rotation around some axis. For, concreteness let's say around  :math:`z`-axis by an infinitesimal angle :math:`\delta\theta`. For small angles, as illustrated in the figure, the rotation operator can be written as :math:`R_z(\delta\theta) = I + \delta \theta \boldsymbol e_z \times` (neglecting higher order terms :math:`\mathcal O(\delta\theta^2)` ) where :math:`I` is identity operator and :math:`e_z` is a unit vector along the :math:`z`-axis, such that a vector :math:`\boldsymbol v` becomes
+So let's start with small steps. Suppose that you want to make a really tiny rotation around some axis. For, concreteness let's say around  :math:`z`-axis by an infinitesimal angle :math:`\delta\theta`. For small angles, as illustrated in the figure, the rotation operator can be written as :math:`R_z(\delta\theta) = I + \delta \theta \boldsymbol e_z \times` (neglecting higher order terms :math:`\mathcal O(\delta\theta^2)` ) where :math:`I` is identity operator and :math:`\boldsymbol e_z` is a unit vector along the :math:`z`-axis, such that a vector :math:`\boldsymbol v` becomes
 
 .. math::
 
@@ -25,7 +25,7 @@ So let's start with small steps. Suppose that you want to make a really tiny rot
 
 (If this isn't clear, you can verify this by looking at the figure: :math:`\boldsymbol v` is rotated into :math:`\boldsymbol v'` in the plane (so the rotation axis :math:`\boldsymbol e_z` is pointing out of screen). The overlap of two vectors is :math:`\boldsymbol v \cdot \boldsymbol v' = v^2\cos\delta\theta \approx v^2 + \mathcal O(\delta\theta^2)` since the rotation is just a tiny amount, so the part of :math:`\boldsymbol v'` parallel to :math:`\boldsymbol v` is indeed :math:`\boldsymbol v`. Here, :math:`v = |\boldsymbol v|`. What about the perpendicular part, which must be :math:`\boldsymbol v' - \boldsymbol v`? Using the right-hand rule, the direction is :math:`\boldsymbol e_z \times \boldsymbol v/v`, and to the first order in :math:`\delta\theta`, we can approximate the length of the difference vector by the arc length (blue arc in the figure) which is :math:`\delta \theta v`, so the perpendicular component :math:`\delta \theta \boldsymbol e_z \times \boldsymbol v` also checks out.)
 
-Now, a practical way of representing operators is by using matrices (note that an operator is not a matrix, and there are different mathematical objects other than matrices which be used to represent operators, such as quaternions, a point which we will come back to later when we're discussing `representations <https://en.wikipedia.org/wiki/Group_representation>`_ . In terms of real :math:`3 \times 3` matrices, the identity operator :math:`I` simply corresponds to a :math:`3 \times 3` identity matrix, and the cross product :math:`\boldsymbol e_z \times` can be represented as
+Now, a practical way of representing operators is by using matrices (note that an `operator <https://en.wikipedia.org/wiki/Operator_(mathematics)>`_ is not a matrix, and there are different mathematical objects other than matrices which be used to represent operators, such as quaternions, a point which we will come back to later when we're discussing `representations <https://en.wikipedia.org/wiki/Group_representation>`_ . In terms of real :math:`3 \times 3` matrices, the identity operator :math:`I` simply corresponds to a :math:`3 \times 3` identity matrix, and the cross product :math:`\boldsymbol e_z \times` can be represented as
 
 .. math::
 
@@ -74,15 +74,15 @@ Or, if we did a rotation around an arbitrary axis :math:`\boldsymbol n`, the res
 where :math:`\boldsymbol J = (J_x, J_y, J_z)`.
 Note how the rotation axis :math:`\boldsymbol n` and rotation angle :math:`\theta` plays a central role in the final expression. Axis-angle is *the* parametrization for *all* Lie groups, not just 3D rotations. (We will come back to this point later when we're discussing Euler angle parametrization, which is an unnatural and defective parametrization of rotations in 3D.)
 
-If you ever tried to derive the rotation matrix corresponding to a :math:`\theta` rotation around :math:`\boldsymbol n`, you can appreciate the simplicity and elegance of we obtained this result. To be fair, we still need to figure out how to actually use an operator sitting on top of an exponent (by summing up the Taylor series), of course, but that's merely a "programmatic" labor and you just need to follow the finite multiplication table of :math:`J_i` operators. But this is much straightforward than trying to draw geometric diagrams and angles and figure out the rotation matrix. For the particular case of the algebra corresponding to rotations in 3D Euclidean space that we've been talking about so far, the exponent can simply be written as
+If you ever tried to derive the rotation matrix corresponding to a :math:`\theta` rotation around :math:`\boldsymbol n`, you can appreciate the simplicity and elegance of how we obtained this result. To be fair, we still need to figure out how to actually use an operator sitting on top of an exponent (by summing up the Taylor series), of course, but that's merely a "programmatic" labor and you just need to follow the finite multiplication table of :math:`J_i` operators. But this is much straightforward than trying to draw geometric diagrams and angles and figure out the rotation matrix. For the particular case of the algebra corresponding to rotations in 3D Euclidean space that we've been talking about so far, the exponent can simply be written as
 
 .. math::
 
 	R_n(\theta) = e^{\theta\boldsymbol n \cdot \boldsymbol J} = I + 2 \cos\frac{\theta}{2} \sin\frac{\theta}{2}(\boldsymbol n \cdot \boldsymbol J) + 2 \sin^2\frac{\theta}{2} (\boldsymbol n \cdot \boldsymbol J)^2
 
-which is known as Rodrigues' rotation formula. Note that we only ended up with terms up to second order in :math:`\boldsymbol n \cdot \boldsymbol J` when we summed the series expansion; the reason is higher powers can be reduce to 0th, 1st or 2nd order terms due to the relation :math:`(\boldsymbol n \cdot \boldsymbol J)^3 = -\boldsymbol n \cdot \boldsymbol J`, which makes summing up the series straightforward).
+which is known as Rodrigues' rotation formula. Note that we only ended up with terms up to second order in :math:`\boldsymbol n \cdot \boldsymbol J` when we summed the series expansion; the reason is higher powers can be reduced to 0th, 1st or 2nd order terms due to the relation :math:`(\boldsymbol n \cdot \boldsymbol J)^3 = -\boldsymbol n \cdot \boldsymbol J`, which makes summing up the series straightforward.
 
-The thing that sits son top of :math:`e`, which is a linear combination :math:`J_i` operators (where :math:`i = x,y,z`), forms an algebra; in fact, you it it a vector space with basis "vectors" as :math:`J_i`. Furthermore, the algebra is closed under the Lie bracket (which is essentially a commutator: :math:`[a,b] = a b - ba`, and is something like a cross-product in this vector space). In the particular case of 3D rotations, this "multiplication table" is :math:`[J_x, J_y] = J_z` and its cyclic permutations :math:`x\to y, y\to z, z\to x`.
+The thing that sits on top of :math:`e`, which is a linear combination :math:`J_i` operators (where :math:`i = x,y,z`), forms an algebra; in fact, it forms a vector space whose basis "vectors" are :math:`J_i`. Furthermore, the algebra is closed under the Lie bracket (which is essentially a commutator: :math:`[a,b] = a b - ba`, and is something like a cross-product in this vector space). In the particular case of 3D rotations, this "multiplication table" is :math:`[J_x, J_y] = J_z` and its cyclic permutations :math:`x\to y, y\to z, z\to x`.
 
 Rotations form what is called a `group <https://en.wikipedia.org/wiki/Group_(mathematics>`_: simply put, it means that if you combine two rotations, you get another rotation. And you can observe it here too: when you put an element of the Lie algebra (which are simply linear combinations of :math:`J_i` ) on top of :math:`e`, you get what is called a Lie group, and the Lie algebra is said to *generate* the Lie group. For example, the operator :math:`J_z \equiv \boldsymbol e_z \times` is said to *generate* the rotations around the :math:`z`-axis. The group of rotations in the 3D Euclidean space is called SO(3).
 
@@ -132,7 +132,7 @@ A point in the 2D Euclidean space can be represented by a pair of 2D real number
 
 So for example, when :math:`\theta=\pi/2`, we get :math:`R(\pi/2) \boldsymbol v = (-y,x)`.
 
-In the complex representation, a rotation is represented by  a unit complex number :math:`e^{\imath\theta} = \cos\theta + \imath \sin\theta`, where we used `Euler's formula <https://en.wikipedia.org/wiki/Euler%27s_formula>`_, is an element of the Lie group U(1), which can be represented by complex numbers of unit norm. Again, for :math:`\theta=\pi`, you recover :math:`e^{\imath\pi}(x+\imath y) = \imath(x+\imath y) = (-y) + \imath x`.
+In the complex representation, a rotation is represented by  a unit complex number :math:`e^{\imath\theta} = \cos\theta + \imath \sin\theta`, where we used `Euler's formula <https://en.wikipedia.org/wiki/Euler%27s_formula>`_, is an element of the Lie group U(1), which can be represented by complex numbers of unit norm. Again, for :math:`\theta=\pi/2`, you recover :math:`e^{\imath\pi/2}(x+\imath y) = \imath(x+\imath y) = (-y) + \imath x`.
 
 Rotations in the complex number representation look simpler, but it's only an illusion: the complications of performing a matrix multiplication is absorbed by the introduction of something that lives outside of the realm of real numbers, which follows a rather "odd" algebra: :math:`\imath^2 = -1`. The way complex numbers mimic 2D rotations can be made clearer if we rewrite the rotation matrix in terms of
 
@@ -197,7 +197,7 @@ In 2D, we considered vectors lying in the :math:`xy` plane, and the only axis we
 
 Just like the 2D rotation matrix, the 3D rotation matrix can also be derived with some effort by drawing lots of arrows and angles and some linear algebra, but this would be very opaque and won't give us much insight to what's really going on. A less straightforward, but more rewarding way of deriving this matrix is to understand the rotation group SO(3).
 
-SO(3) is the group of rotations in Euclidean 3D space (for which the signature is :math:`(+1,+1,+1)`), which preserve the magnitude and handedness of the vectors it acts on. The most typical way to represent its elements is to use :math:`3 \times 3` real orthogonal matrices with determinant :math:`+1`. This :math:`\text{Mat}(3, \mathbb R)` representation is called the fundamental representation of SO(3).
+SO(3) is the group of rotations in Euclidean 3D space (for which the `signature <https://en.wikipedia.org/wiki/Metric_signature>`_ is :math:`(+1,+1,+1)`), which preserve the magnitude and handedness of the vectors it acts on. The most typical way to represent its elements is to use :math:`3 \times 3` real orthogonal matrices with determinant :math:`+1`. This :math:`\text{Mat}(3, \mathbb R)` representation is called the fundamental representation of SO(3).
 
 To recap what we discussed earlier, SO(3) has 3 generators, :math:`J_x, J_y, J_z` and we found that they can be represented using these :math:`3\times 3` real matrices:
 
@@ -241,12 +241,12 @@ If you want, you can plug-in the matrix representations for :math:`J_i` and deri
 
 (Hint: you can use the relation :math:`(\boldsymbol n \cdot \boldsymbol J)^2 = \boldsymbol n \otimes \boldsymbol n-I` to quickly evaluate the last term in the Rodrigues' formula, where :math:`\otimes` is the `Kronecker product <https://en.wikipedia.org/wiki/Kronecker_product>`_ which is also called `outer product <https://en.wikipedia.org/wiki/Outer_product>`_ for vectors. Using the `half-angle formulae <https://en.wikipedia.org/wiki/List_of_trigonometric_identities#Half-angle_formulae>`_ to rewrite :math:`\sin\varphi = 2 \cos\frac{\varphi}{2} \sin\frac{\varphi}{2}`  and :math:`1-\cos\varphi = 2 \sin^2\frac{\varphi}{2}` in Rodrigues' formula, you can use cosine and sine terms as a visual aid when comparing to the matrix form.)
 
-However, we don't really *have to* use matrices to represent SO(3) generators :math:`J_i`. Remember how we used :math:`i`, the imaginary unit to emulate :math:`J_z` rather than using a :math:`2 \times 2` matrix? As it turns out we can do something similar here.
+However, we don't really *have to* use matrices to represent SO(3) generators :math:`J_i`. Remember how we used :math:`\imath`, the imaginary unit to emulate :math:`J_z` rather than using a :math:`2 \times 2` matrix? As it turns out we can do something similar here.
 
 `Hamilton <https://en.wikipedia.org/wiki/William_Rowan_Hamilton>`_ is mostly commonly known for the omnipresent `Hamiltonian <https://en.wikipedia.org/wiki/Hamiltonian_mechanics>`_ in physics. One of his less known contributions is essentially an alternative way of representing 3D cross product, which eventually gave in to popularity of usual vector `cross products <https://en.wikipedia.org/wiki/Cross_product#History>`_. He essentially realized that there are three different non-commuting rotations in 3D, and gave a name to the generator for each. He identified the operators :math:`\{\boldsymbol e_x \times, \boldsymbol e_y \times, \boldsymbol e_z \times\}` as the elements of an algebra, naming them as :math:`\{i,j,k\}`.
 
 This may sound trivial at this point, because we're equipped with all the machinery of Lie groups and Lie algebras: apparently, quaternion units :math:`\{i,j,k\}` are just another representation of the SO(3) generators, which satisfy the Lie bracket. Well, no so fast. While the Lie *algebra* :math:`\mathfrak{so}(3)`, whose elements are the linear combination of :math:`J_i`
-s, quaternions are :math:`1 w + x i + y j + z k` in general, so there's also an identity part, which isn't a vector that is a part of any Lie algebra. Quaternions look more like the *group* SO(3) (when they're normalized, because SO(3) preserves vector norms). But it actually isn't isomorphic to SO(3). It turns out that unit quaternions are isomorphic to the group SU(2) (which is isomorphic to Spin(3)), which is a double cover of SO(3).
+s are isomorphic to unit quaternions, but quaternions are :math:`1 w + x i + y j + z k` in general, so there's also an identity part, which isn't a vector that is a part of any Lie algebra. Quaternions look more like the *group* SO(3) (when they're normalized, because SO(3) preserves vector norms). But it actually isn't isomorphic to SO(3). It turns out that unit quaternions are isomorphic to the group SU(2) (which is isomorphic to Spin(3)), which in turn is a double cover of SO(3).
 
 SU(2) is essentially the group of unitary rotations with determinant +1 (called Special Unitary groups) which preserve the norm of complex vectors it acts on, generated by `Pauli spin matrices <https://en.wikipedia.org/wiki/Pauli_matrices>`_ :math:`\sigma_i`, and :math:`i,j,k` correspond to :math:`\sigma_x/\imath\ \sigma_y/\imath, \sigma_z/\imath`. To exemplify, :math:`R = e^{\varphi \boldsymbol n \cdot \boldsymbol J} \in \text{SO}(3)` rotates a real vector by :math:`R \boldsymbol v` and the corresponding rotation :math:`U = e^{-\imath\varphi \boldsymbol n \cdot \boldsymbol \sigma/2} \in \text{SU}(2)` rotates the same vector  through :math:`U (\boldsymbol v \cdot \boldsymbol \sigma) U^\dagger`. Note that :math:`U \to -U` achieves the same SO(3) rotation, SU(2) it's said to be a double cover of SO(3) (this is mapping gives the adjoint representation of SU(2) by the way). Here :math:`-\imath\boldsymbol \sigma = -\imath (\sigma_x, \sigma_y, \sigma_z) \cong (i,j,k)`.
 
@@ -255,11 +255,11 @@ SU(2) and SO(3) look the same locally (their tangent spaces dictated by their Li
 But taking a step back, why do we bother *emulating* SO(3) at all? For computational purposes, we already have something that works: the matrix representation. Why do we need to both with a weird group that isn't even exactly the same as SO(3)?
 
 
-The answer is the cost of computation, and this is two fold. First, you see, the matrix representation of a rotation has only 3 degrees of freedom: two for the unit vector which is the rotation axis, and one for the rotation angle around that axis. A :math:`3\times 3` matrix, on the other hand has 9 elements. It's an overkill. For example, whenever you multiply two rotations, you need to multiply two :math:`3\times 3` matrices, summing and multiplying every single element. In terms of CPU cycles, this is wasted effort and we can be more optimal. Second part is precision errors. The errors are worse in matrix representation, because originally, we have only 3 degrees of freedom,  which means we can have precision errors in axis and angle (only 3 errors) but it's still an element of SO(3), whereas with matrices, we can have errors in any one of the 9 elements in the matrix and so we can even have a matrix that isn't even an element of SO(3). These errors can quickly build up quickly especially if you're for example modifying the orientation of an object every frame by doing a smooth interpolation between an initial and a target orientation (discussed further in SLERP section).
+The answer is the cost of computation, and this is two fold. First, you see, a rotation operator has only 3 degrees of freedom: two for the unit vector which is the rotation axis, and one for the rotation angle around that axis. A :math:`3\times 3` matrix, on the other hand has 9 elements. It's an overkill. For example, whenever you multiply two rotations, you need to multiply two :math:`3\times 3` matrices, summing and multiplying every single element. In terms of CPU cycles, this is wasted effort and we can be more optimal. Second part is precision errors. The errors are worse in matrix representation, because originally, we have only 3 degrees of freedom,  which means we can have precision errors in axis and angle (only 3 errors) but it's still an element of SO(3), whereas with matrices, we can have errors in any one of the 9 elements in the matrix and so we can even have a matrix that isn't even an element of SO(3). These errors can quickly build up quickly especially if you're for example modifying the orientation of an object every frame by doing a smooth interpolation between an initial and a target orientation (discussed further in SLERP section).
 
 Sure, we know that elements of SO(3) can be represented by using orthogonal matrices with determinant +1 (hence the name Special Orthogonal) such that :math:`R R^T = I`; in plain language, this means the columns of :math:`R` form an orthonormal set of vectors, so we can eliminate the errors if we perform `Gram-Schmidt <https://en.wikipedia.org/wiki/Gram%E2%80%93Schmidt_process>`_ orthonormalization once in a while, and force it back into SO(3), such that it's an actual rotation matrix (albeit still noisy in axis and angle). But this is expensive and still quite bad in terms of errors.
 
-So, what is the alternative then? Shall we go back to the Rodrigues' formula and hardcode the behavior of :math:`J_i` into our program? A nicer alternative is, we use SU(2) (which we know covers SO(3), twice in fact!), because the equivalent of the Rodrigues' formula is much simple
+So, what is the alternative then? Shall we go back to the Rodrigues' formula and hardcode the behavior of :math:`J_i` into our program? A nicer alternative is, we use SU(2) (which we know covers SO(3), twice in fact!), because the equivalent of the Rodrigues' formula is much simpler:
 
 .. math::
 
@@ -303,9 +303,9 @@ Above, :math:`r,\theta,\phi` are spherical coordinates corresponding to :math:`x
 A note about the SU(2) vector
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
-We earlier mentioned that rotation of a real vector in SU(2) is done via :math:`(R \boldsymbol v) \cdot \boldsymbol \sigma = U (\boldsymbol v \cdot \boldsymbol \sigma) U^\dagger`, and you may be wondering what the complex vector  listed above :math:`|\psi\rangle = (\cos\frac{\theta}{2}, e^{\imath \phi} \sin\frac{\theta}{2})` has to do with that. The answer is, there vector :math:`|\psi\rangle` is the one :math:`U` acts on, and in terms of it, we can rewrite  :math:`U (\boldsymbol v \cdot \boldsymbol \sigma) U^\dagger` as :math:`r U (|\psi\rangle \otimes \langle \psi|) U^\dagger` up to some trivial identity term, where :math:`\langle \psi| = |\psi\rangle^\dagger` (this is the way complex vectors are typically denoted in quantum mechanics and is called `bra-ket notation <https://en.wikipedia.org/wiki/Bra%E2%80%93ket_notation>`_: bra is like the vector and ket is the `conjugate transpose <https://en.wikipedia.org/wiki/Hermitian_adjoint>`_, and people typically omit the :math:`\otimes`  in between because that's already implied when you multiply a ket with a bra, and likewise there is no :math:`\cdot` when you multiply a bra with ket since that's also implied).
+We earlier mentioned that rotation of a real vector in SU(2) is done via :math:`(R \boldsymbol v) \cdot \boldsymbol \sigma = U (\boldsymbol v \cdot \boldsymbol \sigma) U^\dagger`, and you may be wondering what the complex vector  listed above :math:`|\psi\rangle = (\cos\frac{\theta}{2}, e^{\imath \phi} \sin\frac{\theta}{2})` has to do with that. The answer is, there vector :math:`|\psi\rangle` is the one a single :math:`U` acts on, and in terms of it, we can rewrite  :math:`U (\boldsymbol v \cdot \boldsymbol \sigma) U^\dagger` as :math:`r U (|\psi\rangle \otimes \langle \psi|) U^\dagger` up to some trivial identity term, where :math:`\langle \psi| = |\psi\rangle^\dagger` (this is the way complex vectors are typically denoted in quantum mechanics and is called `bra-ket notation <https://en.wikipedia.org/wiki/Bra%E2%80%93ket_notation>`_: bra is like the vector and ket is the `conjugate transpose <https://en.wikipedia.org/wiki/Hermitian_adjoint>`_, and people typically omit the :math:`\otimes`  in between because that's already implied when you multiply a ket with a bra, and likewise there is no :math:`\cdot` when you multiply a bra with ket since that's also implied).
 
-So, notational concerns aside long story short, the vector listed above is in a generalized sense "half" of what we are rotating:
+So, notational concerns aside, long story short, the vector listed above is in a generalized sense "half" of what we are rotating:
 
 .. math::
 
@@ -337,14 +337,14 @@ For (embedded) 2D rotations in the :math:`xy`-plane, the rotation axis is taken
 In 3D, the rotation axis can be pointing toward any direction (since the axis is a unit vector, you can think of it as a point on the unit sphere, if you like).
 This way of parametrizing rotations is called axis-angle parametrization, and is the easiest to picture intuitively.
 
-Another advantage of the axis angle parametrization is, it is very easy to interpolate between two different rotations (let's call their parameters :math:`\boldsymbol n_1, \varphi_1` and :math:`\boldsymbol n_2, \varphi_2`), which is useful when you're changing the orientation of an object, starting from a given initial orientation and going toward a final one. A nice way of doing this turns out to be this: uniformly rotate the axis of rotation from the initial axis :math:`\boldsymbol n_1` onto the final one :math:`\boldsymbol n_2` (again, you can imagine that these two vectors represent two points on a sphere, and by doing this, you'd be travelling from the initial to the final point on the sphere using the shortest possible curve  --also called a geodesic), while also linearly interpolating the angle of rotation from the angle of initial rotation :math:`\varphi_1` to the angle of the final rotation :math:`\varphi_2`. If you image that :math:`\boldsymbol n_i` are points specified on the surface of a sphere, this is essentially a linear interpolation on a geodesic on the surface of the sphere connecting the two points. It results in a smooth motion, rather than a "jerky" motion which may start fast, go slow in the middle and go fast again etc. It turns out that if a mass is transported this way, it experiences the least amount of torque (compared to other possible trajectories). This way of linearly interpolating rotations in the axis-angle parametrization is called Spherical Linear Interpolation or SLERP, and is almost ubiquitously used in games.
+Another advantage of the axis angle parametrization is, it is very easy to interpolate between two different rotations (let's call their parameters :math:`\boldsymbol n_1, \varphi_1` and :math:`\boldsymbol n_2, \varphi_2`), which is useful when you're changing the orientation of an object, starting from a given initial orientation and going toward a final one. A nice way of doing this is described in a later section where we describe SLERP. It results in a smooth motion, rather than a "jerky" motion which may start fast, go slow in the middle and go fast again etc. It turns out that if a mass is transported this way, it experiences the least amount of torque (compared to other possible trajectories). This way of linearly interpolating rotations in the axis-angle parametrization is called Spherical Linear Interpolation or SLERP, and is almost ubiquitously used in games.
 
 
 
 Euler angles (and Tait-Bryan angles): :math:`(\varphi_1, \varphi_2, \varphi_3 )`
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
-Another way of parametrizing 3D rotations is by considering a sequence of 3 rotations around certain, fixed axes.
+Another way of parametrizing 3D rotations is by considering a sequence of at least 3 rotations around certain, fixed axes.
 This could be, for example "rotate around the :math:`Z`-axis by :math:`\varphi_1`, then rotate around the :math:`Y`-axis by :math:`\varphi_2`, and finally rotate around the :math:`x`-axis by :math:`\varphi_3`". Of course, these axes don't have to be Z, then Y, then X.
 As long as two sequential rotations are not around the same axis (in which case they would combine into a single rotation, hence reducing the number of actually independent parameters by 1), they can be anything.
 They don't even need to be aligned with any "named" axis. Another thing important think to watch out is, if you imagine that there is a local coordinate system "painted" on the object, as you go through the
@@ -362,7 +362,7 @@ All in all, despite being an ill-defined parametrization for rotations, Euler an
 
 While Euler angles may not be too useful when calculating the rotation operator (be it a matrix or a quaternion) in body dynamics, people still find them useful to think about and describe the *orientation* of 3D objects starting from the initial default *"unrotated"* state (it's very difficult to calculate the 3 Euler angles for driving an object from a non-trivial initial orientation to a non-trivial final orientation ---it can't be calculated intuitively in general, it is a task for computers). For this reason, Godot's property editor uses Euler angles (in extrinsic YXZ convention; if the node has a parent node, the YXZ axes refer to the local axes of the parent) for the rotation property of a Transform --this is pretty much the only place Euler angles are used in Godot.
 
-So the answer to the question "should I use Euler angles or axis-angle parametrization in my game" is: unless you're trying to orient an object in a particular way starting from an *unrotated, default orientation* (for which you can still use axis-angle parametrization in your script, if you prefer), you shouldn't be using Euler angles. Major reasons are:
+So the answer to the question "should I use Euler angles or axis-angle parametrization in my game" is: unless you're trying to *statically* orient an object in a particular way starting from an *unrotated, default orientation* (for which you can still use axis-angle parametrization in your script, if you prefer), you shouldn't be using Euler angles. Major reasons are:
 
 1. Jerky interpolations. You can't interpolate two orientations smoothly (torque-free) in a way that is reference independent (which doesn't depend on how you choose the 3 fixed rotation axes).
 2. Gimbal lock. Rotation dynamics (which includes interpolations) can get worse than jerky, you can get stuck in a weird coordinate singularity (the kind which doesn't exist in axis-angle parametrization) and never reach your target.
@@ -380,16 +380,17 @@ Imagine an ant walking on the surface of a donut illustrated below (image borrow
 
 If it keeps walking along either the red or the blue lines, it will eventually come back to where it started. At any time, we can use two angles to describe where the ant is: one angle (:math:`\theta` which goes between :math:`0` and :math:`2\pi`) describing it's position along the red line, and another one (:math:`\phi`, again between :math:`0` and :math:`2\pi`) for the blue line. And note that we have periodicity: :math:`(\theta,\phi)`  and :math:`(\theta + 2\pi N,\phi + 2\pi N)`  describe exactly the same point on the donut for an integer :math:`N`. We have two angles, of course, because we're talking about a two-dimensional surface. Now we're ready to talk about :math:`n`-dimensional surfaces.
 
-If you have a set of :math:`n` "coordinates" (or angles) which are periodic, just like :math:`\theta` and :math:`\phi` were, then people say those coordinates describe a point on the surface of an :math:`n`-torus. (In the case that the period of a "coordinate" is different than :math:`2\pi`, that coordinate can be scaled to make it so, such that it corresponds to an :math:`n`-torus).
+If you have a set of :math:`n` "coordinates" (or angles) which are periodic, just like :math:`\theta` and :math:`\phi` were (which is the case for the three Euler angles), then people say those coordinates describe a point on the surface of an :math:`n`-torus. (In the case that the period of a "coordinate" is different than :math:`2\pi`, that coordinate can be scaled to make it so, such that it corresponds to an :math:`n`-torus).
 
 Now, back to our original issue. The axis of the axis-angle parametrization (which is *the* natural way of parametrizing rotations, and is a one-to-one covering map of SO(3); in fact, this is true for all Lie groups, not just rotations in 3D) spans a sphere (every point in a ball of radius :math:`\pi` corresponds to a rotation in SO(3) where the rotation amount is mapped to radius and rotation axis points is the direction from the origin; with the additional caveat that if you flip the sign of the axis and angle simultaneously, it maps to the same rotation), which is described using spherical coordinates, whereas Euler angles span the surface of a 3-torus (such that every point on the 3-torus corresponds to a rotation), which is described by the three Euler angles.
 The problem here is, a sphere is topologically different from a torus.
-In simple terms, this means that it's impossible to deform a sphere to a torus "smoothly": at some point, you have to punch a hole in it to make a donut from a ball.
+In simple terms, this means that it's impossible to deform a sphere to a torus "smoothly": at some point, you have to punch a hole in it to make a donut from a ball (and you can never "punch a hole" or change the topology when you stick with a parametrization: if you use Euler angles, you're forever stuck walking the surface of a 3-donut, and if you use axis-angle, you're forever stuck flying inside the sphere).
 
 Why is this a problem at all?
-Because it means that you a smooth walk (flight?) inside the sphere doesn't always correspond to a smooth walk on the surface of the 3-torus, vice versa: a 3-torus and sphere are globally different, which is a fact you're bound to discover if you walk the parameter space.
-Axis-angle parametrization has singularities in the poles (the azimuthal angle is-ill defined) but that's fine because that's exactly how SO(3) is, after all, axis-angle is how Lie groups are parametrized. Euler angle parametrization also has singularities corresponding to points when two gimbals are aligned, but those singularities are different from SO(3)'s poles.
+Because it means that a smooth walk (flight?) inside the sphere doesn't always correspond to a smooth walk on the surface of the 3-torus, vice versa: a 3-torus and sphere are globally different, which is a fact you're bound to discover if you walk the parameter space by a smoothly rotating a body using these parametrizations.
+Axis-angle parametrization has singularities at the poles (where the azimuthal angle is ill-defined) but that's fine because that's exactly how SO(3) is, after all, axis-angle is how Lie groups are parametrized. Euler angle parametrization also has singularities corresponding to points where two gimbals are aligned, but those singularities are different from SO(3)'s poles.
 
+Suppose that you're at a nice spot, a rotation that can be parametrized by both axis-angle and Euler angles uniquely. Sometimes, it can just happen that if you take a wrong step, you'll fall into a "hole" (meaning a singularity at which infinitely many parameters correspond to the same rotation, like at the poles, all choices for the azimuthal angle give the same rotation, or the similar situation with gimbal lock) in one parametrization, while you can continue a smooth journey in the other parametrization. When you fall a "hole" using Euler angles, it's called gimbal lock, and since there may not be a corresponding "hole" when you take the similar step in the sphere, this tells us that Euler angles is a defective parametrization of SO(3).
 
 The root of the problem isn't just the fact that Euler angle parametrization has singularties, just as axis-angle does which is fine on its own, but that those singularities don't match with SO(3)'s singularities.
 
@@ -413,7 +414,7 @@ Summary: representation versus parametrization
 We can sum it up in a table:
 
 +-------------------------------+----------------------------------------------------------------+-----------------------------------------------------------------+
-|Parametrization/Representation | Matrix                                                         | Quaternion                                                      |
+|Parametrization/Representation | Matrix representation of SO(3)                                 | Quaternion representation of SU(2)                              |
 +===============================+================================================================+=================================================================+
 |Axis-angle                     | :math:`e^{\varphi \boldsymbol v \cdot \boldsymbol J}`          | :math:`e^{\varphi \boldsymbol v \cdot (i,j,k)/2}`               |
 +-------------------------------+----------------------------------------------------------------+-----------------------------------------------------------------+
@@ -422,17 +423,17 @@ We can sum it up in a table:
 
 where :math:`\boldsymbol J`  denotes the matrix representation of the :math:`\boldsymbol J` operators (too lazy to introduce a new symbol for that). YXZ Euler angles is chosen for concreteness (as it is the default convention in Godot), and can be replaced by any three axes (as long as two neighboring axes aren't the same).
 
-In each case, Rodrigues' formula (or it's analogue for quaternions) given above can be used for practical purposes.
+In all cases listed in the above table, Rodrigues' formula (or it's analogue for quaternions) given above can be used for practical purposes.
 
-In the context of 3D rotations, one representation isn't superior or inferior to another. Whatever representation you're using, you are representing exactly the same thing. A difference appears only when you implement it on a computer: different representations have trade offs when it comes to precision errors, CPU cycles and memory usage (for example, accessing to rotation axis-angle with quaternions is trivial but requires some algebra in matrix representation whereas the converse is true when accessing the basis vectors, SLERP, composition of rotations and orthonormalization is faster with quaternions but a conversion to matrix representation, which isn't free, is always required because that's the representation OpenGL uses and rotating a vector), and they may have different characteristics when doing finite precision arithmetic with floating point numbers. In principle, you can do everything you do with quaternions using matrices, vice versa. The performance could be bad in one representation, but the point is, there is nothing in their mathematics that prevent you from doing that.
+In the context of 3D rotations, one representation isn't superior or inferior to another. Whatever representation you're using, you are representing exactly the same thing. A difference appears only when you implement it on a computer: different representations have trade offs when it comes to precision errors, CPU cycles and memory usage (for example, accessing to rotation axis-angle with quaternions is trivial but requires some algebra in matrix representation whereas the converse is true when accessing the basis vectors, SLERP, composition of rotations and orthonormalization is faster with quaternions but a conversion to matrix representation, which isn't free, is always required because that's the representation OpenGL uses and rotating a 3D vector is faster in matrix representation since they are written in the same basis), and they may have different characteristics when doing finite precision arithmetic with floating point numbers. In principle, you can do everything you do with quaternions using matrices, vice versa. The performance could be bad in one representation, but the point is, there is nothing in their mathematics that prevent you from doing that.
 
-Parametrizations, on the other hand, are vastly different. Axis-angle is the "one true" parametrization of rotations. Euler angles, despite being a defective parametrization of rotations, could be more intuitive for simple (involving only 1 or 2 angles)  and *static* situations like orienting a body/vehicle in the editor, but should be avoided for rotational *dynamics* which would eventually lead to a gimbal lock
+Parametrizations, on the other hand, are vastly different. Axis-angle is the "one true" parametrization of rotations. Euler angles, despite being a defective parametrization of rotations, could be more intuitive for simple (involving only 1 or 2 angles)  and *static* situations like orienting a body/vehicle in the editor, but should be avoided for rotational *dynamics* which would eventually lead to a gimbal lock.
 
 
 Interpolating rotations
 -----------------------
 
-In games, it's common problem to interpolate between two different orientation in a "nice way" which doesn't depend on arbitrary things like how the reference frame, and which doesn't result in a jerky motion such that the angular speed remains constant during the interpolation. These are the properties that we seek when we say "nice".
+In games, it's common problem to interpolate between two different orientation in a "nice way" which doesn't depend on arbitrary things like how the reference frame, and which doesn't result in a "jerky" motion (that is, a torque-free motion) such that the angular speed remains constant during the interpolation. These are the properties that we seek when we say "nice".
 
 Formally, we'd like to interpolate between an initial rotation :math:`R_1 = e^{\lambda \varphi_1 \boldsymbol n_1 \cdot \boldsymbol J }` and a final one :math:`R_2 = e^{\varphi_2 \boldsymbol n \cdot \boldsymbol J }` a function of time, and what we're seeking is something that transforms one into another smoothly, :math:`R(\lambda)`, where :math:`\lambda` is the normalized time which is 0 at the beginning and 1 at the end. Clearly, we must have :math:`R(\lambda=0)=R_1` and :math:`R(\lambda=1) = R_2`. Since we also know that rotations form a group, we can relate :math:`R(\lambda)` to :math:`R_1` and :math:`R_2` using another rotation, such that we can for example write
 
@@ -465,7 +466,7 @@ or isomorphically, in terms of quaternions:
 
 For any Lie group, including SO(3) and SU(2), this "nice" interpolation is called SLERP.
 
-Note that at no step we made any reference to axes of some fixed reference frame (as it is in the case of Euler angle parametrization), everything we did is independent of the reference frame. Also note that this scheme can work for any Lie group, and is independent of the representation used (matrix, quaternion, ...).
+Note that at no step we made any reference to axes of some fixed reference frame (as it is in the case of Euler angle parametrization, which are defined with respect to certain "special" 3 axes), everything we did is independent of the reference frame. Also note that this scheme can work for any Lie group, and is independent of the representation used (matrix, quaternion, ...).
 
 After some tedious algebra (which involves using :math:`\text{tr}(\sigma_i \sigma_j) = 2 \delta_{ij}`), this result can be simplified to
 
@@ -486,7 +487,7 @@ Consider a ship in the ocean. You can imagine, however that there's a coordinate
 
 The global coordinate system corresponds to a coordinate system world painted somewhere on the ground in the world (let's say we live in a flat world for simplicity). Then every object, including the ship and the passengers have their own reference frames, they're called object-local frames. But notice that for passengers, the most natural frame would be where they are located (and how they're oriented) relative to the ship. After all, when someone asks "Where's Joe?", you'd reply with something like "I saw him in the front deck" rather than trying to look up GPS coordinates (global frame) or saying something like "7 meters to my five o'clock" (passenger/object-local). The ship is referred to as the parent-local frame.
 
-In Godot, Basis matrices refer to the parent-local frame. It the object is top level, then it's Basis is written in the global frame.
+In Godot, Basis matrices refer to the parent-local frame. If the object is top level, then it's Basis is written in the global frame.
 
 
 
@@ -508,7 +509,7 @@ You can also transform the matrix representations of operators. For example, :ma
 
 	M' = R_n(\varphi) M R_n^T(\varphi).
 
-These are called passive transformation.
+These are called passive transformations.
 
 Now let's consider actually moving those objects (we consider only one reference frame and it's fixed). We rotate a vector around some :math:`\boldsymbol n` axis by :math:`\varphi`
 
@@ -523,6 +524,8 @@ Similarly, for matrices
 
 	M' = R_n(\varphi) M R_n^T(\varphi).
 
+These are called active transformations.
+
 
 Note how things fit nicely, for example, when you consider how a rotated vector :math:`R_0 \boldsymbol v_0` transforms: