Numerical Methods
Three numerical building blocks support the kinematics and dynamics chapters: a
linear solver that extracts the joint acceleration from the equation of
motion, a least-squares solver that underlies numerical inverse kinematics,
and an ODE integrator that advances the state through time. skelarm leans
on mature library routines for these operations, but the classic methods behind
them are worth seeing.
1. Linear equation solver
The forward dynamics chapter leaves a linear system
\(H \ddot{q} = \tau - b + J_E^{T} f_E\) to solve for \(\ddot{q}\) at every step — a
problem of the general form \(A x = b\). Because \(H\) is symmetric positive definite,
it can be solved robustly (Cholesky is the natural specialized choice); skelarm
delegates to NumPy's numpy.linalg.solve, an LU-based LAPACK routine. The
textbook method underlying such solvers is Gaussian elimination.
Gaussian elimination
The idea is to reduce \(A\) to triangular form and then read off the unknowns:
- Forward elimination. For each pivot column \(k = 1, \dots, n-1\) and each row \(i > k\), subtract a multiple \(f = A_{ik}/A_{kk}\) of row \(k\) from row \(i\) so that \(A_{ik}\) becomes zero, applying the same operation to the right-hand side: \(A_{ij} \leftarrow A_{ij} - f A_{kj}\) and \(b_i \leftarrow b_i - f b_k\). This leaves an upper-triangular system.
- Back substitution. Solve from the last row upward, \(x_i = \bigl(b_i - \sum_{j>i} A_{ij} x_j\bigr) / A_{ii}\).
Robust implementations add pivoting — reordering rows so the pivot \(|A_{kk}|\) is large — for numerical stability. The equation of motion's \(H\) is regular, symmetric, and positive definite, so even a naive pivot-free elimination is safe here.
2. Least-squares and damping
Numerical inverse kinematics rarely leaves a square, exactly solvable system. Instead, it often asks for the joint step \(\Delta q\) that best satisfies a linearized residual equation
The least-squares form is
When \(J\) has full column rank, setting the gradient to zero gives the normal equation
For a redundant planar arm, \(J\) has more columns than rows. The minimum-norm step can instead be written with the right pseudoinverse,
as long as \(JJ^{T}\) is regular. This is efficient for a two-dimensional endpoint task because it solves a \(2 \times 2\) system, but it becomes unstable when the Jacobian approaches a singular posture.
The standard stabilization is Tikhonov regularization, also called damped least squares in inverse kinematics:
Its normal equation is
Equivalently, for the endpoint task,
The damping term keeps the matrix invertible and bounds the step near singularities. A larger \(\mu\) is safer but slower; a smaller \(\mu\) is more accurate when the Jacobian is well-conditioned but can amplify numerical noise.
Implementation note
The normal equations are useful for deriving the methods, but they square the
condition number of the Jacobian. Implementation code should prefer library
solvers over manually inverting matrices: numpy.linalg.solve for the small
positive-definite damped systems, numpy.linalg.lstsq or
numpy.linalg.pinv for baseline least-squares behavior, and SciPy options
such as scipy.linalg.solve, scipy.linalg.lstsq, or
scipy.optimize.least_squares when richer solver controls are needed.
The Numerical Inverse Kinematics chapter extends this idea to weighted nonlinear least squares. In that setting, Levenberg-Marquardt repeatedly solves
where \(W_e\) weights task residuals and \(W_n\) damps joint motion.
3. Time integration
Simulating motion means integrating the joint acceleration twice, to velocity and
then position. Stacking the state as \(X = [q^{T}, \dot{q}^{T}]^{T}\) recasts the
second-order dynamics as a first-order system \(\dot{X} = f(t, X)\), whose velocity
half is \(\dot{q}\) and whose acceleration half is the
forward-dynamics solve. skelarm integrates it with
SciPy's scipy.integrate.solve_ivp using the adaptive RK45 (Dormand–Prince)
method, which adjusts its step size automatically to control the error. The two
fixed-step schemes below are the ideas it refines.
Euler's method
The simplest scheme advances the state along its current slope over a fixed step \(\Delta t\):
It is easy but only first-order accurate (global error \(O(\Delta t)\)), and it drifts off the true trajectory for large steps or stiff dynamics.
Runge–Kutta (RK4)
The classical fourth-order Runge–Kutta method samples the slope at four points across the step and blends them, which buys much higher accuracy. For a state \(y\) (standing in for the stacked \(X\)),
with
Its global error is \(O(\Delta t^{4})\), making it the usual workhorse for smooth
mechanical systems — and the fixed-step sibling of the adaptive RK45 that
skelarm actually uses.