feat(ClassicalMechanics): add the body-frame angular velocity of a rigid body#1417
Conversation
…gid body Introduce the co-rotating (body-frame) angular velocity in `RigidBody/AngularVelocity.lean`, mirroring the existing spatial angular velocity: - `bodyAngularVelocityTensor` (`Ω_body = Rᵀ Ṙ`) with `bodyAngularVelocityTensor_eq` - `bodyAngularVelocityTensor_transpose`: skew-symmetry `Ω_bodyᵀ = -Ω_body` - `orientation_mul_bodyAngularVelocityTensor`: `Ṙ = R Ω_body` - `angularVelocityTensor_eq_orientation_conj`: `Ω = R Ω_body Rᵀ` (body↔spatial bridge) - `bodyAngularVelocity` (`ω_body = Ω_bodyᵛ`, d = 3) with `bodyAngularVelocity_eq` - `crossProductMatrix_bodyAngularVelocity`: `[ω_body]ₓ = Ω_body` - constant orientation ⇒ zero body-frame angular velocity (tensor and vector) Co-authored-by: Claude Opus 4.8 <no-reply+claude-opus-4-8@anthropic.com>
|
Thank you for this PR, which will now be reviewed. If submitting to ./Physlib or ./QuantumInfo, please see our review guidelines if you are not familiar with the process. You should expect a back and forth with a reviewer before your PR is merged. See also that link for how to add appropriate labels to your PR. The PR will also go through a number of automated checks. You can learn more about these here, including how to run them locally. If you are submitting to ./PhyslibAlpha there will be a lighter review process, though your PR must still pass the automated checks. If you want to bring attention to this PR, please write a message on this thread of the Lean Zulip. Important: If a reviewer adds an |
| `ω(t) = Ωᵛ` via the hat map (`Physlib.Mathematics.CrossProductMatrix`), with `[ω]ₓ = Ω`; `ω` is the | ||
| angular velocity proper, appearing in the decomposition `v = V + ω × r` as an honest cross product. | ||
|
|
||
| The angular velocity can equally be expressed in the frame co-rotating with the body. The |
There was a problem hiding this comment.
Just a quick comment from me (will leave a full review to @nateabr). I think it might be worth explaining what the body frame actually is here more concretely, since I think this is the first time it has been mentioned anywhere in Physlib. E.g. How does it relate to the lab frame, is it inertial etc.
There was a problem hiding this comment.
Good point, thanks — done. The module docstring now defines the body frame concretely: the coordinate system rigidly attached to the body (origin at the centre of mass, axes rotating with the body), in which every material point has time-independent coordinates. It also spells out how the frames are related — R(t) is the rotational part of the change of frame, mapping body-frame to lab-frame coordinates — and notes that the body frame is in general not inertial, but is the natural setting for the inertia tensor and Euler's equations since the mass distribution is time-independent there. I have rebased the stacked #1418 accordingly.
There was a problem hiding this comment.
Great! May also want to consider if it makes sense to give the Body frame its own file system. Also at some-point, we should relate this to the action of rotation group and translation group on RidgidBody (discussed previously I think)
There was a problem hiding this comment.
Thanks! On a dedicated file: my instinct is to keep the body-frame kinematics next to the spatial angular velocity for now — the two are tied together by the conjugation bridge Ω = R Ω_body Rᵀ and share the same time-derivative infrastructure — and to split out a dedicated file once the body-frame API grows beyond kinematics (inertia tensor in body axes, Euler's equations), which is where I am heading next. Happy to split already in this PR if you prefer.
On the group actions: agreed — that is exactly the TODO recorded in Motion.lean ("Define an action of the rotation and translation groups on RigidBodyMotion, and recover displacement as the composite of those group actions"). Once that action exists, the body frame is naturally characterised through it; I would tackle it together with the Euler-equations arc.
There was a problem hiding this comment.
Why not define the angular velocity tensor through conjugation initially?
There was a problem hiding this comment.
Both choices are equivalent — Rᵀ Ω R = Rᵀ (Ṙ Rᵀ) R = Rᵀ Ṙ is one line of algebra — so it is really a question of which fact is definitional. I defined Ω_body := Rᵀ Ṙ because that is the intrinsic, first-principles definition: the spatial and body tensors are the derivative Ṙ translated back to the identity from the two sides (Ω = Ṙ Rᵀ on the right, Ω_body = Rᵀ Ṙ on the left — the standard ġ g⁻¹ vs g⁻¹ ġ of geometric mechanics), so the two frames sit on an equal footing and neither is derived from the other; the conjugation is then a theorem rather than a definition. Proof economy is essentially a wash: under either definition every other fact is a one-liner. I kept the direct product-rule proof of skew-symmetry because it differentiates the second orthogonality identity Rᵀ R = 1, the left-handed twin of the spatial argument, so each tensor's membership in 𝔰𝔬(d) comes from its own defining identity — happy to golf it through the conjugation instead if you prefer.
I have now also added the converse bridge lemma bodyAngularVelocityTensor_eq_orientation_conj : Ω_body = Rᵀ Ω R (previously only Ω = R Ω_body Rᵀ was stated), so the conjugation you mention is available as a rewrite in both directions, and reworded the module/def docstrings so the definitional status is clear.
There was a problem hiding this comment.
Apologies I missed this comment and only saw it after my review. Although I appreciate the symmetry of your argument, but from maintenance perspective I do believe we would want a shorter algebraic proof.
There was a problem hiding this comment.
No problem — agreed, and done: the latest commit golfs the skew-symmetry proof through the conjugation lemma (see the thread on bodyAngularVelocityTensor_transpose for the details).
…Velocity Expand the module docstring following review on leanprover-community#1417: define the body frame concretely (the coordinate system rigidly attached to the body, with origin at the centre of mass), state how the orientation R(t) relates body-frame and lab-frame coordinates, and note that the frame is non-inertial yet the natural setting for the inertia tensor and Euler's equations. Gloss the body-frame angular velocity vector as the angular velocity resolved along the body-fixed axes. Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Express the rotational kinetic energy of a rigid body in motion through the body-frame angular velocity `ω_body`, giving König's theorem as `T = ½ M ⟪V, V⟫ + rotationalKineticEnergy ω_body` when the reference point is the centre of mass. - `Mathematics/OrthogonalMatrix.lean` (new): `Matrix.dotProduct_mulVec_orthogonal` — an orthogonal matrix (`Aᵀ A = 1`) preserves the dot product, `(A v) ⬝ᵥ (A w) = v ⬝ᵥ w`. - `RigidBody/AngularVelocity.lean`: `deriv_orientation_mulVec_eq_orientation_bodyAngularVelocity_cross` — `Ṙ v = R (ω_body × v)`. - `RigidBody/KineticEnergy.lean`: `kineticEnergy_eq_translational_add_bodyAngularVelocity` — body-frame König, using orthogonality of `R` to identify `|Ṙ (y − c)|² = |ω_body × (y − c)|²`. Stacked on leanprover-community#1417 (body-frame angular velocity). Co-authored-by: Claude Opus 4.8 <no-reply+claude-opus-4-8@anthropic.com>
…body-frame tensor Following review discussion on leanprover-community#1417: add bodyAngularVelocityTensor_eq_orientation_conj (Omega_body = R^T Omega R), the converse of angularVelocityTensor_eq_orientation_conj, and reword the module and def docstrings so that Omega_body := R^T dR/dt reads as the intrinsic definition, with the conjugation as the derived bridge. Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Express the rotational kinetic energy of a rigid body in motion through the body-frame angular velocity `ω_body`, giving König's theorem as `T = ½ M ⟪V, V⟫ + rotationalKineticEnergy ω_body` when the reference point is the centre of mass. - `Mathematics/OrthogonalMatrix.lean` (new): `Matrix.dotProduct_mulVec_orthogonal` — an orthogonal matrix (`Aᵀ A = 1`) preserves the dot product, `(A v) ⬝ᵥ (A w) = v ⬝ᵥ w`. - `RigidBody/AngularVelocity.lean`: `deriv_orientation_mulVec_eq_orientation_bodyAngularVelocity_cross` — `Ṙ v = R (ω_body × v)`. - `RigidBody/KineticEnergy.lean`: `kineticEnergy_eq_translational_add_bodyAngularVelocity` — body-frame König, using orthogonality of `R` to identify `|Ṙ (y − c)|² = |ω_body × (y − c)|²`. Stacked on leanprover-community#1417 (body-frame angular velocity). Co-authored-by: Claude Opus 4.8 <no-reply+claude-opus-4-8@anthropic.com>
nateabr
left a comment
There was a problem hiding this comment.
Generally things look great!
Adding Joseph's remarks have made the file better but I have to point out that the doc-strings for the lemmas are repeating points from the overview verbatim and are quite verbose/redundant (for eg. bodyAngularVelocityTensor). I would recommend making them more concise as your overview is great and explains everything quite well.
| (fun s => (M.orientation s).1) t hR.matrix_transpose hR | ||
| rw [Time.deriv_matrix_transpose (fun s => (M.orientation s).1) t hR, hderiv0] at hprod | ||
| rw [bodyAngularVelocityTensor, transpose_mul, transpose_transpose] | ||
| exact eq_neg_of_add_eq_zero_right hprod.symm |
There was a problem hiding this comment.
I believe this is quite an easy golf using the other lemmas in this file.
You can use the conjugation lemma bodyAngularVelocityTensor_eq_orientation_conj and the spatial skew-symmetry angularVelocityTensor_transpose to prove it algebraically without calculus. Should be no more than 3-4 lines but please do check this.
This would require you to reorder the lemmas in this file but I do believe this is a better logical flow for the overall file
There was a problem hiding this comment.
Done — good call. The body-frame section is now ordered def → Ṙ = R Ω_body → the two conjugation bridges → skew-symmetry, and bodyAngularVelocityTensor_transpose is a single algebraic rewrite from bodyAngularVelocityTensor_eq_orientation_conj plus the spatial angularVelocityTensor_transpose, no calculus. Agreed the file reads better this way.
…onjugation Following review on leanprover-community#1417: reorder the body-frame section so the conjugation bridges precede the skew-symmetry lemma, prove bodyAngularVelocityTensor_transpose algebraically from bodyAngularVelocityTensor_eq_orientation_conj and the spatial angularVelocityTensor_transpose (no calculus), and make the body-frame docstrings concise, deferring to the module overview. Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Express the rotational kinetic energy of a rigid body in motion through the body-frame angular velocity `ω_body`, giving König's theorem as `T = ½ M ⟪V, V⟫ + rotationalKineticEnergy ω_body` when the reference point is the centre of mass. - `Mathematics/OrthogonalMatrix.lean` (new): `Matrix.dotProduct_mulVec_orthogonal` — an orthogonal matrix (`Aᵀ A = 1`) preserves the dot product, `(A v) ⬝ᵥ (A w) = v ⬝ᵥ w`. - `RigidBody/AngularVelocity.lean`: `deriv_orientation_mulVec_eq_orientation_bodyAngularVelocity_cross` — `Ṙ v = R (ω_body × v)`. - `RigidBody/KineticEnergy.lean`: `kineticEnergy_eq_translational_add_bodyAngularVelocity` — body-frame König, using orthogonality of `R` to identify `|Ṙ (y − c)|² = |ω_body × (y − c)|²`. Stacked on leanprover-community#1417 (body-frame angular velocity). Co-authored-by: Claude Opus 4.8 <no-reply+claude-opus-4-8@anthropic.com>
|
Thanks for the review! Both points are addressed in the latest commit: the skew-symmetry proof is golfed via the conjugation lemma (with the section reordered accordingly), and the body-frame docstrings are now concise — the defs just name their objects and the lemmas carry one-line statements, leaving the discussion to the overview. |
|
Merged - many thanks |
Express the rotational kinetic energy of a rigid body in motion through the body-frame angular velocity `ω_body`, giving König's theorem as `T = ½ M ⟪V, V⟫ + rotationalKineticEnergy ω_body` when the reference point is the centre of mass. - `Mathematics/OrthogonalMatrix.lean` (new): `Matrix.dotProduct_mulVec_orthogonal` — an orthogonal matrix (`Aᵀ A = 1`) preserves the dot product, `(A v) ⬝ᵥ (A w) = v ⬝ᵥ w`. - `RigidBody/AngularVelocity.lean`: `deriv_orientation_mulVec_eq_orientation_bodyAngularVelocity_cross` — `Ṙ v = R (ω_body × v)`. - `RigidBody/KineticEnergy.lean`: `kineticEnergy_eq_translational_add_bodyAngularVelocity` — body-frame König, using orthogonality of `R` to identify `|Ṙ (y − c)|² = |ω_body × (y − c)|²`. Stacked on leanprover-community#1417 (body-frame angular velocity). Co-authored-by: Claude Opus 4.8 <no-reply+claude-opus-4-8@anthropic.com>
* feat(ClassicalMechanics): König's theorem in the body frame Express the rotational kinetic energy of a rigid body in motion through the body-frame angular velocity `ω_body`, giving König's theorem as `T = ½ M ⟪V, V⟫ + rotationalKineticEnergy ω_body` when the reference point is the centre of mass. - `Mathematics/OrthogonalMatrix.lean` (new): `Matrix.dotProduct_mulVec_orthogonal` — an orthogonal matrix (`Aᵀ A = 1`) preserves the dot product, `(A v) ⬝ᵥ (A w) = v ⬝ᵥ w`. - `RigidBody/AngularVelocity.lean`: `deriv_orientation_mulVec_eq_orientation_bodyAngularVelocity_cross` — `Ṙ v = R (ω_body × v)`. - `RigidBody/KineticEnergy.lean`: `kineticEnergy_eq_translational_add_bodyAngularVelocity` — body-frame König, using orthogonality of `R` to identify `|Ṙ (y − c)|² = |ω_body × (y − c)|²`. Stacked on #1417 (body-frame angular velocity). Co-authored-by: Claude Opus 4.8 <no-reply+claude-opus-4-8@anthropic.com> * refactor(ClassicalMechanics): address König body-frame review comments - generalize `dotProduct_mulVec_orthogonal` to an arbitrary finite index type - golf the `centerOfMass = 0` rewrite to `simp [hc]` - trim the body-frame König docstring, deferring to the module overview Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * docs(ClassicalMechanics): clarify lab-frame vs body-frame in König body-frame theorem Spell out that the left-hand side is the total kinetic energy formed from the lab-frame point velocities, while the rotational term is evaluated from the body-frame angular velocity. The spatial and body rotational forms agree because Ṙ(y−c) = R(ω_body×(y−c)) and R, being orthogonal, preserves the norm. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.8 <no-reply+claude-opus-4-8@anthropic.com> Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Body-frame angular velocity of a rigid body
Adds the co-rotating (body-frame) angular velocity to
Physlib/ClassicalMechanics/RigidBody/AngularVelocity.lean, mirroring the existing spatialangular-velocity section (
angularVelocityTensor/angularVelocity). This is the naturalkinematic prerequisite for the inertia tensor in body-fixed axes and, downstream, Euler's
equations. One new concept, one file, no new files.
The spatial tensor is
Ω = Ṙ Rᵀ; the body-frame tensor is its conjugateΩ_body = Rᵀ Ṙ = Rᵀ Ω R,again skew-symmetric, with 3-dimensional dual
ω_body = Ω_bodyᵛ.New declarations (all in
namespace RigidBodyMotion)bodyAngularVelocityTensor(def)Ω_body(t) = R(t)ᵀ Ṙ(t)bodyAngularVelocityTensor_eqrfl)bodyAngularVelocityTensor_transposeΩ_bodyᵀ = -Ω_body, fromRᵀ R = 1orientation_mul_bodyAngularVelocityTensorṘ = R Ω_bodyangularVelocityTensor_eq_orientation_conjΩ = R Ω_body Rᵀ(body ↔ spatial bridge)bodyAngularVelocity(def,d = 3)ω_body(t) = Ω_body(t)ᵛvia the hat mapbodyAngularVelocity_eqrfl)crossProductMatrix_bodyAngularVelocity[ω_body]ₓ = Ω_bodybodyAngularVelocityTensor_of_orientation_constΩ_body = 0bodyAngularVelocity_of_orientation_constω_body = 0The module docstring gains a paragraph on the body frame; references updated to Landau–Lifshitz
Sections 31 and 32.
Reviewer reading order
bodyAngularVelocityTensor→bodyAngularVelocityTensor_transpose(skew) →orientation_mul_bodyAngularVelocityTensor(Ṙ = R Ω_body) →angularVelocityTensor_eq_orientation_conj(Ω = R Ω_body Rᵀ) →bodyAngularVelocity→crossProductMatrix_bodyAngularVelocity→ the two const-orientation lemmas.Verification
lake build Physlib.ClassicalMechanics.RigidBody.AngularVelocity— succeeds; downstreamKineticEnergystill builds.#print axiomson all 10 new declarations: onlypropext,Classical.choice,Quot.sound.lake exe runLinter Physlib.ClassicalMechanics.RigidBody.AngularVelocity— 0 issues in thisfile. (The reported errors are the pre-existing
RigidBody/Basic.leaninformal-stubunderscore names and
Meta/TODO, unchanged from master.)./scripts/lint-style.sh— exit 0.Follow-up (separate PR): König's theorem in the body frame,
T = ½ M ⟪V,V⟫ + rotationalKineticEnergy ω_bodyundercenterOfMass = 0.🤖 Drafted with AI assistance (Claude); the human author has reviewed and certifies every
statement.