Chapter 12: Newton–Euler Recursive Dynamics

Lesson 2: Backward Recursion (forces/torques)

This lesson develops the backward sweep of the Newton–Euler algorithm, where link inertial forces and moments are aggregated from the end-effector back to the base to obtain joint forces/torques. Building on the forward recursion (velocities/accelerations) and rigid-body inertial modeling from previous chapters, we derive the recursive equilibrium equations and provide multi-language implementations at a university level of rigor.

1. Role of Backward Recursion in Newton–Euler Dynamics

In the Newton–Euler formulation for an \( n \)-link serial manipulator, the forward recursion of Lesson 1 provides, for each link \( i \), the angular velocity \( \boldsymbol{\omega}_i \), angular acceleration \( \boldsymbol{\alpha}_i \), and linear acceleration of the center of mass \( \mathbf{a}_i^c \), all expressed in a body-fixed frame \( \{i\} \). The backward recursion uses these kinematic quantities and inertial parameters to compute:

  • The net inertial force \( \mathbf{F}_i \) and moment \( \mathbf{N}_i \) of each link.
  • The internal wrench \( (\mathbf{f}_i, \mathbf{n}_i) \) transmitted across each joint.
  • The generalized joint effort \( \tau_i \) for the \( i \)-th joint.

The overall structure is:

\[ \text{Forward sweep:} \quad \{q_i, \dot{q}_i, \ddot{q}_i\}_{i=1}^n \;\Rightarrow\; \{\boldsymbol{\omega}_i, \boldsymbol{\alpha}_i, \mathbf{a}_i^c\}_{i=1}^n \]

\[ \text{Backward sweep:} \quad \{\boldsymbol{\omega}_i, \boldsymbol{\alpha}_i, \mathbf{a}_i^c\}_{i=1}^n \;\Rightarrow\; \{\mathbf{F}_i, \mathbf{N}_i, \mathbf{f}_i, \mathbf{n}_i, \tau_i\}_{i=1}^n. \]

The backward recursion is essentially a subtree equilibrium computation: starting from the terminal body (possibly with external wrench at the end-effector), we propagate wrenches inward, enforcing Newton–Euler laws on each link.

2. Inertial Force and Moment of a Single Link

Consider link \( i \) with mass \( m_i \), center of mass (CoM) located at vector \( \mathbf{r}_i^c \) from frame origin \( \{i\} \), and inertia tensor about its CoM in frame \( \{i\} \), \( \mathbf{I}_i \in \mathbb{R}^{3\times 3} \). From rigid-body mechanics, the inertial (net) force and moment acting on the CoM are:

\[ \mathbf{F}_i = m_i \,\mathbf{a}_i^c \]

\[ \mathbf{N}_i = \mathbf{I}_i \,\boldsymbol{\alpha}_i + \boldsymbol{\omega}_i \times (\mathbf{I}_i \,\boldsymbol{\omega}_i). \]

Here \( \mathbf{a}_i^c \), \( \boldsymbol{\omega}_i \), \( \boldsymbol{\alpha}_i \) are obtained from the forward recursion (Lesson 1). These quantities represent the inertial reaction of link \( i \) to its motion; they will be balanced by internal and external wrenches in the backward recursion.

Denote by \( \mathbf{f}_i \) the force transmitted from link \( i \) to link \( i-1 \) through joint \( i \), and \( \mathbf{n}_i \) the corresponding moment at the origin of frame \( \{i\} \). We adopt the sign convention that \( \mathbf{f}_i \) and \( \mathbf{n}_i \) act on link \( i \) from its parent.

If the end-effector is subject to a known external wrench \( (\mathbf{f}_{n+1}^{\text{ext}}, \mathbf{n}_{n+1}^{\text{ext}}) \), that wrench is treated as acting on a fictitious link \( n+1 \) attached to link \( n \). In many models we set \( \mathbf{f}_{n+1}^{\text{ext}} = \mathbf{0},\; \mathbf{n}_{n+1}^{\text{ext}} = \mathbf{0} \), corresponding to free end conditions.

3. Derivation of Backward Recursion from Subtree Equilibrium

Let \( \mathcal{T}_i \) be the subtree consisting of link \( i \) and all its descendants. The total inertial wrench of the subtree, expressed at frame \( \{i\} \), must be balanced by external wrenches and the internal reaction at joint \( i \). For a serial chain, each link has at most one child (link \( i+1 \)), so the recursion is one-dimensional along the chain.

Let \( \;^i\mathbf{R}_{i+1} \) be the rotation matrix that maps vectors from frame \( \{i+1\} \) to frame \( \{i\} \), and \( \mathbf{p}_i \) the vector from origin of frame \( \{i\} \) to origin of frame \( \{i+1\} \), both expressed in \( \{i\} \). The child wrench at joint \( i+1 \), expressed in frame \( \{i+1\} \), is \( (\mathbf{f}_{i+1}, \mathbf{n}_{i+1}) \); expressed in \( \{i\} \), it is:

\[ \mathbf{f}_{i+1}^{(i)} = \;^i\mathbf{R}_{i+1}\,\mathbf{f}_{i+1},\quad \mathbf{n}_{i+1}^{(i)} = \;^i\mathbf{R}_{i+1}\,\mathbf{n}_{i+1} + \mathbf{p}_i \times \;^i\mathbf{R}_{i+1}\,\mathbf{f}_{i+1}. \]

The equilibrium of link \( i \) (Newton–Euler) in frame \( \{i\} \) is:

\[ \mathbf{f}_i + \mathbf{f}_{i+1}^{(i)} + \mathbf{f}_i^{\text{ext}} = \mathbf{F}_i, \]

\[ \mathbf{n}_i + \mathbf{n}_{i+1}^{(i)} + \mathbf{n}_i^{\text{ext}} = \mathbf{N}_i + \mathbf{r}_i^c \times \mathbf{F}_i, \]

where \( \mathbf{f}_i^{\text{ext}}, \mathbf{n}_i^{\text{ext}} \) denote any external wrenches acting directly on link \( i \) (e.g., gravity can be modeled as inertial force via \( \mathbf{a}_i^c \), so often the only external load is at the end-effector).

Solving for \( \mathbf{f}_i \) and \( \mathbf{n}_i \) gives the backward recursion:

\[ \mathbf{f}_i = \mathbf{F}_i + \mathbf{f}_i^{\text{ext}} + \;^i\mathbf{R}_{i+1}\,\mathbf{f}_{i+1}, \]

\[ \mathbf{n}_i = \mathbf{N}_i + \mathbf{r}_i^c \times \mathbf{F}_i + \mathbf{n}_i^{\text{ext}} + \;^i\mathbf{R}_{i+1}\,\mathbf{n}_{i+1} + \mathbf{p}_i \times \;^i\mathbf{R}_{i+1}\,\mathbf{f}_{i+1}. \]

At the terminal end \( i = n \), we use the boundary condition:

\[ \mathbf{f}_{n+1} = \mathbf{f}_{n+1}^{\text{ext}}, \quad \mathbf{n}_{n+1} = \mathbf{n}_{n+1}^{\text{ext}}, \]

which is often chosen as zero for a free end-effector or as the known reaction wrench when the end-effector is in contact with the environment (but still treated as a known, not an unknown for this recursive pass).

4. Joint Forces/Torques from Internal Wrenches

The internal wrench \( (\mathbf{f}_i, \mathbf{n}_i) \) at joint \( i \) must be projected onto the joint’s motion subspace to obtain the generalized effort \( \tau_i \). Let \( \mathbf{z}_i \) be the unit joint axis expressed in frame \( \{i\} \).

Revolute joint. The generalized coordinate is an angle \( q_i \), and the power equality \( \tau_i \dot{q}_i = \mathbf{n}_i^{\top}\boldsymbol{\omega}_i^J \) for joint-relative angular velocity \( \boldsymbol{\omega}_i^J = \dot{q}_i\mathbf{z}_i \) yields:

\[ \tau_i = \mathbf{z}_i^{\top}\mathbf{n}_i. \]

Prismatic joint. The generalized coordinate is a displacement \( q_i \), and the power equality \( \tau_i \dot{q}_i = \mathbf{f}_i^{\top}\mathbf{v}_i^J \) for joint-relative linear velocity \( \mathbf{v}_i^J = \dot{q}_i\mathbf{z}_i \) yields:

\[ \tau_i = \mathbf{z}_i^{\top}\mathbf{f}_i. \]

In a compact notation using the joint motion subspace \( \mathbf{s}_i \in \mathbb{R}^6 \) and the spatial wrench \( \mathbf{w}_i \in \mathbb{R}^6 \), the joint effort is \( \tau_i = \mathbf{s}_i^{\top}\mathbf{w}_i \), but full spatial vector theory will only be systematically introduced in later chapters on inertia parameterization.

5. Algorithmic Structure and Complexity

The Newton–Euler algorithm achieves \( \mathcal{O}(n) \) complexity for an \( n \)-link chain. The backward recursion uses only local operations at each link: evaluating \( \mathbf{F}_i, \mathbf{N}_i \) and propagating wrenches from child to parent. A high-level procedure is:

  1. Run forward recursion (Lesson 1) to obtain \( \boldsymbol{\omega}_i, \boldsymbol{\alpha}_i, \mathbf{a}_i^c \).
  2. For each link, compute \( \mathbf{F}_i, \mathbf{N}_i \) from inertial parameters.
  3. Initialize terminal wrenches \( \mathbf{f}_{n+1}, \mathbf{n}_{n+1} \) from external load.
  4. For \( i = n, n-1, \dots, 1 \), compute \( \mathbf{f}_i, \mathbf{n}_i, \tau_i \).
flowchart TD
  S["Inputs: q, qdot, qddot, transforms, inertial params, end-effector wrench"] --> FWD["Forward sweep: compute omega_i, alpha_i, a_i_c"]
  FWD --> INERT["For each link i: compute F_i = m_i a_i_c and N_i = I_i alpha_i + omega_i x (I_i omega_i)"]
  INERT --> INIT["Set f_(n+1), n_(n+1) from external load (often zero)"]
  INIT --> BWD["For i = n down to 1: propagate f_i, n_i using subtree equilibrium"]
  BWD --> TAU["Project wrench on joint axis to get tau_i"]
  TAU --> OUT["Outputs: joint efforts tau_1,...,tau_n and internal wrenches"]
        

Each recursion step uses only matrix–vector products and cross products. Assuming constant-time operations per link, the total cost scales linearly with the number of links, in contrast to naive Lagrangian formulations that may scale as \( \mathcal{O}(n^3) \) if implemented without exploiting sparsity.

6. Python Implementation of Backward Recursion

In Python, popular robotics libraries such as roboticstoolbox-python (Corke) provide Newton–Euler algorithms on top of a SerialLink or rigid-body-tree abstraction. Here we implement the core backward recursion from scratch using numpy, assuming the forward recursion has already supplied \( \mathbf{F}_i \) and \( \mathbf{N}_i \) for each link.


import numpy as np

def newton_euler_backward(F_list, N_list, R_ip1_i_list, p_i_list,
                          z_list, joint_type_list,
                          f_tip=None, n_tip=None):
    """
    Backward recursion for a serial chain.

    Parameters
    ----------
    F_list : list of (3,) arrays
        Inertial forces F_i at link CoM in frame {i}.
    N_list : list of (3,) arrays
        Inertial moments N_i about frame origin {i}.
    R_ip1_i_list : list of (3,3) arrays
        Rotation matrices ^i R_{i+1} (from frame {i+1} to {i}).
        Length n, but R_ip1_i_list[-1] is used only if you model a tip link.
    p_i_list : list of (3,) arrays
        Vectors p_i from origin of frame {i} to origin of frame {i+1}, in frame {i}.
    z_list : list of (3,) arrays
        Joint axes z_i expressed in frame {i}.
    joint_type_list : list of str
        "R" for revolute, "P" for prismatic.
    f_tip, n_tip : (3,) arrays or None
        External wrench at the terminal body (expressed in last frame).

    Returns
    -------
    f_list, n_list, tau_list : lists of arrays/scalars
        Internal forces, moments, and generalized efforts at each joint.
    """
    n = len(F_list)
    assert len(N_list) == n
    assert len(R_ip1_i_list) == n
    assert len(p_i_list) == n
    assert len(z_list) == n
    assert len(joint_type_list) == n

    if f_tip is None:
        f_next = np.zeros(3)
    else:
        f_next = np.asarray(f_tip).reshape(3)
    if n_tip is None:
        n_next = np.zeros(3)
    else:
        n_next = np.asarray(n_tip).reshape(3)

    f_list = [np.zeros(3) for _ in range(n)]
    n_list = [np.zeros(3) for _ in range(n)]
    tau_list = [0.0 for _ in range(n)]

    # Backward sweep: i = n-1, ..., 0
    for i in range(n - 1, -1, -1):
        R_ip1_i = R_ip1_i_list[i]
        p_i = p_i_list[i]
        F_i = F_list[i]
        N_i = N_list[i]
        z_i = z_list[i]
        jt = joint_type_list[i]

        # Propagate child wrench into frame {i}
        f_child_i = R_ip1_i @ f_next
        n_child_i = R_ip1_i @ n_next + np.cross(p_i, f_child_i)

        # Internal wrench at joint i
        f_i = F_i + f_child_i
        # r_i_c is already accounted for in N_i via N_i + r_i_c x F_i,
        # or you can add that explicitly here depending on how you define N_i.
        n_i = N_i + n_child_i

        f_list[i] = f_i
        n_list[i] = n_i

        if jt == "R":
            tau_i = float(z_i.dot(n_i))
        elif jt == "P":
            tau_i = float(z_i.dot(f_i))
        else:
            raise ValueError("joint_type_list must contain only 'R' or 'P'")

        tau_list[i] = tau_i

        # Wrench at this joint becomes "child" for previous joint
        f_next = f_i
        n_next = n_i

    return f_list, n_list, tau_list

# Example usage: 2-link planar manipulator (simplified)
if __name__ == "__main__":
    n = 2
    F_list = [np.array([1.0, 0.0, 0.0]),
              np.array([0.5, 0.0, 0.0])]
    N_list = [np.array([0.0, 0.0, 0.2]),
              np.array([0.0, 0.0, 0.1])]
    R_ip1_i_list = [np.eye(3), np.eye(3)]
    p_i_list = [np.array([0.5, 0.0, 0.0]),
                np.array([0.3, 0.0, 0.0])]
    z_list = [np.array([0.0, 0.0, 1.0]),
              np.array([0.0, 0.0, 1.0])]
    joint_type_list = ["R", "R"]

    f_list, n_list, tau_list = newton_euler_backward(
        F_list, N_list, R_ip1_i_list, p_i_list,
        z_list, joint_type_list,
        f_tip=np.zeros(3), n_tip=np.zeros(3)
    )

    print("Joint torques:", tau_list)
      

In practice, the forward recursion provides \( \mathbf{F}_i, \mathbf{N}_i \) consistently with the modeling of gravity and any CoM offsets. A robotics toolbox can be used to validate this implementation by comparing with its built-in inverse dynamics routine.

7. C++ Implementation of Backward Recursion

In C++, widely used libraries such as Orocos KDL and RBDL implement Newton–Euler inverse dynamics efficiently and are integrated into many robotics frameworks (e.g., ROS). Below is a minimal illustration using Eigen for vector/matrix operations; it mirrors the Python logic at a lower level.


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

struct LinkDynamics {
    Eigen::Vector3d F;   // inertial force
    Eigen::Vector3d N;   // inertial moment
    Eigen::Matrix3d R_ip1_i; // ^i R_(i+1)
    Eigen::Vector3d p_i; // from frame i to i+1 in frame i
    Eigen::Vector3d z;   // joint axis
    char joint_type;     // 'R' or 'P'
};

void newtonEulerBackward(const std::vector<LinkDynamics>& links,
                         const Eigen::Vector3d& f_tip,
                         const Eigen::Vector3d& n_tip,
                         std::vector<Eigen::Vector3d>& f_list,
                         std::vector<Eigen::Vector3d>& n_list,
                         std::vector<double>& tau_list)
{
    int n = static_cast<int>(links.size());
    f_list.assign(n, Eigen::Vector3d::Zero());
    n_list.assign(n, Eigen::Vector3d::Zero());
    tau_list.assign(n, 0.0);

    Eigen::Vector3d f_next = f_tip;
    Eigen::Vector3d n_next = n_tip;

    for (int i = n - 1; i >= 0; --i) {
        const auto& L = links[i];

        Eigen::Vector3d f_child_i = L.R_ip1_i * f_next;
        Eigen::Vector3d n_child_i = L.R_ip1_i * n_next
                                  + L.p_i.cross(f_child_i);

        Eigen::Vector3d f_i = L.F + f_child_i;
        Eigen::Vector3d n_i = L.N + n_child_i;

        f_list[i] = f_i;
        n_list[i] = n_i;

        double tau_i;
        if (L.joint_type == 'R') {
            tau_i = L.z.dot(n_i);
        } else { // 'P'
            tau_i = L.z.dot(f_i);
        }
        tau_list[i] = tau_i;

        f_next = f_i;
        n_next = n_i;
    }
}

int main() {
    std::vector<LinkDynamics> links(2);
    // Initialize with some toy data (in a real application, fill from model)
    links[0].F = Eigen::Vector3d(1.0, 0.0, 0.0);
    links[0].N = Eigen::Vector3d(0.0, 0.0, 0.2);
    links[0].R_ip1_i = Eigen::Matrix3d::Identity();
    links[0].p_i = Eigen::Vector3d(0.5, 0.0, 0.0);
    links[0].z = Eigen::Vector3d(0.0, 0.0, 1.0);
    links[0].joint_type = 'R';

    links[1].F = Eigen::Vector3d(0.5, 0.0, 0.0);
    links[1].N = Eigen::Vector3d(0.0, 0.0, 0.1);
    links[1].R_ip1_i = Eigen::Matrix3d::Identity();
    links[1].p_i = Eigen::Vector3d(0.3, 0.0, 0.0);
    links[1].z = Eigen::Vector3d(0.0, 0.0, 1.0);
    links[1].joint_type = 'R';

    Eigen::Vector3d f_tip = Eigen::Vector3d::Zero();
    Eigen::Vector3d n_tip = Eigen::Vector3d::Zero();

    std::vector<Eigen::Vector3d> f_list, n_list;
    std::vector<double> tau_list;

    newtonEulerBackward(links, f_tip, n_tip, f_list, n_list, tau_list);

    std::cout << "Joint torques: ";
    for (double tau : tau_list) {
        std::cout << tau << " ";
    }
    std::cout << std::endl;
    return 0;
}
      

Libraries like RBDL encapsulate this pattern in functions such as InverseDynamics(model, q, qd, qdd, tau), which internally perform both forward and backward recursions on a tree-structured model.

8. Java, MATLAB/Simulink, and Mathematica Implementations

8.1 Java Skeleton (with EJML for Linear Algebra)

Java does not have a canonical robotics library, but matrix packages such as EJML simplify linear algebra. Below is a conceptual skeleton (only the core loop is shown):


import org.ejml.simple.SimpleMatrix;

class LinkDynamics {
    SimpleMatrix F;        // 3x1
    SimpleMatrix N;        // 3x1
    SimpleMatrix R_ip1_i;  // 3x3
    SimpleMatrix p_i;      // 3x1
    SimpleMatrix z;        // 3x1
    char jointType;        // 'R' or 'P'
}

public class NewtonEulerBackward {

    static class Result {
        SimpleMatrix[] fList;
        SimpleMatrix[] nList;
        double[] tauList;
    }

    public static Result compute(LinkDynamics[] links,
                                 SimpleMatrix fTip,
                                 SimpleMatrix nTip) {
        int n = links.length;
        SimpleMatrix[] fList = new SimpleMatrix[n];
        SimpleMatrix[] nList = new SimpleMatrix[n];
        double[] tauList = new double[n];

        SimpleMatrix fNext = fTip.copy();
        SimpleMatrix nNext = nTip.copy();

        for (int i = n - 1; i >= 0; --i) {
            LinkDynamics L = links[i];

            SimpleMatrix fChild_i = L.R_ip1_i.mult(fNext);
            SimpleMatrix nChild_i = L.R_ip1_i.mult(nNext)
                    .plus(L.p_i.cross(fChild_i)); // cross: helper returning 3x1

            SimpleMatrix f_i = L.F.plus(fChild_i);
            SimpleMatrix n_i = L.N.plus(nChild_i);

            fList[i] = f_i;
            nList[i] = n_i;

            double tau_i;
            if (L.jointType == 'R') {
                tau_i = L.z.dot(n_i);
            } else {
                tau_i = L.z.dot(f_i);
            }
            tauList[i] = tau_i;

            fNext = f_i;
            nNext = n_i;
        }

        Result res = new Result();
        res.fList = fList;
        res.nList = nList;
        res.tauList = tauList;
        return res;
    }
}
      

8.2 MATLAB/Simulink Implementation

MATLAB’s Robotics System Toolbox offers rigidBodyTree and inverseDynamics, which encapsulate the Newton–Euler recursions. A simple from-scratch backward recursion for an \( n \)-link chain is:


function [f_list, n_list, tau] = ne_backward(F_list, N_list, R_ip1_i_list, ...
                                             p_i_list, z_list, joint_type_list, ...
                                             f_tip, n_tip)
% F_list, N_list: 3xN
% R_ip1_i_list: 3x3xN
% p_i_list, z_list: 3xN
% joint_type_list: 1xN char array: 'R' or 'P'
N = size(F_list, 2);
f_list = zeros(3, N);
n_list = zeros(3, N);
tau = zeros(1, N);

f_next = f_tip(:);
n_next = n_tip(:);

for i = N:-1:1
    R_ip1_i = R_ip1_i_list(:, :, i);
    p_i = p_i_list(:, i);
    F_i = F_list(:, i);
    N_i = N_list(:, i);
    z_i = z_list(:, i);
    jt = joint_type_list(i);

    f_child_i = R_ip1_i * f_next;
    n_child_i = R_ip1_i * n_next + cross(p_i, f_child_i);

    f_i = F_i + f_child_i;
    n_i = N_i + n_child_i;

    f_list(:, i) = f_i;
    n_list(:, i) = n_i;

    if jt == 'R'
        tau(i) = z_i.' * n_i;
    else
        tau(i) = z_i.' * f_i;
    end

    f_next = f_i;
    n_next = n_i;
end
end
      

In Simulink, one can encapsulate this function in a MATLAB Function block, driven by the joint states \( q, \dot{q}, \ddot{q} \) and model parameters (possibly precomputed in the workspace), and use the outputs as inputs to actuator or control blocks.

8.3 Wolfram Mathematica (Symbolic 2-Link Example)

Mathematica is particularly convenient for symbolic verification of the Newton–Euler algorithm. For a planar 2R arm, the backward recursion can be formulated as:


(* Symbolic variables *)
ClearAll["Global`*"];
n = 2;
m1 = Symbol["m1"]; m2 = Symbol["m2"];
I1 = Symbol["I1"]; I2 = Symbol["I2"];

(* Assume planar motion about z-axis, so we keep only scalar moments about z *)
F1 = {Symbol["Fx1"], Symbol["Fy1"], 0};
F2 = {Symbol["Fx2"], Symbol["Fy2"], 0};
N1 = {0, 0, I1*Symbol["alpha1"] + Symbol["omega1"]*I1*Symbol["omega1"]};
N2 = {0, 0, I2*Symbol["alpha2"] + Symbol["omega2"]*I2*Symbol["omega2"]};

R21 = IdentityMatrix[3];
p1 = {Symbol["l1"], 0, 0};
z1 = {0, 0, 1}; z2 = {0, 0, 1};

f3 = {0, 0, 0};
n3 = {0, 0, 0};

(* Backward recursion *)
f2 = F2 + R21.f3;
n2 = N2 + R21.n3 + Cross[p1, R21.f3];

f1 = F1 + R21.f2;
n1 = N1 + R21.n2 + Cross[p1, R21.f2];

tau2 = z2.n2;
tau1 = z1.n1;

Simplify[{tau1, tau2}]
      

Comparing the resulting symbolic expressions for \( \tau_1, \tau_2 \) with those obtained via a Lagrangian derivation gives a strong consistency check for both modeling and implementation.

9. Problems and Solutions

Problem 1 (Backward Recursion for a Free-Flying End-Effector): Consider an \( n \)-link serial manipulator with no external wrench acting at the end-effector. Assume the forward recursion has provided \( \mathbf{a}_i^c, \boldsymbol{\omega}_i, \boldsymbol{\alpha}_i \) and you have the inertial parameters \( m_i, \mathbf{I}_i \). Show that if you initialize \( \mathbf{f}_{n+1} = \mathbf{0} \) and \( \mathbf{n}_{n+1} = \mathbf{0} \), then the backward recursion yields joint efforts \( \tau_i \) that satisfy the Euler–Lagrange equations for the same model.

Solution: The Euler–Lagrange equations for generalized coordinates \( q_i \) are:

\[ \tau_i = \frac{d}{dt}\left( \frac{\partial L}{\partial \dot{q}_i} \right) - \frac{\partial L}{\partial q_i}, \quad L = T - V. \]

For a serial manipulator, both the Lagrangian and the Newton–Euler formulation are derived from the same rigid-body kinetic and potential energies. It can be shown (see classic derivations in Newton–Euler literature) that the sum of all wrenches in the subtree \( \mathcal{T}_i \), projected onto the joint motion subspace, equals the generalized force given by Euler–Lagrange. Therefore, \( \tau_i = \mathbf{z}_i^{\top}\mathbf{n}_i \) (revolute) or \( \mathbf{z}_i^{\top}\mathbf{f}_i \) (prismatic) matches the corresponding Euler–Lagrange expression. The key steps are:

  • Express kinetic energy of each link in terms of \( \boldsymbol{\omega}_i, \mathbf{v}_i^c \).
  • Relate \( \boldsymbol{\omega}_i, \mathbf{v}_i^c \) to \( q, \dot{q} \) via Jacobians.
  • Show that differentiating and summing over the subtree recovers the Newton–Euler wrenches.

Problem 2 (2-Link Planar Arm: Hand-Derived Backward Recursion): A planar 2R manipulator moves in the \( x\!-\!y \) plane, with both joints rotating about the \( z \)-axis. Let \( m_i \) be the link masses, \( l_i \) the link lengths, \( c_i \) the CoM offsets from the proximal joint, and \( I_i \) the scalar inertia about \( z \) through the CoM. Assume gravity acts in the \( -y \) direction and is accounted for in \( \mathbf{a}_i^c \). Using the backward recursion, show that the torque at joint 2 is:

\[ \tau_2 = I_2 \ddot{q}_2 + m_2 c_2^2 \ddot{q}_2 + \text{terms involving } \ddot{q}_1, \dot{q}_1, \dot{q}_2 \]

(You do not need to compute all cross-coupling terms explicitly.)

Solution: For link 2, in plane motion, the relevant components are:

\[ \mathbf{F}_2 = m_2 \mathbf{a}_2^c,\quad \mathbf{N}_2 = I_2 \boldsymbol{\alpha}_2 + \boldsymbol{\omega}_2 \times (I_2 \boldsymbol{\omega}_2). \]

Because motion is planar, \(\boldsymbol{\omega}_2\) and \(\boldsymbol{\alpha}_2\) are along \( z \). The term \( \boldsymbol{\omega}_2 \times (I_2 \boldsymbol{\omega}_2) \) vanishes, so \( \mathbf{N}_2 = [0, 0, I_2 \ddot{q}_1 + I_2 \ddot{q}_2]^{\top} \) after expressing \(\boldsymbol{\alpha}_2\) in terms of joint accelerations. The torques due to translational inertia are \( m_2 c_2^2 \ddot{q}_2 \) plus mixed terms involving \(\ddot{q}_1\) and Coriolis/centrifugal contributions in \(\dot{q}_1, \dot{q}_2\). Projecting \( \mathbf{n}_2 \) onto \( \mathbf{z}_2 = [0, 0, 1]^{\top} \) yields the stated expression plus cross-coupling, which is consistent with standard 2R dynamic models.

Problem 3 (Effect of External End-Effector Force): For a 3-link serial arm with an external force \( \mathbf{f}_4^{\text{ext}} \neq \mathbf{0} \) at the end-effector and no external moments, write the explicit expression for \( \mathbf{f}_3 \) in terms of \( \mathbf{F}_3 \) and \( \mathbf{f}_4^{\text{ext}} \). Assume no other external wrenches and that \( \mathbf{f}_4 = \mathbf{f}_4^{\text{ext}} \).

Solution: With \( \mathbf{f}_4 = \mathbf{f}_4^{\text{ext}} \) and \( \mathbf{f}_3^{\text{ext}} = \mathbf{0} \), the recursion gives:

\[ \mathbf{f}_3 = \mathbf{F}_3 + \;^3\mathbf{R}_{4} \,\mathbf{f}_4 = \mathbf{F}_3 + \;^3\mathbf{R}_{4} \,\mathbf{f}_4^{\text{ext}}. \]

The external end-effector force is thus transmitted through the chain, rotated into each upstream link frame and added to its inertial force.

Problem 4 (Complexity Comparison): Consider a naive implementation of the Lagrange–Euler equations that computes the mass matrix \( \mathbf{M}(q) \) by symbolic or numerical differentiation and then evaluates \( \tau = \mathbf{M}(q)\ddot{\mathbf{q}} + \mathbf{C}(q,\dot{q})\dot{\mathbf{q}} + \mathbf{g}(q) \). Explain why this approach can scale as \( \mathcal{O}(n^3) \) in the number of joints, whereas the Newton–Euler recursion is \( \mathcal{O}(n) \).

Solution: Building \( \mathbf{M}(q) \in \mathbb{R}^{n\times n} \) generally requires computing \( \mathcal{O}(n^2) \) entries, each of which may involve contributions from multiple links and hence \( \mathcal{O}(n) \) operations, leading to \( \mathcal{O}(n^3) \). Additional effort is required to obtain \( \mathbf{C} \) and \( \mathbf{g} \) consistently. In contrast, the Newton–Euler algorithm works directly with local recursive relations, performing a constant amount of work per link in each sweep, hence \( \mathcal{O}(n) \).

Problem 5 (Decision Flow: When to Use Newton–Euler?): Sketch a reasoning flow for deciding whether to implement robot dynamics via Newton–Euler recursion or via a precomputed Lagrangian form, considering model size, need for symbolic expressions, and numerical performance.

Solution (flow):

flowchart TD
  S["Start: need inverse dynamics for serial robot"] --> SYM["Need closed-form symbolic expressions?"]
  SYM -->|yes| LAG["Use Lagrange-based symbolic \nderivation for small n"]
  SYM -->|no| SIZE["Is n large (many links) \nor multiple evaluations required \nin real time?"]
  SIZE -->|yes| NE["Use Newton-Euler recursion (O(n))"]
  SIZE -->|no| PREF["Either approach acceptable;\n pick based on tooling and \nease of implementation"]
      

10. Summary

In this lesson, we developed the backward recursion of the Newton–Euler algorithm. Starting from rigid-body inertial forces and moments, we derived subtree equilibrium relations that propagate wrenches from the end-effector to the base in \( \mathcal{O}(n) \) time. We showed how to project internal wrenches onto joint motion subspaces to obtain the generalized efforts \( \tau_i \), and we implemented the algorithm in Python, C++, Java, MATLAB/Simulink, and Mathematica. These results provide a computationally efficient and physically transparent method for inverse dynamics, which will be compared to Lagrange–Euler formulations and extended in later chapters to more complex multibody topologies.

11. References

  1. Luh, J.Y.S., Walker, M.W., & Paul, R.P. (1980). On-line computational scheme for mechanical manipulators. ASME Journal of Dynamic Systems, Measurement, and Control, 102(2), 69–76.
  2. Hollerbach, J.M. (1980). A recursive Lagrangian formulation of manipulator dynamics and a comparative study of dynamics formulation complexity. IEEE Transactions on Systems, Man, and Cybernetics, 10(11), 730–736.
  3. Walker, M.W., & Orin, D.E. (1982). Efficient dynamic computer simulation of robotic mechanisms. ASME Journal of Dynamic Systems, Measurement, and Control, 104(3), 205–211.
  4. Featherstone, R. (1983). The calculation of robot dynamics using articulated-body inertias. International Journal of Robotics Research, 2(1), 13–30.
  5. Featherstone, R., & Orin, D.E. (2000). Robot dynamics: Equations and algorithms. Proceedings of the IEEE International Conference on Robotics and Automation, 826–834.
  6. Angeles, J. (1988). Rational Kinematics. Springer. (Chapters on recursive dynamics.)
  7. Khatib, O. (1987). A unified approach for motion and force control of robot manipulators: The operational space formulation. IEEE Journal of Robotics and Automation, 3(1), 43–53.
  8. Craig, J.J. (1989). Introduction to Robotics: Mechanics and Control. Addison-Wesley. (Appendix on Newton–Euler formulation.)
  9. Sciavicco, L., & Siciliano, B. (2000). Modelling and Control of Robot Manipulators. Springer. (Chapter on recursive Newton–Euler dynamics.)
  10. Spong, M.W., Hutchinson, S., & Vidyasagar, M. (2006). Robot Modeling and Control. Wiley. (Sections on Newton–Euler and Lagrange dynamics.)