Companion to walkthroughv2.md,
derivation_7dof.md, and
dynamics_modifications_7dof.md. This note answers one
specific question: how do you get from \[
\boldsymbol J^\dagger\boldsymbol J_{\nu_e}^\oplus \;=\; \boldsymbol E_7
- \hat{\boldsymbol n}\hat{\boldsymbol n}^\top
\qquad\text{(the arm pseudoinverse identity)}
\] to \[
\boldsymbol z_a^\top \;=\; \frac{\hat{\boldsymbol k}^\top\boldsymbol
M}{\hat{\boldsymbol k}^\top\boldsymbol M\hat{\boldsymbol k}}
\qquad\text{(the self-motion covector)?}
\] Throughout, \(\boldsymbol
E\) is the identity (your \(\mathbb
I\)) and \((\cdot)^\top\) is
transpose.
The honest headline, stated before any algebra, because it is the thing you are not seeing: the starting identity is purely Euclidean, and the target is inertia-weighted. The arm identity hands you a direction (\(\hat{\boldsymbol n}\), and from it \(\hat{\boldsymbol k}\)); it cannot hand you the covector \(\boldsymbol z_a\), because a covector requires a metric and the arm identity contains none. The matrix \(\boldsymbol M\) has to be injected by a separate, deliberate step. The whole journey is four moves, and the metric enters only at move 3 → 4: \[ \boxed{\;\underbrace{\boldsymbol J^\dagger\boldsymbol J_{\nu_e}^\oplus = \boldsymbol E_7 - \hat{\boldsymbol n}\hat{\boldsymbol n}^\top}_{\text{Step 1: read off } \hat{\boldsymbol n}} \;\xrightarrow{\ \text{block solve}\ }\; \underbrace{\hat{\boldsymbol k} = \begin{bmatrix}-\bar{\boldsymbol J}_v\hat{\boldsymbol n}\\ \boldsymbol 0_3\\ \hat{\boldsymbol n}\end{bmatrix}}_{\text{Step 2: lift to the full system}} \;\xrightarrow{\ \text{inject } \boldsymbol M\ }\; \underbrace{\boldsymbol z_a = \frac{\boldsymbol M\hat{\boldsymbol k}}{\hat{\boldsymbol k}^\top\boldsymbol M\hat{\boldsymbol k}}}_{\text{Steps 3--4: dynamic consistency}}\;} \] Steps 1 and 2 are kinematics (Euclidean, no \(\boldsymbol M\)). Steps 3 and 4 are dynamics (the energy metric). If you try to ride Euclidean geometry the whole way, you land on the wrong covector — and seeing exactly where and why is the point of §7.
On the operating region \(\Omega\): the circumcentroidal arm Jacobian \(\boldsymbol J_{\nu_e}^\oplus \in \mathbb R^{6\times 7}\) has full row rank \(6\) (its smallest singular value \(\sigma_6 > 0\)); the task map \(\boldsymbol\Gamma \in \mathbb R^{12\times 13}\) has full row rank \(12\), so \(\ker\boldsymbol\Gamma\) is one-dimensional; \(\boldsymbol M \in \mathbb R^{13\times 13}\) is symmetric positive definite (SPD); and \(\hat{\boldsymbol n} \in \mathbb R^7\), \(\hat{\boldsymbol k} \in \mathbb R^{13}\) are unit kernel vectors. The pseudoinverse is the Moore–Penrose right inverse of the wide \(\boldsymbol J_{\nu_e}^\oplus\), \[ \boldsymbol J^\dagger \;=\; \boldsymbol J_{\nu_e}^{\oplus\top}\big(\boldsymbol J_{\nu_e}^\oplus\boldsymbol J_{\nu_e}^{\oplus\top}\big)^{-1} \in \mathbb R^{7\times 6}, \qquad \boldsymbol J_{\nu_e}^\oplus\boldsymbol J^\dagger = \boldsymbol E_6 . \]
Look at the identity not as a fact to memorize but as a machine for extracting the arm’s null direction. Rearrange it: \[ \hat{\boldsymbol n}\hat{\boldsymbol n}^\top \;=\; \boldsymbol E_7 - \boldsymbol J^\dagger\boldsymbol J_{\nu_e}^\oplus . \] The right-hand side is a fully computable \(7\times 7\) matrix. The claim is that it is a rank-one orthogonal projector, and the unit vector it projects onto is exactly the arm self-motion \(\hat{\boldsymbol n}\). Let us see why each word is true, because each one is used later.
Why \(\boldsymbol J^\dagger\boldsymbol J_{\nu_e}^\oplus\) is the (orthogonal) projector onto the row space. For a full-row-rank wide matrix, the product \(\boldsymbol J^\dagger\boldsymbol J_{\nu_e}^\oplus\) is the standard Moore–Penrose projector onto \(\mathrm{row}(\boldsymbol J_{\nu_e}^\oplus) = (\ker\boldsymbol J_{\nu_e}^\oplus)^\perp\). It is symmetric and idempotent: using \(\boldsymbol J_{\nu_e}^\oplus\boldsymbol J^\dagger = \boldsymbol E_6\), \[ \big(\boldsymbol J^\dagger\boldsymbol J_{\nu_e}^\oplus\big)^2 = \boldsymbol J^\dagger\big(\boldsymbol J_{\nu_e}^\oplus\boldsymbol J^\dagger\big)\boldsymbol J_{\nu_e}^\oplus = \boldsymbol J^\dagger\boldsymbol J_{\nu_e}^\oplus . \] Its range is the six-dimensional row space, so its complement \(\boldsymbol E_7 - \boldsymbol J^\dagger\boldsymbol J_{\nu_e}^\oplus\) is the orthogonal projector onto the one-dimensional kernel \(\ker\boldsymbol J_{\nu_e}^\oplus\).
Why that complement equals \(\hat{\boldsymbol n}\hat{\boldsymbol n}^\top\). The orthogonal projector onto a line spanned by a unit vector \(\hat{\boldsymbol n}\) is precisely the outer product \(\hat{\boldsymbol n}\hat{\boldsymbol n}^\top\) (it is symmetric; it is idempotent because \(\hat{\boldsymbol n}\hat{\boldsymbol n}^\top\hat{\boldsymbol n}\hat{\boldsymbol n}^\top = \hat{\boldsymbol n}(\hat{\boldsymbol n}^\top\hat{\boldsymbol n})\hat{\boldsymbol n}^\top = \hat{\boldsymbol n}\hat{\boldsymbol n}^\top\) since \(\|\hat{\boldsymbol n}\| = 1\); and it fixes \(\hat{\boldsymbol n}\)). Since both sides are the orthogonal projector onto the same line, they are equal. That is the identity.
What you do with it. The identity isolates \(\hat{\boldsymbol n}\): form the computable matrix \(\boldsymbol E_7 - \boldsymbol J^\dagger\boldsymbol J_{\nu_e}^\oplus\), and \(\hat{\boldsymbol n}\) is its (unit) column direction. Physically, \(\hat{\boldsymbol n}\) is the one joint-rate direction the arm can move along while producing zero end-effector velocity about the CoM: \(\boldsymbol J_{\nu_e}^\oplus\hat{\boldsymbol n} = \boldsymbol 0\).
Keep your eye on the metric. Everything here lives in the ordinary dot product of the seven-dimensional joint space: \(\hat{\boldsymbol n}\hat{\boldsymbol n}^\top\) is the Euclidean orthogonal projector. No inertia has appeared. This matters in §7.
The arm null direction \(\hat{\boldsymbol n}\) only says the joints can move invisibly. The full question is which whole-system velocity \(\boldsymbol x = [\boldsymbol v_b;\, \boldsymbol\omega_b;\, \dot{\boldsymbol q}]\) moves none of the twelve task coordinates — that is, \(\ker\boldsymbol\Gamma\). We find it by solving \(\boldsymbol\Gamma\boldsymbol x = \boldsymbol 0\) block-row by block-row, using the structure of \(\boldsymbol\Gamma\): \[ \boldsymbol\Gamma = \begin{bmatrix} \boldsymbol R_{cb} & -\boldsymbol R_{cb}\,\boldsymbol p_{bc}^\times & \boldsymbol R_{cb}\bar{\boldsymbol J}_v \\ \boldsymbol 0 & \boldsymbol E & \boldsymbol 0 \\ \boldsymbol 0 & \boldsymbol G_{\omega_b} & \boldsymbol J_{\nu_e}^\oplus \end{bmatrix} \begin{matrix} \leftarrow \boldsymbol v_c \text{ row} \\ \leftarrow \boldsymbol\omega_b \text{ row} \\ \leftarrow \boldsymbol\nu_e^\oplus \text{ row} \end{matrix} \]
One free parameter \(\alpha\), so a one-dimensional family 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}, \qquad \boldsymbol\Gamma\hat{\boldsymbol k} = \boldsymbol 0 . \] Here \(\bar{\boldsymbol J}_v\) is the mass-averaged linear Jacobian, so \(\bar{\boldsymbol J}_v\hat{\boldsymbol n}\) is “how far the arm’s mass-lump moves” along \(\hat{\boldsymbol n}\), and \(\boldsymbol v_b = -\bar{\boldsymbol J}_v\hat{\boldsymbol n}\) is the base counter-translating to keep the CoM frozen. Arm swings, base shuffles, everything the mission watches stays still.
Still no metric. We used \(\hat{\boldsymbol n}\) (from the Euclidean Step 1) and the kinematic Jacobian \(\bar{\boldsymbol J}_v\). We now possess the direction \(\hat{\boldsymbol k}\) of self-motion in the full \(13\)-space. We do not yet have \(\boldsymbol z_a\), and nothing so far could produce it.
Here is the conceptual hinge, and the precise place your intuition stalls. You have a column \(\hat{\boldsymbol k} \in \mathbb R^{13}\) — a direction. What you want is a row \(\boldsymbol z_a^\top\) — a covector, a linear functional that eats a velocity \(\boldsymbol x\) and returns the number \(v_n = \boldsymbol z_a^\top\boldsymbol x\) telling you “how much self-motion is in \(\boldsymbol x\).” A column and a row are different kinds of object, and converting one into the other requires choosing an inner product — a rule for pairing directions with measurements. That choice is the missing ingredient.
The naive conversion is to transpose and Euclidean-normalize: \[
\boldsymbol z_{a,\text{Euclid}}^\top \;=\; \frac{\hat{\boldsymbol
k}^\top}{\hat{\boldsymbol k}^\top\hat{\boldsymbol k}}
\qquad\Longrightarrow\qquad v_n = \frac{\hat{\boldsymbol
k}^\top\boldsymbol x}{\hat{\boldsymbol k}^\top\hat{\boldsymbol k}} .
\] This is the covector you get if you carry the
Euclidean geometry of Step 1 all the way through — it is what
the Moore–Penrose / block-formula machinery produces by itself. And it
is wrong for our purpose. Why? Because it declares the
“no self-motion” set to be the Euclidean complement of \(\hat{\boldsymbol k}\), \[
\{v_n = 0\} = \{\boldsymbol x : \hat{\boldsymbol k}^\top\boldsymbol x =
0\},
\] whereas the physically meaningful “no self-motion” set is the
one with no kinetic-energy coupling to \(\hat{\boldsymbol k}\) — the \(\boldsymbol M\)-orthogonal
complement \(\{\boldsymbol x :
\hat{\boldsymbol k}^\top\boldsymbol M\boldsymbol x = 0\}\).
(Recall from walkthroughv2.md §I: \(\hat{\boldsymbol k}^\top\boldsymbol M\boldsymbol
x\) is the energy cross-term between the motions \(\hat{\boldsymbol k}\) and \(\boldsymbol x\); it vanishing is what
“energetically independent” means.) Euclidean orthogonality is
not \(\boldsymbol
M\)-orthogonality, so the naive covector reports a nonzero \(v_n\) on motions that are genuinely
self-motion-free, and conversely hides real self-motion. That mismatch
is exactly the non-decaying ghost you measured (\(\bar{|v_n|} = 0.157\)).
The moral of the gap. The arm identity, and everything kinematic that flows from it, can only ever give you the direction \(\hat{\boldsymbol k}\) and the Euclidean covector. To get the right covector you must replace the Euclidean ruler with the inertia ruler. That single replacement is Step 4.
We now demand the covector satisfy exactly two requirements, and watch them pin it uniquely.
Requirement (i) — normalization. A unit of self-motion reads as one unit: \(\boldsymbol z_a^\top\hat{\boldsymbol k} = 1\).
Requirement (ii) — dynamic consistency. The reconstruction set \(\{v_n = 0\} = \ker\boldsymbol z_a^\top\) is the \(\boldsymbol M\)-orthogonal complement of the self-motion: \[ \ker\boldsymbol z_a^\top \;=\; \{\boldsymbol x : \hat{\boldsymbol k}^\top\boldsymbol M\boldsymbol x = 0\} . \]
That is the entire specification, and it determines \(\boldsymbol z_a\) in two lines.
Scratch work. Requirement (ii) is a statement that two covectors share a kernel. The set \(\{\boldsymbol x : \hat{\boldsymbol k}^\top\boldsymbol M\boldsymbol x = 0\}\) is the kernel of the row vector \(\hat{\boldsymbol k}^\top\boldsymbol M\). So (ii) says \(\boldsymbol z_a^\top\) and \(\hat{\boldsymbol k}^\top\boldsymbol M\) have the same kernel — and two linear functionals with the same kernel are proportional. That fixes the direction of \(\boldsymbol z_a\); (i) then fixes its scale.
Derivation. The row \(\hat{\boldsymbol k}^\top\boldsymbol M\) is nonzero, because \(\boldsymbol M\) is SPD and \(\hat{\boldsymbol k} \neq \boldsymbol 0\) imply \(\boldsymbol M\hat{\boldsymbol k} \neq \boldsymbol 0\); hence its kernel is a genuine \(12\)-dimensional hyperplane. By requirement (ii), \(\boldsymbol z_a^\top\) has that same hyperplane as its kernel, so there is a scalar \(c\) with \[ \boldsymbol z_a^\top \;=\; c\,\hat{\boldsymbol k}^\top\boldsymbol M, \qquad\text{equivalently}\qquad \boldsymbol z_a = c\,\boldsymbol M\hat{\boldsymbol k}, \]
A covector (row vector / linear functional) \(\bm\phi^\top\) acts on a vector \(\bm x\) by \(\bm\phi^\top\bm x\) (a scalar). Its kernel is everything it sends to zero: \[\ker\bm\phi^\top = {\bm x : \bm\phi^\top\bm x = 0}.\] For a single nonzero row vector acting on \(\mathbb{R}^{13}\), rank–nullity gives the size immediately: the functional has rank 1, so its nullity is \(13 - 1 = 12\). That’s why \({\bm x : \hat{\bm k}^\top\bm M\bm x = 0}\) is a 12-dimensional hyperplane — it’s the kernel of the one nonzero row \(\hat{\bm k}^\top\bm M\). (The “is nonzero” check in the Derivation paragraph is exactly to guarantee rank 1, not rank 0.)
Second: the “By requirement (ii)” step is definitional Requirement (ii), as you stated it on line 170–173, is the equation \[\ker\bm z_a^\top ;=; {\bm x : \hat{\bm k}^\top\bm M\bm x = 0}.\] So when the text says “By requirement (ii), \(\bm z_a^\top\) has that same hyperplane as its kernel,” it is simply reading requirement (ii) out loud. You demanded that \(\bm z_a^\top\)’s kernel equal that hyperplane. There’s nothing to prove there — it’s the specification. The logic is:
The right-hand set \(= \ker(\hat{\bm k}^\top\bm M)\), which we just argued is a 12-D hyperplane \(H\). Requirement (ii) says \(\ker\bm z_a^\top = H\). Therefore \(\ker\bm z_a^\top = H\). ✔ (pure substitution) Third: the part that is real content — same kernel ⟹ proportional This is the step worth understanding, and it’s the next clause (“two linear functionals with the same kernel are proportional”). Here’s the three-line proof:
Let \(\bm\phi^\top = \bm z_a^\top\) and \(\bm\psi^\top = \hat{\bm k}^\top\bm M\), with \(\ker\bm\phi^\top = \ker\bm\psi^\top = H\) (a hyperplane). Pick any \(\bm u\notin H\), so \(\bm\psi^\top\bm u \neq 0\). Every \(\bm x\in\mathbb{R}^{13}\) splits uniquely as \[\bm x = t,\bm u + \bm h,\qquad \bm h\in H,\quad t = \frac{\bm\psi^\top\bm x}{\bm\psi^\top\bm u}.\] Apply \(\bm\phi^\top\): the \(\bm h\) part dies (\(\bm h\in H = \ker\bm\phi^\top\)), leaving \[\bm\phi^\top\bm x = t,\bm\phi^\top\bm u = \underbrace{\frac{\bm\phi^\top\bm u}{\bm\psi^\top\bm u}}_{=:c};\bm\psi^\top\bm x.\] Since this holds for all \(\bm x\), \(\bm\phi^\top = c,\bm\psi^\top\), i.e. \(\bm z_a^\top = c,\hat{\bm k}^\top\bm M\). Transposing (and using \(\bm M=\bm M^\top\)) gives \(\bm z_a = c,\bm M\hat{\bm k}\). Requirement (i) then sets \(c = 1/(\hat{\bm k}^\top\bm M\hat{\bm k})\).
★ Insight ─────────────────────────────────────
A linear functional is determined by its kernel up to one scalar. The kernel (the hyperplane it kills) fixes the functional’s orientation; the level sets \({\bm\phi^\top\bm x = \text{const}}\) are all parallel copies of that hyperplane, and the only remaining freedom is their spacing — a single number, the scale \(c\). That’s the whole logic of Step 4: (ii) fixes orientation, (i) fixes spacing, so \(\bm z_a\) is pinned uniquely. Why this matters physically: the “naive” Euclidean covector \(\hat{\bm k}^\top\) and the dynamically-consistent one \(\hat{\bm k}^\top\bm M\) have different kernels — they kill different hyperplanes of motions. Requirement (ii) is precisely the act of swapping the Euclidean ruler for the inertia ruler \(\bm M\), so that “\(v_n=0\)” means \(\bm M\)-orthogonal to self-motion (energetically decoupled), not merely Euclidean-orthogonal. That swap is what kills your \(\bar{|v_n|}=0.157\) ghost (line 153). The 12 is not a coincidence: \(\bm z_a^\top\) lives in \(\mathbb{R}^{13}\)-dual, its kernel is 12-D, and \(\dim\ker = 12\) is exactly \(13 - 1\) — one functional, one constraint, codimension one. The “1” left over is the self-motion direction \(\hat{\bm k}\) that \(\bm z_a\) is built to measure.
using \(\boldsymbol M = \boldsymbol M^\top\). Imposing requirement (i), \[ 1 = \boldsymbol z_a^\top\hat{\boldsymbol k} = c\,\hat{\boldsymbol k}^\top\boldsymbol M\hat{\boldsymbol k} \qquad\Longrightarrow\qquad c = \frac{1}{\hat{\boldsymbol k}^\top\boldsymbol M\hat{\boldsymbol k}}, \] where the denominator is strictly positive (it is twice the kinetic energy of a unit self-motion, and \(\boldsymbol M\) is SPD), so \(c\) is well defined on all of \(\Omega\). Therefore \[ \boxed{\;\boldsymbol z_a^\top \;=\; \frac{\hat{\boldsymbol k}^\top\boldsymbol M}{\hat{\boldsymbol k}^\top\boldsymbol M\hat{\boldsymbol k}}\;} \] as claimed. Compare it term by term against the wrong Euclidean covector of §3: the numerator \(\hat{\boldsymbol k}^\top\) has become \(\hat{\boldsymbol k}^\top\boldsymbol M\), and the denominator \(\hat{\boldsymbol k}^\top\hat{\boldsymbol k}\) has become \(\hat{\boldsymbol k}^\top\boldsymbol M\hat{\boldsymbol k}\). The two insertions of \(\boldsymbol M\) are the entire content of “dynamic consistency,” and they are exactly what Steps 1–2 could not supply.
Where this \(\boldsymbol M\) comes from is not arbitrary. Requirement (ii) is the dynamic consistency of Khatib (1987, eqs. 51–52): the reconstruction on \(\{v_n=0\}\) is the minimum-kinetic-energy solution of \(\boldsymbol\Gamma\boldsymbol x = \boldsymbol z\), whose residual is automatically \(\boldsymbol M\)-orthogonal to \(\hat{\boldsymbol k}\) (proved in
walkthroughv2.mdPart II). So (ii) is not a taste; it is “reconstruct with least kinetic energy,” which is the physically correct way to resolve the redundancy.
Take the napkin system of derivation_7dof.md §2: a base
of mass \(M_b\) on a rail, an elbow
mass \(m_1\) at \(x_b + q_1\), a hand mass \(m_2\) at \(x_b +
q_1 + q_2\). The velocity is \(\boldsymbol x = [v_b,\, \dot q_1,\, \dot
q_2]^\top\), the task is \(\boldsymbol
z = [v_c,\, \nu_e]^\top\). Set \(M_b =
m_1 = m_2 = 1\), so the total mass is \(m_t = 3\).
The pieces. The mass-averaged Jacobian is \(\bar{\boldsymbol J}_v = \big[\tfrac{m_1+m_2}{m_t},\, \tfrac{m_2}{m_t}\big] = \big[\tfrac23,\, \tfrac13\big]\). The hand-velocity-relative-to-base Jacobian is \([1,\,1]\), so the circumcentroidal arm Jacobian is \[ \boldsymbol J_{\nu_e}^\oplus = [1,\,1] - \bar{\boldsymbol J}_v = \big[\tfrac13,\, \tfrac23\big] \;\propto\; [1,\,2]. \]
Step 1 (read off \(\hat{\boldsymbol n}\)). Using \(\boldsymbol J_{\nu_e}^\oplus \propto [1,2]\), its pseudoinverse is \(\boldsymbol J^\dagger = [1,2]^\top/5\), so \[ \boldsymbol J^\dagger\boldsymbol J_{\nu_e}^\oplus = \tfrac15\begin{bmatrix}1&2\\2&4\end{bmatrix}, \qquad \boldsymbol E_2 - \boldsymbol J^\dagger\boldsymbol J_{\nu_e}^\oplus = \tfrac15\begin{bmatrix}4&-2\\-2&1\end{bmatrix} = \hat{\boldsymbol n}\hat{\boldsymbol n}^\top, \] with \(\hat{\boldsymbol n} = [2,\,-1]^\top/\sqrt5\). The arm identity has handed us \(\hat{\boldsymbol n} \propto [2,-1]\): the joints can move as \(\dot q_1 : \dot q_2 = 2 : -1\) with no EE motion about the CoM. (Check: \(\boldsymbol J_{\nu_e}^\oplus[2,-1]^\top \propto [1,2]\cdot[2,-1]^\top = 0\).)
Step 2 (lift to \(\hat{\boldsymbol k}\)). There is no \(\boldsymbol\omega_b\) in this 1-D toy, so \(\hat{\boldsymbol k} = [-\bar{\boldsymbol J}_v\hat{\boldsymbol n};\, \hat{\boldsymbol n}]\). Using the unnormalized \(\hat{\boldsymbol n} = [2,-1]\), \[ \bar{\boldsymbol J}_v\hat{\boldsymbol n} = \big[\tfrac23,\tfrac13\big]\begin{bmatrix}2\\-1\end{bmatrix} = \tfrac43 - \tfrac13 = 1, \qquad \hat{\boldsymbol k} = \begin{bmatrix} -1 \\ 2 \\ -1\end{bmatrix}. \] This is precisely the napkin’s boxed self-motion (\(v_b = -m_1 = -1\), \(\dot q_1 = 2\), \(\dot q_2 = -1\)): arm swings, base counter-translates, CoM frozen.
Steps 3–4 (inject \(\boldsymbol M\)). The kinetic energy is \(T = \tfrac12\big[v_b^2 + (v_b+\dot q_1)^2 + (v_b+\dot q_1+\dot q_2)^2\big]\), which gives the inertia matrix \[ \boldsymbol M = \begin{bmatrix} 3 & 2 & 1 \\ 2 & 2 & 1 \\ 1 & 1 & 1 \end{bmatrix} \quad(\text{SPD: leading minors } 3,\,2,\,1 > 0). \] Now compute the covector. First \[ \boldsymbol M\hat{\boldsymbol k} = \begin{bmatrix} 3&2&1\\2&2&1\\1&1&1\end{bmatrix}\begin{bmatrix}-1\\2\\-1\end{bmatrix} = \begin{bmatrix} -3+4-1 \\ -2+4-1 \\ -1+2-1 \end{bmatrix} = \begin{bmatrix} 0 \\ 1 \\ 0 \end{bmatrix}, \qquad \hat{\boldsymbol k}^\top\boldsymbol M\hat{\boldsymbol k} = \hat{\boldsymbol k}^\top\begin{bmatrix}0\\1\\0\end{bmatrix} = 2 . \] Therefore \[ \boldsymbol z_a^\top = \frac{\hat{\boldsymbol k}^\top\boldsymbol M}{\hat{\boldsymbol k}^\top\boldsymbol M\hat{\boldsymbol k}} = \tfrac12\,[0,\,1,\,0] = \big[0,\, \tfrac12,\, 0\big]. \] Check the normalization: \(\boldsymbol z_a^\top\hat{\boldsymbol k} = \tfrac12(2) = 1\). So in this system the self-motion amplitude is read purely off the elbow rate, \(v_n = \tfrac12\dot q_1\) — a clean, falsifiable prediction you can feel is right (the elbow is the joint that swings).
The contrast that shows \(\boldsymbol M\) was necessary. The naive Euclidean covector of §3 would have been \[ \boldsymbol z_{a,\text{Euclid}}^\top = \frac{\hat{\boldsymbol k}^\top}{\hat{\boldsymbol k}^\top\hat{\boldsymbol k}} = \tfrac16[-1,\,2,\,-1] = \big[-\tfrac16,\, \tfrac13,\, -\tfrac16\big], \] since \(\hat{\boldsymbol k}^\top\hat{\boldsymbol k} = 6\). Utterly different from \([0,\tfrac12,0]\) — it spreads the “self-motion reading” across all three coordinates instead of localizing it on the elbow. Same direction \(\hat{\boldsymbol k}\), two rulers, two covectors. Only the \(\boldsymbol M\) one is energetically consistent.
walkthroughv2.md reaches \(\boldsymbol z_a\) through the projector
\(\boldsymbol N = \boldsymbol E_{13} -
\boldsymbol\Gamma^{-R}\boldsymbol\Gamma\). The arm identity is
the bottom-right block of that construction: when the right inverse is
the block formula built from \(\boldsymbol
J^\dagger\), the product \(\boldsymbol\Gamma^{-R}\boldsymbol\Gamma\)
has arm block exactly \(\boldsymbol
J^\dagger\boldsymbol J_{\nu_e}^\oplus = \boldsymbol E_7 -
\hat{\boldsymbol n}\hat{\boldsymbol n}^\top\) — your starting
equation. So the two notes meet here: v3’s Step 1 is literally one
block of v2’s \(\boldsymbol N\).
But this is exactly where the metric subtlety bites, so read the next section before identifying the projector route with the covector.
You asked to write \(\boldsymbol\Gamma^{-R}\) rather than \(\bar{\boldsymbol\Gamma}\), on the grounds that “right inverse” is the more honest name. You are right about the concept — \(\boldsymbol\Gamma\) is wide, it has no inverse, only right inverses, and \(\boldsymbol\Gamma^{-R}\) names that honestly. But there is a catch that is the very thing making this derivation feel stuck, so it must be stated plainly: there is more than one right inverse, and they give different covectors.
A right inverse is any matrix with \(\boldsymbol\Gamma\,\boldsymbol\Gamma^{-R} = \boldsymbol E_{12}\). Two are relevant:
dynamics_modifications_7dof.md Prop. 2). Its arm block is
your \(\boldsymbol J^\dagger\boldsymbol
J_{\nu_e}^\oplus = \boldsymbol E_7 - \hat{\boldsymbol n}\hat{\boldsymbol
n}^\top\). It is the Euclidean min-norm
reconstruction.7dof_walkthrough.md and v2 wrote \(\bar{\boldsymbol\Gamma}\)). It is the
minimum-kinetic-energy reconstruction.These are different matrices for \(n = 7\) (they coincide only when \(\boldsymbol M = \boldsymbol E\)). And the covector you extract depends on which one you use: \[ \boldsymbol N_E = \boldsymbol E_{13} - \boldsymbol\Gamma^{-R}_E\boldsymbol\Gamma \;\Rightarrow\; \boldsymbol z_a^\top \propto \hat{\boldsymbol k}^\top \quad(\text{wrong}), \qquad \boldsymbol N_M = \boldsymbol E_{13} - \boldsymbol\Gamma^{-R}_M\boldsymbol\Gamma \;\Rightarrow\; \boldsymbol z_a^\top \propto \hat{\boldsymbol k}^\top\boldsymbol M \quad(\text{right}). \] So if you literally substitute the block-formula \(\boldsymbol\Gamma^{-R}\) (the one whose arm block is your starting identity) into the projector and read off the row, you get the Euclidean covector \(\hat{\boldsymbol k}^\top/(\hat{\boldsymbol k}^\top\hat{\boldsymbol k})\) — not \(\boldsymbol z_a\). This is not a contradiction; it is the §3 gap wearing matrix notation. The arm identity belongs to the Euclidean inverse; \(\boldsymbol z_a\) belongs to the \(\boldsymbol M\)-weighted one.
Practical upshot for the thesis. Write \(\boldsymbol\Gamma^{-R}\) if you prefer it to \(\bar{\boldsymbol\Gamma}\), but subscript it — \(\boldsymbol\Gamma^{-R}_E\) vs \(\boldsymbol\Gamma^{-R}_M\) — wherever both appear, because your
dynamics_modifications_7dof.mdalready relies on the distinction (its §6 “the reduced matrices are now an approximation” caveat is precisely the gap between \(\boldsymbol\Gamma^{-R}_E\) used in the code and the \(\boldsymbol\Gamma^{-R}_M\) the reconstruction realizes). Dropping the subscript is what made this derivation look like it should close in Euclidean geometry when it cannot.
The arm identity \(\boldsymbol J^\dagger\boldsymbol J_{\nu_e}^\oplus = \boldsymbol E_7 - \hat{\boldsymbol n}\hat{\boldsymbol n}^\top\) is an Euclidean projector that isolates the arm null direction \(\hat{\boldsymbol n}\). Solving \(\boldsymbol\Gamma\boldsymbol x = \boldsymbol 0\) lifts it to the full self-motion direction \(\hat{\boldsymbol k} = [-\bar{\boldsymbol J}_v\hat{\boldsymbol n};\, \boldsymbol 0;\, \hat{\boldsymbol n}]\) — still Euclidean, still just a direction. To turn that direction into the covector \(\boldsymbol z_a\) you must choose an inner product, and the physically correct choice is the inertia metric \(\boldsymbol M\) (dynamic consistency = minimum kinetic energy). That choice replaces \(\hat{\boldsymbol k}^\top\) by \(\hat{\boldsymbol k}^\top\boldsymbol M\) and \(\hat{\boldsymbol k}^\top\hat{\boldsymbol k}\) by \(\hat{\boldsymbol k}^\top\boldsymbol M\hat{\boldsymbol k}\), giving \(\boldsymbol z_a^\top = \hat{\boldsymbol k}^\top\boldsymbol M/(\hat{\boldsymbol k}^\top\boldsymbol M\hat{\boldsymbol k})\). You could not see the bridge because there is a genuine missing plank — the metric — and the Euclidean machinery you started from does not contain it. That is the whole point: the arm identity gives the direction; the energy metric gives the measurement.
Verification: the toy of §5 is hand-checked end to end; the
general \(\boldsymbol M\)-weighted
result and the Euclidean falsifier were confirmed over 2000 random
trials (walkthroughv2.md Part VII). Nothing here touches
deriv_7dof.tex.