# 2D Direction Cosine Matrix

A Direction Cosine Matrix (DCM) rotates the *components* of a vector between two reference frames without moving the vector itself. The 2D version is the cleanest place to build that intuition: one frame stays fixed, the other rotates by an angle $\theta$, and the same physical vector $\mathbf{v}$ sits unchanged in space — only its component representation changes.

## The convention

This course uses the "components from frame a to frame b" convention:

$$
\mathbf{v}^b = \mathbf{C}_a^b(\theta)\,\mathbf{v}^a, \qquad
\mathbf{C}_a^b(\theta) = \begin{bmatrix} \cos\theta & \sin\theta \\ -\sin\theta & \cos\theta \end{bmatrix}.
$$

$\mathbf{v}^a$ are the components of $\mathbf{v}$ expressed in frame a; $\mathbf{v}^b$ are the components of the *same physical* $\mathbf{v}$ in frame b. As $\theta$ changes, the b-frame's axes rotate, so the components in that rotating frame change — but the physical vector itself never moves.

## Interactive demo

<a class="demo-fullscreen" href="../_static/demos/DcmExample.html" target="_blank" rel="noopener">Open in full screen</a>

<div class="demo-wrap">
<iframe src="../_static/demos/DcmExample.html"
        title="Interactive 2D DCM demo"
        width="100%"
        loading="lazy">
</iframe>
</div>

## Walkthrough

Try the following sequence to build intuition:

1. **Start at $\theta = 0°$.** The b-frame is aligned with the a-frame, and $\mathbf{v}^b = \mathbf{v}^a$. The rotation matrix is the identity.
2. **Click the "30°" preset.** The b-frame rotates 30° counter-clockwise. The brown vector hasn't moved — but the readout shows $\mathbf{v}^b$ has changed: more component along b-x, less along b-y. This is exactly the matrix-vector product $\mathbf{C}_a^b(30°)\,\mathbf{v}^a$.
3. **Click "90°."** The b-x axis now points where a-y used to, and b-y points opposite a-x. With the default $\mathbf{v}^a = [3, 1]^\top$ this gives $\mathbf{v}^b = [1, -3]^\top$ — a quarter-turn of the components.
4. **Press "Play."** The b-frame rotates continuously. Watch the $\Delta = \lVert\mathbf{v}^b\rVert - \lVert\mathbf{v}^a\rVert$ readout. It stays at exactly 0 (within machine epsilon) for every angle — that equality is the numerical signature of an orthonormal DCM.
5. **Toggle "Show v_b decomposition."** Two dashed segments appear: from the origin along the b-x axis a length $v_b^x$, then along the b-y axis a length $v_b^y$. Head-to-tail, they land exactly on the brown vector tip — visual confirmation that the b-frame components really do rebuild the same physical vector.
6. **Edit $\mathbf{v}^a$.** Change x and y to anything you like. Repeat the rotation experiments and observe that the magnitudes always agree.

## Key observations

- **$\lVert\mathbf{v}^a\rVert = \lVert\mathbf{v}^b\rVert$ at every $\theta$,** to machine precision. Norm preservation is the simplest unit test you can run on any DCM implementation: rotate a vector, check the norm. If it changed, you have a bug — most likely a sign flip in the matrix.
- **At $\theta = 360°$ you should recover $\mathbf{v}^b = \mathbf{v}^a$ exactly.** If your implementation drifts after a full revolution (visible in the $\Delta$ readout), something is wrong.
- **Frames are bookkeeping; vectors are real.** The same physical $\mathbf{v}$ has different *components* in different frames, but the vector — and any frame-invariant quantity such as its norm — is the same regardless of which frame you write it in.

## Connection to 3D

The 2D version exists to make the geometry visible. In 3D, DCMs are 3×3 orthonormal matrices and the same identities hold — $\lVert\mathbf{v}^b\rVert = \lVert\mathbf{v}^a\rVert$, $\mathbf{C}^\top\mathbf{C} = \mathbf{I}$, $\det\mathbf{C} = +1$. The 3D rotation matrices used throughout the rest of the course (between body, NED, ECEF, and ECI frames) are direct generalizations. Block 2 starts using them in earnest for inertial-error mechanization.

## Source

<a class="matlab-link" href="../_static/downloads/SY6301%20Navigation%20and%20State%20Estimation%20%E2%80%93%20Code.zip#code/DcmExample.m" download><svg viewBox="0 0 22 22" width="14" height="14" aria-hidden="true" style="vertical-align:-2px;margin-right:6px;"><rect width="22" height="22" rx="3" fill="#e87722"/><text x="11" y="15.5" text-anchor="middle" font-family="'Inter',sans-serif" font-size="9" font-weight="800" fill="#fff" letter-spacing="-0.04em">MAT</text></svg><span class="ml-text">MATLAB · code/DcmExample.m</span><span class="ml-arrow">↓</span></a>
