Imports
/-
Copyright (c) 2026 Giuseppe Sorge. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Giuseppe Sorge
-/
module
public import Mathlib.Data.Matrix.Mul
public import Mathlib.Data.Real.Basic
public import Mathlib.LinearAlgebra.CrossProduct
public import Mathlib.LinearAlgebra.Matrix.NotationThe hat map on three-dimensional vectors
The hat map sends a vector ω : Fin 3 → ℝ to the skew-symmetric matrix [ω]ₓ characterised by
[ω]ₓ *ᵥ v = ω ⨯₃ v. It realises the correspondence between ℝ³ and the skew-symmetric 3 × 3
matrices (the Lie algebra 𝖘𝖔(3)), and underlies the angular velocity of a rigid body.
@[expose] public section
The hat map [ω]ₓ: the skew-symmetric 3 × 3 matrix acting as the cross product with ω,
i.e. [ω]ₓ *ᵥ v = ω ⨯₃ v.
def crossProductMatrix (ω : Fin 3 → ℝ) : Matrix (Fin 3) (Fin 3) ℝ :=
!![0, -ω 2, ω 1; ω 2, 0, -ω 0; -ω 1, ω 0, 0]The hat matrix acts on a vector as the cross product.
@[simp]
lemma crossProductMatrix_mulVec (ω v : Fin 3 → ℝ) :
crossProductMatrix ω *ᵥ v = ω ⨯₃ v := ω:Fin 3 → ℝv:Fin 3 → ℝ⊢ crossProductMatrix ω *ᵥ v = (crossProduct ω) v
ω:Fin 3 → ℝv:Fin 3 → ℝi:Fin 3⊢ (crossProductMatrix ω *ᵥ v) i = (crossProduct ω) v i
ω:Fin 3 → ℝv:Fin 3 → ℝ⊢ (crossProductMatrix ω *ᵥ v) ((fun i => i) ⟨0, ⋯⟩) = (crossProduct ω) v ((fun i => i) ⟨0, ⋯⟩)ω:Fin 3 → ℝv:Fin 3 → ℝ⊢ (crossProductMatrix ω *ᵥ v) ((fun i => i) ⟨1, ⋯⟩) = (crossProduct ω) v ((fun i => i) ⟨1, ⋯⟩)ω:Fin 3 → ℝv:Fin 3 → ℝ⊢ (crossProductMatrix ω *ᵥ v) ((fun i => i) ⟨2, ⋯⟩) = (crossProduct ω) v ((fun i => i) ⟨2, ⋯⟩) ω:Fin 3 → ℝv:Fin 3 → ℝ⊢ (crossProductMatrix ω *ᵥ v) ((fun i => i) ⟨0, ⋯⟩) = (crossProduct ω) v ((fun i => i) ⟨0, ⋯⟩)ω:Fin 3 → ℝv:Fin 3 → ℝ⊢ (crossProductMatrix ω *ᵥ v) ((fun i => i) ⟨1, ⋯⟩) = (crossProduct ω) v ((fun i => i) ⟨1, ⋯⟩)ω:Fin 3 → ℝv:Fin 3 → ℝ⊢ (crossProductMatrix ω *ᵥ v) ((fun i => i) ⟨2, ⋯⟩) = (crossProduct ω) v ((fun i => i) ⟨2, ⋯⟩)
ω:Fin 3 → ℝv:Fin 3 → ℝ⊢ -(ω 1 * v 0) + ω 0 * v 1 = ω 0 * v 1 - ω 1 * v 0 ω:Fin 3 → ℝv:Fin 3 → ℝ⊢ -(ω 2 * v 1) + ω 1 * v 2 = ω 1 * v 2 - ω 2 * v 1ω:Fin 3 → ℝv:Fin 3 → ℝ⊢ ω 2 * v 0 + -(ω 0 * v 2) = ω 2 * v 0 - ω 0 * v 2ω:Fin 3 → ℝv:Fin 3 → ℝ⊢ -(ω 1 * v 0) + ω 0 * v 1 = ω 0 * v 1 - ω 1 * v 0 All goals completed! 🐙The hat map produces skew-symmetric matrices.
@[simp]
lemma crossProductMatrix_transpose (ω : Fin 3 → ℝ) :
(crossProductMatrix ω)ᵀ = - crossProductMatrix ω := ω:Fin 3 → ℝ⊢ (crossProductMatrix ω)ᵀ = -crossProductMatrix ω
ω:Fin 3 → ℝi:Fin 3j:Fin 3⊢ (crossProductMatrix ω)ᵀ i j = (-crossProductMatrix ω) i j
ω:Fin 3 → ℝj:Fin 3⊢ (crossProductMatrix ω)ᵀ ((fun i => i) ⟨0, ⋯⟩) j = (-crossProductMatrix ω) ((fun i => i) ⟨0, ⋯⟩) jω:Fin 3 → ℝj:Fin 3⊢ (crossProductMatrix ω)ᵀ ((fun i => i) ⟨1, ⋯⟩) j = (-crossProductMatrix ω) ((fun i => i) ⟨1, ⋯⟩) jω:Fin 3 → ℝj:Fin 3⊢ (crossProductMatrix ω)ᵀ ((fun i => i) ⟨2, ⋯⟩) j = (-crossProductMatrix ω) ((fun i => i) ⟨2, ⋯⟩) j ω:Fin 3 → ℝj:Fin 3⊢ (crossProductMatrix ω)ᵀ ((fun i => i) ⟨0, ⋯⟩) j = (-crossProductMatrix ω) ((fun i => i) ⟨0, ⋯⟩) jω:Fin 3 → ℝj:Fin 3⊢ (crossProductMatrix ω)ᵀ ((fun i => i) ⟨1, ⋯⟩) j = (-crossProductMatrix ω) ((fun i => i) ⟨1, ⋯⟩) jω:Fin 3 → ℝj:Fin 3⊢ (crossProductMatrix ω)ᵀ ((fun i => i) ⟨2, ⋯⟩) j = (-crossProductMatrix ω) ((fun i => i) ⟨2, ⋯⟩) j ω:Fin 3 → ℝ⊢ (crossProductMatrix ω)ᵀ ((fun i => i) ⟨2, ⋯⟩) ((fun i => i) ⟨0, ⋯⟩) =
(-crossProductMatrix ω) ((fun i => i) ⟨2, ⋯⟩) ((fun i => i) ⟨0, ⋯⟩)ω:Fin 3 → ℝ⊢ (crossProductMatrix ω)ᵀ ((fun i => i) ⟨2, ⋯⟩) ((fun i => i) ⟨1, ⋯⟩) =
(-crossProductMatrix ω) ((fun i => i) ⟨2, ⋯⟩) ((fun i => i) ⟨1, ⋯⟩)ω:Fin 3 → ℝ⊢ (crossProductMatrix ω)ᵀ ((fun i => i) ⟨2, ⋯⟩) ((fun i => i) ⟨2, ⋯⟩) =
(-crossProductMatrix ω) ((fun i => i) ⟨2, ⋯⟩) ((fun i => i) ⟨2, ⋯⟩) ω:Fin 3 → ℝ⊢ (crossProductMatrix ω)ᵀ ((fun i => i) ⟨0, ⋯⟩) ((fun i => i) ⟨0, ⋯⟩) =
(-crossProductMatrix ω) ((fun i => i) ⟨0, ⋯⟩) ((fun i => i) ⟨0, ⋯⟩)ω:Fin 3 → ℝ⊢ (crossProductMatrix ω)ᵀ ((fun i => i) ⟨0, ⋯⟩) ((fun i => i) ⟨1, ⋯⟩) =
(-crossProductMatrix ω) ((fun i => i) ⟨0, ⋯⟩) ((fun i => i) ⟨1, ⋯⟩)ω:Fin 3 → ℝ⊢ (crossProductMatrix ω)ᵀ ((fun i => i) ⟨0, ⋯⟩) ((fun i => i) ⟨2, ⋯⟩) =
(-crossProductMatrix ω) ((fun i => i) ⟨0, ⋯⟩) ((fun i => i) ⟨2, ⋯⟩)ω:Fin 3 → ℝ⊢ (crossProductMatrix ω)ᵀ ((fun i => i) ⟨1, ⋯⟩) ((fun i => i) ⟨0, ⋯⟩) =
(-crossProductMatrix ω) ((fun i => i) ⟨1, ⋯⟩) ((fun i => i) ⟨0, ⋯⟩)ω:Fin 3 → ℝ⊢ (crossProductMatrix ω)ᵀ ((fun i => i) ⟨1, ⋯⟩) ((fun i => i) ⟨1, ⋯⟩) =
(-crossProductMatrix ω) ((fun i => i) ⟨1, ⋯⟩) ((fun i => i) ⟨1, ⋯⟩)ω:Fin 3 → ℝ⊢ (crossProductMatrix ω)ᵀ ((fun i => i) ⟨1, ⋯⟩) ((fun i => i) ⟨2, ⋯⟩) =
(-crossProductMatrix ω) ((fun i => i) ⟨1, ⋯⟩) ((fun i => i) ⟨2, ⋯⟩)ω:Fin 3 → ℝ⊢ (crossProductMatrix ω)ᵀ ((fun i => i) ⟨2, ⋯⟩) ((fun i => i) ⟨0, ⋯⟩) =
(-crossProductMatrix ω) ((fun i => i) ⟨2, ⋯⟩) ((fun i => i) ⟨0, ⋯⟩)ω:Fin 3 → ℝ⊢ (crossProductMatrix ω)ᵀ ((fun i => i) ⟨2, ⋯⟩) ((fun i => i) ⟨1, ⋯⟩) =
(-crossProductMatrix ω) ((fun i => i) ⟨2, ⋯⟩) ((fun i => i) ⟨1, ⋯⟩)ω:Fin 3 → ℝ⊢ (crossProductMatrix ω)ᵀ ((fun i => i) ⟨2, ⋯⟩) ((fun i => i) ⟨2, ⋯⟩) =
(-crossProductMatrix ω) ((fun i => i) ⟨2, ⋯⟩) ((fun i => i) ⟨2, ⋯⟩) All goals completed! 🐙
The vee map: reads the vector off a 3 × 3 matrix. It is a left inverse of the hat map.
def crossProductVee (A : Matrix (Fin 3) (Fin 3) ℝ) : Fin 3 → ℝ := ![A 2 1, A 0 2, A 1 0]The vee map is a left inverse of the hat map.
@[simp]
lemma crossProductVee_crossProductMatrix (ω : Fin 3 → ℝ) :
crossProductVee (crossProductMatrix ω) = ω := ω:Fin 3 → ℝ⊢ (crossProductMatrix ω).crossProductVee = ω
ω:Fin 3 → ℝi:Fin 3⊢ (crossProductMatrix ω).crossProductVee i = ω i
ω:Fin 3 → ℝ⊢ (crossProductMatrix ω).crossProductVee ((fun i => i) ⟨0, ⋯⟩) = ω ((fun i => i) ⟨0, ⋯⟩)ω:Fin 3 → ℝ⊢ (crossProductMatrix ω).crossProductVee ((fun i => i) ⟨1, ⋯⟩) = ω ((fun i => i) ⟨1, ⋯⟩)ω:Fin 3 → ℝ⊢ (crossProductMatrix ω).crossProductVee ((fun i => i) ⟨2, ⋯⟩) = ω ((fun i => i) ⟨2, ⋯⟩) ω:Fin 3 → ℝ⊢ (crossProductMatrix ω).crossProductVee ((fun i => i) ⟨0, ⋯⟩) = ω ((fun i => i) ⟨0, ⋯⟩)ω:Fin 3 → ℝ⊢ (crossProductMatrix ω).crossProductVee ((fun i => i) ⟨1, ⋯⟩) = ω ((fun i => i) ⟨1, ⋯⟩)ω:Fin 3 → ℝ⊢ (crossProductMatrix ω).crossProductVee ((fun i => i) ⟨2, ⋯⟩) = ω ((fun i => i) ⟨2, ⋯⟩) All goals completed! 🐙
On skew-symmetric matrices the hat map is also a right inverse of the vee map: if Aᵀ = -A
then [Aᵛ]ₓ = A. Together with crossProductVee_crossProductMatrix this identifies ℝ³ with the
skew-symmetric 3 × 3 matrices 𝖘𝖔(3).
A:Matrix (Fin 3) (Fin 3) ℝhA:Aᵀ = -Ah:∀ (i j : Fin 3), A i j = -A j i⊢ crossProductMatrix A.crossProductVee = A
have hdiag : ∀ i, A i i = 0 := fun i => CharZero.eq_neg_self_iff.mp (h i i) A:Matrix (Fin 3) (Fin 3) ℝhA:Aᵀ = -Ah:∀ (i j : Fin 3), A i j = -A j ihdiag:∀ (i : Fin 3), A i i = 0⊢ crossProductMatrix A.crossProductVee = A
ext i j A:Matrix (Fin 3) (Fin 3) ℝhA:Aᵀ = -Ah:∀ (i j : Fin 3), A i j = -A j ihdiag:∀ (i : Fin 3), A i i = 0i:Fin 3j:Fin 3⊢ crossProductMatrix A.crossProductVee i j = A i j
fin_cases i «0» A:Matrix (Fin 3) (Fin 3) ℝhA:Aᵀ = -Ah:∀ (i j : Fin 3), A i j = -A j ihdiag:∀ (i : Fin 3), A i i = 0j:Fin 3⊢ crossProductMatrix A.crossProductVee ((fun i => i) ⟨0, ⋯⟩) j = A ((fun i => i) ⟨0, ⋯⟩) j«1» A:Matrix (Fin 3) (Fin 3) ℝhA:Aᵀ = -Ah:∀ (i j : Fin 3), A i j = -A j ihdiag:∀ (i : Fin 3), A i i = 0j:Fin 3⊢ crossProductMatrix A.crossProductVee ((fun i => i) ⟨1, ⋯⟩) j = A ((fun i => i) ⟨1, ⋯⟩) j«2» A:Matrix (Fin 3) (Fin 3) ℝhA:Aᵀ = -Ah:∀ (i j : Fin 3), A i j = -A j ihdiag:∀ (i : Fin 3), A i i = 0j:Fin 3⊢ crossProductMatrix A.crossProductVee ((fun i => i) ⟨2, ⋯⟩) j = A ((fun i => i) ⟨2, ⋯⟩) j <;> «0» A:Matrix (Fin 3) (Fin 3) ℝhA:Aᵀ = -Ah:∀ (i j : Fin 3), A i j = -A j ihdiag:∀ (i : Fin 3), A i i = 0j:Fin 3⊢ crossProductMatrix A.crossProductVee ((fun i => i) ⟨0, ⋯⟩) j = A ((fun i => i) ⟨0, ⋯⟩) j«1» A:Matrix (Fin 3) (Fin 3) ℝhA:Aᵀ = -Ah:∀ (i j : Fin 3), A i j = -A j ihdiag:∀ (i : Fin 3), A i i = 0j:Fin 3⊢ crossProductMatrix A.crossProductVee ((fun i => i) ⟨1, ⋯⟩) j = A ((fun i => i) ⟨1, ⋯⟩) j«2» A:Matrix (Fin 3) (Fin 3) ℝhA:Aᵀ = -Ah:∀ (i j : Fin 3), A i j = -A j ihdiag:∀ (i : Fin 3), A i i = 0j:Fin 3⊢ crossProductMatrix A.crossProductVee ((fun i => i) ⟨2, ⋯⟩) j = A ((fun i => i) ⟨2, ⋯⟩) j fin_cases j «2».«0» A:Matrix (Fin 3) (Fin 3) ℝhA:Aᵀ = -Ah:∀ (i j : Fin 3), A i j = -A j ihdiag:∀ (i : Fin 3), A i i = 0⊢ crossProductMatrix A.crossProductVee ((fun i => i) ⟨2, ⋯⟩) ((fun i => i) ⟨0, ⋯⟩) =
A ((fun i => i) ⟨2, ⋯⟩) ((fun i => i) ⟨0, ⋯⟩)«2».«1» A:Matrix (Fin 3) (Fin 3) ℝhA:Aᵀ = -Ah:∀ (i j : Fin 3), A i j = -A j ihdiag:∀ (i : Fin 3), A i i = 0⊢ crossProductMatrix A.crossProductVee ((fun i => i) ⟨2, ⋯⟩) ((fun i => i) ⟨1, ⋯⟩) =
A ((fun i => i) ⟨2, ⋯⟩) ((fun i => i) ⟨1, ⋯⟩)«2».«2» A:Matrix (Fin 3) (Fin 3) ℝhA:Aᵀ = -Ah:∀ (i j : Fin 3), A i j = -A j ihdiag:∀ (i : Fin 3), A i i = 0⊢ crossProductMatrix A.crossProductVee ((fun i => i) ⟨2, ⋯⟩) ((fun i => i) ⟨2, ⋯⟩) =
A ((fun i => i) ⟨2, ⋯⟩) ((fun i => i) ⟨2, ⋯⟩) <;> «0».«0» A:Matrix (Fin 3) (Fin 3) ℝhA:Aᵀ = -Ah:∀ (i j : Fin 3), A i j = -A j ihdiag:∀ (i : Fin 3), A i i = 0⊢ crossProductMatrix A.crossProductVee ((fun i => i) ⟨0, ⋯⟩) ((fun i => i) ⟨0, ⋯⟩) =
A ((fun i => i) ⟨0, ⋯⟩) ((fun i => i) ⟨0, ⋯⟩)«0».«1» A:Matrix (Fin 3) (Fin 3) ℝhA:Aᵀ = -Ah:∀ (i j : Fin 3), A i j = -A j ihdiag:∀ (i : Fin 3), A i i = 0⊢ crossProductMatrix A.crossProductVee ((fun i => i) ⟨0, ⋯⟩) ((fun i => i) ⟨1, ⋯⟩) =
A ((fun i => i) ⟨0, ⋯⟩) ((fun i => i) ⟨1, ⋯⟩)«0».«2» A:Matrix (Fin 3) (Fin 3) ℝhA:Aᵀ = -Ah:∀ (i j : Fin 3), A i j = -A j ihdiag:∀ (i : Fin 3), A i i = 0⊢ crossProductMatrix A.crossProductVee ((fun i => i) ⟨0, ⋯⟩) ((fun i => i) ⟨2, ⋯⟩) =
A ((fun i => i) ⟨0, ⋯⟩) ((fun i => i) ⟨2, ⋯⟩)«1».«0» A:Matrix (Fin 3) (Fin 3) ℝhA:Aᵀ = -Ah:∀ (i j : Fin 3), A i j = -A j ihdiag:∀ (i : Fin 3), A i i = 0⊢ crossProductMatrix A.crossProductVee ((fun i => i) ⟨1, ⋯⟩) ((fun i => i) ⟨0, ⋯⟩) =
A ((fun i => i) ⟨1, ⋯⟩) ((fun i => i) ⟨0, ⋯⟩)«1».«1» A:Matrix (Fin 3) (Fin 3) ℝhA:Aᵀ = -Ah:∀ (i j : Fin 3), A i j = -A j ihdiag:∀ (i : Fin 3), A i i = 0⊢ crossProductMatrix A.crossProductVee ((fun i => i) ⟨1, ⋯⟩) ((fun i => i) ⟨1, ⋯⟩) =
A ((fun i => i) ⟨1, ⋯⟩) ((fun i => i) ⟨1, ⋯⟩)«1».«2» A:Matrix (Fin 3) (Fin 3) ℝhA:Aᵀ = -Ah:∀ (i j : Fin 3), A i j = -A j ihdiag:∀ (i : Fin 3), A i i = 0⊢ crossProductMatrix A.crossProductVee ((fun i => i) ⟨1, ⋯⟩) ((fun i => i) ⟨2, ⋯⟩) =
A ((fun i => i) ⟨1, ⋯⟩) ((fun i => i) ⟨2, ⋯⟩)«2».«0» A:Matrix (Fin 3) (Fin 3) ℝhA:Aᵀ = -Ah:∀ (i j : Fin 3), A i j = -A j ihdiag:∀ (i : Fin 3), A i i = 0⊢ crossProductMatrix A.crossProductVee ((fun i => i) ⟨2, ⋯⟩) ((fun i => i) ⟨0, ⋯⟩) =
A ((fun i => i) ⟨2, ⋯⟩) ((fun i => i) ⟨0, ⋯⟩)«2».«1» A:Matrix (Fin 3) (Fin 3) ℝhA:Aᵀ = -Ah:∀ (i j : Fin 3), A i j = -A j ihdiag:∀ (i : Fin 3), A i i = 0⊢ crossProductMatrix A.crossProductVee ((fun i => i) ⟨2, ⋯⟩) ((fun i => i) ⟨1, ⋯⟩) =
A ((fun i => i) ⟨2, ⋯⟩) ((fun i => i) ⟨1, ⋯⟩)«2».«2» A:Matrix (Fin 3) (Fin 3) ℝhA:Aᵀ = -Ah:∀ (i j : Fin 3), A i j = -A j ihdiag:∀ (i : Fin 3), A i i = 0⊢ crossProductMatrix A.crossProductVee ((fun i => i) ⟨2, ⋯⟩) ((fun i => i) ⟨2, ⋯⟩) =
A ((fun i => i) ⟨2, ⋯⟩) ((fun i => i) ⟨2, ⋯⟩) simp [crossProductVee, crossProductMatrix] «2».«2» A:Matrix (Fin 3) (Fin 3) ℝhA:Aᵀ = -Ah:∀ (i j : Fin 3), A i j = -A j ihdiag:∀ (i : Fin 3), A i i = 0⊢ 0 = A 2 2 <;> «0».«0» A:Matrix (Fin 3) (Fin 3) ℝhA:Aᵀ = -Ah:∀ (i j : Fin 3), A i j = -A j ihdiag:∀ (i : Fin 3), A i i = 0⊢ 0 = A 0 0«0».«1» A:Matrix (Fin 3) (Fin 3) ℝhA:Aᵀ = -Ah:∀ (i j : Fin 3), A i j = -A j ihdiag:∀ (i : Fin 3), A i i = 0⊢ -A 1 0 = A 0 1«1».«1» A:Matrix (Fin 3) (Fin 3) ℝhA:Aᵀ = -Ah:∀ (i j : Fin 3), A i j = -A j ihdiag:∀ (i : Fin 3), A i i = 0⊢ 0 = A 1 1«1».«2» A:Matrix (Fin 3) (Fin 3) ℝhA:Aᵀ = -Ah:∀ (i j : Fin 3), A i j = -A j ihdiag:∀ (i : Fin 3), A i i = 0⊢ -A 2 1 = A 1 2«2».«0» A:Matrix (Fin 3) (Fin 3) ℝhA:Aᵀ = -Ah:∀ (i j : Fin 3), A i j = -A j ihdiag:∀ (i : Fin 3), A i i = 0⊢ -A 0 2 = A 2 0«2».«2» A:Matrix (Fin 3) (Fin 3) ℝhA:Aᵀ = -Ah:∀ (i j : Fin 3), A i j = -A j ihdiag:∀ (i : Fin 3), A i i = 0⊢ 0 = A 2 2
first
| exact (h _ _).symm «2».«2» A:Matrix (Fin 3) (Fin 3) ℝhA:Aᵀ = -Ah:∀ (i j : Fin 3), A i j = -A j ihdiag:∀ (i : Fin 3), A i i = 0⊢ 0 = A 2 2
| exact (hdiag _).symm All goals completed! 🐙