Chapter 4: Serial-Chain Kinematics Structure
Lesson 1: Links, Joints, and Generalized Coordinates
This lesson formalizes the kinematic structure of serial-chain manipulators in terms of rigid links, joints, and generalized coordinates. We treat a robot arm as a multi-body system whose configuration is described by a minimal coordinate vector \( \mathbf{q} \in \mathbb{R}^n \), and we relate these coordinates to the underlying rigid-body configurations in \( \mathrm{SE}(3) \). The constructions here are the backbone for forward kinematics, Jacobians, and dynamics in later chapters.
1. Conceptual Overview of Serial Chains
A serial-chain manipulator is a sequence of rigid bodies (links) connected by joints that form an open-chain (no closed loops). One link is attached to the ground (base), and the last link carries the end-effector. Each joint introduces one or more degrees of freedom (DOFs) and is actuated by a joint variable. The collection of all joint variables forms the vector of generalized coordinates.
Let there be \( n \) joints and \( n+1 \) links labelled \( L_0,\dots,L_n \), with \( L_0 \) the base and \( L_n \) the terminal link. For each link \( L_i \) we attach a body-fixed frame whose pose with respect to a world frame is a homogeneous transform
\[ \mathbf{T}_i(\mathbf{q}) \in \mathrm{SE}(3),\quad \mathbf{T}_i(\mathbf{q}) = \begin{bmatrix} \mathbf{R}_i(\mathbf{q}) & \mathbf{p}_i(\mathbf{q}) \\ \mathbf{0}^\top & 1 \end{bmatrix}, \quad i = 0,\dots,n. \]
The vector of joint coordinates is \( \mathbf{q} = (q_1,\dots,q_n)^\top \). The configuration space of the manipulator is modeled as a differentiable manifold (typically a subset of \( \mathbb{R}^n \) or a product of circles and intervals), and \( \mathbf{q} \) serves as a coordinate chart on this manifold.
flowchart TD
W["World / Base frame (L0)"]
--> J1["Joint 1 (q1)"]
--> L1["Link L1"]
--> J2["Joint 2 (q2)"]
--> L2["Link L2"]
--> J3["Joint 3 (q3)"]
--> Ln["Link Ln (end-effector)"]
Conceptually, each joint \( J_i \) reparameterizes the relative motion between consecutive links with a small number of scalar variables, instead of treating each link pose as an independent element of \( \mathrm{SE}(3) \).
2. Links as Rigid Bodies and Frame Assignment
From Chapter 2, a rigid body configuration is an element of \( \mathrm{SE}(3) \). For each link \( L_i \) we choose a body-fixed frame and denote its pose relative to the world frame by \( \mathbf{T}_i(\mathbf{q}) \).
In a serial chain, these poses satisfy kinematic compatibility constraints induced by the joints. Specifically, if joint \( J_i \) connects \( L_{i-1} \) to \( L_i \), then
\[ \mathbf{T}_i(\mathbf{q}) = \mathbf{T}_{i-1}(\mathbf{q})\,\mathbf{G}_i(q_i), \quad i = 1,\dots,n, \]
where \( \mathbf{G}_i(q_i) \in \mathrm{SE}(3) \) is the relative transform of link \( L_i \) with respect to link \( L_{i-1} \) induced by the joint displacement \( q_i \). The base link pose \( \mathbf{T}_0 \) is usually fixed:
\[ \mathbf{T}_0(\mathbf{q}) = \mathbf{T}_0^{\mathrm{base}} \quad\text{(often } \mathbf{T}_0^{\mathrm{base}} = \mathbf{I}_4\text{)}. \]
Thus the entire kinematic structure is encoded by the set of joint transforms \( \{\mathbf{G}_i(q_i)\}_{i=1}^n \) and the base pose. Forward kinematics (Chapter 5) will build upon this relation, but our focus here is on how the joint variables \( q_i \) are defined.
3. Joint Types and Joint Coordinates
A joint is a kinematic pair that constrains the relative motion between two links. Common low-order joints used in robotic manipulators include:
- Revolute joint (R): one rotational DOF about a fixed axis. Joint variable \( q_i \) is an angle (in radians).
- Prismatic joint (P): one translational DOF along a fixed axis. Joint variable \( q_i \) is a signed displacement.
- Spherical joint (S): three rotational DOFs about a single point. Joint coordinates often parameterize orientation (e.g., Euler angles or unit-quaternion parameters).
- Planar joint: three DOFs (two translations in a plane plus one rotation about an axis normal to that plane).
- Fixed joint: zero DOFs; used to attach tooling or sensors rigidly.
In this course, the majority of examples will be based on 1-DOF joints (revolute or prismatic). For a 1-DOF joint, the relative transform has the form
\[ \mathbf{G}_i(q_i) = \begin{bmatrix} \mathbf{R}_i(q_i) & \mathbf{p}_i(q_i) \\ \mathbf{0}^\top & 1 \end{bmatrix} \in \mathrm{SE}(3), \]
where \( \mathbf{R}_i(q_i) \in \mathrm{SO}(3) \) and \( \mathbf{p}_i(q_i) \in \mathbb{R}^3 \) are smooth functions of \( q_i \). Two canonical examples are:
-
Revolute about fixed axis with axis unit vector
\( \hat{\omega}_i \) and rotation angle
\( q_i \):
\[ \mathbf{R}_i(q_i) = \exp\!\big(\widehat{\hat{\omega}_i}\,q_i\big), \quad \mathbf{p}_i(q_i) = \mathbf{p}_i^0, \]
where \( \widehat{\hat{\omega}_i} \) is the skew-symmetric matrix from Chapter 2 and \( \mathbf{p}_i^0 \) is a constant offset. -
Prismatic along fixed axis with direction unit vector
\( \hat{d}_i \) and displacement
\( q_i \):
\[ \mathbf{R}_i(q_i) = \mathbf{R}_i^0,\quad \mathbf{p}_i(q_i) = \mathbf{p}_i^0 + q_i\,\hat{d}_i. \]
These functions define how the joint coordinate \( q_i \) enters the kinematic model. In later chapters we will exploit their smoothness to obtain Jacobians and dynamics.
4. Generalized Coordinates and Configuration Manifolds
In analytical mechanics, generalized coordinates are any set of independent variables that uniquely describe the configuration of a mechanical system, subject to holonomic constraints. For a serial-chain manipulator with \( n \) independent joints, a natural choice of generalized coordinates is the vector of joint variables
\[ \mathbf{q} = \begin{bmatrix} q_1 & \dots & q_n \end{bmatrix}^\top \in \mathcal{Q}, \]
where \( \mathcal{Q} \) is the joint space or configuration manifold. Ignoring joint limits, if there are \( n_R \) revolute joints and \( n_P \) prismatic joints, then
\[ \mathcal{Q} \cong (S^1)^{n_R} \times \mathbb{R}^{n_P}, \quad n_R + n_P = n, \]
where \( S^1 \) is the unit circle (angles modulo \( 2\pi \)). With joint limits, each coordinate is restricted to an interval (for both revolute and prismatic joints), and \( \mathcal{Q} \) becomes a subset of \( \mathbb{R}^n \).
The generalized coordinates are related to the physical link configurations by a smooth map
\[ \Phi: \mathcal{Q} \rightarrow \mathrm{SE}(3)^{n+1}, \quad \Phi(\mathbf{q}) = \big(\mathbf{T}_0(\mathbf{q}),\dots,\mathbf{T}_n(\mathbf{q})\big), \]
with the property that \( \Phi \) is locally one-to-one and onto the physically feasible configurations of the chain. The dimension of \( \mathcal{Q} \) is then the number of DOFs of the mechanism.
5. DOF Counting for Open Serial Chains
We now justify the intuitive statement that an open-chain manipulator with \( n \) 1-DOF joints has \( n \) DOFs. The argument is based on counting constraints among rigid-body configurations.
Consider \( n+1 \) links, each with an independent pose in \( \mathrm{SE}(3) \). The space of all such collections has dimension
\[ \dim\big(\mathrm{SE}(3)^{n+1}\big) = 6(n+1), \]
since each element of \( \mathrm{SE}(3) \) contributes 3 rotational and 3 translational DOFs.
Now suppose these links are connected into a chain by \( n \) joints, each allowing one DOF of relative motion. Without joints, the relative pose of \( L_i \) with respect to \( L_{i-1} \) could be any element of \( \mathrm{SE}(3) \) (6 DOFs). A 1-DOF joint restricts this relative pose to a 1-dimensional subset \( \mathcal{M}_i \subset \mathrm{SE}(3) \). Thus each joint introduces \( 6-1 = 5 \) independent constraints.
The total number of constraints from the joints is then \( 5n \). In addition, we usually fix the base link pose \( \mathbf{T}_0 \) with respect to the world, introducing 6 more constraints. Therefore, the DOF count is
\[ \text{DOF} = 6(n+1) - 5n - 6 = n. \]
This calculation confirms that the dimension of the configuration manifold is equal to the number of 1-DOF joints for an open serial chain with a fixed base and no closed loops or additional constraints.
More complex mechanisms (closed chains, constraints between non-adjacent links) will modify the constraint count, and the generalized coordinates will no longer be simply the list of joint variables. These topics will be treated in later chapters.
6. Joint Limits and Topology of Joint Space
Real manipulators have joint limits. For a revolute joint, \( q_i \) is often constrained to a range \( [q_i^{\min}, q_i^{\max}] \) with \( q_i^{\max} - q_i^{\min} < 2\pi \). For a prismatic joint, \( q_i \) may be limited to \( [d_i^{\min}, d_i^{\max}] \). As a result, the actual configuration space is
\[ \mathcal{Q}_{\mathrm{phys}} = \big\{\mathbf{q} \in \mathbb{R}^n \,\big|\, q_i^{\min} \le q_i \le q_i^{\max},\; i=1,\dots,n \big\}. \]
This set is typically a hyper-rectangle (possibly with additional forbidden regions due to self-collision). From a modeling point of view, joint limits are inequality constraints on the generalized coordinates, and they will influence planning and control algorithms but not the local differential structure of \( \mathcal{Q} \) within the admissible region.
flowchart TD
Qdef["Define ideal joint space Q = (S1)^n_R x R^n_P"]
--> Limits["Apply joint limits: q_i_min <= q_i <= q_i_max"]
--> Qphys["Physical joint space Q_phys (subset of R^n)"]
--> Use["Use Q_phys for planning, kinematics, dynamics"]
7. Python Lab — Basic Link/Joint Data Structures
We now implement simple data structures in Python to represent links,
joints, and generalized coordinates for a serial chain. We use
numpy for linear algebra; more advanced courses may use
roboticstoolbox-python (Corke) or
pin (Pinocchio Python bindings) for full robot models.
import numpy as np
from enum import Enum, auto
from dataclasses import dataclass
from typing import List
class JointType(Enum):
REVOLUTE = auto()
PRISMATIC = auto()
FIXED = auto()
def rot_z(theta: float) -> np.ndarray:
"""Rotation about z-axis."""
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 homog(R: np.ndarray, p: np.ndarray) -> np.ndarray:
"""Build 4x4 homogeneous transform."""
T = np.eye(4)
T[:3, :3] = R
T[:3, 3] = p
return T
@dataclass
class Joint:
jtype: JointType
axis: np.ndarray # 3D unit vector
offset: float = 0.0 # constant offset (angle or length)
@dataclass
class Link:
name: str
length: float
joint: Joint
@dataclass
class SerialChain:
links: List[Link]
def forward_kinematics(self, q: np.ndarray) -> List[np.ndarray]:
"""
Compute link frames T_i(q) (i = 0..n) in a simple planar-style model:
all joints rotate about z, link frames lie in xy-plane.
"""
assert q.shape[0] == len(self.links)
Ts = []
T = np.eye(4) # base frame
Ts.append(T.copy())
for i, (link, qi) in enumerate(zip(self.links, q), start=1):
if link.joint.jtype == JointType.REVOLUTE:
theta = link.joint.offset + qi
R = rot_z(theta)
# translation along x-axis by link.length
p = np.array([link.length, 0.0, 0.0])
A_i = homog(R, p)
elif link.joint.jtype == JointType.PRISMATIC:
d = link.joint.offset + qi
R = np.eye(3)
p = np.array([d, 0.0, 0.0])
A_i = homog(R, p)
else: # FIXED
A_i = np.eye(4)
T = T @ A_i
Ts.append(T.copy())
return Ts
# Example: 2R planar arm
link1 = Link("L1", length=1.0, joint=Joint(JointType.REVOLUTE, axis=np.array([0, 0, 1])))
link2 = Link("L2", length=0.7, joint=Joint(JointType.REVOLUTE, axis=np.array([0, 0, 1])))
arm = SerialChain([link1, link2])
q = np.array([np.deg2rad(45.0), np.deg2rad(-30.0)])
Ts = arm.forward_kinematics(q)
print("End-effector transform:\n", Ts[-1])
This model assumes all joints rotate about the z-axis, so
the chain is effectively planar. In Chapter 5 we will generalize this to
full 3D chains and relate SerialChain to standard robotics
toolboxes.
8. C++ Implementation Sketch (Eigen / KDL-style)
In C++, it is common to use Eigen for matrix operations and
libraries like Orocos KDL or Pinocchio for
robot kinematics and dynamics. The following minimal example shows how
one might encode a revolute joint and accumulate transforms.
#include <iostream>
#include <vector>
#include <Eigen/Dense>
enum class JointType { REVOLUTE, PRISMATIC, FIXED };
struct Joint {
JointType type;
Eigen::Vector3d axis; // axis in parent link frame
double offset; // constant offset
};
struct Link {
std::string name;
double length;
Joint joint;
};
Eigen::Matrix4d rotZ(double theta) {
double c = std::cos(theta), s = std::sin(theta);
Eigen::Matrix4d T = Eigen::Matrix4d::Identity();
T(0,0) = c; T(0,1) = -s;
T(1,0) = s; T(1,1) = c;
return T;
}
Eigen::Matrix4d transX(double d) {
Eigen::Matrix4d T = Eigen::Matrix4d::Identity();
T(0,3) = d;
return T;
}
std::vector<Eigen::Matrix4d>
forwardKinematics(const std::vector<Link>& links,
const Eigen::VectorXd& q) {
std::vector<Eigen::Matrix4d> Ts;
Eigen::Matrix4d T = Eigen::Matrix4d::Identity(); // base
Ts.push_back(T);
for (std::size_t i = 0; i < links.size(); ++i) {
const Link& L = links[i];
double qi = q[i];
Eigen::Matrix4d A = Eigen::Matrix4d::Identity();
if (L.joint.type == JointType::REVOLUTE) {
double theta = L.joint.offset + qi;
A = rotZ(theta) * transX(L.length);
} else if (L.joint.type == JointType::PRISMATIC) {
double d = L.joint.offset + qi;
A = transX(d);
}
// FIXED: A is identity
T = T * A;
Ts.push_back(T);
}
return Ts;
}
int main() {
std::vector<Link> links;
links.push_back({"L1", 1.0, {JointType::REVOLUTE, {0,0,1}, 0.0}});
links.push_back({"L2", 0.7, {JointType::REVOLUTE, {0,0,1}, 0.0}});
Eigen::VectorXd q(2);
q << M_PI / 4.0, -M_PI / 6.0;
auto Ts = forwardKinematics(links, q);
std::cout << "End-effector transform:\n" << Ts.back() << std::endl;
return 0;
}
Full-featured libraries such as Orocos KDL use similar
concepts (links, segments, joints) but provide more flexible joint
models, tree structures, and efficient Jacobian and dynamics
computations.
9. Java Implementation Sketch (Joint Space Representation)
While robotics libraries in Java are less standardized, one can use
EJML or Apache Commons Math for linear algebra
and implement kinematic chains similarly. Below is a lightweight
representation using EJML-style matrices.
public enum JointType {
REVOLUTE, PRISMATIC, FIXED
}
public class Joint {
public JointType type;
public double offset;
public Joint(JointType type, double offset) {
this.type = type;
this.offset = offset;
}
}
public class Link {
public String name;
public double length;
public Joint joint;
public Link(String name, double length, Joint joint) {
this.name = name;
this.length = length;
this.joint = joint;
}
}
public class SerialChain {
private List<Link> links;
public SerialChain(List<Link> links) {
this.links = links;
}
// Simple 4x4 transform represented as double[4][4]
private static double[][] identity4() {
double[][] I = new double[4][4];
for (int i = 0; i < 4; ++i) {
I[i][i] = 1.0;
}
return I;
}
private static double[][] rotZ(double theta) {
double c = Math.cos(theta), s = Math.sin(theta);
double[][] T = identity4();
T[0][0] = c; T[0][1] = -s;
T[1][0] = s; T[1][1] = c;
return T;
}
private static double[][] transX(double d) {
double[][] T = identity4();
T[0][3] = d;
return T;
}
private static double[][] matMul(double[][] A, double[][] B) {
double[][] C = new double[4][4];
for (int i = 0; i < 4; ++i) {
for (int j = 0; j < 4; ++j) {
double sum = 0.0;
for (int k = 0; k < 4; ++k) {
sum += A[i][k] * B[k][j];
}
C[i][j] = sum;
}
}
return C;
}
public List<double[][]> forwardKinematics(double[] q) {
if (q.length != links.size()) {
throw new IllegalArgumentException("Dimension mismatch");
}
List<double[][]> Ts = new ArrayList<>();
double[][] T = identity4(); // base
Ts.add(T);
for (int i = 0; i < links.size(); ++i) {
Link L = links.get(i);
double qi = q[i];
double[][] A = identity4();
if (L.joint.type == JointType.REVOLUTE) {
double theta = L.joint.offset + qi;
A = matMul(rotZ(theta), transX(L.length));
} else if (L.joint.type == JointType.PRISMATIC) {
double d = L.joint.offset + qi;
A = transX(d);
}
T = matMul(T, A);
Ts.add(T);
}
return Ts;
}
}
This Java model encapsulates the same kinematic structure: a list of links with associated joints and a method that maps generalized coordinates \( \mathbf{q} \) to link transforms.
10. MATLAB/Simulink Representation (RigidBodyTree)
MATLAB's Robotics System Toolbox provides the
rigidBodyTree class to represent serial and tree-structured
mechanisms. Simulink integration (via Simscape Multibody or custom
blocks) uses the same notion of links and joints. A simple 2R arm can be
modeled as follows:
% Define a 2R planar arm as a rigidBodyTree
robot = rigidBodyTree("DataFormat","row","MaxNumBodies",3);
% Link 1
body1 = rigidBody("L1");
jnt1 = rigidBodyJoint("J1","revolute");
setFixedTransform(jnt1, trvec2tform([0 0 0])); % base to joint 1
jnt1.JointAxis = [0 0 1]; % rotation about z
body1.Joint = jnt1;
addBody(robot, body1, robot.BaseName);
% Link 2
body2 = rigidBody("L2");
jnt2 = rigidBodyJoint("J2","revolute");
L1 = 1.0;
setFixedTransform(jnt2, trvec2tform([L1 0 0])); % along x from joint 1
jnt2.JointAxis = [0 0 1];
body2.Joint = jnt2;
addBody(robot, body2, "L1");
% End-effector frame
tool = rigidBody("tool");
setFixedTransform(tool.Joint, trvec2tform([0.7 0 0]));
addBody(robot, tool, "L2");
% Joint configuration (generalized coordinates)
q = [deg2rad(45) deg2rad(-30)];
T_ee = getTransform(robot, q, "tool", robot.BaseName);
disp(T_ee);
In Simulink, one can either import such a model into Simscape Multibody or build an equivalent chain of Rigid Transform and Revolute Joint blocks, with joint state variables serving as the generalized coordinates.
11: Wolfram Mathematica Symbolic Link–Joint Model
Wolfram Mathematica is well suited for symbolic kinematic modeling, providing closed-form expressions for link transforms and end-effector pose as functions of generalized coordinates.
(* Define symbolic joint variables *)
Clear[q1, q2, L1, L2];
Assuming[{L1 > 0, L2 > 0},
Rz[theta_] := { {Cos[theta], -Sin[theta], 0, 0},
{Sin[theta], Cos[theta], 0, 0},
{0, 0, 1, 0},
{0, 0, 0, 1} };
Tx[d_] := { {1, 0, 0, d},
{0, 1, 0, 0},
{0, 0, 1, 0},
{0, 0, 0, 1} };
T1[q1_] := Rz[q1].Tx[L1];
T2[q2_] := Rz[q2].Tx[L2];
(* Overall transform for 2R planar chain *)
Tee[q1_, q2_] := Simplify[T1[q1].T2[q2]];
(* Extract end-effector position as function of q1, q2 *)
pe[q1_, q2_] := Tee[q1, q2][[1 ;; 3, 4]];
pe[q1, q2]
]
This snippet constructs symbolic homogeneous transforms for a 2R planar arm and extracts the end-effector position vector \( \mathbf{p}_e(q_1,q_2) \), which will be useful when differentiating to obtain Jacobians in later chapters.
12. Problems and Solutions
Problem 1 (DOF Count for a 6R Manipulator): Consider a classical 6R industrial manipulator: six revolute joints in an open chain, base fixed to the ground, and no additional constraints. Assuming all joints are 1-DOF and non-redundant, compute the DOFs of the manipulator and describe the topology of its ideal joint space (ignoring limits).
Solution:
We have \( n = 6 \) 1-DOF joints, so by the argument in Section 5, the DOF count is
\[ \text{DOF} = n = 6. \]
Since all joints are revolute, we have \( n_R = 6 \) and \( n_P = 0 \). The ideal joint space is
\[ \mathcal{Q} \cong (S^1)^6, \]
a 6-dimensional torus. In practice, joint limits restrict each angle to an interval, so the physically accessible set is a subset of \( \mathbb{R}^6 \).
Problem 2 (DOF Count via Constraint Counting): Show explicitly that an open chain with \( n+1 \) links and \( n \) 1-DOF joints, with a fixed base, has \( n \) DOFs by counting independent coordinates and constraints. Use the constraint that each joint restricts the relative motion between its two incident links to a 1-dimensional subset of \( \mathrm{SE}(3) \).
Solution:
Start from the unconstrained system: \( n+1 \) free links, each with a pose in \( \mathrm{SE}(3) \). This has \( 6(n+1) \) DOFs. Next, we connect links by joints. For each joint between \( L_{i-1} \) and \( L_i \), the relative pose \( \mathbf{T}_{i-1}^{-1}\mathbf{T}_i \) is restricted from arbitrary \( \mathrm{SE}(3) \) (6 DOFs) to a 1D set \( \mathcal{M}_i \), introducing \( 6-1 = 5 \) constraints. The total number of constraints from joints is therefore \( 5n \).
Fixing the base link pose adds 6 more constraints. Thus
\[ \text{DOF} = 6(n+1) - 5n - 6 = n. \]
Hence the configuration manifold is \( n \)-dimensional, and a minimal set of generalized coordinates can be taken as the vector of joint variables \( \mathbf{q} \).
Problem 3 (Configuration Map for a 2R Planar Manipulator): A 2R planar arm lies in the \( x\!-\!y \) plane with link lengths \( L_1, L_2 > 0 \) and joint angles \( q_1, q_2 \) (measured from the preceding link). Derive the end-effector position \( \mathbf{p}_e(q_1,q_2) \) and show that the map \( \Phi: \mathbb{R}^2 \rightarrow \mathbb{R}^2 \) given by joint angles to planar position is smooth.
Solution:
The kinematic chain is \( L_0 \xrightarrow{q_1} L_1 \xrightarrow{q_2} L_2 \). The end-effector position in the base frame is
\[ \mathbf{p}_e(q_1,q_2) = \begin{bmatrix} L_1\cos q_1 + L_2\cos(q_1 + q_2) \\ L_1\sin q_1 + L_2\sin(q_1 + q_2) \end{bmatrix}. \]
Each component is a composition of smooth functions (sums, products, sines, cosines), hence \( \Phi(q_1,q_2) = \mathbf{p}_e(q_1,q_2) \) is smooth on \( \mathbb{R}^2 \). This confirms that \( (q_1,q_2) \) are valid local generalized coordinates for the planar arm configuration.
Problem 4 (Topology of Joint Space with Limits): Suppose a 3R planar arm has joint limits \( q_i \in [q_i^{\min}, q_i^{\max}] \) with \( q_i^{\max} - q_i^{\min} < 2\pi \) for each \( i = 1,2,3 \). Describe the topology of the reachable joint space and discuss whether it is homeomorphic to \( (S^1)^3 \).
Solution:
Because each joint is restricted to a closed interval strictly shorter than a full revolution, the physically reachable joint space is
\[ \mathcal{Q}_{\mathrm{phys}} = [q_1^{\min},q_1^{\max}]\times [q_2^{\min},q_2^{\max}]\times [q_3^{\min},q_3^{\max}] \subset \mathbb{R}^3. \]
Topologically, this is a 3D box (a compact convex subset of \( \mathbb{R}^3 \)), not a 3-torus. Thus \( \mathcal{Q}_{\mathrm{phys}} \) is not homeomorphic to \( (S^1)^3 \). Only when joint angles are allowed to wrap continuously modulo \( 2\pi \) (with no limits) does the joint space become a torus.
Problem 5 (Fixed Joint as Zero-DOF Constraint): Consider a chain with three links \( L_0,L_1,L_2 \) where \( L_0 \) and \( L_1 \) are connected by a fixed joint (zero DOF), and \( L_1 \) and \( L_2 \) are connected by a revolute joint (1 DOF). Show that the configuration space has 1 DOF and explain why treating the fixed joint as a 1-DOF joint with permanently locked coordinate is conceptually misleading.
Solution:
Two free links and a base-fixed system would initially yield \( 6\times3 = 18 \) DOFs. A fixed joint between \( L_0 \) and \( L_1 \) enforces that their poses are identical, restricting their relative motion to a single point in \( \mathrm{SE}(3) \). This removes 6 DOFs and introduces no generalized coordinate. The revolute joint between \( L_1 \) and \( L_2 \) restricts their relative motion to a 1D subset, removing 5 DOFs and adding a single generalized coordinate \( q_1 \). Fixing the base adds 6 constraints. Thus
\[ \text{DOF} = 18 - 6\;(\text{fixed joint}) - 5\;(\text{revolute}) - 6\;(\text{fixed base}) = 1. \]
Modeling the fixed joint as a revolute with coordinate permanently set to a constant introduces an unnecessary generalized coordinate and a constraint equation, which complicates analysis without changing the configuration manifold. It is therefore preferable to represent fixed joints explicitly as zero-DOF connections.
13. Summary
In this lesson we formalized the kinematic structure of serial-chain manipulators. We modeled links as rigid bodies with configurations in \( \mathrm{SE}(3) \), joints as kinematic pairs restricting relative motion to low-dimensional subsets of \( \mathrm{SE}(3) \), and generalized coordinates as a minimal set of variables describing the chain configuration. We showed that an open chain with \( n \) 1-DOF joints has \( n \) DOFs, and we examined the topology of joint space with and without joint limits. We also illustrated code-level representations of links, joints, and joint coordinates in Python, C++, Java, MATLAB/Simulink, and Wolfram Mathematica. These abstractions will be the foundation for forward kinematics, Jacobians, dynamics, and control in subsequent chapters.
14. References
- Denavit, J., & Hartenberg, R.S. (1955). A kinematic notation for lower-pair mechanisms based on matrices. Journal of Applied Mechanics, 22, 215–221.
- Paul, R.P. (1979). A mathematical formulation of manipulator kinematics. Journal of Mechanisms, Transmissions, and Automation in Design, 101(2), 187–193.
- Angeles, J. (1982). Kinematic isotropy and the conditioning index of serial robotic manipulators. International Journal of Robotics Research, 2(2), 21–34.
- Brockett, R.W. (1984). Robotic manipulators and the product of exponentials formula. In Mathematical Theory of Networks and Systems, 120–129.
- Murray, R.M., Li, Z., & Sastry, S.S. (1994). A mathematical introduction to robotic manipulation. Various journal and conference excerpts on kinematic modeling.
- Featherstone, R. (1999). A divide-and-conquer articulated-body algorithm for parallel O(log n) calculation of rigid-body dynamics. International Journal of Robotics Research, 18(9), 867–875.
- Park, F.C., & Kim, J. (1998). Manipulability and singularity analysis of robot mechanisms using Lie groups. International Journal of Robotics Research, 17(6), 659–674.
- Selig, J.M. (2005). Geometric fundamentals of robotics. Journal article series on screw theory and kinematics.