Long-form companion to
GNC/Framing_Paper_coordinated_control/coordinated_control.md
(the corrected n = 6 equation reference; bare equation numbers below
refer to it) and to derivation_7dof.md (the intuition
layer). Numeric verification:
validation/test_robot7_nullspace.py,
test_wide_gamma.py,
test_null_space_suppression.py. Prior art: the redundant
coordinated formulation appears in Giordano’s PhD thesis §5.2 and
Appendix C.4 (giordano2020wholebody, in corpus); our derivation
converged on the same construction and serves as cross-validation. What
follows documents precisely what we changed, what we
proved about the changes, and what we deliberately
left alone.
Before any mathematics, here is the complete list of modifications, so the reader knows the size of the territory. Five things changed; two important things did not.
| # | Object | Was (n = 6) | Is (n = 7) | Where | Status |
|---|---|---|---|---|---|
| M1 | \(\boldsymbol J_{\nu_e}^\oplus\), \(\boldsymbol\Gamma\) | \(6\times 6\), \(12\times 12\) | \(6\times 7\), \(12\times 13\) | construction unchanged | dimension-generic after audit (two wrapper literals fixed; R9 sweep clean) |
| M2 | singularity region \(\Omega\) (36) | \(\sigma_{\min} > 0\) of a square matrix | \(\sigma_6 > 0\) of a wide matrix | dyn.s_min_J |
definition generalizes verbatim |
| M3 | healthy branch of the damped inverse | \(\boldsymbol J^{-1}\) | Moore–Penrose \(\boldsymbol J^{+}\) | robot.py damped_inverse |
Prop. 2 below |
| M4 | velocity reconstruction (34d) | \(\dot{\boldsymbol q} = (\boldsymbol J_{\nu_e}^\oplus)^{-1}(\cdot)\), unique | augmented solve \([\boldsymbol\Gamma; \hat{\boldsymbol z}_a^T]\boldsymbol x = [\boldsymbol y; 0]\) (the \(v_n=0\) section) | reconstruct_generalized_velocity |
Prop. 3, Thm. 1 |
| M5 | (new objects) | — | \(\hat{\boldsymbol n},\ \hat{\boldsymbol k},\ \boldsymbol z_a\) | dyn.k_hat, dyn.z_a |
Prop. 1 |
| — | force map (20): \(\boldsymbol F = \boldsymbol\Gamma^T\boldsymbol G\) | unchanged | unchanged (13-vector output) | all_control_terms |
no null-space force injected |
| — | reduced matrices \(\breve{\boldsymbol M}, \breve{\boldsymbol C}\) (21) | exact | approximation (see §6) | dyn.M_breve etc. |
open: P1 bookkeeping |
The reader in a hurry may read §3 (the kernel), §5 (the reconstruction theorem), and §6 (the honest caveat), and trust the rest.
The controller never works in the robot’s native velocity coordinates. It transforms them. Writing \(\boldsymbol x = [\boldsymbol v_b; \boldsymbol\omega_b; \dot{\boldsymbol q}] \in \mathbb R^{6+n}\) for the generalized velocity and \(\boldsymbol z = [\boldsymbol v_c; \boldsymbol\omega_b; \boldsymbol\nu_e^\oplus] \in \mathbb R^{12}\) for the task velocity, the transform is \(\boldsymbol z = \boldsymbol\Gamma\boldsymbol x\) with \(\boldsymbol\Gamma \in \mathbb R^{12\times(6+n)}\) — equation (19). For a six-joint arm both vectors have twelve entries, \(\boldsymbol\Gamma\) is square, and Giordano’s derivation inverts it in two places: to obtain the triangular dynamics (21), and to reconstruct the joint rates from the task state — equation (34d). His own words mark the spot: “Let us assume a nonredundant manipulator, i.e., n = 6.”
With a seventh joint, the vector \(\boldsymbol x\) has thirteen entries while \(\boldsymbol z\) keeps twelve. The map \(\boldsymbol\Gamma\) becomes wide, and “invert” stops being a well-posed verb: infinitely many \(\boldsymbol x\) produce the same \(\boldsymbol z\). Every modification below is, in one way or another, an answer to the question: which of those infinitely many \(\boldsymbol x\) should the controller mean?
It is worth pausing on why this question has physical content. The difference between two such reconstructions is a motion that produces no task velocity — the arm reconfigures, the base counter-moves, and the CoM, base attitude, and end-effector all stay put. Choosing a reconstruction is choosing what the robot’s “invisible” motion does. Choosing carelessly lets it drift; we measured exactly that (mean \(|v_n| = 0.157\), non-decaying) before making the choice deliberate.
We record these first because their correctness is an inspection, not a derivation, and because the committee should know how little of the original machinery we touched.
The circumcentroidal Jacobian (14) is built as \(\boldsymbol J_{\nu_e}^\oplus = \boldsymbol
J_{\nu_e} - [\boldsymbol R_{eb}; \boldsymbol 0]\,\bar{\boldsymbol
J}_v\), a difference of two matrices each having one column per
joint. Nothing in the construction counts the columns. The same is true
of the rows of \(\boldsymbol\Gamma\) in
(19): each block is defined for general \(n\), and our implementation builds them
from self.n. For \(n = 7\)
we therefore obtain \(\boldsymbol
J_{\nu_e}^\oplus \in \mathbb R^{6\times 7}\) and \(\boldsymbol\Gamma \in \mathbb R^{12\times
13}\) with no code or formula change.
The singularity-free region (36) reads \(\Omega = \{\,\sigma_{\min}(\boldsymbol J_{\nu_e}^\oplus) > 0\,\}\). For a wide matrix the smallest singular value is \(\sigma_6\), and the condition \(\sigma_6 > 0\) says precisely that the six task directions remain reachable — full row rank. The definition generalizes without edits, though its meaning improves: a \(6\times 7\) matrix containing the six old columns plus one more can only have \(\sigma_6\) at least as large as the old \(\sigma_{\min}\), because appending a column cannot shrink the maximal reachable set. (Empirically, the mission-run derate fraction fell from 0.64–0.80 to 0.31–0.34 — the seventh column is doing exactly this.)
The moral. The circumcentroidal decomposition was never a six-joint idea. The six-joint assumption lived entirely in the two inversions, which is where all the work below concentrates.
We want the set of generalized velocities that the task coordinates cannot see — the kernel of \(\boldsymbol\Gamma\). Rather than guess, we solve \(\boldsymbol\Gamma\boldsymbol x = \boldsymbol 0\) block row by block row, using the explicit form (19). Let \(\boldsymbol x = [\boldsymbol v_b; \boldsymbol\omega_b; \dot{\boldsymbol q}]\), where \(\boldsymbol v_b, \boldsymbol\omega_b \in \mathbb R^3\) and \(\dot{\boldsymbol q} \in \mathbb R^7\).
The middle row of (19) is the identity acting on \(\boldsymbol\omega_b\), so the second block equation reads \(\boldsymbol\omega_b = \boldsymbol 0\): any base rotation is itself a task coordinate and is therefore visible by construction.
With \(\boldsymbol\omega_b = \boldsymbol 0\), the bottom row reduces to \(\boldsymbol J_{\nu_e}^\oplus\dot{\boldsymbol q} = \boldsymbol 0\). Since \(\boldsymbol J_{\nu_e}^\oplus\) has full row rank on \(\Omega\), its kernel is one-dimensional. Let \(\hat{\boldsymbol n} \in \mathbb R^7\) be a unit vector spanning it; then \(\dot{\boldsymbol q} = \alpha\hat{\boldsymbol n}\) for some real scalar \(\alpha\).
Finally, the top row with both substitutions reads \(\boldsymbol R_{cb}\big(\boldsymbol v_b + \bar{\boldsymbol J}_v\dot{\boldsymbol q}\big) = \boldsymbol 0\), and since a rotation matrix is invertible, it follows that \(\boldsymbol v_b = -\alpha\,\bar{\boldsymbol J}_v\hat{\boldsymbol n}\).
Proposition 1 (self-motion basis). On \(\Omega\), the kernel of \(\boldsymbol\Gamma \in \mathbb R^{12\times 13}\) is one-dimensional and spanned by
\[ \hat{\boldsymbol k} \;=\; \begin{bmatrix} -\bar{\boldsymbol J}_v\,\hat{\boldsymbol n} \\ \boldsymbol 0_3 \\ \hat{\boldsymbol n} \end{bmatrix} \in \mathbb R^{13}, \]
where \(\hat{\boldsymbol n} \in \mathbb R^7\) is a unit vector spanning \(\ker \boldsymbol J_{\nu_e}^\oplus\) and \(\bar{\boldsymbol J}_v \in \mathbb R^{3\times 7}\) is the mass-averaged linear Jacobian of equation (7).
Proof. The scratch work above shows every kernel element has this form, so the kernel is contained in the span of \(\hat{\boldsymbol k}\). Conversely, substituting \(\hat{\boldsymbol k}\) into the three block rows of (19) gives, in order: \(\boldsymbol R_{cb}(-\bar{\boldsymbol J}_v\hat{\boldsymbol n}) + \boldsymbol R_{cb}\bar{\boldsymbol J}_v\hat{\boldsymbol n} = \boldsymbol 0\) for the CoM row; the zero vector for the attitude row, since the \(\boldsymbol\omega_b\) slot of \(\hat{\boldsymbol k}\) is zero; and \(\boldsymbol J_{\nu_e}^\oplus\hat{\boldsymbol n} = \boldsymbol 0\) for the end-effector row, by the definition of \(\hat{\boldsymbol n}\). Hence \(\boldsymbol\Gamma\hat{\boldsymbol k} = \boldsymbol 0\), and the kernel is exactly the span of \(\hat{\boldsymbol k}\). Since the thirteen columns of \(\boldsymbol\Gamma\) minus its rank \(12\) leave dimension one, no larger kernel is possible. \(\blacksquare\)
Physically: the arm moves along its null direction while the base
translates by the mass-weighted opposite, so that the system CoM — and
everything else the mission watches — stays frozen. We verify \(\|\boldsymbol\Gamma\hat{\boldsymbol k}\| <
10^{-10}\) at machine precision across random configurations in
test_robot7_nullspace.py.
A computational caution that cost us nothing only because we caught
it early: the economy-size SVD (full_matrices=False) of a
\(6\times 7\) matrix returns six right
singular vectors — it describes what the map does and omits
what it ignores. The kernel vector \(\hat{\boldsymbol n}\) requires the full
SVD. A second caution we flag rather than resolve: a globally smooth
choice of sign for \(\hat{\boldsymbol
n}(\boldsymbol q)\) need not exist; all our uses below are
sign-invariant, so no continuity enforcement is currently needed.
To regulate the invisible motion we must first measure it. We seek a row vector — a covector, an object that eats velocities and returns a number — reading one on a unit of self-motion. Among all such rows, define
\[ \boldsymbol z_a^T \;=\; \frac{\hat{\boldsymbol k}^T\boldsymbol M}{\hat{\boldsymbol k}^T\boldsymbol M\hat{\boldsymbol k}}, \qquad v_n \;=\; \boldsymbol z_a^T\boldsymbol x, \]
where \(\boldsymbol M \in \mathbb R^{13\times 13}\) is the generalized inertia matrix of equation (4). The denominator \(\hat{\boldsymbol k}^T\boldsymbol M\hat{\boldsymbol k}\) is twice the kinetic energy of the self-motion at unit speed; since \(\boldsymbol M\) is symmetric positive definite and \(\hat{\boldsymbol k}\) is nonzero, the denominator is strictly positive at every configuration in \(\Omega\), so \(\boldsymbol z_a\) is well defined everywhere we operate, and \(\boldsymbol z_a^T\hat{\boldsymbol k} = 1\) by construction. This inertia weighting is the same dynamically-consistent device as Giordano’s thesis equation (5.22) (there imposed as \([\boldsymbol J_{\omega_b}^\oplus; \boldsymbol J_e^\oplus]\boldsymbol M^{-1}\boldsymbol J_n^{\oplus T} = \boldsymbol 0\)); we arrived at it independently, which we offer as cross-validation rather than novelty.
The moral. The gradient-row alternative (extended Jacobian) can vanish against \(\hat{\boldsymbol n}\) and so manufactures singularities that exist only in the bookkeeping. The inertia row cannot: positive kinetic energy is not negotiable.
The routine damped_inverse conditions \((\boldsymbol J_{\nu_e}^\oplus)^{-1}\) near
singularities: below a hard floor it refuses and reuses the last
inverse; in a soft band it applies Tikhonov regularization; in the
healthy regime it used np.linalg.inv. Only the healthy
branch assumed squareness. We replaced it, only for non-square
input, by the Moore–Penrose pseudoinverse assembled from the
already-computed economy SVD factors: if \(\boldsymbol J = \boldsymbol
U\boldsymbol\Sigma\boldsymbol V_6^T\) with \(\boldsymbol U \in \mathbb R^{6\times 6}\),
\(\boldsymbol\Sigma \in \mathbb R^{6\times
6}\) positive diagonal, and \(\boldsymbol V_6 \in \mathbb R^{7\times 6}\)
having orthonormal columns, then
\[ \boldsymbol J^{+} \;=\; \boldsymbol V_6\,\boldsymbol\Sigma^{-1}\boldsymbol U^T \in \mathbb R^{7\times 6}. \]
The square branch is untouched — bit-for-bit — which is what lets all five pinned 6-DOF baselines reproduce at \(0.000\mathrm{e}{+00}\) after the change.
The analytic block inverse of \(\boldsymbol\Gamma\) (Appendix B of the equation reference) is assembled from \(\boldsymbol J^{+}\). We must check what that formula is once \(\boldsymbol J^{+}\) is merely a right inverse of a wide \(\boldsymbol J_{\nu_e}^\oplus\).
Proposition 2 (the block formula yields a right inverse). On \(\Omega\), with \(\boldsymbol J^{+}\) the Moore–Penrose pseudoinverse of \(\boldsymbol J_{\nu_e}^\oplus\), the matrix
\[ \boldsymbol\Gamma^{-R} \;=\; \begin{bmatrix} \boldsymbol R_{bc} & [\boldsymbol p_{bc}]^\wedge + \bar{\boldsymbol J}_v\boldsymbol J^{+}\boldsymbol G_{\omega_b} & -\bar{\boldsymbol J}_v\boldsymbol J^{+} \\ \boldsymbol 0 & \boldsymbol E & \boldsymbol 0 \\ \boldsymbol 0 & -\boldsymbol J^{+}\boldsymbol G_{\omega_b} & \boldsymbol J^{+} \end{bmatrix} \in \mathbb R^{13\times 12} \]
satisfies \(\boldsymbol\Gamma\,\boldsymbol\Gamma^{-R} = \boldsymbol E_{12}\). It is not a left inverse; instead \(\boldsymbol\Gamma^{-R}\boldsymbol\Gamma\) is the projector along \(\mathrm{span}\{\hat{\boldsymbol k}\}\) whose arm block is \(\boldsymbol J^{+}\boldsymbol J_{\nu_e}^\oplus = \boldsymbol E_7 - \hat{\boldsymbol n}\hat{\boldsymbol n}^T\).
Proof. We multiply blocks. Three of the products cancel identically without any property of \(\boldsymbol J^{+}\) at all: in the first row of the product, the second column gives \[ \boldsymbol R_{cb}\big([\boldsymbol p_{bc}]^\wedge + \bar{\boldsymbol J}_v\boldsymbol J^{+}\boldsymbol G_{\omega_b}\big) - \boldsymbol R_{cb}[\boldsymbol p_{bc}]^\wedge - \boldsymbol R_{cb}\bar{\boldsymbol J}_v\boldsymbol J^{+}\boldsymbol G_{\omega_b} \] , and the terms cancel in pairs; the third column cancels the same way; the first column is \(\boldsymbol R_{cb}\boldsymbol R_{bc} = \boldsymbol E_3\) since rotations are orthogonal. The middle row of the product is trivially \([\boldsymbol 0\ \boldsymbol E\ \boldsymbol 0]\). The bottom row is where the inverse property is actually consumed: its second column is \(\boldsymbol G_{\omega_b} - \boldsymbol J_{\nu_e}^\oplus\boldsymbol J^{+}\boldsymbol G_{\omega_b} = (\boldsymbol E_6 - \boldsymbol J_{\nu_e}^\oplus\boldsymbol J^{+})\boldsymbol G_{\omega_b}\), and its third column is \(\boldsymbol J_{\nu_e}^\oplus\boldsymbol J^{+}\). For the Moore–Penrose pseudoinverse of a full-row-rank matrix, \(\boldsymbol J_{\nu_e}^\oplus\boldsymbol J^{+} = \boldsymbol E_6\), and both entries collapse to the required identity blocks. For the failed left-inverse claim, note \(\boldsymbol\Gamma^{-R}\boldsymbol\Gamma\) has rank at most twelve, so it cannot be \(\boldsymbol E_{13}\); applying it to \(\hat{\boldsymbol k}\) gives zero (since \(\boldsymbol\Gamma\hat{\boldsymbol k} = \boldsymbol 0\)), and on the orthogonal complement of \(\hat{\boldsymbol n}\) in the arm block the Moore–Penrose identity \(\boldsymbol J^{+}\boldsymbol J_{\nu_e}^\oplus = \boldsymbol E_7 - \hat{\boldsymbol n}\hat{\boldsymbol n}^T\) is the standard projector formula. \(\blacksquare\)
We verify \(\|\boldsymbol\Gamma\boldsymbol\Gamma^{-R} - \boldsymbol E_{12}\| < 10^{-8}\) numerically at well-conditioned configurations.
The moral. The old closed-form inverse survives as a right inverse with no formula change — but a right inverse is a choice (this one is the Euclidean min-norm choice in the arm block), and §5 is about making a better choice on the reconstruction path. Where the choice quietly persists, §6 owns up to it.
This is the load-bearing modification, and it needs one architectural
fact to make sense. The closed loop does not integrate
the thirteen-dimensional dynamics. It integrates the task states (the
CoM law (22a) and the breve subsystem (22b)) and then
reconstructs the generalized velocity from the task state at
every step — equation (34d), implemented in
reconstruct_generalized_velocity. For square \(\boldsymbol\Gamma\) that reconstruction is
unique. For wide \(\boldsymbol\Gamma\)
the code’s lstsq (and the damped-normal-equation variant)
silently selects the minimum-Euclidean-norm solution.
Here is the subtlety that motivated the change. The min-norm solution \(\boldsymbol x_E\) is Euclidean-orthogonal to \(\hat{\boldsymbol k}\), that is, \(\boldsymbol x_E^T\hat{\boldsymbol k} = 0\). But the physically meaningful ghost content is the inertia-weighted component \(v_n = \boldsymbol z_a^T\boldsymbol x = \hat{\boldsymbol k}^T\boldsymbol M\boldsymbol x / (\hat{\boldsymbol k}^T\boldsymbol M\hat{\boldsymbol k})\), and Euclidean orthogonality does not imply \(\boldsymbol M\)-orthogonality. The mismatch is not hypothetical: over a two-second closed-loop window the reconstructed velocity carried a mean \(|v_n|\) of \(0.157\ \mathrm{rad\,s^{-1}}\) that did not decay. The minimum-norm convention was, itself, the ghost injector.
We replace the underdetermined solve by the square augmented system
\[ \begin{bmatrix} \boldsymbol\Gamma \\ \hat{\boldsymbol z}_a^T \end{bmatrix}\boldsymbol x \;=\; \begin{bmatrix} \boldsymbol y \\ 0 \end{bmatrix}, \qquad \hat{\boldsymbol z}_a = \boldsymbol z_a / \|\boldsymbol z_a\|, \]
where \(\boldsymbol y \in \mathbb
R^{12}\) is the stacked task velocity. The row is normalized
purely for numerical hygiene: because its right-hand side is zero,
scaling the row does not move the exact solution, only the conditioning
of the regularized variant. The knob
controller.arm.null_space.enable gates the augmentation;
when the robot has six joints the kernel objects are None
and the code path is untouched, which the baselines confirm
byte-exactly.
Remark (terminology, for the record). The vocabulary here is borrowed from fiber bundles, and one of our own shorthands deserves a correction. The surjective linear map \(\boldsymbol\Gamma : \mathbb R^{13} \to \mathbb R^{12}\) organizes \(\mathbb R^{13}\) as a (trivial, linear) bundle over the task space: the fiber over a point \(\boldsymbol y\) is the affine solution line \(\boldsymbol\Gamma^{-1}(\boldsymbol y) = \boldsymbol x_p + \ker\boldsymbol\Gamma\). A reconstruction rule is a section — a map \(\sigma : \mathbb R^{12} \to \mathbb R^{13}\) with \(\boldsymbol\Gamma\sigma = \mathrm{id}\), choosing one point on each fiber. The set \(\{v_n = 0\}\) is therefore not a fiber but the image of a section: the twelve-dimensional \(\boldsymbol M\)-orthogonal complement of \(\hat{\boldsymbol k}\), a plane crossing every fiber exactly once (the horizontal subspace, in connection language). The
lstsqconvention is the Euclidean-orthogonal section; ours is the \(\boldsymbol M\)-orthogonal one — in geometric mechanics, the horizontal space of the mechanical connection (Marsden–Montgomery; Kelly & Murray’s locomotion work), which is also exactly what the robotics literature names dynamically consistent (Khatib). The free-floating literature’s path-dependent workspace is the holonomy of this same kind of connection — the falling-cat phenomenon; our actuated base makes holonomy a curiosity here rather than a constraint. Where the shorthand “the \(v_n = 0\) fiber” survives in code comments and earlier notes, read “the \(v_n = 0\) section.”
Proposition 3 (well-posedness). On \(\Omega\), the augmented matrix \(\boldsymbol\Gamma_a = [\boldsymbol\Gamma; \hat{\boldsymbol z}_a^T] \in \mathbb R^{13\times 13}\) is invertible.
Proof. A square matrix fails to be invertible exactly when some nonzero vector annihilates all its rows. Suppose \(\boldsymbol\Gamma_a\boldsymbol x = \boldsymbol 0\) for some \(\boldsymbol x \in \mathbb R^{13}\). The first twelve rows give \(\boldsymbol\Gamma\boldsymbol x = \boldsymbol 0\), so by Proposition 1 we may write \(\boldsymbol x = \alpha\hat{\boldsymbol k}\) for a real scalar \(\alpha\). The last row then gives \(\alpha\,\hat{\boldsymbol z}_a^T\hat{\boldsymbol k} = 0\). Since \(\hat{\boldsymbol z}_a^T\hat{\boldsymbol k} = (\boldsymbol z_a^T\hat{\boldsymbol k})/\|\boldsymbol z_a\| = 1/\|\boldsymbol z_a\| > 0\), it follows that \(\alpha = 0\), hence \(\boldsymbol x = \boldsymbol 0\). \(\blacksquare\)
Theorem 1 (inertial decoupling of the chosen coordinates). Write the columns of \(\boldsymbol\Gamma_a^{-1}\) as \(\boldsymbol c_1, \dots, \boldsymbol c_{13}\), so that \(\boldsymbol c_i\) is the unique generalized velocity producing one unit of the \(i\)-th coordinate and zero of the others. Then \(\boldsymbol c_{13} = \|\boldsymbol z_a\|\,\hat{\boldsymbol k}\) (statement corrected per review R2: from \(\hat{\boldsymbol z}_a^T\boldsymbol c_{13} = 1\) with \(\boldsymbol c_{13} = \beta\hat{\boldsymbol k}\) and \(\boldsymbol z_a^T\hat{\boldsymbol k} = 1\) it follows \(\beta = \|\boldsymbol z_a\|\); only the proportionality \(\boldsymbol c_{13} \propto \hat{\boldsymbol k}\) is used downstream) — and for every \(i \le 12\),
\[ \hat{\boldsymbol k}^T\boldsymbol M\,\boldsymbol c_i \;=\; 0 . \]
Consequently the transformed inertia \(\hat{\boldsymbol M} = \boldsymbol\Gamma_a^{-T}\boldsymbol M\boldsymbol\Gamma_a^{-1}\) is block diagonal between the twelve task coordinates and the ghost coordinate.
Proof. For the last column: \(\boldsymbol c_{13}\) satisfies \(\boldsymbol\Gamma\boldsymbol c_{13} = \boldsymbol 0\) and \(\hat{\boldsymbol z}_a^T\boldsymbol c_{13} = 1\); the first condition forces \(\boldsymbol c_{13} = \beta\hat{\boldsymbol k}\) for a real scalar \(\beta\), and the second fixes \(\beta = \|\boldsymbol z_a\| / (\boldsymbol z_a^T\hat{\boldsymbol k}) = \|\boldsymbol z_a\|\). For the cross terms, read one entry of the identity \(\boldsymbol\Gamma_a\boldsymbol\Gamma_a^{-1} = \boldsymbol E_{13}\): row thirteen against column \(i \le 12\) gives \(\hat{\boldsymbol z}_a^T\boldsymbol c_i = 0\), and multiplying out the definition of \(\hat{\boldsymbol z}_a\) yields \(\hat{\boldsymbol k}^T\boldsymbol M\boldsymbol c_i = 0\). The inertia entries are \(\hat M_{ij} = \boldsymbol c_i^T\boldsymbol M\boldsymbol c_j\), so every entry coupling \(i \le 12\) to \(j = 13\) vanishes. \(\blacksquare\)
The moral. We did not have to prove the decoupling so much as read it off an identity matrix — that is what the inertia-weighted row buys. This is the hard half of proof obligation P1; the remaining half (relating the \(12\times 12\) task block to the old \(\breve{\boldsymbol M}\)) is bookkeeping we have not yet done, and §6 treats its consequence.
The thesis regulates the ghost with a force, \(\varsigma_n = -\boldsymbol D_n\tilde v_n\) (its equation 5.8c). We do not currently apply any null-space force; instead we reconstruct on the set \(\{v_n = 0\}\). These are the same idea at opposite ends of a limit, and the claim deserves a careful statement.
Proposition 4 (suppression as the high-damping limit; proof sketch). Consider the augmented reduced dynamics in the coordinates of Theorem 1, with the ghost equation \(\hat m_n\dot v_n + c(\cdot) = u_n\), where \(\hat m_n = (\hat{\boldsymbol k}^T\boldsymbol M\hat{\boldsymbol k})^{-1} > 0\) and \(c(\cdot)\) collects the velocity-dependent Coriolis couplings. Premise (per review R5): \(c\) is bounded only on compact velocity sets — in practice enforced by the loop’s saturation elements, whose interaction with the limit is exactly what P4 must treat; the phrase “input-to-state stable” carries these hypotheses and must not travel without them. Under the damping law \(u_n = -d\,v_n\) with gain \(d > 0\), the ghost dynamics is input-to-state stable with ultimate bound \(|v_n| = O(1/d)\), and in the singular-perturbation limit \(d \to \infty\) the closed loop collapses onto the invariant manifold \(\{v_n = 0\}\), on which the velocity reconstruction is exactly the augmented solve of §5.2.
Sketch. The ghost equation with the damping law is a scalar, exponentially contracting system driven by the bounded coupling \(c\); the standard ISS bound gives \(\limsup|v_n| \le \sup|c|/d\). Treating \(1/d\) as the singular parameter, the boundary-layer system is exponentially stable, and Tikhonov-type arguments apply on compact time intervals. On \(\{v_n \equiv 0\}\), a generalized velocity consistent with the task state satisfies \(\boldsymbol\Gamma\boldsymbol x = \boldsymbol y\) and \(\boldsymbol z_a^T\boldsymbol x = 0\) — the two block rows of the augmented system. The rigorous treatment — hypotheses for the Tikhonov theorem, interval of validity, interaction with the saturation elements — is part of proof obligation P4 and is not claimed here. \(\square\)
Empirically the limit behaves as advertised: in-loop mean \(|v_n|\) fell from \(0.157\) to \(0.0011\) in the short window (the residual is the \(\lambda\)-regularization footprint of the production solver, of size \(O(\lambda/\sigma^2)\), measured at \(1.7\times 10^{-6}\) in the unit test where \(\lambda\) is small), and from \(0.234\) to \(0.0058\) over the full mission.
Honesty about the boundary of the modification is worth a section of its own, because this is where a referee should push.
The force map is untouched. The controller still assembles \(\boldsymbol F = \boldsymbol\Gamma^T\boldsymbol G\) from the twelve task forces (20); for \(n = 7\) the result is a thirteen-vector with no ghost component added. This is consistent with §5: on the \(v_n \equiv 0\) section there is no ghost state to actuate. When a finite-gain null law or a posture objective arrives (P4), it enters here as \(\boldsymbol F \mathrel{+}= \boldsymbol z_a u_n\), the force dual to \(v_n\).
The reduced matrices are now an approximation. The
implementation builds \(\hat{\boldsymbol M} =
(\boldsymbol\Gamma^{-R})^T\boldsymbol M\,\boldsymbol\Gamma^{-R}\)
and its Coriolis companion with the Euclidean-convention right
inverse of Proposition 2 — not with the \(\boldsymbol M\)-consistent section of
Theorem 1. For \(n = 6\) the two
coincide (there is only one inverse); for \(n
= 7\) they differ, so the \(9\times
9\) blocks \(\breve{\boldsymbol M},
\breve{\boldsymbol C}\) feeding the model-based terms of the
control law (the feedforward and Coriolis compensation inside
RHS34b) are those of a slightly different
reduction than the one the reconstruction realizes. The mismatch enters
the loop as a bounded model error handled by feedback; it does not
threaten stability (the energy argument below never uses exactness of
those terms), but it is an inconsistency we can and should remove by
finishing P1 — rebuilding the congruence with \(\boldsymbol\Gamma_a^{-1}\) and taking the
task block. We flag it rather than hide it; the mission-scale empirical
results in §8 include whatever cost it imposes.
The boundary mechanisms are re-dimensioned, not redesigned. Joint-limit clipping with outward-velocity zeroing and the INITIAL posture pull operate on seven entries instead of six. The engineered envelope itself was derived from six-joint operating data; the roll joint currently carries a placeholder range of \(\pm 2\pi\), and the mission runs show the elbow riding its fence about 30% of the time — evidence that the envelope must be re-derived for the seven-joint posture family (this re-derivation is already on the weekly agenda for independent reasons).
The Lyapunov argument of the paper, equations (37)–(38), rests on the skew-symmetry property (23): in any velocity coordinates obtained by a legitimate transformation, the matrix \(\dot{\boldsymbol M} - 2\boldsymbol C\) is skew, so the Coriolis terms do no work and the energy ledger closes. Our modifications introduce a new coordinate (the ghost) and a new transformation (the augmentation). The natural worry: does skewness survive an augmentation whose thirteenth row is a configuration-dependent, inertia-weighted object with no clean geometric pedigree?
The technique is direct computation — the claim is an algebraic identity in the transformed matrices, so we differentiate the congruence and watch the terms.
Lemma 1 (passivity survives any invertible augmentation). Let \(\boldsymbol\Gamma_a(\boldsymbol q) \in \mathbb R^{13\times 13}\) be invertible and continuously differentiable along the motion, and define
\[ \hat{\boldsymbol M} = \boldsymbol\Gamma_a^{-T}\boldsymbol M\,\boldsymbol\Gamma_a^{-1}, \qquad \hat{\boldsymbol C} = \boldsymbol\Gamma_a^{-T}\big(\boldsymbol C - \boldsymbol M\,\boldsymbol\Gamma_a^{-1}\dot{\boldsymbol\Gamma}_a\big)\boldsymbol\Gamma_a^{-1}. \]
If \(\dot{\boldsymbol M} - 2\boldsymbol C\) is skew-symmetric, then so is \(\dot{\hat{\boldsymbol M}} - 2\hat{\boldsymbol C}\).
Proof. Differentiating the identity \(\boldsymbol\Gamma_a\boldsymbol\Gamma_a^{-1} = \boldsymbol E\) and solving for the derivative of the inverse gives \(\tfrac{d}{dt}(\boldsymbol\Gamma_a^{-1}) = -\boldsymbol\Gamma_a^{-1}\dot{\boldsymbol\Gamma}_a\boldsymbol\Gamma_a^{-1}\), and transposing gives the companion rule for \(\boldsymbol\Gamma_a^{-T}\). Applying the product rule to \(\hat{\boldsymbol M}\) therefore produces three terms:
\[ \dot{\hat{\boldsymbol M}} = -\,\boldsymbol\Gamma_a^{-T}\dot{\boldsymbol\Gamma}_a^T\boldsymbol\Gamma_a^{-T}\boldsymbol M\boldsymbol\Gamma_a^{-1} \;+\; \boldsymbol\Gamma_a^{-T}\dot{\boldsymbol M}\,\boldsymbol\Gamma_a^{-1} \;-\; \boldsymbol\Gamma_a^{-T}\boldsymbol M\boldsymbol\Gamma_a^{-1}\dot{\boldsymbol\Gamma}_a\boldsymbol\Gamma_a^{-1}. \]
Subtracting twice \(\hat{\boldsymbol C}\) — whose second term cancels one copy of the third term above and contributes one more with the opposite sign — and writing \(\boldsymbol S = \boldsymbol\Gamma_a^{-T}\boldsymbol M\boldsymbol\Gamma_a^{-1}\dot{\boldsymbol\Gamma}_a\boldsymbol\Gamma_a^{-1}\) for brevity, the terms collect into
\[ \dot{\hat{\boldsymbol M}} - 2\hat{\boldsymbol C} = \boldsymbol\Gamma_a^{-T}\big(\dot{\boldsymbol M} - 2\boldsymbol C\big)\boldsymbol\Gamma_a^{-1} \;+\; \big(\boldsymbol S - \boldsymbol S^T\big), \]
where the identification of the first product-rule term as \(-\boldsymbol S^T\) uses the symmetry of \(\boldsymbol M\). The first summand is a congruence of a skew matrix, and a congruence preserves skewness because transposing \(\boldsymbol P^T\boldsymbol A\boldsymbol P\) flips the sign of \(\boldsymbol A\) exactly when \(\boldsymbol A^T = -\boldsymbol A\). The second summand is skew by construction. A sum of skew matrices is skew, which is what we wanted to show. \(\blacksquare\)
The moral. The energy bookkeeping does not care which thirteenth row we appended — only that the transformation is invertible and smooth. All the risk of the redundant extension therefore lives in structure (which blocks couple to which), never in passivity. This is why we could safely run the mission before finishing P1, P3, and P4.
Could it be simpler? There is a coordinate-free one-liner — the property “\(\dot{\boldsymbol M}-2\boldsymbol C\) skew” is equivalent to energy balance \(\tfrac{d}{dt}(\tfrac12\boldsymbol x^T\boldsymbol M\boldsymbol x) = \boldsymbol x^T\boldsymbol F\), which is a statement about the physical system, not about coordinates — but the committee will rightly ask where the \(\dot{\boldsymbol\Gamma}_a\) correction goes in that argument, and the computation above answers by exhibiting it inside \(\boldsymbol S - \boldsymbol S^T\).
What the lemma does not give. It does not give the closed-loop theorem for the augmented system with a finite-gain null law — that needs the cascade argument re-run with the extended Lyapunov function \(V \mathrel{+}= \tfrac12\hat m_n v_n^2 + \tfrac12 k_n\tilde x_n^2\) (obligation P4), and it does not bound the Coriolis cross-couplings between the ghost and the task (obligation P3 — which the thesis confirms are genuinely present: the internal Coriolis matrix “is still fully coupled”).
Framing revised per review R3: the same-speed columns are a
feasibility demonstration, not a controlled comparison
— the 7-DOF arm completes ~29% faster at 0.90 m/s commanded speed, which
inflates every velocity-dependent error. The controlled comparison is
the matched-pace column (commanded speed 0.45 m/s,
restoring \(\nu_e\) parity with the
6-DOF SOTA). Solver provenance (review R7): all mission columns were
produced by the Breve override of
reconstruct_generalized_velocity — damped normal equations
with \(\lambda\) keyed to \(\sigma_{\min}\) of the unaugmented*
\(\boldsymbol\Gamma\), a known
conditioning-signal mismatch — while the unit tests exercise the exact
lstsq path; these are not the same algorithm, and their
unification is deferred to avoid a behavior change mid-campaign.*
| metric | 6-DOF SOTA | 7-DOF min-norm (0.90) | 7-DOF M-orth. (0.90) | 7-DOF M-orth., matched pace (0.45) |
|---|---|---|---|---|
| mission complete at | 1064.5 s | 786.9 s | 757.5 s | 1521.6 s |
| coverage | 0.9990 | 1.0000 | 1.0000 | 1.0000 |
| derate fraction | 0.64–0.80 | 0.309 | 0.344 | 0.235 |
| \(p_e\) median | 0.0708 m | 0.1205 m | 0.1170 m | 0.0315 m |
| \(p_e\) p99 | 0.1654 m | 0.5041 m | 0.2217 m | 0.1721 m |
| \(\nu_e\) p99 | 0.92 | 1.67 | 2.07 | 1.07 |
| mean \(\lvert v_n\rvert\) | — | 0.234 | 0.0058 | 0.0016 |
| elbow-fence contact | 0.000 | 0.353 | 0.304 | 0.203 |
| gates (cov \(\ge\) 0.99 / \(p_e^{p99} < 0.2\)) | PASS / PASS | PASS / FAIL | PASS / FAIL | PASS / PASS |
Reading, with the confounders separated: (i) pace — resolved by the matched-pace column: both mission gates pass, \(p_e\) median improves \(2.2\times\) over the 6-DOF SOTA, and the derate fraction falls \(\sim 3\times\) (the M1–M2 conditioning claim, now unconfounded); (ii) envelope — still open: the seven-joint posture family rides the six-joint-derived elbow fence 20–30% of steps (re-derivation on the weekly agenda), but tail-conditioning analysis shows the \(p_e\) tail is derate-enriched and fence-neutral, so the envelope is not the tail’s owner; (iii) the \(\breve{\boldsymbol M}\) approximation — now sized (§9/R4). The gap to the \(p_e^{p99} < 0.1\) objective is owned by the derated windows; the named next lever is the null-space posture pull toward larger \(\sigma_6\) (the P4 objective), for which the suppression law is the zero-gain special case.
review_7dof.md, Jun
11)validation/r1_kernel_continuity.py, run on both logged
missions): healthy windows rotate \(\hat{\boldsymbol n}\) by median 0.03°/step
(p99 ≈ 1.3–1.5°); derated windows reach 69°/step at
\(\sigma_6 \sim 10^{-3}\) (p99 ratio
4.7 at 0.90 m/s; matched pace touches \(\sigma_6 = 0.0000\), a momentary rank-2
kernel). Mitigation, mirroring damped_inverse’s last-value
reuse: below null_space.freeze_floor (default 0.025) the
basis \((\hat{\boldsymbol n}, \hat{\boldsymbol
k}, \boldsymbol z_a)\) is frozen at its last healthy value, with
sign-continuity alignment on refresh — trading exact \(\boldsymbol M\)-orthogonality for
directional stability exactly where Ω frays. TDD 6/6; baselines
byte-identical. A freeze-enabled mission run is queued behind the
current re-runs.validation/r4_mbreve_inconsistency.py): relative \(\breve{\boldsymbol M}\) discrepancy between
the Euclidean and \(\boldsymbol
M\)-consistent reductions: median 1.9% healthy,
but \(\sim\)100% in
derated tails (caveat: near \(\sigma_6 \to
0\) the comparator \((\boldsymbol\Gamma\boldsymbol
M^{-1}\boldsymbol\Gamma^T)^{-1}\) itself degrades, so the tail
number partly reflects the comparison’s own conditioning). Consequence:
finishing P1 is promoted from bookkeeping to a measured-payoff
item.assets.yaml blocks (config
override > robot block > model tails; harness overrides removed;
arity assert retained). R9 — sweep done: no remaining
hardcoded generalized-space dimension literals (the ledger’s M1 row
should read “dimension-generic after an audit found two wrapper
exceptions”, which is now the checked truth). R10 —
noted; the duplicate SVD stays until profiling says
otherwise.