A car’s LiDAR detects a pedestrian in sensor coordinates, but planning and navigation need vehicle and world coordinates. Rigid transforms connect these descriptions: calibration locates the sensor on the car, and localization places the car in the world. The pedestrian stays the same; only its coordinates change.
The sensor, vehicle, and world each provide a reference frame for the detection.
We will build this frame-to-frame mapping, learn to invert and compose it, then explore rotation representations and random sampling. Throughout, we use column vectors, right-handed frames, and radians unless degrees are explicitly marked.
0. Prerequisites
We will use matrices to transform vector components, and two vector operations to describe geometric relationships.
The dot product measures alignment:
For nonzero vectors, its sign distinguishes acute from obtuse angles; perpendicular vectors have a dot product of zero.
The cross product in three dimensions gives a vector perpendicular to both inputs:
Its magnitude is the area of the parallelogram spanned by the inputs, and its direction follows the right-hand rule. The main special cases are:
| Relationship between nonzero vectors | Dot product | Cross product |
|---|---|---|
| Perpendicular | Perpendicular to both; magnitude | |
| Parallel, same direction | ||
| Parallel, opposite directions |
A right-handed orthonormal frame satisfies . Point your right thumb along a positive rotation axis; the curl of your fingers gives the positive rotation direction. Which axis points forward or upward is a separate convention, not something guaranteed by the words “right-handed.”
1. Coordinate Frames and Poses
A coordinate frame consists of an origin and an ordered set of perpendicular unit axes. A pedestrian might have coordinates in a LiDAR frame and in a world frame: each vector measures displacement from a different origin along a different set of axes.
A rigid body’s pose combines:
- position: where the body-frame origin is located; and
- orientation: how the body-frame axes are aligned.
A rigid body keeps the distances between its points fixed. Its pose describes its position and orientation at one instant; a full dynamical state may also include velocity. A transform uses the pose to convert coordinates between frames.
It helps to start in two dimensions. A car’s reference point needs two coordinates , and its heading needs one angle :
These are three degrees of freedom, meaning three independently variable quantities. Attaching axes to the car creates its body frame: both the origin and axes move with the car. A point bolted to the car has constant body coordinates even when its world coordinates change.
The primed axes move with the car; the world axes stay fixed.
In three dimensions, a free rigid body has six degrees of freedom: three translations and three rotations. Using roll, pitch, and yaw for orientation, we can collect them into
where denote roll, pitch, and yaw under the convention developed in Section 6. For computation, we will first represent orientation with a rotation matrix and position with a translation vector .
Three translational and three rotational degrees of freedom.
1.1 Notation
We will attach frame labels to each quantity. The left superscript in identifies the frame in which the point’s coordinates are expressed. A transform needs both a source and a destination:
Read as “map coordinates from frame into frame .” Rotation and translation use the same labels: expresses the axes in frame , while locates the origin in frame . Section 3 combines them into the matrix .
1.2 Building the transformation step by step
Given a point in body coordinates , we want to find its world coordinates . The construction is a head-to-tail sum of two displacements.
Step 1: locate the body origin. The translation
runs from the world origin to the body origin, expressed along the world axes.
The first displacement reaches the body origin.
Step 2: describe the point relative to the body. The vector runs from the body origin to the point, but its components are measured along the body axes. Because the body axes are rotated relative to the world axes, we cannot add this vector directly to .
The second displacement is initially measured along the body axes.
Step 3: rotate the local displacement into the world basis. The rotation converts components measured along the body axes into components measured along the world axes:
The displacement now uses the same basis as the translation.
Re-express the second displacement along the world axes.
Step 4: add vectors that now share the same basis. Both and are expressed in frame , so they can be added:
The orange vector reaches the body origin, the red vector continues to the point, and their dashed purple sum gives its world position.
Changing coordinates versus moving a point
An active rotation moves a vector while its reference axes stay fixed. A passive change of frame describes the same geometric vector using different axes. Here, the frame-to-frame equations are coordinate conversions. Reversing the conversion requires the inverse rotation. Always identify the input and output frames before choosing a matrix.
2. Rigid Transforms
The construction above gives the rigid transform
To use it, we need to construct the rotation matrix and understand which properties make the mapping rigid.
2.1 Deriving the 2D rotation matrix
For a counterclockwise angle , the body unit -axis has world components . The perpendicular body unit -axis has world components . Put these vectors in the columns:
Why columns? A point with body coordinates means steps along the body -axis plus steps along the body -axis. Matrix multiplication forms exactly that linear combination of columns. This also explains the columns of a 3D rotation matrix.
Suppose the body is rotated counterclockwise, its origin is at world position , and a point has body coordinates . Then
2.2 What makes the transform rigid?
In either two or three dimensions, a proper rotation satisfies
The entry of is the dot product of columns and . A diagonal entry of gives unit length; an off-diagonal entry of gives perpendicularity. Together these properties are called orthonormality, and they imply . For the planar matrix, write and :
Now transform two points by and . Their squared distance becomes
Translation disappears in the difference, and rotation preserves the remaining norm. Inner products satisfy
Since both lengths and dot products remain unchanged, the cosine of the angle between any two nonzero displacement vectors remains unchanged too.
Orthogonal matrices can have determinant or . The condition rules out reflections, so handedness is preserved. For example, preserves planar distances but reflects across the -axis; it is not a proper rotation.
The square changes position and orientation while corresponding distances, angles, and handedness remain fixed.
3. Homogeneous Coordinates
Homogeneous coordinates combine rotation and translation in one matrix, allowing us to chain entire transforms by multiplication. The formula already works, but requires us to track the two operations separately.
The obstacle is that ordinary matrix multiplication cannot express a nonzero translation. Every matrix maps the zero vector to itself, , but translation must move the origin to . This is why is affine rather than linear when .
Appending a constant gives the matrix something to multiply the translation by. For example, translating a 2D point by becomes
The extra coordinate is not another physical dimension. It allows matrix multiplication to produce a constant offset. Adding rotation to the same construction gives the homogeneous point and transform:
Then a rigid transform becomes
With this representation, a chain of frame conversions becomes a product of matrices. We can precompute that product and apply it to every point in a LiDAR scan; Section 5 works through the sensor-to-world example.
In 2D, the same construction uses a matrix:
In 3D, the matrix belongs to the special Euclidean group , the set of all proper 3D rigid transforms. Euclidean refers to preserving distances and angles, special excludes reflections, and 3 names the spatial dimension:
Why call it a group? Its elements obey four rules under matrix multiplication:
- Closure: composing two rigid transforms gives another rigid transform, so .
- Associativity: grouping does not change the result: .
- Identity: performs no rotation or translation.
- Inverse: every transform has an undo operation , which also belongs to .
Associativity lets us regroup a product, but does not let us swap its factors: generally, .
The matrix has 12 nontrivial entries but only six degrees of freedom: the nine rotation entries are constrained, while the three translation entries are independent. Section 6 examines the rotation-only group .
3.1 Points and directions are different
A point uses a final coordinate of :
A direction uses a final coordinate of :
Consequently,
Translation affects locations, not directions. For a rigid transform this distinction applies to surface normals, ray directions, axis vectors, and the components of a given velocity vector. Relating velocities measured by moving observers requires additional motion terms.
Subtracting two homogeneous points naturally produces a displacement with last coordinate zero:
4. Inverting a Transform
To convert coordinates in the opposite direction, undo the translation first, then the rotation. Starting from gives
The inverse transform is therefore
The inverse translation is : negating the displacement reverses it, and multiplying by expresses it in the reversed frame. This is why transposing the whole matrix does not generally give its inverse.
Multiplication verifies the result:
For the example in Section 2.1, this recovers the original body coordinates:
5. Composing Coordinate Frames
Return to the LiDAR example. Perception supplies , calibration supplies , and localization supplies . These two transforms connect the measurement to the world.
The two frame mappings form one sensor-to-world path.
The desired world coordinate is
Read the product from right to left: sensor coordinates become body coordinates, then world coordinates. The adjacent frame labels match, just as units must match in a dimensional calculation:
Expanding the product shows how its rotation and translation combine:
The sensor offset is expressed in body coordinates. Rotate it into world coordinates before adding the body’s world position . Simply adding the two translation vectors would mix bases.
5.1 A numerical 2D example
Suppose a sensor is mounted one meter ahead of a vehicle’s body origin:
The vehicle is at in the world and rotated counterclockwise:
A pedestrian detected two meters along the sensor’s -axis has . First map sensor to body:
Then map body to world:
The local phrase “three meters ahead” becomes the world location because the vehicle’s forward axis points along world .
Real systems have many frames, but every measurement follows the same composition rule along a connected path.
For a rigidly mounted sensor, the calibration transform is usually fixed. Localization changes the body-to-world transform over time. On an articulated robot, joint motion also changes the transforms between links.
6. Rotation Matrices and
So far, a matrix has represented orientation. We will now compare it with Euler angles, axis-angle, and quaternions. Each describes the same geometry but makes different calculations convenient.
We will follow a positive turn about the -axis through all four representations. Here we use the active interpretation from Section 1.2: vectors rotate about the origin while the reference axes stay fixed.
6.1 Understanding what a rotation matrix stores
The column interpretation from Section 2.1 extends directly to 3D: each column gives the destination of one unit axis.
Write the standard unit vectors as , , and . Multiplication by each unit vector selects a column:
For our turn about ,
Putting those destination vectors into columns gives
There is no need to memorize this particular matrix: following the three axes reconstructs it. To rotate any other vector, express that vector as a combination of the same axes. For example, means , so
The orthonormality and handedness conditions established in Section 2.2 apply to these three columns. The set of all such matrices is called the special orthogonal group :
This is the rotation-only counterpart of . Its identity is , its inverse is , and multiplication composes rotations.
Although a matrix stores nine entries, it has only three independent degrees of freedom. One way to see this geometrically is to choose its first unit axis : a direction on a sphere needs two parameters. The second axis must be perpendicular to the first, leaving one angle around that first axis. Right-handedness then fixes the third axis as .
Beyond the distance and angle preservation proved earlier, proper 3D rotations also preserve the cross product. Rotating two vectors first gives the same result as rotating their cross product:
For example, our quarter-turn sends to and to . Their new cross product is still , just as rotating the original cross product leaves it unchanged.
For a general proof, recall that is the signed volume spanned by three vectors. A proper rotation preserves this volume because . Therefore, for every ,
The two candidate vectors have the same dot product with every possible direction, so they must be equal.
Applications also need to calculate new orientations. Three tasks motivate the choice of representation:
- Composition connects a camera orientation to the world through the robot: . This is the rotation part of the frame chain in Section 5, handled naturally by matrix multiplication.
- Interpolation fills in a smooth motion. If a camera must turn left in one second, a constant-speed turn places it at halfway through. An animation or controller needs these intermediate orientations.
- Optimization improves an orientation estimate. A robot starts with a guess, compares its predicted camera observations with the actual measurements, and adjusts the guess to reduce the error. Each update must remain a valid rotation.
The last two tasks require more care than ordinary arithmetic on matrix entries. For example, averaging the matrices for no rotation and a turn about gives
The average collapses to zero rather than giving an intermediate orientation. Arbitrary optimization updates can likewise destroy perpendicularity, which normalizing each column alone cannot restore. Quaternions and rotation vectors provide convenient alternatives for these tasks; applications that only apply or compose rotations can continue using matrices.
6.2 Euler angles: describing a turn as three steps
Euler angles describe a rotation through a sequence of simpler turns. For roll, pitch, and yaw, the three parameters are
| Parameter | Axis | Physical intuition when is forward, is left, and is up |
|---|---|---|
| Roll | Banking from side to side | |
| Pitch | Tilting the nose up or down | |
| Yaw | Turning left or right |
These descriptions identify the type of motion; the right-hand rule determines its sign. Under the convention used here,
Read this equation as a recipe applied to a column vector:
Substituting the intermediate vectors produces the matrix product above. The rightmost matrix acts first because it is closest to the input vector.
Each elemental matrix leaves one coordinate unchanged and performs a 2D rotation in the perpendicular plane:
Here the component stays fixed while the components rotate. Similarly,
Our running example has . The first two matrices are identities, leaving exactly the quarter-turn matrix from Section 6.1.
To see the effect of order, follow through two sequences:
A turn about does nothing to a vector already on the -axis. After a turn about , however, that vector points along , so a subsequent turn about does affect it. Thus and are generally different.
The axes used at each step must also be specified. Extrinsic rotations use fixed reference axes; intrinsic rotations use axes that move with the body. For example, “turn about the room’s vertical axis” names a fixed axis, whereas “turn about the object’s current forward axis” names a moving one. The product above is fixed-axis then then ; it is equivalently moving-axis then the new then the new , starting from aligned frames.
There are twelve standard three-axis sequences: six with distinct axes (, , , , , ) and six that repeat the first axis (, , , , , ). The distinct-axis cases are also called Tait–Bryan angles. You do not need to memorize the list to use this section; you do need to record the chosen sequence, fixed or moving axes, and angle units.
6.3 Gimbal lock: when two angle controls do the same job
Euler angles use three numbers, but at certain orientations those three controls stop producing three independent local changes. A physical gimbal makes this visible: it holds an object in nested rotating rings, and two of the rings’ axes can line up. Once aligned, turning either ring rotates about the same line.
The configuration on the right has two aligned gimbal axes. The ring labels belong to this particular mechanism; the roll–yaw calculation below uses our stated Euler convention.
For our convention, this happens when pitch is , or . At that value, and . Substituting them into gives
Roll and yaw appear only as , so they cannot be recovered separately. For example, both triples
and
produce the same rotation because both have . Increasing roll and yaw together by any equal amount leaves the orientation unchanged. Increasing roll alone has the same effect as decreasing yaw alone.
Near this singularity, even a small orientation change can require large changes in the reported angles, making estimation and control unstable. The same convention becomes singular at pitch , with a different roll–yaw coupling.
The object does not lose the ability to rotate
A freely moving rigid body still has three rotational degrees of freedom. Its Euler-angle coordinates cannot describe three independent infinitesimal changes at gimbal lock. A quaternion or rotation matrix can represent that same orientation without this Euler singularity.
6.4 Axis-angle: one axis and one amount of turning
Axis-angle represents the entire rotation as one turn about one axis. Every proper 3D rotation admits this description, with the axis passing through the origin. Translation remains separate.
Let be a unit vector along the axis, and let be the right-handed rotation angle. For our running quarter-turn,
The axis stores three components, but the constraint leaves only two independent parameters. Adding the angle gives three degrees of freedom overall.
The rotation vector, also called the Euler vector, combines the axis and angle:
Its direction gives the axis and its length gives the angle. For our example, . When , recover the angle as and the axis as . The zero vector represents no rotation.
A rotation vector is not a triple of roll, pitch, and yaw angles. Its components encode one axis scaled by one angle, not three sequential turns.
The axis sets the direction of the turn. The figure labels its angle or ; our equations use .
To rotate a vector about this axis, split it into parallel and perpendicular components:
The dot product measures the component along the unit axis; multiplying by reconstructs that parallel vector. The remainder lies in the plane of rotation.
The parallel part stays fixed. The perpendicular part turns in a 2D plane. Within that plane, is a turn of with the same length. Just as a planar rotation combines cosine and sine components,
We used because the parallel component contributes zero to that cross product.
For a concrete example, rotate by about . Its parallel part is , its perpendicular part is , and . Since and ,
The height stays fixed while the horizontal part turns. This formula already lets us rotate vectors directly, without first constructing a matrix.
Rodrigues’ formula packages this geometry into a matrix. Define
The bracket notation is simply a matrix implementation of “take the cross product with .” Substituting the parallel and perpendicular components into the vector formula gives
Here projects onto the rotation axis. The identity
for a unit axis implies . Using it yields the usual form:
Axis-angle is not unique. Reversing both the axis and angle sign, or adding to the angle, leaves the rotation unchanged. At zero angle any axis works; at angle , either axis direction works.
A common rotation-vector convention restricts , but opposite points on the boundary represent the same rotation. This creates a numerical seam. Consider two turns about , expressed here in degrees for readability:
Both are nearly a half-turn, so their actual orientations are only apart. Their coordinate difference is nevertheless . Averaging the vectors gives zero rotation, which is nowhere near the short-path midpoint at .
Rotation vectors are useful for small local changes. For small in radians, and to first order, so Rodrigues’ formula becomes . This approximation helps explain their role in optimization, but it does not make global vector averaging valid.
6.5 Unit quaternions: encoding axis-angle in four numbers
A unit quaternion encodes axis-angle using four real numbers. Starting from that connection lets us understand its geometry before introducing its multiplication rule.
Using scalar-first order, write
The three numbers in point along the rotation axis, but their length is generally not one. Given a unit axis and angle , set
The scalar part stores the cosine of the half-angle; the vector part stores the axis scaled by the sine of the half-angle. These four numbers satisfy
That is what unit means. Four stored numbers minus one constraint leaves three degrees of freedom; there is no fourth physical direction of rotation.
For our turn about ,
The identity rotation has quaternion , and a turn about has quaternion . These examples make clear that the vector part is not an ordinary position vector. Some libraries store instead, so component order must be checked.
To compose rotations, quaternions use a multiplication rule called the Hamilton product. For and , write the result as , where
We denote the result by . This is not componentwise multiplication: the dot and cross products couple the inputs. Swapping them changes the cross-product sign, making composition order-dependent.
The notation describes the same algebra using imaginary units satisfying . For instance, while . You can compute rotations entirely with the four real components and the Hamilton formula above.
To reverse a rotation, use the quaternion conjugate, which negates the vector part:
For a unit quaternion this is the inverse, . Geometrically, the sign change reverses the angle about the same axis. For a general nonzero quaternion, the inverse is instead ; the unit-norm assumption matters.
To apply the rotation to a 3D vector, package it as a quaternion with scalar part zero, , and compute
The output has zero scalar part and the rotated vector as its remaining components. Both multiplications are needed.
This also explains the half-angle. Take a rotation about , write with and , and rotate . The two products give
The vector part has turned through the full angle . At , it is exactly , agreeing with the matrix and axis-angle examples.
Under this convention, applying first and second uses . For example, composing two turns about multiplies by itself, giving : a turn.
The two-sided formula also explains why and represent the same rotation. Negating the quaternion negates its inverse as well, so the two signs cancel:
Every orientation therefore has two opposite quaternion representatives, a property called a double cover. An apparent jump from to need not mean any physical motion. When processing a sequence, choose signs consistently, and renormalize quaternions if numerical error causes their lengths to drift.
6.6 Interpolating orientations with SLERP
We can now solve the camera-interpolation problem from Section 6.1. Unit quaternions lie on a sphere in four-dimensional space. A straight line between two of them generally passes inside that sphere; spherical linear interpolation (SLERP) follows an arc on its surface instead. Let measure progress from the starting orientation to the ending orientation.
Start with unit quaternions and . If , replace with . This leaves its physical orientation unchanged while selecting a shorter arc. Let
Here is the angle between the quaternions in four-dimensional space. After this sign choice, the corresponding shortest physical rotation angle is . For ,
The sine weights replace the straight-line weights and . They keep the result on the unit sphere and make angular progress proportional to . At the second weight vanishes and the first is one; at the reverse happens.
For example, interpolate from no rotation, , to our turn, . Their dot product is , so . Halfway through,
which represents a physical turn about . If advances uniformly with time, the camera turns at constant angular speed along this path.
For implementation, clamp the dot product to before applying . When is very small, dividing by is numerically awkward. A useful approximation is normalized linear interpolation:
Use the same sign choice first. This approximation preserves unit norm, though its angular speed is not exactly constant in general.
6.7 Choosing a representation
Choose a representation according to what you need to do:
| Representation | Stored values | Useful when | What to watch for |
|---|---|---|---|
| Rotation matrix | 9 | Rotating point clouds and composing frame mappings | Columns must remain orthonormal and right-handed |
| Euler angles | 3 | Displaying understandable roll, pitch, and yaw | Axis conventions, order, and gimbal lock |
| Axis-angle | 4 | Explaining a turn geometrically | Nonunique axes at zero angle and sign ambiguity at |
| Rotation vector | 3 | Expressing small rotation updates | Global subtraction and averaging can cross a boundary |
| Unit quaternion | 4 | Storing orientations, composing turns, and interpolating | Unit norm, component order, and versus |
A pipeline can store a pose with a quaternion and translation, convert it to a matrix to transform a point cloud, and display Euler angles to a person. These conversions change the representation while preserving the orientation.
7. Uniform Sampling on Curved Spaces
The geometry that complicates interpolation also matters when generating random directions or orientations. Uniformly sampling coordinates does not necessarily produce a uniform geometric distribution: equal coordinate intervals may cover different amounts of area or volume.
7.1 Uniform directions on the sphere
With azimuth and polar angle , a unit direction is
Here is the polar angle, measured down from the positive -axis; it differs from geographic latitude.
The sphere’s area element is
Near a pole, a fixed angular rectangle covers less area than near the equator. Uniformly sampling both angles therefore produces too many samples near the poles per unit area.
Instead, sample and independently, then set
Since , the area element becomes : equal-height strips of a sphere have equal area. Another valid method is to normalize a vector of three independent standard normal samples: its rotationally symmetric distribution has no preferred direction.
7.2 Uniform rotations in
A random direction is not a full random orientation: after choosing where one axis points, rotation about that axis is still free. Nor does sampling roll, pitch, and yaw independently and uniformly yield uniform orientations.
For with , the uniform rotation measure is proportional to
One valid sampler draws roll and yaw uniformly over a full turn, samples , and sets .
An especially simple alternative uses unit quaternions:
- Draw four independent standard normal samples .
- Form .
- Normalize: .
- Interpret as a unit quaternion.
The normalized Gaussian is uniform on the three-dimensional unit sphere in four-dimensional space. Its quaternion-to-rotation mapping produces the uniform, or Haar, distribution on . The two-to-one mapping is harmless because every rotation has exactly the pair .
Normalize Gaussian samples, not uniform cube samples
Normalizing four samples from does not give the same distribution. A Gaussian is rotationally symmetric; a cube is not. The same distinction applies when sampling directions on .
8. Implementation Pattern
The geometry translates directly into NumPy. In variable names, A_T_B means the transform from frame B to frame A; the functions below assume valid rigid-transform inputs.
import numpy as np
def make_transform(R: np.ndarray, t: np.ndarray) -> np.ndarray:
"""Construct destination_T_source from destination_R_source and destination_t_source."""
T = np.eye(4)
T[:3, :3] = R
T[:3, 3] = t
return T
def invert_transform(A_T_B: np.ndarray) -> np.ndarray:
"""Return B_T_A."""
R = A_T_B[:3, :3]
t = A_T_B[:3, 3]
B_T_A = np.eye(4)
B_T_A[:3, :3] = R.T
B_T_A[:3, 3] = -R.T @ t
return B_T_A
def transform_point(A_T_B: np.ndarray, B_p: np.ndarray) -> np.ndarray:
"""Map a 3D point from frame B to frame A."""
B_p_h = np.append(B_p, 1.0)
return (A_T_B @ B_p_h)[:3]
def is_rotation_matrix(R: np.ndarray, atol: float = 1e-7) -> bool:
return (
np.allclose(R.T @ R, np.eye(3), atol=atol, rtol=0.0)
and np.isclose(np.linalg.det(R), 1.0, atol=atol, rtol=0.0)
)Reusing the sensor setup from Section 5.1 in 3D lets us check composition, inversion, point-versus-direction behavior, and distance preservation:
W_T_B = make_transform(
np.array([[0., -1., 0.], [1., 0., 0.], [0., 0., 1.]]),
np.array([10., 5., 0.]),
)
B_T_S = make_transform(np.eye(3), np.array([1., 0., 0.]))
S_p = np.array([2., 0., 0.])
W_T_S = W_T_B @ B_T_S
W_p = transform_point(W_T_S, S_p)
assert np.allclose(W_p, [10., 8., 0.])
assert np.allclose(W_T_S @ invert_transform(W_T_S), np.eye(4))
assert np.allclose(transform_point(invert_transform(W_T_S), W_p), S_p)
assert is_rotation_matrix(W_T_S[:3, :3])
# The last homogeneous coordinate controls whether translation applies.
assert np.allclose(W_T_B @ [1., 0., 0., 0.], [0., 1., 0., 0.])
assert np.allclose(W_T_B @ [1., 0., 0., 1.], [10., 6., 0., 1.])
S_p2 = np.array([-1., 2., 4.])
assert np.isclose(
np.linalg.norm(transform_point(W_T_S, S_p) - transform_point(W_T_S, S_p2)),
np.linalg.norm(S_p - S_p2),
)One normalization routine implements both Gaussian samplers from Section 7. The four-dimensional result is interpreted in scalar-first (w, x, y, z) order:
rng = np.random.default_rng(42)
def sample_unit_vectors(rng, count: int, dimension: int) -> np.ndarray:
samples = rng.normal(size=(count, dimension))
norms = np.linalg.norm(samples, axis=1, keepdims=True)
# Exact zeros have probability zero in the ideal distribution;
# resample them defensively for finite-precision computation.
zero = norms[:, 0] == 0
while np.any(zero):
samples[zero] = rng.normal(size=(np.count_nonzero(zero), dimension))
norms = np.linalg.norm(samples, axis=1, keepdims=True)
zero = norms[:, 0] == 0
return samples / norms
directions = sample_unit_vectors(rng, count=1000, dimension=3)
quaternions_wxyz = sample_unit_vectors(rng, count=1000, dimension=4)Library conventions differ
Before combining libraries, check axis handedness, quaternion component order (
wxyzversusxyzw), angle units, Euler order, whether vectors are rows or columns, and whether a matrix maps source-to-destination or destination-to-source. Shape compatibility alone does not prove semantic compatibility.
9. Summary
Keep frame labels attached to every quantity, then choose the operation that matches the task:
- Convert a point: .
- Chain frames: ; adjacent frame labels must match.
- Reverse a mapping: use and .
- Interpolate, estimate, or sample orientations: respect the constraints of the chosen representation rather than treating its entries as unconstrained coordinates.