Chapter 9: Coordinate Frames and Spatial Representation (Intro Only)

Lesson 3: Rotations and Translations as Concepts

In robotics, describing “where things are” and “how they are oriented” is impossible without two primitive geometric notions: rotations and translations. This lesson formalizes them as mappings between coordinate frames, proves their key properties, and shows how they combine into rigid-body motions. We stay at an introductory mathematical level and avoid homogeneous-transform derivations (reserved for Lesson 4).

1. Conceptual Overview

Recall from Lessons 1–2 that a coordinate frame is an origin plus three orthonormal axes. If a point has coordinates \( \mathbf{x}^A \in \mathbb{R}^3 \) in frame A, and \( \mathbf{x}^B \in \mathbb{R}^3 \) in frame B, then the change of coordinates between the frames is always a combination of:

  • Rotation: changes orientation of axes.
  • Translation: changes origin location.

The generic rigid relation is:

\[ \mathbf{x}^B = \mathbf{R}_{BA}\,\mathbf{x}^A + \mathbf{p}_{BA}, \quad \mathbf{R}_{BA}\in \mathbb{R}^{3\times 3},\ \mathbf{p}_{BA}\in \mathbb{R}^3. \]

Here \( \mathbf{R}_{BA} \) encodes the rotation from A to B, and \( \mathbf{p}_{BA} \) is the translation vector from the origin of B to the origin of A, expressed in B.

flowchart TD
  A["Point coords in frame A: x^A"] --> B["Rotate axes or point"]
  B --> C["Apply rotation matrix R_BA"]
  C --> D["Translate origin by p_BA"]
  D --> E["Point coords in frame B: x^B"]
  

2. Rotations as Linear Maps

A rotation in 3D is a distance- and angle-preserving linear transformation. Mathematically, rotation matrices form the special orthogonal group:

\[ SO(3)=\left\{\mathbf{R}\in\mathbb{R}^{3\times 3}\ \middle|\ \mathbf{R}^\top\mathbf{R}=\mathbf{I},\ \det(\mathbf{R})=1\right\}. \]

2.1 Orthonormality and Length Preservation

Let \( \mathbf{y}=\mathbf{R}\mathbf{x} \) with \( \mathbf{R}\in SO(3) \). Then

\[ \|\mathbf{y}\|^2 = \mathbf{y}^\top\mathbf{y} = (\mathbf{R}\mathbf{x})^\top(\mathbf{R}\mathbf{x}) = \mathbf{x}^\top\mathbf{R}^\top\mathbf{R}\mathbf{x} = \mathbf{x}^\top\mathbf{I}\mathbf{x} = \|\mathbf{x}\|^2. \]

Therefore rotations preserve Euclidean length and thus distances between points.

2.2 Angle Preservation

Using the dot product identity \( \mathbf{a}^\top\mathbf{b}=\|\mathbf{a}\|\,\|\mathbf{b}\|\cos\theta \), for any two vectors \( \mathbf{u},\mathbf{v} \):

\[ (\mathbf{R}\mathbf{u})^\top(\mathbf{R}\mathbf{v}) = \mathbf{u}^\top\mathbf{R}^\top\mathbf{R}\mathbf{v} = \mathbf{u}^\top\mathbf{v}. \]

Since lengths are also preserved, the cosine of the angle between \( \mathbf{u} \) and \( \mathbf{v} \) is unchanged. Hence angles are preserved.

2.3 Right-Handedness and Determinant

The condition \( \det(\mathbf{R})=1 \) excludes reflections. If a matrix is orthonormal with determinant \( -1 \), it flips handedness and is not a physical rotation in robotics.

2.4 Example: Axis Rotations

Rotations about the coordinate axes by angle \( \theta \) (right-hand rule) are:

\[ \mathbf{R}_x(\theta)= \begin{bmatrix} 1 & 0 & 0\\ 0 & \cos\theta & -\sin\theta\\ 0 & \sin\theta & \cos\theta \end{bmatrix},\quad \mathbf{R}_y(\theta)= \begin{bmatrix} \cos\theta & 0 & \sin\theta\\ 0 & 1 & 0\\ -\sin\theta & 0 & \cos\theta \end{bmatrix}, \]

\[ \mathbf{R}_z(\theta)= \begin{bmatrix} \cos\theta & -\sin\theta & 0\\ \sin\theta & \cos\theta & 0\\ 0 & 0 & 1 \end{bmatrix}. \]

2.5 Non-Commutativity (Important!)

In 3D, rotations generally do not commute: \( \mathbf{R}_1\mathbf{R}_2 \neq \mathbf{R}_2\mathbf{R}_1 \). A concrete proof uses a counterexample.

Proof (by counterexample): Let \( \mathbf{R}_1=\mathbf{R}_x(\frac{\pi}{2}) \) and \( \mathbf{R}_2=\mathbf{R}_y(\frac{\pi}{2}) \). Apply to the vector \( \mathbf{e}_z=[0,0,1]^\top \):

\[ \mathbf{R}_2\mathbf{e}_z = \mathbf{e}_x,\quad \mathbf{R}_1(\mathbf{R}_2\mathbf{e}_z)=\mathbf{R}_1\mathbf{e}_x=\mathbf{e}_x. \]

\[ \mathbf{R}_1\mathbf{e}_z = \mathbf{e}_y,\quad \mathbf{R}_2(\mathbf{R}_1\mathbf{e}_z)=\mathbf{R}_2\mathbf{e}_y=\mathbf{e}_y. \]

Since \( \mathbf{e}_x \neq \mathbf{e}_y \), the compositions differ, proving non-commutativity.

3. Translations as Affine Maps

A translation shifts all points by a fixed vector \( \mathbf{p}\in\mathbb{R}^3 \):

\[ T_{\mathbf{p}}:\ \mathbf{x}\mapsto \mathbf{x}+\mathbf{p}. \]

3.1 Properties

  • Additivity: \( T_{\mathbf{p}_1}\circ T_{\mathbf{p}_2} = T_{\mathbf{p}_1+\mathbf{p}_2} \).
  • Commutativity: \( T_{\mathbf{p}_1}\circ T_{\mathbf{p}_2} = T_{\mathbf{p}_2}\circ T_{\mathbf{p}_1} \).
  • Inverse: \( T_{\mathbf{p}}^{-1}=T_{-\mathbf{p}} \).

Proof of commutativity:

\[ T_{\mathbf{p}_1}(T_{\mathbf{p}_2}(\mathbf{x})) = (\mathbf{x}+\mathbf{p}_2)+\mathbf{p}_1 = \mathbf{x}+(\mathbf{p}_1+\mathbf{p}_2) = T_{\mathbf{p}_2}(T_{\mathbf{p}_1}(\mathbf{x})). \]

3.2 Why Translations Are Not Linear

A linear map must satisfy \( f(\mathbf{0})=\mathbf{0} \). But for a translation:

\[ T_{\mathbf{p}}(\mathbf{0})=\mathbf{p}\neq \mathbf{0}\ \text{unless }\mathbf{p}=\mathbf{0}. \]

Thus translations are affine transformations, not linear ones. This is why combining rotations and translations cleanly motivates homogeneous coordinates later (Lesson 4).

4. Rigid-Body Motions

A rigid-body motion keeps internal distances fixed. The most general rigid motion between two frames is:

\[ \mathbf{x}^B = \mathbf{R}_{BA}\mathbf{x}^A + \mathbf{p}_{BA}. \]

We interpret this in two equivalent ways:

  1. Passive view (change of basis): the physical point stays fixed, the coordinates change because the frame B is rotated/translated w.r.t. A.
  2. Active view (move the point): the frame stays fixed, the point is rotated/translated in space.

4.1 Composition Rule

Suppose frame A to B uses \( (\mathbf{R}_{BA},\mathbf{p}_{BA}) \), and B to C uses \( (\mathbf{R}_{CB},\mathbf{p}_{CB}) \). Then A to C is:

\[ \mathbf{R}_{CA}=\mathbf{R}_{CB}\mathbf{R}_{BA},\quad \mathbf{p}_{CA}=\mathbf{R}_{CB}\mathbf{p}_{BA}+\mathbf{p}_{CB}. \]

Proof:

\[ \mathbf{x}^C = \mathbf{R}_{CB}\mathbf{x}^B + \mathbf{p}_{CB} = \mathbf{R}_{CB}(\mathbf{R}_{BA}\mathbf{x}^A + \mathbf{p}_{BA}) + \mathbf{p}_{CB} = (\mathbf{R}_{CB}\mathbf{R}_{BA})\mathbf{x}^A + (\mathbf{R}_{CB}\mathbf{p}_{BA}+\mathbf{p}_{CB}). \]

4.2 Inverse Motion

From \( \mathbf{x}^B = \mathbf{R}_{BA}\mathbf{x}^A + \mathbf{p}_{BA} \), solve for \( \mathbf{x}^A \):

\[ \mathbf{x}^A = \mathbf{R}_{BA}^\top(\mathbf{x}^B - \mathbf{p}_{BA}), \quad \text{since }\mathbf{R}_{BA}^{-1}=\mathbf{R}_{BA}^\top. \]

Hence the inverse transformation is \( (\mathbf{R}_{AB},\mathbf{p}_{AB}) \) where \( \mathbf{R}_{AB}=\mathbf{R}_{BA}^\top \) and

\[ \mathbf{p}_{AB}=-\mathbf{R}_{BA}^\top\mathbf{p}_{BA}. \]

5. Programming Lab — Working with (R, p)

We implement (i) axis rotations, (ii) rigid motion application \( \mathbf{x}'=\mathbf{R}\mathbf{x}+\mathbf{p} \), and (iii) composition in four languages.

5.1 Python (NumPy)


import numpy as np

def Rz(theta):
    c, s = np.cos(theta), np.sin(theta)
    return np.array([[c, -s, 0.0],
                     [s,  c, 0.0],
                     [0.0, 0.0, 1.0]])

def rigid_apply(R, p, x):
    # x' = R x + p
    return R @ x + p

def rigid_compose(R_cb, p_cb, R_ba, p_ba):
    # R_ca = R_cb R_ba ; p_ca = R_cb p_ba + p_cb
    R_ca = R_cb @ R_ba
    p_ca = R_cb @ p_ba + p_cb
    return R_ca, p_ca

theta = np.pi/4
R = Rz(theta)
p = np.array([0.5, -0.2, 0.1])
xA = np.array([1.0, 0.0, 0.0])

xB = rigid_apply(R, p, xA)
print("xB =", xB)
      

5.2 C++ (Eigen)


#include <iostream>
#include <Eigen/Dense>

Eigen::Matrix3d Rz(double theta) {
    double c = std::cos(theta), s = std::sin(theta);
    Eigen::Matrix3d R;
    R << c, -s, 0,
         s,  c, 0,
         0,  0, 1;
    return R;
}

Eigen::Vector3d rigidApply(const Eigen::Matrix3d& R,
                           const Eigen::Vector3d& p,
                           const Eigen::Vector3d& x) {
    return R * x + p;
}

void rigidCompose(const Eigen::Matrix3d& R_cb, const Eigen::Vector3d& p_cb,
                  const Eigen::Matrix3d& R_ba, const Eigen::Vector3d& p_ba,
                  Eigen::Matrix3d& R_ca, Eigen::Vector3d& p_ca) {
    R_ca = R_cb * R_ba;
    p_ca = R_cb * p_ba + p_cb;
}

int main() {
    double theta = M_PI / 4.0;
    Eigen::Matrix3d R = Rz(theta);
    Eigen::Vector3d p(0.5, -0.2, 0.1);
    Eigen::Vector3d xA(1.0, 0.0, 0.0);

    Eigen::Vector3d xB = rigidApply(R, p, xA);
    std::cout << "xB = " << xB.transpose() << std::endl;
    return 0;
}
      

5.3 Java (EJML)


import org.ejml.simple.SimpleMatrix;

public class RigidMotion {
    public static SimpleMatrix Rz(double theta) {
        double c = Math.cos(theta), s = Math.sin(theta);
        double[][] data = {
            { c, -s, 0 },
            { s,  c, 0 },
            { 0,  0, 1 }
        };
        return new SimpleMatrix(data);
    }

    public static SimpleMatrix rigidApply(SimpleMatrix R, SimpleMatrix p, SimpleMatrix x) {
        return R.mult(x).plus(p);
    }

    public static SimpleMatrix[] rigidCompose(SimpleMatrix R_cb, SimpleMatrix p_cb,
                                              SimpleMatrix R_ba, SimpleMatrix p_ba) {
        SimpleMatrix R_ca = R_cb.mult(R_ba);
        SimpleMatrix p_ca = R_cb.mult(p_ba).plus(p_cb);
        return new SimpleMatrix[]{R_ca, p_ca};
    }

    public static void main(String[] args) {
        double theta = Math.PI/4.0;
        SimpleMatrix R = Rz(theta);
        SimpleMatrix p = new SimpleMatrix(3,1,true, new double[]{0.5, -0.2, 0.1});
        SimpleMatrix xA = new SimpleMatrix(3,1,true, new double[]{1,0,0});

        SimpleMatrix xB = rigidApply(R, p, xA);
        System.out.println("xB = " + xB);
    }
}
      

5.4 MATLAB / Simulink (built-ins)


function R = Rz(theta)
    c = cos(theta); s = sin(theta);
    R = [ c -s  0;
          s  c  0;
          0  0  1 ];
end

function xB = rigid_apply(R, p, xA)
    xB = R*xA + p;
end

function [R_ca, p_ca] = rigid_compose(R_cb, p_cb, R_ba, p_ba)
    R_ca = R_cb * R_ba;
    p_ca = R_cb * p_ba + p_cb;
end

% Demo
theta = pi/4;
R = Rz(theta);
p = [0.5; -0.2; 0.1];
xA = [1;0;0];
xB = rigid_apply(R, p, xA)
      

Simulink note: you can implement \( \mathbf{x}'=\mathbf{R}\mathbf{x}+\mathbf{p} \) using a “Matrix Multiply” block followed by a “Sum” block. Later in the course, this becomes part of full robot pose pipelines.

6. Problems and Solutions

Problem 1 (Verify a Rotation): Let \( \mathbf{R}=\begin{bmatrix} 0 & -1 & 0 \\ 1 & 0 & 0 \\ 0 & 0 & 1 \end{bmatrix} \). Show that \( \mathbf{R}\in SO(3) \).

Solution:

Compute \( \mathbf{R}^\top\mathbf{R} \). Since columns are \( [0,1,0]^\top,\ [-1,0,0]^\top,\ [0,0,1]^\top \), they are orthonormal, thus \( \mathbf{R}^\top\mathbf{R}=\mathbf{I} \). The determinant is \( \det(\mathbf{R})=1 \) (it is a +90° rotation around z). Hence \( \mathbf{R}\in SO(3) \).

Problem 2 (Angle Preservation): Prove that for any rotation \( \mathbf{R}\in SO(3) \) and vectors \( \mathbf{u},\mathbf{v} \), the angle between them is unchanged after rotation.

Solution:

Let \( \theta \) be the angle between \( \mathbf{u},\mathbf{v} \). Then \( \cos\theta = \frac{\mathbf{u}^\top\mathbf{v}}{\|\mathbf{u}\|\|\mathbf{v}\|} \). Using orthonormality:

\[ \cos\theta' = \frac{(\mathbf{R}\mathbf{u})^\top(\mathbf{R}\mathbf{v})} {\|\mathbf{R}\mathbf{u}\|\ \|\mathbf{R}\mathbf{v}\|} = \frac{\mathbf{u}^\top\mathbf{R}^\top\mathbf{R}\mathbf{v}} {\|\mathbf{u}\|\ \|\mathbf{v}\|} = \cos\theta. \]

Therefore \( \theta'=\theta \).

Problem 3 (Composition): Frame A to B is a rotation \( \mathbf{R}_{BA} \) and translation \( \mathbf{p}_{BA} \). Frame B to C is \( \mathbf{R}_{CB},\mathbf{p}_{CB} \). Derive the A to C transformation.

Solution:

Starting from \( \mathbf{x}^B=\mathbf{R}_{BA}\mathbf{x}^A+\mathbf{p}_{BA} \) and \( \mathbf{x}^C=\mathbf{R}_{CB}\mathbf{x}^B+\mathbf{p}_{CB} \), substitute to get:

\[ \mathbf{x}^C = \mathbf{R}_{CB}\mathbf{R}_{BA}\mathbf{x}^A + \mathbf{R}_{CB}\mathbf{p}_{BA}+\mathbf{p}_{CB}. \]

Hence \( \mathbf{R}_{CA}=\mathbf{R}_{CB}\mathbf{R}_{BA} \) and \( \mathbf{p}_{CA}=\mathbf{R}_{CB}\mathbf{p}_{BA}+\mathbf{p}_{CB} \).

Problem 4 (Translation Not Linear): Show that \( T_{\mathbf{p}}(\alpha\mathbf{x}) \neq \alpha T_{\mathbf{p}}(\mathbf{x}) \) in general, for scalar \( \alpha \neq 1 \).

Solution:

We have \( T_{\mathbf{p}}(\alpha\mathbf{x})=\alpha\mathbf{x}+\mathbf{p} \), while \( \alpha T_{\mathbf{p}}(\mathbf{x})=\alpha(\mathbf{x}+\mathbf{p}) =\alpha\mathbf{x}+\alpha\mathbf{p} \). If \( \alpha\neq 1 \) and \( \mathbf{p}\neq\mathbf{0} \), these are unequal. Therefore translations are not linear.

7. Summary

We modeled rotations as elements of \( SO(3) \), proved their distance and angle preservation, and highlighted their non-commutativity. We treated translations as affine shifts, proved their commutative composition, and showed why they are not linear. Combining both yields the rigid-motion rule \( \mathbf{x}^B=\mathbf{R}_{BA}\mathbf{x}^A+\mathbf{p}_{BA} \), with clear composition and inverse formulas. Lesson 4 will package this into homogeneous transformations for compact representation.

8. References (Theoretical Papers)

  1. Chasles, M. (1830). Note sur les propriétés générales du système de deux corps semblables. Bulletin des Sciences Mathématiques, Astronomiques, Physiques et Chimiques, 14, 321–326.
  2. Rodrigues, O. (1840). Des lois géométriques qui régissent les déplacements d’un système solide dans l’espace. Journal de Mathématiques Pures et Appliquées, 5, 380–440.
  3. Euler, L. (1776). Formulae generales pro translatione quacunq; corporum rigidorum. Novi Commentarii academiae scientiarum Petropolitanae, 20, 189–207.
  4. Cayley, A. (1846). About the algebraic structure of orthogonal transformations. Cambridge Mathematical Journal, 5, 267–271.
  5. Cartan, É. (1922). Sur la structure des groupes infinis de transformations. Annales Scientifiques de l’École Normale Supérieure, 39, 325–412.
  6. Murray, R.M., Li, Z., & Sastry, S.S. (1994). A mathematical introduction to robotic manipulation: rigid motions and \( SO(3) \)/\( SE(3) \) foundations. IEEE/ASME Transactions on Mechatronics, 1(1), 1–17.