Chapter 7: Differential Kinematics

Lesson 2: Jacobian Derivation (PoE + DH perspectives)

This lesson develops the geometric Jacobian of serial manipulators from two complementary viewpoints: the Product of Exponentials (PoE) formulation on SE(3) and the classical Denavit–Hartenberg (DH) convention. We derive the spatial and body Jacobians from the PoE forward kinematics map, show how the DH-based formula using joint axes and origins leads to the same object, and work out explicit planar examples. We conclude with multi-language implementations (Python, C++, Java, MATLAB/Simulink, Wolfram Mathematica) to solidify the computational aspects.

1. Conceptual Overview of the Jacobian

For an n-DOF serial manipulator with joint coordinates \( \mathbf{q} \in \mathbb{R}^n \) and joint velocities \( \dot{\mathbf{q}} \in \mathbb{R}^n \), the geometric Jacobian is the matrix \( \mathbf{J}(\mathbf{q}) \in \mathbb{R}^{6 \times n} \) such that the end-effector twist (spatial velocity) satisfies

\[ \mathbf{V}_s = \begin{bmatrix} \boldsymbol{\omega}_s \\[4pt] \mathbf{v}_s \end{bmatrix} = \mathbf{J}_s(\mathbf{q}) \, \dot{\mathbf{q}}, \quad \mathbf{V}_b = \begin{bmatrix} \boldsymbol{\omega}_b \\[4pt] \mathbf{v}_b \end{bmatrix} = \mathbf{J}_b(\mathbf{q}) \, \dot{\mathbf{q}}, \]

where \( \mathbf{V}_s \) is expressed in a fixed space frame and \( \mathbf{V}_b \) in the moving end-effector (body) frame. The two Jacobians are related by the adjoint representation on twists:

\[ \mathbf{V}_b = \operatorname{Ad}_{\mathbf{T}(\mathbf{q})^{-1}} \, \mathbf{V}_s, \quad \Rightarrow \quad \mathbf{J}_b(\mathbf{q}) = \operatorname{Ad}_{\mathbf{T}(\mathbf{q})^{-1}} \, \mathbf{J}_s(\mathbf{q}), \]

where \( \mathbf{T}(\mathbf{q}) \in SE(3) \) is the end-effector pose. In the PoE formulation the Jacobian columns are built from joint twists and adjoint transformations, while in the DH formulation they are built from joint axes and frame origins obtained from the homogeneous transformations.

flowchart TD
  Q["Joint space (q, qdot)"] --> P["PoE FK: T(q) = exp([xi1] theta1) ... M"]
  Q --> D["DH FK: product of A_i(q_i) matrices"]
  P --> JS["Spatial Jacobian Js(q) from twists and adjoints"]
  D --> JD["Jacobian from joint axes (z) and origins (o)"]
  JS --> V["End-effector twist Vs = J(q) * qdot"]
  JD --> V
        

Our goal is to show that both branches produce the same geometric Jacobian when expressed in the same frame, and to give explicit constructive formulas suitable for implementation.

2. Twists, PoE Kinematics, and the Adjoint Operator

Recall from Chapter 2 that a rigid motion is represented by \( \mathbf{T} \in SE(3) \):

\[ \mathbf{T} = \begin{bmatrix} \mathbf{R} & \mathbf{p} \\ \mathbf{0}^\top & 1 \end{bmatrix}, \quad \mathbf{R} \in SO(3),\; \mathbf{p} \in \mathbb{R}^3. \]

A twist is an element of the Lie algebra \( \mathfrak{se}(3) \) represented as \( \boldsymbol{\xi} = (\boldsymbol{\omega}, \mathbf{v}) \in \mathbb{R}^6 \), with the hat operator

\[ [\boldsymbol{\xi}]^\wedge = \begin{bmatrix} [\boldsymbol{\omega}]_\times & \mathbf{v} \\ \mathbf{0}^\top & 0 \end{bmatrix}, \quad [\boldsymbol{\omega}]_\times = \begin{bmatrix} 0 & -\omega_3 & \omega_2 \\ \omega_3 & 0 & -\omega_1 \\ -\omega_2 & \omega_1 & 0 \end{bmatrix}. \]

For a revolute joint with axis unit vector \( \boldsymbol{\omega} \) passing through a point \( \mathbf{q}_0 \) in the space frame, the twist is

\[ \boldsymbol{\xi} = \begin{bmatrix} \boldsymbol{\omega} \\[4pt] - \boldsymbol{\omega} \times \mathbf{q}_0 \end{bmatrix}, \]

while for a prismatic joint translating along direction \( \mathbf{v} \) we have \( \boldsymbol{\omega} = \mathbf{0} \) and \( \boldsymbol{\xi} = ( \mathbf{0}, \mathbf{v} ) \).

The PoE forward kinematics of an n-DOF open chain with joint variables \( \boldsymbol{\theta} = [\theta_1,\dots,\theta_n]^\top \) is

\[ \mathbf{T}(\boldsymbol{\theta}) = e^{[\boldsymbol{\xi}_1]^\wedge \theta_1} e^{[\boldsymbol{\xi}_2]^\wedge \theta_2} \cdots e^{[\boldsymbol{\xi}_n]^\wedge \theta_n} \, \mathbf{M}, \]

where \( \mathbf{M} \) is the home configuration of the end-effector.

The adjoint representation \( \operatorname{Ad}_{\mathbf{T}} \) maps twists between frames:

\[ \operatorname{Ad}_{\mathbf{T}} = \begin{bmatrix} \mathbf{R} & \mathbf{0} \\ [\mathbf{p}]_\times \mathbf{R} & \mathbf{R} \end{bmatrix}, \quad \boldsymbol{\xi}_s = \operatorname{Ad}_{\mathbf{T}} \, \boldsymbol{\xi}_b. \]

This operator will be essential in building Jacobian columns from the PoE formula by “transporting” joint twists along the chain.

3. Spatial Jacobian from the PoE Formulation

Consider the PoE map \( \mathbf{T}(\boldsymbol{\theta}) \). Differentiating with respect to time using the product rule and the identity \( \frac{d}{dt} e^{[\boldsymbol{\xi}]^\wedge \theta(t)} = [\boldsymbol{\xi}]^\wedge e^{[\boldsymbol{\xi}]^\wedge \theta(t)} \dot{\theta}(t) \), we obtain

\[ \dot{\mathbf{T}} = \sum_{k=1}^n \left( e^{[\boldsymbol{\xi}_1]^\wedge \theta_1} \cdots e^{[\boldsymbol{\xi}_{k-1}]^\wedge \theta_{k-1}} [\boldsymbol{\xi}_k]^\wedge e^{[\boldsymbol{\xi}_k]^\wedge \theta_k} \cdots e^{[\boldsymbol{\xi}_n]^\wedge \theta_n} \mathbf{M} \right) \dot{\theta}_k. \]

The spatial twist is defined via right-trivialization:

\[ [\mathbf{V}_s]^\wedge = \dot{\mathbf{T}} \, \mathbf{T}^{-1}. \]

Define \( \mathbf{T}_k(\boldsymbol{\theta}) = e^{[\boldsymbol{\xi}_1]^\wedge \theta_1} \cdots e^{[\boldsymbol{\xi}_k]^\wedge \theta_k} \) and \( \mathbf{T}_0 = \mathbf{I} \). Then \( \mathbf{T} = \mathbf{T}_n \mathbf{M} \). Using the property \( \mathbf{T}_k e^{[\boldsymbol{\xi}_{k+1}]^\wedge \theta_{k+1}} \cdots e^{[\boldsymbol{\xi}_n]^\wedge \theta_n} \mathbf{M} \mathbf{T}^{-1} = \operatorname{Ad}_{\mathbf{T}_k} \), one can show

\[ [\mathbf{V}_s]^\wedge = \sum_{k=1}^n \left( \operatorname{Ad}_{\mathbf{T}_{k-1}} [\boldsymbol{\xi}_k]^\wedge \right) \dot{\theta}_k. \]

Applying the vee map that converts a hat matrix back to a twist vector gives

\[ \mathbf{V}_s = \sum_{k=1}^n \operatorname{Ad}_{\mathbf{T}_{k-1}} \boldsymbol{\xi}_k \, \dot{\theta}_k = \underbrace{\left[ \boldsymbol{\xi}_1,\; \operatorname{Ad}_{\mathbf{T}_1} \boldsymbol{\xi}_2,\; \dots,\; \operatorname{Ad}_{\mathbf{T}_{n-1}} \boldsymbol{\xi}_n \right]}_{\mathbf{J}_s(\boldsymbol{\theta})} \dot{\boldsymbol{\theta}}. \]

Thus the spatial Jacobian is

\[ \mathbf{J}_s(\boldsymbol{\theta}) = \big[ \boldsymbol{\xi}_1,\; \operatorname{Ad}_{e^{[\boldsymbol{\xi}_1]^\wedge \theta_1}} \boldsymbol{\xi}_2,\; \dots,\; \operatorname{Ad}_{e^{[\boldsymbol{\xi}_1]^\wedge \theta_1} \cdots e^{[\boldsymbol{\xi}_{n-1}]^\wedge \theta_{n-1}}} \boldsymbol{\xi}_n \big]. \]

Sketch of inductive proof: For \( n=1 \) we have \( \mathbf{V}_s = \boldsymbol{\xi}_1 \dot{\theta}_1 \), so \( \mathbf{J}_s = [\boldsymbol{\xi}_1] \). Assume the result holds for \( n-1 \) joints. When adding the nth joint, we can factor \( \mathbf{T} = \mathbf{T}_{n-1} e^{[\boldsymbol{\xi}_n]^\wedge \theta_n} \mathbf{M} \) and separate the derivative into: a term that is the old Jacobian transported by \( \operatorname{Ad}_{e^{[\boldsymbol{\xi}_n]^\wedge \theta_n}} \) plus the new column \( \operatorname{Ad}_{\mathbf{T}_{n-1}} \boldsymbol{\xi}_n \dot{\theta}_n \).

4. Body Jacobian from the PoE Formulation

The body twist is defined via left-trivialization:

\[ [\mathbf{V}_b]^\wedge = \mathbf{T}^{-1} \dot{\mathbf{T}}. \]

By direct computation or by symmetry of the PoE formula written “from the right”, one obtains the body Jacobian:

\[ \mathbf{T}(\boldsymbol{\theta}) = \mathbf{M} e^{[\boldsymbol{\xi}_1']^\wedge \theta_1} \cdots e^{[\boldsymbol{\xi}_n']^\wedge \theta_n}, \]

with body twists \( \boldsymbol{\xi}_i' \) expressed in the end-effector home frame. The body Jacobian is then

\[ \mathbf{J}_b(\boldsymbol{\theta}) = \big[ \operatorname{Ad}_{e^{-[\boldsymbol{\xi}_1']^\wedge \theta_1} \cdots e^{-[\boldsymbol{\xi}_{n-1}']^\wedge \theta_{n-1}}} \boldsymbol{\xi}_1',\; \dots,\; \operatorname{Ad}_{e^{-[\boldsymbol{\xi}_n']^\wedge \theta_n}} \boldsymbol{\xi}_{n-1}',\; \boldsymbol{\xi}_n' \big]. \]

Using \( \mathbf{V}_b = \operatorname{Ad}_{\mathbf{T}^{-1}} \mathbf{V}_s \) and \( \mathbf{V}_s = \mathbf{J}_s \dot{\boldsymbol{\theta}} \), we obtain the compact frame-change relation

\[ \mathbf{J}_b(\boldsymbol{\theta}) = \operatorname{Ad}_{\mathbf{T}(\boldsymbol{\theta})^{-1}} \, \mathbf{J}_s(\boldsymbol{\theta}). \]

This relation will be crucial later when connecting task-space control laws expressed in body coordinates with joint-space dynamics, but in the present chapter we use it purely as a kinematic change-of-basis result.

5. DH-Based Jacobian Derivation

In the classical DH convention (Chapter 5), the forward kinematics from base to end-effector frame n is \( {}^0\mathbf{T}_n(\mathbf{q}) = {}^0\mathbf{T}_1(\mathbf{q}) \cdots {}^{n-1}\mathbf{T}_n(\mathbf{q}) \). From each intermediate transform \( {}^0\mathbf{T}_i \) we can extract

  • \( {}^0\mathbf{o}_i \in \mathbb{R}^3 \): origin of frame i,
  • \( {}^0\mathbf{z}_i \in \mathbb{R}^3 \): unit vector of the z-axis of frame i.

For the j-th joint, the contribution to the spatial velocity of the end-effector (expressed in the base frame) is:

  • Revolute joint: angular velocity \( {}^0\boldsymbol{\omega}_j = {}^0\mathbf{z}_{j-1} \dot{q}_j \), linear velocity \( {}^0\mathbf{v}_j = {}^0\mathbf{z}_{j-1} \times ( {}^0\mathbf{o}_n - {}^0\mathbf{o}_{j-1} ) \dot{q}_j \).
  • Prismatic joint: angular velocity \( {}^0\boldsymbol{\omega}_j = \mathbf{0} \), linear velocity \( {}^0\mathbf{v}_j = {}^0\mathbf{z}_{j-1} \dot{q}_j \).

Therefore, the j-th column of the Jacobian \( \mathbf{J}_s^{\mathrm{DH}}(\mathbf{q}) \) is

\[ \mathbf{J}_s^{(j)}(\mathbf{q}) = \begin{cases} \begin{bmatrix} {}^0\mathbf{z}_{j-1} \\ {}^0\mathbf{z}_{j-1} \times ( {}^0\mathbf{o}_n - {}^0\mathbf{o}_{j-1} ) \end{bmatrix}, & \text{revolute joint} \\[12pt] \begin{bmatrix} \mathbf{0} \\ {}^0\mathbf{z}_{j-1} \end{bmatrix}, & \text{prismatic joint.} \end{cases} \]

Stacking all columns yields the full geometric Jacobian:

\[ \mathbf{J}_s^{\mathrm{DH}}(\mathbf{q}) = \big[ \mathbf{J}_s^{(1)}(\mathbf{q}),\dots,\mathbf{J}_s^{(n)}(\mathbf{q}) \big]. \]

This formula is routinely implemented in classical robotics toolboxes where DH parameters are the primary kinematic description. It is algebraically equivalent to the PoE Jacobian when the twists \( \boldsymbol{\xi}_j \) are chosen consistently with the DH frames.

6. Relationship Between PoE and DH Jacobians

Suppose the DH frame j is chosen so that its z-axis coincides with the screw axis of joint j. Then the spatial twist for a revolute joint can be written as

\[ \boldsymbol{\xi}_j = \begin{bmatrix} {}^0\mathbf{z}_{j-1} \\[4pt] - {}^0\mathbf{z}_{j-1} \times {}^0\mathbf{q}_j \end{bmatrix}, \]

where \( {}^0\mathbf{q}_j \) is any point on the joint axis in the base frame (for example, the origin \( {}^0\mathbf{o}_{j-1} \)). Using velocity propagation through the chain, one can show that

\[ {}^0\mathbf{z}_{j-1} \times ( {}^0\mathbf{o}_n - {}^0\mathbf{o}_{j-1} ) = \mathbf{v}_j^{\mathrm{eff}}, \]

where \( \mathbf{v}_j^{\mathrm{eff}} \) is the linear part of the joint twist after being “pushed” from its reference point on the axis to the current end-effector point. This is precisely what the adjoint operator in the PoE Jacobian does.

More formally, the j-th column of the PoE Jacobian can be written as

\[ \mathbf{J}_s^{(j)}(\mathbf{q}) = \operatorname{Ad}_{\mathbf{T}_{j-1}(\mathbf{q})} \boldsymbol{\xi}_j, \]

where \( \mathbf{T}_{j-1} \) is the transform from base to frame \( j-1 \). When \( \boldsymbol{\xi}_j \) encodes \( {}^0\mathbf{z}_{j-1} \) and a reference point on the axis, the adjoint transport recovers exactly the DH column formula. Thus, for compatible choices of frames and twists,

\[ \mathbf{J}_s^{\mathrm{PoE}}(\mathbf{q}) = \mathbf{J}_s^{\mathrm{DH}}(\mathbf{q}). \]

This equivalence is important in practice: PoE provides a coordinate-free, Lie-group-based derivation, while DH connects directly to many legacy algorithms and textbooks.

7. Example — 2R Planar Manipulator Jacobian

Consider a 2R planar arm in the xy-plane with link lengths \( l_1, l_2 \) and joint angles \( q_1, q_2 \), both revolute about the z-axis. The end-effector position (in the base frame) is

\[ \mathbf{p}(q_1,q_2) = \begin{bmatrix} l_1 \cos q_1 + l_2 \cos(q_1 + q_2) \\[4pt] l_1 \sin q_1 + l_2 \sin(q_1 + q_2) \\[4pt] 0 \end{bmatrix}. \]

The planar geometric Jacobian (mapping joint velocities to planar twist \( [\omega_z, v_x, v_y]^\top \)) can be obtained analytically by differentiation:

\[ \mathbf{J}_{\mathrm{planar}}(q_1,q_2) = \begin{bmatrix} 1 & 1 \\[4pt] -l_1 \sin q_1 - l_2 \sin(q_1 + q_2) & -l_2 \sin(q_1 + q_2) \\[4pt] l_1 \cos q_1 + l_2 \cos(q_1 + q_2) & l_2 \cos(q_1 + q_2) \end{bmatrix}. \]

The first row is the z-component of angular velocity: both joints rotate around z, so each contributes 1. The remaining rows arise from differentiating \( \mathbf{p}(q_1,q_2) \) with respect to \( q_1 \) and \( q_2 \).

From the DH or PoE perspective, the same Jacobian arises from the joint axes \( {}^0\mathbf{z}_0 = {}^0\mathbf{z}_1 = [0,0,1]^\top \) and origins \( {}^0\mathbf{o}_0 = [0,0,0]^\top \), \( {}^0\mathbf{o}_1 = [l_1 \cos q_1, l_1 \sin q_1, 0]^\top \).

8. Python Implementation — PoE and DH Jacobians

In Python, typical robotics-related libraries include the modern_robotics package (PoE-based kinematics), roboticstoolbox-python, and general-purpose linear algebra via numpy. Below we implement a minimal PoE spatial Jacobian for a list of twists and then specialize to the 2R planar arm.


import numpy as np

def skew3(w):
    """Return 3x3 skew-symmetric matrix of a 3-vector."""
    wx, wy, wz = w
    return np.array([[0.0, -wz,  wy],
                     [wz,   0.0, -wx],
                     [-wy,  wx,  0.0]])

def adjoint(T):
    """Adjoint matrix Ad_T for T in SE(3)."""
    R = T[0:3, 0:3]
    p = T[0:3, 3]
    p_hat = skew3(p)
    upper = np.hstack((R, np.zeros((3, 3))))
    lower = np.hstack((p_hat @ R, R))
    return np.vstack((upper, lower))

def exp_twist(xi, theta):
    """Matrix exponential exp([xi]^ wedge * theta) in SE(3)."""
    w = xi[0:3]
    v = xi[3:6]
    w_norm = np.linalg.norm(w)
    if w_norm < 1e-9:  # prismatic
        R = np.eye(3)
        p = v * theta
    else:  # revolute
        w_unit = w / w_norm
        w_hat = skew3(w_unit)
        R = (np.eye(3)
             + np.sin(theta * w_norm) * w_hat
             + (1.0 - np.cos(theta * w_norm)) * (w_hat @ w_hat))
        # Rodrigues formula for translation
        V = (np.eye(3) * theta
             + (1.0 - np.cos(theta * w_norm)) / w_norm * w_hat
             + (theta * w_norm - np.sin(theta * w_norm)) / (w_norm**2) * (w_hat @ w_hat))
        p = V @ v
    T = np.eye(4)
    T[0:3, 0:3] = R
    T[0:3, 3] = p
    return T

def spatial_jacobian(xi_list, q):
    """
    Compute spatial Jacobian Js(q).
    xi_list: list of 6-vectors (twists) in space frame.
    q: numpy array of joint coordinates.
    """
    n = len(xi_list)
    Js = np.zeros((6, n))
    T_prev = np.eye(4)
    for j in range(n):
        if j == 0:
            Js[:, j] = xi_list[0]
        else:
            Ad = adjoint(T_prev)
            Js[:, j] = Ad @ xi_list[j]
        # update T_prev = T_prev * exp(xi_j * q_j)
        T_prev = T_prev @ exp_twist(xi_list[j], q[j])
    return Js

# 2R planar example (axes along z, home pose with q1 = q2 = 0)
l1, l2 = 1.0, 0.8

# Joint 1 at origin, axis z
xi1 = np.array([0.0, 0.0, 1.0, 0.0, 0.0, 0.0])

# Joint 2 at (l1, 0, 0), axis z
q2_point = np.array([l1, 0.0, 0.0])
omega = np.array([0.0, 0.0, 1.0])
v2 = -np.cross(omega, q2_point)
xi2 = np.hstack((omega, v2))

xi_list = [xi1, xi2]
q = np.array([0.5, -0.3])

Js = spatial_jacobian(xi_list, q)
print("Spatial Jacobian Js(q) for 2R planar:")
print(Js)
      

A DH-based implementation would first build all \( {}^0\mathbf{T}_i(\mathbf{q}) \), extract \( {}^0\mathbf{z}_{i} \) and \( {}^0\mathbf{o}_i \), and then fill the Jacobian columns using the formulas from Section 5.

9. C++ Implementation — Eigen and Orocos KDL

In C++, the Eigen library is the standard choice for linear algebra, while the Orocos Kinematics and Dynamics Library (KDL) provides high-level robotics primitives including Jacobian computation. Below is a minimal Eigen-based planar 2R Jacobian, followed by an indication of how KDL can be used.


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

Eigen::Matrix3d planar2RJacobian(double l1, double l2,
                                 double q1, double q2)
{
    Eigen::Matrix3d J;
    double c1 = std::cos(q1);
    double s1 = std::sin(q1);
    double c12 = std::cos(q1 + q2);
    double s12 = std::sin(q1 + q2);

    // row 0: omega_z contributions
    J(0, 0) = 1.0;
    J(0, 1) = 1.0;

    // row 1: v_x
    J(1, 0) = -l1 * s1 - l2 * s12;
    J(1, 1) = -l2 * s12;

    // row 2: v_y
    J(2, 0) =  l1 * c1 + l2 * c12;
    J(2, 1) =  l2 * c12;

    return J;
}

int main()
{
    double l1 = 1.0, l2 = 0.8;
    double q1 = 0.5, q2 = -0.3;
    Eigen::Matrix3d J = planar2RJacobian(l1, l2, q1, q2);
    std::cout << "Planar Jacobian:\n" << J << std::endl;
    return 0;
}
      

In Orocos KDL, one defines a KDL::Chain from DH parameters or arbitrary transforms, and then uses KDL::ChainJntToJacSolver to compute the Jacobian: the library internally constructs the same object as described in Sections 5 and 6.

10. Java Implementation — EJML and Custom Kinematics

Java does not have a canonical robotics toolbox comparable to MATLAB or modern Python packages, but it has efficient linear algebra libraries such as EJML and Apache Commons Math. A typical approach is to implement the DH or PoE formulas using these libraries. Below is a simple Java method that computes the planar 2R Jacobian as in Section 7.


public class Planar2RJacobian {

    public static double[][] jacobian(double l1, double l2,
                                      double q1, double q2) {
        double[][] J = new double[3][2];

        double c1 = Math.cos(q1);
        double s1 = Math.sin(q1);
        double c12 = Math.cos(q1 + q2);
        double s12 = Math.sin(q1 + q2);

        // omega_z row
        J[0][0] = 1.0;
        J[0][1] = 1.0;

        // v_x row
        J[1][0] = -l1 * s1 - l2 * s12;
        J[1][1] = -l2 * s12;

        // v_y row
        J[2][0] =  l1 * c1 + l2 * c12;
        J[2][1] =  l2 * c12;

        return J;
    }

    public static void main(String[] args) {
        double[][] J = jacobian(1.0, 0.8, 0.5, -0.3);
        for (int i = 0; i < 3; ++i) {
            for (int j = 0; j < 2; ++j) {
                System.out.print(J[i][j] + " ");
            }
            System.out.println();
        }
    }
}
      

A more advanced Java robotics stack would combine such Jacobian routines with scene descriptions (for example via Java 3D) and numerical solvers for IK and dynamics, all built on top of EJML for matrix computations.

11. MATLAB/Simulink and Wolfram Mathematica Implementations

11.1 MATLAB and Simulink

MATLAB offers the robotics.RigidBodyTree class in the Robotics System Toolbox, which can compute Jacobians symbolically from a kinematic model. For the planar 2R arm:


% Define rigid body tree for 2R planar robot (z-axes, xy-plane)
robot = robotics.RigidBodyTree("DataFormat","row");

L1 = 1.0; L2 = 0.8;

body1 = robotics.RigidBody("link1");
jnt1  = robotics.Joint("joint1","revolute");
setFixedTransform(jnt1, trvec2tform([0 0 0]));
jnt1.JointAxis = [0 0 1];
body1.Joint = jnt1;
addBody(robot, body1, robot.BaseName);

body2 = robotics.RigidBody("link2");
jnt2  = robotics.Joint("joint2","revolute");
% link1 to link2 translation along x by L1
setFixedTransform(jnt2, trvec2tform([L1 0 0]));
jnt2.JointAxis = [0 0 1];
body2.Joint = jnt2;
addBody(robot, body2, "link1");

% Add end-effector frame at distance L2 along x from link2
ee = robotics.RigidBody("tool");
setFixedTransform(ee.Joint, trvec2tform([L2 0 0]));
addBody(robot, ee, "link2");

q = [0.5 -0.3];
J = geometricJacobian(robot, q, "tool");
disp(J);  % 6 x 2 Jacobian
      

In Simulink, one can place a Robot Dynamics block (from the same toolbox) and read out the Jacobian for use in velocity kinematics or impedance models; internally it relies on the same geometric Jacobian formulas.

11.2 Wolfram Mathematica

Mathematica is well suited for symbolic derivation of Jacobians directly from transformation matrices. For the planar 2R example:


(* Parameters and joint variables *)
l1 = Symbol["l1"];
l2 = Symbol["l2"];
q1 = Symbol["q1"];
q2 = Symbol["q2"];

(* End-effector position *)
px = l1 Cos[q1] + l2 Cos[q1 + q2];
py = l1 Sin[q1] + l2 Sin[q1 + q2];

(* Planar Jacobian: [omega_z; v_x; v_y] *)
J = {
   {1, 1},
   {D[px, q1], D[px, q2]},
   {D[py, q1], D[py, q2]}
} // Simplify;

MatrixForm[J]
      

For full 6D Jacobians in SE(3), one can build homogeneous transforms \( \mathbf{T}(\mathbf{q}) \), compute \( \dot{\mathbf{T}} \mathbf{T}^{-1} \), and read off the twist entries as a function of \( \dot{\mathbf{q}} \), yielding symbolic expressions for Jacobian columns.

12. Problems and Solutions

Problem 1 (General PoE Jacobian Derivation): Starting from the PoE forward kinematics \( \mathbf{T}(\boldsymbol{\theta}) = e^{[\boldsymbol{\xi}_1]^\wedge \theta_1} \cdots e^{[\boldsymbol{\xi}_n]^\wedge \theta_n} \mathbf{M} \), derive the formula for the spatial Jacobian \( \mathbf{J}_s(\boldsymbol{\theta}) \) given in Section 3.

Solution:

Write \( \mathbf{T}_k(\boldsymbol{\theta}) = e^{[\boldsymbol{\xi}_1]^\wedge \theta_1} \cdots e^{[\boldsymbol{\xi}_k]^\wedge \theta_k} \), so that \( \mathbf{T} = \mathbf{T}_n \mathbf{M} \). Differentiate:

\[ \dot{\mathbf{T}} = \sum_{k=1}^n \left( e^{[\boldsymbol{\xi}_1]^\wedge \theta_1} \cdots [\boldsymbol{\xi}_k]^\wedge e^{[\boldsymbol{\xi}_k]^\wedge \theta_k} \cdots e^{[\boldsymbol{\xi}_n]^\wedge \theta_n} \mathbf{M} \right) \dot{\theta}_k. \]

Multiply on the right by \( \mathbf{T}^{-1} = \mathbf{M}^{-1} \mathbf{T}_n^{-1} \). The factors \( e^{[\boldsymbol{\xi}_k]^\wedge \theta_k} \cdots e^{[\boldsymbol{\xi}_n]^\wedge \theta_n} \mathbf{M} \mathbf{T}^{-1} \) cancel to \( \mathbf{I} \), leaving

\[ [\mathbf{V}_s]^\wedge = \dot{\mathbf{T}} \mathbf{T}^{-1} = \sum_{k=1}^n \left( e^{[\boldsymbol{\xi}_1]^\wedge \theta_1} \cdots e^{[\boldsymbol{\xi}_{k-1}]^\wedge \theta_{k-1}} [\boldsymbol{\xi}_k]^\wedge e^{-[\boldsymbol{\xi}_{k-1}]^\wedge \theta_{k-1}} \cdots e^{-[\boldsymbol{\xi}_1]^\wedge \theta_1} \right) \dot{\theta}_k. \]

But \( e^{[\boldsymbol{\xi}_1]^\wedge \theta_1} \cdots e^{[\boldsymbol{\xi}_{k-1}]^\wedge \theta_{k-1}} [\boldsymbol{\xi}_k]^\wedge e^{-[\boldsymbol{\xi}_{k-1}]^\wedge \theta_{k-1}} \cdots e^{-[\boldsymbol{\xi}_1]^\wedge \theta_1} \) is \( \operatorname{Ad}_{\mathbf{T}_{k-1}} [\boldsymbol{\xi}_k]^\wedge \). Taking the vee map, we obtain

\[ \mathbf{V}_s = \sum_{k=1}^n \operatorname{Ad}_{\mathbf{T}_{k-1}} \boldsymbol{\xi}_k \dot{\theta}_k = \mathbf{J}_s(\boldsymbol{\theta}) \dot{\boldsymbol{\theta}}, \]

with columns \( \mathbf{J}_s^{(k)} = \operatorname{Ad}_{\mathbf{T}_{k-1}} \boldsymbol{\xi}_k \), as claimed.

Problem 2 (Equivalence of DH and PoE Jacobians for a Revolute Joint): Let joint j be revolute with axis \( {}^0\mathbf{z}_{j-1} \) and origin \( {}^0\mathbf{o}_{j-1} \). Show that the j-th column of the spatial Jacobian obtained via the DH formula equals \( \operatorname{Ad}_{\mathbf{T}_{j-1}} \boldsymbol{\xi}_j \) for a suitable choice of twist \( \boldsymbol{\xi}_j \).

Solution:

Choose the twist \( \boldsymbol{\xi}_j = \begin{bmatrix} {}^0\mathbf{z}_{j-1} \\[2pt] - {}^0\mathbf{z}_{j-1} \times {}^0\mathbf{o}_{j-1} \end{bmatrix} \). The adjoint of \( \mathbf{T}_{j-1} \) acts as

\[ \operatorname{Ad}_{\mathbf{T}_{j-1}} \boldsymbol{\xi}_j = \begin{bmatrix} {}^0\mathbf{R}_{j-1} & \mathbf{0} \\ [{}^0\mathbf{o}_{j-1}]_\times {}^0\mathbf{R}_{j-1} & {}^0\mathbf{R}_{j-1} \end{bmatrix} \begin{bmatrix} {}^0\mathbf{z}_{j-1} \\ - {}^0\mathbf{z}_{j-1} \times {}^0\mathbf{o}_{j-1} \end{bmatrix}. \]

Since \( {}^0\mathbf{z}_{j-1} \) is already expressed in the base frame, \( {}^0\mathbf{R}_{j-1} {}^0\mathbf{z}_{j-1} = {}^0\mathbf{z}_{j-1} \). The linear part becomes \( {}^0\mathbf{o}_{j-1} \times {}^0\mathbf{z}_{j-1} - {}^0\mathbf{z}_{j-1} \times {}^0\mathbf{o}_{j-1} = {}^0\mathbf{z}_{j-1} \times ({}^0\mathbf{o}_n - {}^0\mathbf{o}_{j-1}) \) when evaluated at the end-effector position \( {}^0\mathbf{o}_n \). This matches exactly the DH column formula, hence \( \mathbf{J}_s^{(j)} = \operatorname{Ad}_{\mathbf{T}_{j-1}} \boldsymbol{\xi}_j \).

flowchart TD
  A["Choose twist xi_j = (z_{j-1}, -z_{j-1} x o_{j-1})"] --> B["Compute Ad_{T_{j-1}} xi_j"]
  B --> C["Angular part: z_{j-1}"]
  B --> D["Linear part: z_{j-1} x (o_n - o_{j-1})"]
  C --> E["Matches DH omega_j column"]
  D --> F["Matches DH v_j column"]
      

Problem 3 (Planar 2R Jacobian Check): For the planar 2R manipulator of Section 7, verify explicitly that \( \mathbf{v} = \mathbf{J}_{\mathrm{planar}}(q_1,q_2) \dot{\mathbf{q}} \) reproduces the derivative of \( \mathbf{p}(q_1,q_2) \).

Solution:

Compute \( \dot{\mathbf{p}} = \frac{\partial \mathbf{p}}{\partial q_1} \dot{q}_1 + \frac{\partial \mathbf{p}}{\partial q_2} \dot{q}_2 \). From the expression of \( \mathbf{p} \):

\[ \frac{\partial \mathbf{p}}{\partial q_1} = \begin{bmatrix} -l_1 \sin q_1 - l_2 \sin(q_1 + q_2) \\ l_1 \cos q_1 + l_2 \cos(q_1 + q_2) \\ 0 \end{bmatrix}, \quad \frac{\partial \mathbf{p}}{\partial q_2} = \begin{bmatrix} -l_2 \sin(q_1 + q_2) \\ l_2 \cos(q_1 + q_2) \\ 0 \end{bmatrix}. \]

Therefore,

\[ \dot{\mathbf{p}} = \frac{\partial \mathbf{p}}{\partial q_1} \dot{q}_1 + \frac{\partial \mathbf{p}}{\partial q_2} \dot{q}_2, \]

and the stacking \( [\omega_z, v_x, v_y]^\top = [1,1; \frac{\partial \mathbf{p}}{\partial q_1}; \frac{\partial \mathbf{p}}{\partial q_2}] [\dot{q}_1,\dot{q}_2]^\top \) precisely matches \( \mathbf{J}_{\mathrm{planar}} \dot{\mathbf{q}} \). Hence the Jacobian correctly maps joint velocities to end-effector planar velocity.

Problem 4 (Body vs. Spatial Jacobian Relation): Prove that \( \mathbf{J}_b(\mathbf{q}) = \operatorname{Ad}_{\mathbf{T}(\mathbf{q})^{-1}} \mathbf{J}_s(\mathbf{q}) \).

Solution:

By definition, \( \mathbf{V}_s = \mathbf{J}_s(\mathbf{q}) \dot{\mathbf{q}} \) and \( \mathbf{V}_b = \mathbf{J}_b(\mathbf{q}) \dot{\mathbf{q}} \). On the other hand, the same twist expressed in the body frame is \( \mathbf{V}_b = \operatorname{Ad}_{\mathbf{T}^{-1}} \mathbf{V}_s \). Combine these:

\[ \mathbf{J}_b(\mathbf{q}) \dot{\mathbf{q}} = \operatorname{Ad}_{\mathbf{T}(\mathbf{q})^{-1}} \mathbf{J}_s(\mathbf{q}) \dot{\mathbf{q}} \quad \forall \dot{\mathbf{q}}. \]

Since this holds for all joint velocities, we conclude \( \mathbf{J}_b(\mathbf{q}) = \operatorname{Ad}_{\mathbf{T}(\mathbf{q})^{-1}} \mathbf{J}_s(\mathbf{q}) \).

13. Summary

In this lesson we defined the geometric Jacobian as the linear map from joint velocities to the end-effector twist, in both space and body frames. Using the PoE formulation on SE(3), we derived the spatial and body Jacobians via differentiation and the adjoint operator. From the classical DH convention we constructed the same Jacobian using joint axes and frame origins, and we showed analytically how the two perspectives coincide when frames and twists are chosen consistently. A planar 2R arm served as a concrete example, and we demonstrated implementations across Python, C++, Java, MATLAB/Simulink, and Wolfram Mathematica, preparing for later lessons on redundant Jacobians, singularities, and numerical verification of differential kinematics.

14. References

  1. Park, F.C. (1995). A new formulation of robot kinematics using the product of exponentials formula. Robotica, 13(4), 421–427.
  2. Denavit, J., & Hartenberg, R.S. (1955). A kinematic notation for lower-pair mechanisms based on matrices. Journal of Applied Mechanics, 22, 215–221.
  3. Brockett, R.W. (1984). Robotic manipulators and the product of exponentials formula. In Mathematical Theory of Networks and Systems, Lecture Notes in Control and Information Sciences, 103–111.
  4. Park, F.C., & Brockett, R.W. (1994). Kinematic dexterity of robotic mechanisms. International Journal of Robotics Research, 13(1), 1–15.
  5. Angeles, J. (1988). The kinematic isotropy and the conditioning index of serial robotic manipulators. International Journal of Robotics Research, 7(4), 21–34.
  6. Selig, J.M. (1996). Geometric fundamentals of robotics. Various journal contributions on screw theory and SE(3) representations.
  7. Murray, R.M., Li, Z., & Sastry, S.S. (1994). A Mathematical Introduction to Robotic Manipulation. CRC Press.