Skip to content

Commit 880170e

Browse files
authored
Use LieGroups.MetricLieGroup and other pose related updates (#792)
* Use LieGroups.MetricLieGroup and other pose related updates * update compat * Fix some DFGv1 related tests * Better name SOnxRn_MetricManifold * Rename file also * Pose3Pose3RotOffset: fix tangent and improve test * Simplify naming of Pose3Pose3RotOffset variables * Fix Pose2Pose2 docstring * Fix some tests * Test covarance with propagation * Skip ppe related tests * Fix and test Pose3Pose3UnitTrans * add subproject license * Temporarily test upstream-dev AMP tag in CI * IIF develop branch is now also on AMP15 * try to fix ci with worspaces * fix wrong project path * Update ci.yml * covarage --------- Co-authored-by: Johannes Terblanche <Affie@users.noreply.github.com>
1 parent 2adb03c commit 880170e

39 files changed

Lines changed: 853 additions & 373 deletions

.github/workflows/ci.yml

Lines changed: 43 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -4,73 +4,69 @@ on:
44
push:
55
branches:
66
- develop
7-
- release**
7+
- 'release/**'
88
workflow_dispatch:
9+
910
jobs:
1011
test:
11-
name: Julia ${{ matrix.julia-version }} - ${{ matrix.os }} - ${{ matrix.arch }}
12+
name: Julia ${{ matrix.julia-version }} - Env:${{ matrix.environment }} - ${{ matrix.os }}
1213
runs-on: ${{ matrix.os }}
1314
env:
1415
JULIA_PKG_SERVER: ""
16+
JULIA_PROJECT: ${{ matrix.project-path }}
1517
strategy:
1618
fail-fast: false
1719
matrix:
18-
julia-version: ['1.11', 'nightly']
20+
julia-version: ['1', 'nightly']
1921
os: [ubuntu-latest]
2022
arch: [x64]
23+
environment: ['standard', 'upstream']
24+
25+
include:
26+
- environment: 'standard'
27+
project-path: 'RoME/test'
28+
- environment: 'upstream'
29+
project-path: 'RoME/test/upstream_test'
30+
31+
exclude:
32+
- environment: 'upstream'
33+
julia-version: 'nightly'
34+
2135
steps:
22-
- uses: actions/checkout@v2
36+
- uses: actions/checkout@v4
37+
2338
- uses: julia-actions/setup-julia@v2
2439
with:
2540
version: ${{ matrix.julia-version }}
2641
arch: ${{ matrix.arch }}
27-
- uses: actions/cache@v4
28-
env:
29-
cache-name: cache-artifacts
30-
with:
31-
path: ~/.julia/artifacts
32-
key: ${{ runner.os }}-test-${{ env.cache-name }}-${{ hashFiles('**/Project.toml') }}
33-
restore-keys: |
34-
${{ runner.os }}-test-${{ env.cache-name }}-
35-
${{ runner.os }}-test-
36-
${{ runner.os }}-
37-
- uses: julia-actions/julia-buildpkg@latest
42+
43+
- uses: julia-actions/cache@v2
44+
45+
# Julia automatically spins up in the folder specified by JULIA_PROJECT above.
46+
- name: Instantiate workspace
47+
shell: julia --color=yes {0}
48+
run: |
49+
using Pkg
50+
Pkg.instantiate()
51+
3852
- run: |
3953
git config --global user.name Tester
4054
git config --global user.email te@st.er
41-
- uses: julia-actions/julia-runtest@latest
55+
56+
- name: Run Test Suite
57+
shell: julia --color=yes {0}
58+
run: |
59+
using Pkg
60+
Pkg.test("RoME"; coverage = true)
4261
continue-on-error: ${{ matrix.julia-version == 'nightly' }}
62+
4363
- uses: julia-actions/julia-processcoverage@v1
44-
if: ${{ matrix.julia-version == '1.10' }}
45-
- uses: codecov/codecov-action@v1
4664
with:
47-
file: lcov.info
48-
49-
upstream-dev:
50-
#if: github.ref != 'refs/heads/release**'
51-
name: Upstream Dev
52-
runs-on: ubuntu-latest
53-
env:
54-
JULIA_PKG_SERVER: ""
55-
steps:
56-
- uses: actions/checkout@v4
57-
- uses: julia-actions/setup-julia@v2
65+
directories: RoME/src,RoME/ext,RoMETypes/src
66+
if: ${{ matrix.julia-version == '1' }}
67+
68+
- uses: codecov/codecov-action@v4
69+
if: ${{ matrix.julia-version == '1' }}
5870
with:
59-
version: '1'
60-
arch: x64
61-
- uses: julia-actions/cache@v2
62-
- name: Dev dependencies
63-
shell: julia --color=yes --project=monorepo {0}
64-
run: |
65-
using Pkg;
66-
Pkg.add(PackageSpec(name="DistributedFactorGraphs",rev="develop"))
67-
Pkg.add(PackageSpec(name="ApproxManifoldProducts",rev="develop"))
68-
Pkg.add(PackageSpec(url="https://github.com/JuliaRobotics/IncrementalInference.jl",rev="develop",subdir="IncrementalInferenceTypes"))
69-
Pkg.add(PackageSpec(url="https://github.com/JuliaRobotics/IncrementalInference.jl",rev="develop",subdir="IncrementalInference"))
70-
Pkg.develop([PackageSpec(path="RoMETypes"), PackageSpec(path="RoME")])
71-
- name: Run tests
72-
env:
73-
IIF_TEST_GROUP: 'basic_functional_group'
74-
run: >
75-
julia --color=yes --project=monorepo -e 'using Pkg; Pkg.test("RoME")'
76-
71+
file: lcov.info
72+
token: ${{ secrets.CODECOV_TOKEN }}

Project.toml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
[workspace]
2+
projects = [
3+
"RoMETypes",
4+
"RoME",
5+
"RoME/test"
6+
]

RoME/LICENSE

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
The MIT License (MIT)
2+
3+
Copyright (c) 2026
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in all
13+
copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
SOFTWARE.

RoME/Project.toml

Lines changed: 5 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -58,14 +58,14 @@ Dates = "1.10"
5858
DelimitedFiles = "1"
5959
DifferentialEquations = "7"
6060
Distributed = "1.10"
61-
DistributedFactorGraphs = "0.28"
61+
DistributedFactorGraphs = "0.29"
6262
Distributions = "0.24, 0.25"
6363
DocStringExtensions = "0.8, 0.9"
6464
FileIO = "1"
6565
Flux = "0.14, 0.15, 0.16"
6666
ImageCore = "0.9, 0.10"
6767
ImageIO = "0.6"
68-
IncrementalInference = "0.36.0"
68+
IncrementalInference = "0.37.0"
6969
IncrementalInferenceTypes = "0.1.0"
7070
Interpolations = "0.14, 0.15"
7171
KernelDensityEstimate = "0.5.1, 0.6"
@@ -78,7 +78,7 @@ OrderedCollections = "1"
7878
PrecompileTools = "1"
7979
ProgressMeter = "1"
8080
Random = "1.10"
81-
RecursiveArrayTools = "3"
81+
RecursiveArrayTools = "3, 4"
8282
Reexport = "1"
8383
RoMETypes = "0.1.0"
8484
Rotations = "1.1"
@@ -89,12 +89,5 @@ TimeZones = "1"
8989
TransformUtils = "0.2.17"
9090
julia = "1.10"
9191

92-
[extras]
93-
CameraModels = "0d57b887-6120-40e6-8b8c-29d3116bc0c1"
94-
DifferentialEquations = "0c46a032-eb83-5123-abaf-570d42b7fbaa"
95-
Flux = "587475ba-b771-5e3f-ad9e-33799f191a9c"
96-
ImageIO = "82e4d734-157c-48bb-816b-45c225c6df19"
97-
Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"
98-
99-
[targets]
100-
test = ["CameraModels", "DifferentialEquations", "Flux", "ImageIO", "Test"]
92+
[workspace]
93+
projects = ["test"]

RoME/ext/RoMECameraModelsExt.jl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,7 @@ function solveMultiviewLandmark!(
105105
_c_Xi = Vector{CameraModels.PixelIndex{true, Float64}}()
106106
for fl in flbs
107107
vl = setdiff(ls(dfg, fl), [lmlb;])[1]
108-
push!(_w_P_ci, getState(getVariable(dfg, vl), :parametric).val[1])
108+
push!(_w_P_ci, DFG.refMeans(getState(getVariable(dfg, vl), :parametric))[1])
109109
union!(vlbs, [vl;])
110110

111111
# TODO apply camera intrinsic calibration
@@ -121,7 +121,7 @@ function solveMultiviewLandmark!(
121121
w_Ph0 = [
122122
(
123123
retry * randn(3) .+
124-
getState(getVariable(dfg, lmlb), :parametric).val[1]
124+
DFG.refMeans(getState(getVariable(dfg, lmlb), :parametric))[1]
125125
)...
126126
1.0
127127
]

RoME/src/canonical/GenerateCircular.jl

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ function generateGraph_Circle(
3838
biasTurn::Real = 0.0,
3939
kappaOdo::Real = 1.0,
4040
cyclePoses::Int = poses,
41+
sampleNoise::Bool = false,
4142
)
4243
# assume empty factor graph object fg
4344
@assert offsetPoses < poses "`offsetPoses` must be smaller than total number of `poses`"
@@ -69,10 +70,12 @@ function generateGraph_Circle(
6970
addVariable!(fg, nsym, Pose2)
7071
# TODO rework the addition of noise alongside simulated ground truth, maybe `noise_t_cb`.
7172
pp = Pose2Pose2(
72-
MvNormal(
73-
[10.0; 0; 2pi / (cyclePoses) + biasTurn],
74-
Matrix(Diagonal((kappaOdo * [0.1; 0.1; 0.1]) .^ 2)),
75-
),
73+
let d = MvNormal(
74+
[10.0; 0; 2pi / (cyclePoses) + biasTurn],
75+
Matrix(Diagonal((kappaOdo * [0.1; 0.1; 0.1]) .^ 2)),
76+
)
77+
sampleNoise ? MvNormal(rand(d), d.Σ) : d
78+
end,
7679
)
7780
addFactor!(fg, [psym; nsym], pp; graphinit = graphinit)
7881
end

RoME/src/factors/PartialPose3.jl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -119,12 +119,12 @@ end
119119
# Pose3Pose3XYYaw(z::SamplableBelief) = Pose3Pose3XYYaw(z, (1,2,4,5,6)) # (1,2,6))
120120
Pose3Pose3XYYaw(z::SamplableBelief) = Pose3Pose3XYYaw(z, (1, 2, 6))
121121

122-
DFG.getManifold(::Type{<:Pose3Pose3XYYaw}) = SOnxRn_MetricManifold(2)
122+
DFG.getManifold(::Type{<:Pose3Pose3XYYaw}) = LeftInvariantMetricSE(2)
123123

124124
## NOTE, Yaw only works if you assume a preordained global reference point, such as identity_element(Pose3)
125125
function (cfo::CalcFactor{<:Pose3Pose3XYYaw})(X, wTp, wTq)
126126
#
127-
M = SOnxRn_MetricManifold(2)
127+
M = LeftInvariantMetricSE(2)
128128

129129
rx = normalize(view(wTp.x[2], 1:2, 1))
130130
R = SA[

RoME/src/factors/Pose2D.jl

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ Base.@kwdef struct Pose2Pose2{T <: IIF.SamplableBelief} <: IIF.AbstractManifoldM
2929
Z::T = MvNormal(Diagonal([1.0; 1.0; 1.0]))
3030
end
3131

32-
DFG.getManifold(::InstanceType{Pose2Pose2}) = SOnxRn_MetricManifold(2)
32+
DFG.getManifold(::InstanceType{Pose2Pose2}) = LeftInvariantMetricSE(2)
3333

3434
Pose2Pose2(::UniformScaling) = Pose2Pose2()
3535

@@ -40,6 +40,17 @@ function (cf::CalcFactor{<:Pose2Pose2})(X, p, q)
4040
return vee(M, p, X - X̂) # TODO check sign
4141
end
4242

43+
# An alternative error function that parallel transports the error vector back to p
44+
# function (cf::CalcFactor{<:RobustPose2Pose2})(X, p, q)
45+
# G = getManifold(RobustPose2Pose2)
46+
# q̂ = exp(G, p, X)
47+
# E_q̂ = log(G, q̂, q)
48+
# # Parallel transport the error vector back to p.
49+
# E_p = parallel_transport_to(G, q̂, E_q̂, p)
50+
# return vee(LieAlgebra(G), E_p)
51+
# end
52+
53+
4354
# NOTE, serialization support -- will be reduced to macro in future
4455
# ------------------------------------
4556

RoME/src/factors/Pose2Point2.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ DFG.getManifold(::InstanceType{Pose2Point2}) = getManifold(Point2)
2222
# define the conditional probability constraint
2323
function (cfo::CalcFactor{<:Pose2Point2})(p_Xpq, w_T_p, w_Tl_q)
2424
#
25-
M = SOnxRn_MetricManifold(2)
25+
M = LeftInvariantMetricSE(2)
2626

2727
p_T_qhat = ArrayPartition(SA[p_Xpq[1]; p_Xpq[2]], SMatrix{2, 2}([1 0; 0 1.0]))
2828
_w_T_p = ArrayPartition(SA[w_T_p.x[1]...], SMatrix{2, 2}(w_T_p.x[2]))

0 commit comments

Comments
 (0)