From 78a89554b011598ecdbb68ffbda5c4b3be84fd75 Mon Sep 17 00:00:00 2001 From: Ronny Bergmann Date: Wed, 15 Jan 2025 18:59:56 +0100 Subject: [PATCH] Introduce types to distinguish representations of SE(n), specify zero_vector accordingly --- ext/LieGroupsRecursiveArrayToolsExt.jl | 23 ++++++++++++++++ src/LieGroups.jl | 4 +++ src/Lie_algebra/Lie_algebra_interface.jl | 7 ++++- src/groups/special_euclidean_group.jl | 26 ++++++++++++++----- src/interface.jl | 22 ++++++++++++++-- .../LieGroupsTestSuite.jl | 16 ++++++------ 6 files changed, 81 insertions(+), 17 deletions(-) diff --git a/ext/LieGroupsRecursiveArrayToolsExt.jl b/ext/LieGroupsRecursiveArrayToolsExt.jl index 2ce11a0f..8067eca1 100644 --- a/ext/LieGroupsRecursiveArrayToolsExt.jl +++ b/ext/LieGroupsRecursiveArrayToolsExt.jl @@ -14,6 +14,12 @@ end # disable affine check LieGroups._check_matrix_affine(::ArrayPartition, ::Int; v=1) = nothing +function ManifoldsBase.submanifold_component( + G::LieGroups.SpecialEuclideanGroup, g::ArrayPartition, ::Val{I} +) where {I} + # pass down to manifold by default + return ManifoldsBase.submanifold_component(G.manifold, g, I) +end function ManifoldsBase.submanifold_component( G::LieGroups.LeftSpecialEuclideanGroup, g::ArrayPartition, ::Val{:Rotation} ) @@ -36,6 +42,23 @@ Base.@propagate_inbounds function ManifoldsBase.submanifold_component( return ManifoldsBase.submanifold_component(G.manifold, g, 1) end +function ManifoldsBase.zero_vector( + G::LieGroups.LeftSpecialEuclideanGroup, + e::Identity{LieGroups.SpecialEuclideanOperation}, + ::Union{ComponentsLieAlgebraTVector,ArrayPartition}, +) + n = Manifolds.get_parameter(G.manifold[1].size)[1] + return ArrayPartition(zeros(n, n), zeros(n)) +end +function ManifoldsBase.zero_vector( + G::LieGroups.RightSpecialEuclideanGroup, + e::Identity{LieGroups.SpecialEuclideanOperation}, + ::Union{ComponentsLieAlgebraTVector,ArrayPartition}, +) + n = Manifolds.get_parameter(G.manifold[1].size)[1] + return ArrayPartition(zeros(n), zeros(n, n)) +end + # TODO: Implement? # The following three should also work due to the # AbstractProductGroup s implementations diff --git a/src/LieGroups.jl b/src/LieGroups.jl index ea83ec86..6d1d84dc 100644 --- a/src/LieGroups.jl +++ b/src/LieGroups.jl @@ -104,6 +104,10 @@ export SpecialEuclideanGroup, SpecialOrthogonalGroup, SpecialUnitaryGroup export TranslationGroup export UnitaryGroup +# Points and Tangent representations +export AffineMatrixPoint, AffineMatrixTVector +export ComponentsLieGroupPoint, ComponentsLieAlgebraTVector +# Functions export adjoint, adjoint!, apply, apply! export base_lie_group, base_manifold export compose, compose! diff --git a/src/Lie_algebra/Lie_algebra_interface.jl b/src/Lie_algebra/Lie_algebra_interface.jl index 86ecba5d..cca7ead7 100644 --- a/src/Lie_algebra/Lie_algebra_interface.jl +++ b/src/Lie_algebra/Lie_algebra_interface.jl @@ -130,10 +130,15 @@ function Base.show(io::IO, 𝔤::LieAlgebra) return print(io, "LieAlgebra( $(𝔤.manifold) )") end +function ManifoldsBase.zero_vector(𝔤::LieAlgebra, T::Type) + # pass to Lie group + return ManifoldsBase.zero_vector(𝔤.manifold, Idenitity(𝔤.manifold), T) +end function ManifoldsBase.zero_vector(𝔤::LieAlgebra) + # pass to manifold directly return ManifoldsBase.zero_vector(𝔤.manifold.manifold, identity_element(𝔤.manifold)) end - function ManifoldsBase.zero_vector!(𝔤::LieAlgebra, X) + # pass to manifold directly return ManifoldsBase.zero_vector!(𝔤.manifold.manifold, X, identity_element(𝔤.manifold)) end diff --git a/src/groups/special_euclidean_group.jl b/src/groups/special_euclidean_group.jl index 028be98c..49c8ca64 100644 --- a/src/groups/special_euclidean_group.jl +++ b/src/groups/special_euclidean_group.jl @@ -88,7 +88,6 @@ const SpecialEuclideanOperation = Union{ }, } - """ AffineMatrixPoint <: AbstractLieGroupPoint @@ -117,7 +116,7 @@ where ``$(_tex(:vec, "0"))_n ∈ ℝ^n`` denotes the vector containing zeros. While this tangent vector itself is not an affine matrix itself, it can be used for the Lie algebra of the affine group """ -struct AffineMatrixTVector{T} <: AbstractLieAlgebraTangentVector +struct AffineMatrixTVector{T} <: AbstractLieAlgebraTVector value::T end @@ -135,17 +134,16 @@ struct ComponentsLieGroupPoint{T} <: AbstractLieGroupPoint end """ - ComponentsLieAlgebraTangentVector <: AbstractLieGroupPoint + ComponentsLieAlgebraTVector <: AbstractLieGroupPoint represent a point on a Lie algebra (explicitly) as a point that consists of components """ -struct ComponentsLieAlgebraTangentVector{T} <: AbstractLieAlgebraTangentVector +struct ComponentsLieAlgebraTVector{T} <: AbstractLieAlgebraTVector value::T end ManifoldsBase.@manifold_element_forwards ComponentsLieGroupPoint value -ManifoldsBase.@manifold_vector_forwards ComponentsLieAlgebraTangentVector value - +ManifoldsBase.@manifold_vector_forwards ComponentsLieAlgebraTVector value # This union we can also use for the matrix case where we do not care @@ -303,10 +301,19 @@ function identity_element(G::SpecialEuclideanGroup, ::Type{<:AbstractMatrix}) q = zeros(ManifoldsBase.representation_size(G)...) return identity_element!(G, q) end +function identity_element(G::SpecialEuclideanGroup, ::Type{AffineMatrixPoint}) + q = zeros(ManifoldsBase.representation_size(G)...) + identity_element!(G, q) + return AffineMatrixPoint(q) +end function identity_element!(::SpecialEuclideanGroup, q::AbstractMatrix) copyto!(q, I) return q end +function identity_element!(G::SpecialEuclideanGroup, q::AffineMatrixPoint) + identity_element!(G, q.value) + return q +end _doc_inv_SEn = """ inv(G::SpecialEuclideanGroup, g) @@ -425,6 +432,13 @@ function _SOn_and_Tn(G::RightSpecialEuclideanGroup) return A[2], A[1] end +function ManifoldsBase.zero_vector( + G::SpecialEuclidean, e::Identity{SpecialEuclideanOperation} +) + n = Manifolds.get_parameter(G.manifold[1].size)[1] + return zeros(n + 1, n + 1) +end + function Base.show(io::IO, G::SpecialEuclideanGroup) size = Manifolds.get_parameter(G.manifold[1].size)[1] return print(io, "SpecialEuclideanGroup($(size))") diff --git a/src/interface.jl b/src/interface.jl index 7139bb9b..e7e605bd 100644 --- a/src/interface.jl +++ b/src/interface.jl @@ -99,7 +99,7 @@ By sub-typing the [`AbstractManifoldPoint`](@extref `ManifoldsBase.AbstractManif abstract type AbstractLieGroupPoint <: ManifoldsBase.AbstractManifoldPoint end """ - AbstractLieAlgebraTangentVector <: ManifoldsBase.TVector + AbstractLieAlgebraTVector <: ManifoldsBase.TVector An abstract type for a tangent vector represented in a [`LieAlgebra`](@ref). @@ -113,7 +113,7 @@ it might be necessary to distinguish different types of points, for example By sub-typing the [`AbstractManifoldPoint`](@extref `ManifoldsBase.AbstractManifoldPoint`), this follows the same idea as in $(_link(:ManifoldsBase)). """ -abstract type AbstractLieAlgebraTangentVector <: ManifoldsBase.TVector end +abstract type AbstractLieAlgebraTVector <: ManifoldsBase.TVector end # # @@ -941,6 +941,24 @@ function vee!(G::LieGroup{𝔽}, c, X) where {𝔽} return c end +""" + zero_vector(G::LieGroup, e::Identity, T::Type) + +Generate a $(_link(:zero_vector)) of type `T` in the [`LieAlgebra`](@ref) ``𝔤`` of +the [`LieGroup`](@ref) `G` of type `T`. +By default this calls `zero_vector(G, e)` + +Note that for the in-place variant `zero_vector!(G, X::T, e)` the type can be inferred by `X`. +""" +ManifoldsBase.zero_vector( + G::LieGroup{𝔽,<:O}, ::Identity{<:O}, T::Type +) where {𝔽,O<:AbstractGroupOperation} + +function ManifoldsBase.zero_vector( + G::LieGroup{𝔽,<:O}, e::Identity{<:O}, T::Type +) where {𝔽,O<:AbstractGroupOperation} + return zero_vector(G, e) +end function ManifoldsBase.zero_vector( G::LieGroup{𝔽,<:O}, ::Identity{<:O} ) where {𝔽,O<:AbstractGroupOperation} diff --git a/test/LieGroupsTestSuite.jl/LieGroupsTestSuite.jl b/test/LieGroupsTestSuite.jl/LieGroupsTestSuite.jl index 54c76bfa..ba241616 100644 --- a/test/LieGroupsTestSuite.jl/LieGroupsTestSuite.jl +++ b/test/LieGroupsTestSuite.jl/LieGroupsTestSuite.jl @@ -144,7 +144,7 @@ function test_compose( end if test_identity && test_mutating for g_ in [g, h] - for e in [Identity(G), identity_element(G)] + for e in [Identity(G), identity_element(G, typeof(g))] k1 = compose(G, g_, e) compose!(G, k2, g_, e) @test isapprox(G, k1, k2) @@ -266,7 +266,7 @@ function test_diff_inv(G::LieGroup, g, X; expected=missing, test_mutating::Bool= Y1 = diff_inv(G, g, X) @test is_vector(G, identity_element(G), Y1) if test_mutating - Y2 = zero_vector(𝔤) + Y2 = zero_vector(𝔤, typeof(X)) Y2 = diff_inv!(G, Y2, g, X) @test isapprox(𝔤, Y1, Y2) end @@ -294,7 +294,7 @@ function test_diff_left_compose( Y1 = diff_left_compose(G, g, h, X) @test is_vector(G, identity_element(G), Y1) if test_mutating - Y2 = zero_vector(𝔤) + Y2 = zero_vector(𝔤, typeof(X)) diff_left_compose!(G, Y2, g, h, X) @test isapprox(LieAlgebra(G), Y1, Y2) end @@ -322,7 +322,7 @@ function test_diff_right_compose( Y1 = diff_right_compose(G, g, h, X) @test is_vector(G, identity_element(G), Y1) if test_mutating - Y2 = zero_vector(𝔤) + Y2 = zero_vector(𝔤, typeof(X)) diff_right_compose!(G, Y2, g, h, X) @test isapprox(𝔤, Y1, Y2) end @@ -378,7 +378,7 @@ function test_diff_conjugate( Y1 = diff_conjugate(G, g, h, X) @test is_point(𝔤, Y1; error=:error) if test_mutating - Y2 = zero_vector(𝔤) + Y2 = zero_vector(𝔤, typeof(X)) diff_conjugate!(G, Y2, g, h, X) @test isapprox(𝔤, Y1, Y2) end @@ -442,7 +442,7 @@ function test_exp_log( # Lie group log Y1 = log(G, e, g) if test_mutating - Y2 = zero_vector(G, e) + Y2 = zero_vector(G, e, typeof(X)) log!(G, Y2, e, g) @test isapprox(𝔤, Y1, Y2) log!(G, Y2, e, e) @@ -462,7 +462,7 @@ function test_exp_log( # or equivalently @test is_vector(G, Identity(G), Y1; error=:error) @test is_vector(G, Y1; error=:error) - Y3 = zero_vector(G, e) + Y3 = zero_vector(G, e, typeof(X)) @test isapprox(G, e, Y3, log(G, e, e); atol=atol) log!(G, Y3, e, e) @test isapprox(G, e, Y3, log(G, e, e); atol=atol) @@ -775,7 +775,7 @@ function test_rand( X1 = rand(rng, G; vector_at=g1) @test is_vector(G, g1, X1; error=:error) if test_mutating - X2 = zero_vector(LieAlgebra(G), g1) + X2 = zero_vector(LieAlgebra(G), typeof(X1)) rand!(rng, G, X2; vector_at=g1) @test is_vector(G, g1, X2; error=:error) end