Chapter 7: Differential Kinematics

Lesson 4: Jacobian for Redundant Manipulators

This lesson develops the theory and computation of Jacobians for redundant manipulators, i.e., robots with more joint degrees of freedom than the dimension of the primary task space. We formalize the null space of the Jacobian, derive minimum-norm and weighted pseudoinverse solutions, and construct null-space motions for secondary objectives. The concepts are illustrated on a planar 3R arm and supported by Python, C++, Java, MATLAB/Simulink, and Wolfram Mathematica implementations.

1. Redundant Manipulators and Jacobian Structure

A manipulator with joint vector \( \mathbf{q} \in \mathbb{R}^n \) is redundant for a given task if the task space dimension \( m \) is strictly smaller than the number of joints:

\[ m < n, \qquad \mathbf{x} \in \mathbb{R}^m, \quad \mathbf{q} \in \mathbb{R}^n. \]

Typical examples are 7-DOF arms performing 6D end-effector tasks, or a planar 3R arm executing a 2D end-effector position task. The differential kinematics is expressed as

\[ \dot{\mathbf{x}} = \mathbf{J}(\mathbf{q}) \, \dot{\mathbf{q}}, \qquad \mathbf{J}(\mathbf{q}) \in \mathbb{R}^{m \times n}. \]

For a redundant manipulator, at configurations where \( \operatorname{rank}(\mathbf{J}) = m \) (full row rank), we have

\[ \dim \mathcal{N}(\mathbf{J}) = n - m > 0, \qquad \mathcal{N}(\mathbf{J}) = \{ \dot{\mathbf{q}} \in \mathbb{R}^n \mid \mathbf{J} \dot{\mathbf{q}} = \mathbf{0} \}. \]

Any joint-velocity vector in the null space leaves \( \dot{\mathbf{x}} \) unchanged. This nontrivial null space underlies self-motion and secondary objectives (e.g., posture optimization, joint limit avoidance) compatible with the primary task.

flowchart TD
  Qdot["Joint velocity qdot (R^n)"] --> JMAP["Task mapping: xdot = J(q) qdot (R^m)"]
  JMAP --> TASK["Primary task xdot"]
  Qdot --> NULL["Null space N(J) (dimension n - m)"]
  NULL --> SELF["Self-motion (no change in xdot)"]
  TASK --> REDUND["Redundancy: many qdot realize same xdot"]
        

In previous lessons, the Jacobian \( \mathbf{J}(\mathbf{q}) \) was derived from PoE or DH kinematics. Here, we focus on how to use this Jacobian when \( m < n \).

2. Minimum-Norm Solution via Moore–Penrose Pseudoinverse

Given a desired task-space velocity \( \dot{\mathbf{x}}_\star \in \mathbb{R}^m \), we want joint velocities \( \dot{\mathbf{q}} \) satisfying

\[ \mathbf{J}(\mathbf{q}) \, \dot{\mathbf{q}} = \dot{\mathbf{x}}_\star. \]

For a redundant manipulator there are infinitely many solutions. A classical choice is the minimum-norm solution:

\[ \begin{aligned} &\min_{\dot{\mathbf{q}}} \; \tfrac{1}{2} \| \dot{\mathbf{q}} \|_2^2 \\ &\text{subject to} \quad \mathbf{J}(\mathbf{q}) \, \dot{\mathbf{q}} = \dot{\mathbf{x}}_\star. \end{aligned} \]

Introduce Lagrange multipliers \( \boldsymbol{\lambda} \in \mathbb{R}^m \) and Lagrangian

\[ \mathcal{L}(\dot{\mathbf{q}}, \boldsymbol{\lambda}) = \tfrac{1}{2}\dot{\mathbf{q}}^\top \dot{\mathbf{q}} + \boldsymbol{\lambda}^\top \left( \mathbf{J}\dot{\mathbf{q}} - \dot{\mathbf{x}}_\star \right). \]

Stationarity with respect to \( \dot{\mathbf{q}} \) gives

\[ \frac{\partial \mathcal{L}}{\partial \dot{\mathbf{q}}} = \dot{\mathbf{q}} + \mathbf{J}^\top \boldsymbol{\lambda} = \mathbf{0} \quad \Rightarrow \quad \dot{\mathbf{q}} = - \mathbf{J}^\top \boldsymbol{\lambda}. \]

Enforcing the constraint \( \mathbf{J}\dot{\mathbf{q}} = \dot{\mathbf{x}}_\star \) yields

\[ \mathbf{J}\dot{\mathbf{q}} = -\mathbf{J}\mathbf{J}^\top \boldsymbol{\lambda} = \dot{\mathbf{x}}_\star \quad \Rightarrow \quad \boldsymbol{\lambda} = -\left( \mathbf{J}\mathbf{J}^\top \right)^{-1} \dot{\mathbf{x}}_\star \]

and therefore

\[ \dot{\mathbf{q}}^\star = \mathbf{J}^\top \left( \mathbf{J}\mathbf{J}^\top \right)^{-1} \dot{\mathbf{x}}_\star \equiv \mathbf{J}^+ \dot{\mathbf{x}}_\star, \]

where \( \mathbf{J}^+ \) is the Moore–Penrose pseudoinverse of \( \mathbf{J} \) (for full row rank \( \mathbf{J} \)).

In the redundant case (\( m < n \)), this solution is unique and has minimum Euclidean norm among all feasible \( \dot{\mathbf{q}} \). It is also the solution obtained by SVD-based pseudoinverse with nonzero singular values inverted.

3. General Solution and Null-Space Projector

The set of all joint velocities achieving \( \dot{\mathbf{x}}_\star \) is the affine subspace

\[ \mathcal{S}(\dot{\mathbf{x}}_\star) = \{ \dot{\mathbf{q}} \in \mathbb{R}^n \mid \mathbf{J}\dot{\mathbf{q}} = \dot{\mathbf{x}}_\star \}. \]

Any feasible solution can be written as the minimum-norm solution plus a homogeneous (null-space) component:

\[ \dot{\mathbf{q}} = \dot{\mathbf{q}}^\star + \dot{\mathbf{q}}_{\text{null}}, \qquad \dot{\mathbf{q}}^\star = \mathbf{J}^+ \dot{\mathbf{x}}_\star, \quad \dot{\mathbf{q}}_{\text{null}} \in \mathcal{N}(\mathbf{J}). \]

Using the pseudoinverse, the orthogonal projector onto the null space is

\[ \mathbf{P}_{\mathcal{N}} = \mathbf{I}_n - \mathbf{J}^+ \mathbf{J}. \]

Indeed, for any \( \mathbf{z} \in \mathbb{R}^n \) we have

\[ \mathbf{J}\mathbf{P}_{\mathcal{N}} \mathbf{z} = \mathbf{J}(\mathbf{I}_n - \mathbf{J}^+ \mathbf{J})\mathbf{z} = \mathbf{J}\mathbf{z} - \mathbf{J}\mathbf{J}^+\mathbf{J}\mathbf{z} = \mathbf{J}\mathbf{z} - \mathbf{J}\mathbf{z} = \mathbf{0}, \]

so \( \mathbf{P}_{\mathcal{N}}\mathbf{z} \in \mathcal{N}(\mathbf{J}) \). The general solution can thus be parameterized as

\[ \dot{\mathbf{q}} = \mathbf{J}^+ \dot{\mathbf{x}}_\star + \left( \mathbf{I}_n - \mathbf{J}^+ \mathbf{J} \right) \mathbf{z}, \qquad \mathbf{z} \in \mathbb{R}^n \text{ arbitrary}. \]

Choosing \( \mathbf{z} \) allows us to embed secondary objectives into the null-space motion. For example, if \( h(\mathbf{q}) \) is a posture cost, we can take

\[ \dot{\mathbf{q}} = \mathbf{J}^+ \dot{\mathbf{x}}_\star - \alpha \left( \mathbf{I}_n - \mathbf{J}^+ \mathbf{J} \right) \nabla h(\mathbf{q}), \quad \alpha > 0, \]

which implements a projected gradient descent step on \( h \) that preserves the primary task velocity \( \dot{\mathbf{x}}_\star \).

4. Weighted Pseudoinverse and Joint-Space Metrics

The Euclidean norm in joint space may not reflect physical cost (e.g. due to joint limits, actuator capabilities, or gearing). A more general problem minimizes a quadratic form with a positive-definite weight matrix \( \mathbf{W} \in \mathbb{R}^{n \times n} \):

\[ \begin{aligned} &\min_{\dot{\mathbf{q}}} \; \tfrac{1}{2} \dot{\mathbf{q}}^\top \mathbf{W} \dot{\mathbf{q}} \\ &\text{subject to} \quad \mathbf{J} \dot{\mathbf{q}} = \dot{\mathbf{x}}_\star. \end{aligned} \]

Proceeding as before, the optimal solution is the weighted pseudoinverse solution

\[ \dot{\mathbf{q}}^\star = \mathbf{J}^+_{\mathbf{W}} \, \dot{\mathbf{x}}_\star, \qquad \mathbf{J}^+_{\mathbf{W}} = \mathbf{W}^{-1} \mathbf{J}^\top \left( \mathbf{J} \mathbf{W}^{-1} \mathbf{J}^\top \right)^{-1}. \]

The corresponding weighted null-space projector is

\[ \mathbf{P}_{\mathcal{N},\mathbf{W}} = \mathbf{I}_n - \mathbf{J}^+_{\mathbf{W}} \mathbf{J}. \]

Properly selecting \( \mathbf{W} \) allows one to penalize motion near joint limits or in weak actuators more strongly (though the control aspects of such design will be addressed in later courses).

5. Example — Planar 3R Arm as a Redundant Manipulator

Consider a planar 3R manipulator with link lengths \( l_1, l_2, l_3 > 0 \) and joint angles \( \mathbf{q} = [q_1, q_2, q_3]^\top \). The end-effector position in the plane is

\[ \begin{aligned} x(\mathbf{q}) &= l_1 \cos q_1 + l_2 \cos(q_1 + q_2) + l_3 \cos(q_1 + q_2 + q_3), \\ y(\mathbf{q}) &= l_1 \sin q_1 + l_2 \sin(q_1 + q_2) + l_3 \sin(q_1 + q_2 + q_3). \end{aligned} \]

The position task has \( m = 2 \) and \( n = 3 \). The Jacobian \( \mathbf{J}_p(\mathbf{q}) \in \mathbb{R}^{2 \times 3} \) is

\[ \mathbf{J}_p(\mathbf{q}) = \begin{bmatrix} \frac{\partial x}{\partial q_1} & \frac{\partial x}{\partial q_2} & \frac{\partial x}{\partial q_3} \\ \frac{\partial y}{\partial q_1} & \frac{\partial y}{\partial q_2} & \frac{\partial y}{\partial q_3} \end{bmatrix}. \]

By direct differentiation, we obtain

\[ \begin{aligned} \frac{\partial x}{\partial q_1} &= - l_1 \sin q_1 - l_2 \sin(q_1 + q_2) - l_3 \sin(q_1 + q_2 + q_3), \\ \frac{\partial x}{\partial q_2} &= - l_2 \sin(q_1 + q_2) - l_3 \sin(q_1 + q_2 + q_3), \\ \frac{\partial x}{\partial q_3} &= - l_3 \sin(q_1 + q_2 + q_3), \\ \frac{\partial y}{\partial q_1} &= l_1 \cos q_1 + l_2 \cos(q_1 + q_2) + l_3 \cos(q_1 + q_2 + q_3), \\ \frac{\partial y}{\partial q_2} &= l_2 \cos(q_1 + q_2) + l_3 \cos(q_1 + q_2 + q_3), \\ \frac{\partial y}{\partial q_3} &= l_3 \cos(q_1 + q_2 + q_3). \end{aligned} \]

For almost all configurations, the two rows are linearly independent, so \( \operatorname{rank}(\mathbf{J}_p) = 2 = m \) and the manipulator is redundant. The minimum-norm joint velocity realizing a desired planar velocity \( \dot{\mathbf{x}}_\star = [\dot{x}, \dot{y}]^\top \) is

\[ \dot{\mathbf{q}}^\star = \mathbf{J}_p^+(\mathbf{q}) \, \dot{\mathbf{x}}_\star = \mathbf{J}_p^\top(\mathbf{q}) \left( \mathbf{J}_p(\mathbf{q})\mathbf{J}_p^\top(\mathbf{q}) \right)^{-1} \dot{\mathbf{x}}_\star. \]

flowchart TD
  START["Given xdot_star (R^2) and q (3R arm)"] --> JCOMP["Compute planar Jacobian J_p(q) (2x3)"]
  JCOMP --> PINV["Compute J_p^+ = J_p^T (J_p J_p^T)^(-1)"]
  PINV --> QDOT["qdot_star = J_p^+ xdot_star"]
  QDOT --> NULLSTEP["Add null-space term (I - J_p^+ J_p) z if desired"]
        

6. Implementation Lab — Python (NumPy and Robotics Libraries)

We implement the planar 3R Jacobian and the pseudoinverse-based velocity mapping in Python using numpy. For more complex manipulators, one can use robotics libraries such as modern_robotics (Northwestern) or roboticstoolbox-python, which provide spatial/body Jacobians given PoE parameters.


import numpy as np

def planar3r_fk(q, lengths):
    """
    Forward kinematics for planar 3R arm (position only).
    q: array-like, shape (3,)
    lengths: array-like, [l1, l2, l3]
    """
    q1, q2, q3 = q
    l1, l2, l3 = lengths
    c1 = np.cos(q1); s1 = np.sin(q1)
    c12 = np.cos(q1 + q2); s12 = np.sin(q1 + q2)
    c123 = np.cos(q1 + q2 + q3); s123 = np.sin(q1 + q2 + q3)
    x = l1 * c1 + l2 * c12 + l3 * c123
    y = l1 * s1 + l2 * s12 + l3 * s123
    return np.array([x, y])

def planar3r_jacobian(q, lengths):
    """
    Planar 3R position Jacobian J_p(q) in R^{2x3}.
    """
    q1, q2, q3 = q
    l1, l2, l3 = lengths
    s1 = np.sin(q1); c1 = np.cos(q1)
    s12 = np.sin(q1 + q2); c12 = np.cos(q1 + q2)
    s123 = np.sin(q1 + q2 + q3); c123 = np.cos(q1 + q2 + q3)

    # Partial derivatives
    dx_dq1 = -l1 * s1 - l2 * s12 - l3 * s123
    dx_dq2 = -l2 * s12 - l3 * s123
    dx_dq3 = -l3 * s123

    dy_dq1 =  l1 * c1 + l2 * c12 + l3 * c123
    dy_dq2 =  l2 * c12 + l3 * c123
    dy_dq3 =  l3 * c123

    J = np.array([[dx_dq1, dx_dq2, dx_dq3],
                  [dy_dq1, dy_dq2, dy_dq3]])
    return J

def minimum_norm_qdot(q, lengths, xdot_des):
    """
    Compute minimum-norm joint velocity for a desired planar velocity.
    xdot_des: array-like, shape (2,)
    """
    J = planar3r_jacobian(q, lengths)
    # Compute pseudoinverse using formula for full-row-rank J (2x3)
    JJt = J @ J.T
    J_pinv = J.T @ np.linalg.inv(JJt)
    qdot = J_pinv @ xdot_des
    return qdot

def projected_gradient_step(q, lengths, xdot_des, grad_h, alpha=0.1):
    """
    One differential step with a null-space gradient term.
    grad_h(q): function returning gradient of posture cost h(q).
    """
    J = planar3r_jacobian(q, lengths)
    JJt = J @ J.T
    J_pinv = J.T @ np.linalg.inv(JJt)
    I = np.eye(3)
    P_null = I - J_pinv @ J

    qdot_task = J_pinv @ xdot_des
    qdot_null = -alpha * P_null @ grad_h(q)
    return qdot_task + qdot_null

# Example usage
if __name__ == "__main__":
    lengths = np.array([0.5, 0.4, 0.3])
    q = np.array([0.2, 0.5, -0.4])
    xdot_des = np.array([0.05, -0.02])

    # Simple quadratic posture objective: keep q near q0
    q0 = np.array([0.0, 0.0, 0.0])
    def grad_h(q):
        return q - q0  # gradient of (1/2)||q - q0||^2

    qdot = projected_gradient_step(q, lengths, xdot_des, grad_h, alpha=0.2)
    print("qdot:", qdot)
      

In spatial/body Jacobian settings (for general 6D twists), one can replace planar3r_jacobian by a body Jacobian from modern_robotics.JacobianBody or similar, while the pseudoinverse and null-space formulas remain unchanged.

7. Implementation Lab — C++ with Eigen (and Robotics Libraries)

In C++, the Eigen library is a standard choice for linear algebra in robotics. Higher-level packages such as orocos_kdl (Kinematics and Dynamics Library) can provide Jacobians directly from robot models, but here we implement the planar 3R example with Eigen matrices.


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

using Eigen::Vector2d;
using Eigen::Vector3d;
using Eigen::Matrix2d;
using Eigen::MatrixXd;
using Eigen::Matrix3d;

Vector2d planar3r_fk(const Vector3d& q, const Vector3d& L) {
    double q1 = q(0), q2 = q(1), q3 = q(2);
    double l1 = L(0), l2 = L(1), l3 = L(2);

    double c1 = std::cos(q1), s1 = std::sin(q1);
    double c12 = std::cos(q1 + q2), s12 = std::sin(q1 + q2);
    double c123 = std::cos(q1 + q2 + q3), s123 = std::sin(q1 + q2 + q3);

    double x = l1 * c1 + l2 * c12 + l3 * c123;
    double y = l1 * s1 + l2 * s12 + l3 * s123;
    return Vector2d(x, y);
}

Eigen::Matrix<double, 2, 3> planar3r_jacobian(const Vector3d& q,
                                                const Vector3d& L)
{
    double q1 = q(0), q2 = q(1), q3 = q(2);
    double l1 = L(0), l2 = L(1), l3 = L(2);

    double s1 = std::sin(q1), c1 = std::cos(q1);
    double s12 = std::sin(q1 + q2), c12 = std::cos(q1 + q2);
    double s123 = std::sin(q1 + q2 + q3), c123 = std::cos(q1 + q2 + q3);

    double dx_dq1 = -l1 * s1 - l2 * s12 - l3 * s123;
    double dx_dq2 = -l2 * s12 - l3 * s123;
    double dx_dq3 = -l3 * s123;

    double dy_dq1 =  l1 * c1 + l2 * c12 + l3 * c123;
    double dy_dq2 =  l2 * c12 + l3 * c123;
    double dy_dq3 =  l3 * c123;

    Eigen::Matrix<double, 2, 3> J;
    J << dx_dq1, dx_dq2, dx_dq3,
          dy_dq1, dy_dq2, dy_dq3;
    return J;
}

Vector3d minimum_norm_qdot(const Vector3d& q,
                           const Vector3d& L,
                           const Vector2d& xdot_des)
{
    auto J = planar3r_jacobian(q, L);      // 2x3
    Matrix2d JJt = J * J.transpose();      // 2x2
    Eigen::Matrix<double, 3, 2> J_pinv = J.transpose() * JJt.inverse();
    return J_pinv * xdot_des;
}

int main() {
    Vector3d L(0.5, 0.4, 0.3);
    Vector3d q(0.2, 0.5, -0.4);
    Vector2d xdot_des(0.05, -0.02);

    Vector3d qdot = minimum_norm_qdot(q, L, xdot_des);
    std::cout << "qdot = " << qdot.transpose() << std::endl;
    return 0;
}
      

For general 6D Jacobians obtained from a URDF model, one can use orocos_kdl::ChainJntToJacSolver to compute KDL::Jacobian and then map to Eigen::MatrixXd for pseudoinverse and null-space operations as above.

8. Implementation Lab — Java with EJML

In Java, the EJML library supports dense linear algebra and provides a pseudo-inverse operation. Robotics frameworks in Java (e.g., ROSJava) can represent kinematic chains, while EJML handles matrix operations.


import org.ejml.simple.SimpleMatrix;

public class Planar3RRedundant {

    public static SimpleMatrix jacobian(double[] q, double[] L) {
        double q1 = q[0], q2 = q[1], q3 = q[2];
        double l1 = L[0], l2 = L[1], l3 = L[2];

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

        double dx_dq1 = -l1 * s1 - l2 * s12 - l3 * s123;
        double dx_dq2 = -l2 * s12 - l3 * s123;
        double dx_dq3 = -l3 * s123;

        double dy_dq1 =  l1 * c1 + l2 * c12 + l3 * c123;
        double dy_dq2 =  l2 * c12 + l3 * c123;
        double dy_dq3 =  l3 * c123;

        double[][] data = {
            {dx_dq1, dx_dq2, dx_dq3},
            {dy_dq1, dy_dq2, dy_dq3}
        };
        return new SimpleMatrix(data);  // 2x3
    }

    public static SimpleMatrix minimumNormQdot(double[] q, double[] L,
                                               double[] xdotDes) {
        SimpleMatrix J = jacobian(q, L);
        SimpleMatrix xdot = new SimpleMatrix(2, 1, true, xdotDes);
        // EJML provides a pseudoInverse() method
        SimpleMatrix J_pinv = J.pseudoInverse(); // 3x2
        return J_pinv.mult(xdot);                // 3x1
    }

    public static void main(String[] args) {
        double[] L = {0.5, 0.4, 0.3};
        double[] q = {0.2, 0.5, -0.4};
        double[] xdotDes = {0.05, -0.02};

        SimpleMatrix qdot = minimumNormQdot(q, L, xdotDes);
        qdot.print("qdot:");
    }
}
      

The same EJML-based pseudoinverse machinery can be applied to 6D spatial Jacobians from a Java kinematics model, implementing null-space projections as in the Python and C++ examples.

9. Implementation Lab — MATLAB/Simulink

MATLAB's Robotics System Toolbox provides rigidBodyTree models with built-in Jacobian computation via geometricJacobian. For the planar 3R example, we can either construct a simple symbolic Jacobian or use the same formulas as above.


function qdot = planar3r_min_norm_qdot(q, L, xdot_des)
% q: 3x1, L: 3x1, xdot_des: 2x1

q1 = q(1); q2 = q(2); q3 = q(3);
l1 = L(1); l2 = L(2); l3 = L(3);

s1 = sin(q1); c1 = cos(q1);
s12 = sin(q1 + q2); c12 = cos(q1 + q2);
s123 = sin(q1 + q2 + q3); c123 = cos(q1 + q2 + q3);

dx_dq1 = -l1 * s1 - l2 * s12 - l3 * s123;
dx_dq2 = -l2 * s12 - l3 * s123;
dx_dq3 = -l3 * s123;

dy_dq1 =  l1 * c1 + l2 * c12 + l3 * c123;
dy_dq2 =  l2 * c12 + l3 * c123;
dy_dq3 =  l3 * c123;

J = [dx_dq1, dx_dq2, dx_dq3;
     dy_dq1, dy_dq2, dy_dq3];

% Minimum-norm solution via pseudoinverse
qdot = pinv(J) * xdot_des;
end
      

In Simulink, one common architecture is:

  • Block 1: reads current joint angles q.
  • Block 2: computes J(q) using a MATLAB Function block implementing the above code or using geometricJacobian on a rigidBodyTree.
  • Block 3: computes qdot = pinv(J) * xdot_des (again via a MATLAB Function block).
  • Block 4: integrates qdot to update q.

For general manipulators in MATLAB, one typically defines the kinematic chain with rigidBody and rigidBodyJoint, attaches them to a rigidBodyTree, and calls [J, ~] = geometricJacobian(robot, q, endEffectorName) before applying pinv and null-space projections.

10. Implementation Lab — Wolfram Mathematica

Mathematica offers symbolic and numeric capabilities that are well suited for deriving and analyzing Jacobians. Below is a planar 3R example.


(* Define symbolic variables *)
Clear[q1, q2, q3, l1, l2, l3];
q = {q1, q2, q3};
L = {l1, l2, l3};

x[q1_, q2_, q3_] := l1 Cos[q1] + l2 Cos[q1 + q2] + l3 Cos[q1 + q2 + q3];
y[q1_, q2_, q3_] := l1 Sin[q1] + l2 Sin[q1 + q2] + l3 Sin[q1 + q2 + q3];

pos[q1_, q2_, q3_] := {x[q1, q2, q3], y[q1, q2, q3]};

(* Jacobian matrix 2x3 *)
J = D[pos[q1, q2, q3], {{q1, q2, q3}}];

(* Pseudoinverse (symbolic or numeric) *)
Jpinv = PseudoInverse[J];

(* Example numeric substitution *)
Jnum = J /. {l1 -> 0.5, l2 -> 0.4, l3 -> 0.3,
             q1 -> 0.2, q2 -> 0.5, q3 -> -0.4};

JpinvNum = N[ Jpinv /. {l1 -> 0.5, l2 -> 0.4, l3 -> 0.3,
                        q1 -> 0.2, q2 -> 0.5, q3 -> -0.4} ];

xdotDes = {0.05, -0.02};
qdot = JpinvNum . xdotDes
      

Mathematica's symbolic handling is particularly useful for verifying identities such as \( \mathbf{J}\mathbf{J}^+\mathbf{J} = \mathbf{J} \), or for computing null spaces via NullSpace[J] for specific configurations.

11. Problems and Solutions

Problem 1 (Minimum-Norm Solution): Let \( \mathbf{J} \in \mathbb{R}^{m \times n} \) with \( m < n \) and full row rank. Show that the solution of \( \min_{\dot{\mathbf{q}}} \tfrac{1}{2}\|\dot{\mathbf{q}}\|_2^2 \) subject to \( \mathbf{J}\dot{\mathbf{q}} = \dot{\mathbf{x}}_\star \) is \( \dot{\mathbf{q}}^\star = \mathbf{J}^\top (\mathbf{J}\mathbf{J}^\top)^{-1} \dot{\mathbf{x}}_\star \).

Solution: This is the derivation in Section 2. The KKT conditions give \( \dot{\mathbf{q}} = -\mathbf{J}^\top \boldsymbol{\lambda} \) and \( -\mathbf{J}\mathbf{J}^\top \boldsymbol{\lambda} = \dot{\mathbf{x}}_\star \). Since \( \mathbf{J}\mathbf{J}^\top \) is invertible, \( \boldsymbol{\lambda} = -(\mathbf{J}\mathbf{J}^\top)^{-1}\dot{\mathbf{x}}_\star \), which substituted back yields the stated formula. Uniqueness follows because the objective is strictly convex.

Problem 2 (Null-Space Projector): Prove that \( \mathbf{P}_{\mathcal{N}} = \mathbf{I}_n - \mathbf{J}^+\mathbf{J} \) is a projector onto \( \mathcal{N}(\mathbf{J}) \), i.e. show that \( \mathbf{P}_{\mathcal{N}}^2 = \mathbf{P}_{\mathcal{N}} \) and \( \operatorname{Im}(\mathbf{P}_{\mathcal{N}}) \subseteq \mathcal{N}(\mathbf{J}) \).

Solution: For any \( \mathbf{z} \in \mathbb{R}^n \) we have \( \mathbf{J}\mathbf{P}_{\mathcal{N}}\mathbf{z} = \mathbf{J}(\mathbf{I}_n - \mathbf{J}^+\mathbf{J})\mathbf{z} = \mathbf{J}\mathbf{z} - \mathbf{J}\mathbf{J}^+\mathbf{J}\mathbf{z} = \mathbf{0} \), by the Moore–Penrose property \( \mathbf{J}\mathbf{J}^+\mathbf{J} = \mathbf{J} \). Thus \( \operatorname{Im}(\mathbf{P}_{\mathcal{N}}) \subseteq \mathcal{N}(\mathbf{J}) \). Moreover, \( \mathbf{P}_{\mathcal{N}}^2 = (\mathbf{I}_n - \mathbf{J}^+\mathbf{J})^2 = \mathbf{I}_n - 2\mathbf{J}^+\mathbf{J} + \mathbf{J}^+\mathbf{J}\mathbf{J}^+\mathbf{J} \), and since \( \mathbf{J}^+\mathbf{J}\mathbf{J}^+\mathbf{J} = \mathbf{J}^+\mathbf{J} \), this simplifies to \( \mathbf{P}_{\mathcal{N}}^2 = \mathbf{P}_{\mathcal{N}} \). Therefore \( \mathbf{P}_{\mathcal{N}} \) is a projector onto the null space.

Problem 3 (Dimension of Self-Motion): A 7-DOF spatial manipulator is executing a 6D Cartesian task represented by a twist \( \mathbf{V} \in \mathbb{R}^6 \), with full-rank Jacobian \( \mathbf{J}(\mathbf{q}) \in \mathbb{R}^{6 \times 7} \). Determine the dimension of its instantaneous self-motion manifold and interpret its meaning.

Solution: With \( \operatorname{rank}(\mathbf{J}) = 6 \), the null space has dimension \( 7 - 6 = 1 \). Thus the robot has one scalar degree of freedom for self-motion (e.g., an elbow flexion degree of freedom) that does not affect the instantaneous end-effector twist. This one-dimensional self-motion can be used to improve posture or avoid joint limits while tracking the primary task.

Problem 4 (Weighted Pseudoinverse Derivation): Show that the weighted least-norm problem in Section 4 has solution \( \dot{\mathbf{q}}^\star = \mathbf{W}^{-1}\mathbf{J}^\top(\mathbf{J}\mathbf{W}^{-1}\mathbf{J}^\top)^{-1} \dot{\mathbf{x}}_\star \).

Solution: Define the Lagrangian \( \mathcal{L} = \tfrac{1}{2}\dot{\mathbf{q}}^\top \mathbf{W} \dot{\mathbf{q}} + \boldsymbol{\lambda}^\top(\mathbf{J}\dot{\mathbf{q}} - \dot{\mathbf{x}}_\star) \). Stationarity in \( \dot{\mathbf{q}} \) yields \( \mathbf{W}\dot{\mathbf{q}} + \mathbf{J}^\top\boldsymbol{\lambda} = \mathbf{0} \), so \( \dot{\mathbf{q}} = -\mathbf{W}^{-1}\mathbf{J}^\top\boldsymbol{\lambda} \). The constraint gives \( -\mathbf{J}\mathbf{W}^{-1}\mathbf{J}^\top\boldsymbol{\lambda} = \dot{\mathbf{x}}_\star \), and hence \( \boldsymbol{\lambda} = -(\mathbf{J}\mathbf{W}^{-1}\mathbf{J}^\top)^{-1}\dot{\mathbf{x}}_\star \), which leads directly to the stated formula.

Problem 5 (Planar 3R Numerical Exercise): For the planar 3R arm with \( l_1 = 0.5 \), \( l_2 = 0.4 \), \( l_3 = 0.3 \), configuration \( \mathbf{q} = [0, \pi/4, -\pi/4]^\top \), and desired velocity \( \dot{\mathbf{x}}_\star = [0.1, 0]^\top \), compute \( \mathbf{J}_p(\mathbf{q}) \) and \( \dot{\mathbf{q}}^\star = \mathbf{J}_p^+ \dot{\mathbf{x}}_\star \) numerically (using any of the code snippets).

Solution (outline): Substitute the given lengths and angles into the Jacobian formulas of Section 5, then compute \( \mathbf{J}_p\mathbf{J}_p^\top \) (a \( 2 \times 2 \) matrix), invert it, and form \( \mathbf{J}_p^+ = \mathbf{J}_p^\top (\mathbf{J}_p\mathbf{J}_p^\top)^{-1} \). Multiplying by \( \dot{\mathbf{x}}_\star \) gives \( \dot{\mathbf{q}}^\star \), which can be verified to satisfy \( \mathbf{J}_p \dot{\mathbf{q}}^\star = \dot{\mathbf{x}}_\star \) up to numerical precision.

12. Summary

In this lesson, we analyzed Jacobians for redundant manipulators where the number of joints exceeds the task space dimension. We characterized the nontrivial null space of the Jacobian and derived minimum-norm and weighted pseudoinverse solutions for the differential inverse kinematics problem. The null-space projector enabled a decomposition of motion into task-achieving and self-motion components, which underpins redundancy resolution via secondary objectives (posture, joint limits, etc.). Through the planar 3R example and multi-language implementations, we connected these theoretical constructs to practical computation that will be reused in redundancy-aware kinematics and, later, in dynamics and control.

13. References

  1. Penrose, R. (1955). A generalized inverse for matrices. Proceedings of the Cambridge Philosophical Society, 51, 406–413.
  2. Ben-Israel, A., & Greville, T.N.E. (1974). Generalized Inverses: Theory and Applications. Wiley.
  3. Liegeois, A. (1977). Automatic supervisory control of the configuration and behavior of multibody mechanisms. IEEE Transactions on Systems, Man, and Cybernetics, 7(12), 868–871.
  4. Nakamura, Y. (1991). Advanced Robotics: Redundancy and Optimization. Addison–Wesley.
  5. Siciliano, B. (1990). Kinematic control of redundant robot manipulators: A tutorial. Journal of Intelligent and Robotic Systems, 3(3), 201–212.
  6. Klein, C.A., & Huang, C.H. (1983). Review of pseudoinverse control for use with kinematically redundant manipulators. IEEE Transactions on Systems, Man, and Cybernetics, 13(2), 245–250.
  7. Maciejewski, A.A., & Klein, C.A. (1985). Obstacle avoidance for kinematically redundant manipulators in dynamically varying environments. International Journal of Robotics Research, 4(3), 109–117.
  8. Yoshikawa, T. (1985). Manipulability of robotic mechanisms. International Journal of Robotics Research, 4(2), 3–9.
  9. Chiaverini, S. (1997). Singularities and damped least-squares inverse kinematics. Robotica, 15(5), 567–573.
  10. Moore, E.H., & Penrose, R. (Collected works on generalized inverses and least-squares problems). Various journal contributions.