VLA · Prerequisite · Robotics Fundamentals
M5.4 — Coordinate Frames and Transformations
Expressing positions in different frames and converting between them.
A camera sees the cup in its own frame, and the arm reaches in the base frame. This lesson shows how a point is converted between frames with a rotation and a translation, how transforms chain, and why the order of multiplication is a classic source of silent errors.
Learning objectives
After this lesson, you should be able to:
- Explain what a coordinate frame is and name the frames in a robot system.
- Transform a point with a rotation and a translation.
- Use a homogeneous matrix to do the same in one multiplication.
- Chain and invert transforms in the correct order.
- Explain why 3-D rotations do not commute and name common orientation representations.
- Convert a point from a camera frame to a robot base frame.
- A point is seen in the camera frame
- The camera-to-base transform converts it to the base frame
- The base-to-world transform places it in the world
- The end-effector target is expressed in the base frame
- Inverse kinematics turns it into joint angles
The one-sentence idea
A transform that rotates and then translates converts a point’s coordinates from one frame to another, and chaining such transforms, in the right order, links the camera to the robot.
Same point, different coordinates. Always ask: in which frame?
A frame is an origin and a set of axes
A position such as “(0.4, 0.0, 0.6)” means nothing until you say measured from where, along which directions. A coordinate frame supplies that: an origin and a set of perpendicular axes. A robot system has many frames at once, and the same physical point has different coordinates in each:
- World frame: fixed in the room or workspace.
- Base frame: fixed to the robot’s base.
- End-effector (tool) frame: attached to the hand, and moving with it.
- Camera frame: attached to a camera, which may be fixed in the room or mounted on the robot.
- Object frame: attached to an object being grasped.
A camera sees the cup in the camera frame. The arm must reach for it in the base frame. Converting between them is the job of a transformation, and getting it wrong is one of the most common ways a robot misses its target, so it deserves care. M4.6 ended with a point in the camera frame, and this lesson shows how to express it in the robot’s.
Rotation and translation
Moving between two frames takes a rotation R, which says how the axes of one frame are turned relative to the other, and a translation t, the position of one origin as seen from the other. If a point has coordinates pB in frame B, its coordinates in frame W are:
In two dimensions, a rotation by an angle θ is the matrix from M1.1’s robotics example:
import numpy as np
theta = np.deg2rad(90)
R = np.array([[np.cos(theta), -np.sin(theta)],
[np.sin(theta), np.cos(theta)]])
t = np.array([1.0, 2.0]) # frame B's origin, seen from frame W
p_B = np.array([1.0, 0.0]) # a point one unit along B's x-axis
p_W = R @ p_B + t
print(p_W.round(3))Output:
[1. 3.]
Frame B is turned 90° and shifted to (1, 2). A point 1 unit along B’s x-axis is, in frame W, 1 unit up from B’s origin: the rotation sends it to (0, 1), and the shift moves it to (1, 3). Rotation happens first, about the origin, and translation second.
Homogeneous transforms: one matrix for both
Having a rotate-then-add rule is awkward when chaining many frames. The standard trick is to append a 1 to the point (homogeneous coordinates) and pack R and t into one matrix, so that a transform is a single matrix multiplication:
def make_T(R, t):
n = len(t)
T = np.eye(n + 1)
T[:n, :n] = R
T[:n, n] = t
return T
T_WB = make_T(R, t)
p_h = np.append(p_B, 1.0) # homogeneous point (x, y, 1)
print((T_WB @ p_h)[:2].round(3))Output:
[1. 3.]
The answer matches. In 3-D the same idea uses a 4 × 4 matrix with a 3 × 3 rotation and a 3-vector translation. The notation TWB reads “the pose of B expressed in W”, and it converts coordinates the other way: pW = TWB pB. The letters on the inside line up like …B · B… and cancel, which is a useful way to check an expression.
Chaining frames, and the order of multiplication
Suppose the robot’s base sits in the world at TWB and a camera is mounted on the robot at TBC (the camera’s pose in the base frame). A point seen in the camera, pC, reaches the world frame through the chain TWB · TBC · pC. Matrix multiplication (M1.1) is not commutative, so the order matters:
def Rz(theta):
c, s = np.cos(theta), np.sin(theta)
return np.array([[c, -s], [s, c]])
T_WB = make_T(Rz(np.deg2rad(90)), [1.0, 2.0]) # base in the world
T_BC = make_T(Rz(0.0), [0.5, 0.0]) # camera 0.5 in front of the base, same orientation
p_C = np.append([0.2, 0.0], 1.0) # a point 0.2 in front of the camera
p_W = T_WB @ T_BC @ p_C # camera -> base -> world
step = T_WB @ (T_BC @ p_C) # doing the two steps one after the other
print(p_W[:2].round(3), np.allclose(p_W, step))
print((T_BC @ T_WB @ p_C)[:2].round(3)) # the wrong order gives a different pointOutput:
[1. 2.7] True [1.5 2.2]
Applied correctly, the camera point (0.2 in front of the camera, which is 0.5 in front of the base) is 0.7 in front of the base, and the base faces up the world’s y-axis, so the point lands at (1, 2.7). Reversing the multiplication gives (1.5, 2.2), a plausible-looking but wrong answer that no error message will flag.
Transforms are inverted to go the other way, and for a rigid transform the inverse is cheap: the rotation’s inverse is its transpose, because rotation matrices are orthonormal:
def inv_T(T):
n = T.shape[0] - 1
R_, t_ = T[:n, :n], T[:n, n]
return make_T(R_.T, -R_.T @ t_)
print(np.allclose(inv_T(T_WB) @ T_WB, np.eye(3)))
p_B_again = inv_T(T_WB) @ (T_WB @ p_h) # world back to base
print(p_B_again[:2].round(3))Output:
True [1. 0.]
The inverse transform recovers the original point (1, 0). Writing TBW = TWB−1 shows “B in W” turned into “W in B”.
Three dimensions: rotations and a camera example
A 3-D rotation is a 3 × 3 matrix whose columns are the rotated axes. Two properties identify one: it is orthonormal (RᵀR = I) and has determinant +1, which excludes reflections. The rotation about the z-axis, for instance, is the 2-D one placed in the top-left corner. Rotations in 3-D do not commute, unlike in 2-D, which is why the order in which you rotate matters:
def Rx(a):
c, s = np.cos(a), np.sin(a)
return np.array([[1, 0, 0], [0, c, -s], [0, s, c]])
def Rz3(a):
c, s = np.cos(a), np.sin(a)
return np.array([[c, -s, 0], [s, c, 0], [0, 0, 1]])
R1 = Rx(np.pi / 2) @ Rz3(np.pi / 2) # turn about z, then about x (in the fixed frame)
R2 = Rz3(np.pi / 2) @ Rx(np.pi / 2) # the other way round
print(np.allclose(R1.T @ R1, np.eye(3)), round(float(np.linalg.det(R1)), 3))
print(np.allclose(R1, R2))
print((R1 @ [1, 0, 0]).round(3), (R2 @ [1, 0, 0]).round(3))Output:
True 1.0 False [0. 0. 1.] [0. 1. 0.]
Both orders give valid rotations, and they send the x-axis to different places. Orientation is therefore stored in a few standard ways: a rotation matrix (9 numbers, redundant), Euler angles such as roll, pitch and yaw (3 numbers, but with ambiguities and a failure at certain orientations called gimbal lock), or a unit quaternion (4 numbers, compact and free of that failure). A quaternion (w, x, y, z) for a rotation of angle θ about a unit axis is (cos θ/2, sin θ/2 · axis). Policies and datasets use different conventions, so check which one a system uses.
Now the camera example, ending where M4.6 stopped. Cameras commonly use x to the right, y down and z forward, while a robot base uses x forward, y to the left and z up. Suppose the camera is mounted 0.1 m ahead of the base origin and 0.6 m above it, looking forward. The rotation below sends the camera’s axes to the base frame’s. A point 0.3 m straight ahead of the camera then has the following base-frame coordinates:
R_BC = np.array([[0.0, 0.0, 1.0], # columns are the camera's x, y, z axes written in the base frame
[-1.0, 0.0, 0.0],
[0.0, -1.0, 0.0]])
t_BC = np.array([0.1, 0.0, 0.6])
print(np.allclose(R_BC.T @ R_BC, np.eye(3)), round(float(np.linalg.det(R_BC)), 3))
p_cam = np.array([0.0, 0.0, 0.3]) # 0.3 m straight ahead of the camera
print(R_BC @ p_cam + t_BC)Output:
True 1.0 [0.4 0. 0.6]
The point is 0.4 m ahead of the base and 0.6 m up, as expected for something 0.3 m beyond a camera that sits 0.1 m ahead of the base and 0.6 m above it. The matrix R_BC is a valid rotation (orthonormal, determinant 1), so the check passes. If the axes conventions were mixed up, say by treating the camera’s z as “up”, the point would land somewhere else with no warning. A robot’s camera-to-base transform is found by calibration, which Phase 9 of the roadmap covers in more detail.
Common misconceptions
Misconception 1 “A position is just three numbers.”
Correction The numbers only mean something relative to a frame. The same point has different coordinates in every frame.
Misconception 2 “The order of transforms does not matter.”
Correction Matrix multiplication is not commutative. Reversing a chain gives a different, plausible-looking, wrong result.
Misconception 3 “Rotations behave like positions: add them.”
Correction Rotations are composed by multiplication, they do not commute in 3-D, and Euler angles cannot simply be added.
Misconception 4 “All cameras and robots use the same axis conventions.”
Correction Conventions differ, for example camera z forward versus robot x forward. They must be checked and converted.
Engineering takeaways
- A frame is an origin and a set of axes, and a point has different coordinates in each frame.
- A transform is a rotation followed by a translation:
p_W = R p_B + t. - A homogeneous matrix combines both into one multiplication.
- Chain transforms so the inner frame letters cancel, and mind the order.
- The inverse of a rigid transform uses
Rᵀand−Rᵀ t. - A 3-D rotation is orthonormal with determinant 1, and rotations do not commute.
- Orientations are stored as matrices, Euler angles or quaternions, and conventions vary.
- Camera-to-base transforms come from calibration, and wrong axis conventions fail silently.
Before moving a robot to a point, make sure you know which frame the point is in.
Knowledge check
Try each question first, then reveal the explanation.
Question 1
A point is at (1, 0) in frame B. Frame B is rotated 90° and located at (2, 0) in the world frame W. Where is the point in W?
Explanation
(2, 1). The rotation by 90° sends (1, 0) to (0, 1), and adding the translation (2, 0) gives (2, 1).
Question 2
You compute T_WB @ T_BC @ p_C. What frame is the result in, and which two frame letters cancel inside the product?
Explanation
The result is in W, the world frame. Reading W B · B C · C, the two B’s cancel and the two C’s cancel, leaving W.
Question 3
A rotation matrix has a determinant of −1. What does that tell you?
Explanation
It is not a proper rotation, it includes a reflection (a flip). Valid rotations are orthonormal with determinant +1, so a −1 usually points to a mistake such as mixing a right-handed and a left-handed convention.
What’s next
You can now move points between frames. Next is how the hand’s target pose is turned into joint commands, and the choices that involves.