Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
5972878
harden discrete_geodesic interpolation
mlsdpk Apr 7, 2026
674e5ab
dedup metric norm() and move type_name to core/debug.hpp
mlsdpk Apr 7, 2026
39d2656
add Sampler concept with Stochastic and Halton implementations
mlsdpk Apr 7, 2026
d9f0497
unify has_riemannian_log into core/metric.hpp resolver
mlsdpk Apr 7, 2026
697cb29
alias default metrics to ConstantSPDMetric and own injectivity_radius…
mlsdpk Apr 7, 2026
24a55a0
generalize Sphere to n dimensions
mlsdpk Apr 7, 2026
d7b71b8
wire Euclidean Torus SE2 random_point to Sampler policy
mlsdpk Apr 7, 2026
77953c2
compose Jacobi and SE2LeftInvariant over WeightedMetric and ConstantS…
mlsdpk Apr 7, 2026
13f0fdd
update docs TODO and changelog for core headers refactor
mlsdpk Apr 7, 2026
30271ba
refresh concepts page and bundle geodex-docs skill
mlsdpk Apr 8, 2026
3a76f6f
docs: add discrete-geodesic-interpolation concept page
mlsdpk Apr 8, 2026
c3857cd
docs: update benchmarks readme
mlsdpk Apr 8, 2026
5d42384
address PR review: encapsulation, IdentityMetric, Sphere SamplerT, un…
mlsdpk Apr 9, 2026
980950f
style: apply clang-format (ColumnLimit 100)
mlsdpk Apr 9, 2026
19c222a
added CMake install targets and find_package support
karyna-volokhatiuk Apr 8, 2026
476eb77
fix leaking of GoogleTest and GoogleBenchmark deps; remove Eigen unsu…
karyna-volokhatiuk Apr 20, 2026
741f736
feat: add discrete geodesic caching for OMPL interpolation
mlsdpk Apr 10, 2026
f995c66
feat: add SDF clearance metric, path smoothing, and turning radius API
mlsdpk Apr 10, 2026
63f483b
feat: add geodex collision module
mlsdpk Apr 12, 2026
b92e435
refactor: OMPL integration polish, smoothing fixes, examples cleanup
mlsdpk Apr 17, 2026
0ad2010
docs: update mathjax font and package it inside assets
mlsdpk Apr 19, 2026
f72c912
documentation updates and port pending pybindings for InterpolationRe…
mlsdpk Apr 19, 2026
64e1e38
docs: add planar arm gif and update copyright msg
mlsdpk Apr 20, 2026
86f3310
docs: add se2 planning tutorial, improve landing page
mlsdpk Apr 21, 2026
0e06d1e
fix: se2 distance bug, regenerate all figs
mlsdpk Apr 21, 2026
64a66f2
fix: restore wiring missing from curated v0.1.0 release
mlsdpk Apr 22, 2026
f79d515
docs: update changelog, bump version, minor doc updates
mlsdpk Apr 23, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 23 additions & 0 deletions .clang-format
Original file line number Diff line number Diff line change
@@ -1,2 +1,25 @@
BasedOnStyle: Google
ColumnLimit: 100
SortIncludes: CaseSensitive
IncludeBlocks: Regroup
IncludeCategories:
# 1. C system headers
- Regex: '^<c(assert|errno|math|stddef|stdint|stdio|stdlib|string)>'
Priority: 1
CaseSensitive: true
# 2. Third-party (path-based includes: Eigen/, ompl/, nanobind/, gtest/, etc.)
- Regex: '^<.+/'
Priority: 3
# 3. Platform / architecture headers
- Regex: '^<(arm_neon|immintrin|xmmintrin|emmintrin)\.h>'
Priority: 3
CaseSensitive: true
# 4. C++ standard library (lowercase start, catch-all for remaining <...>)
- Regex: '^<'
Priority: 2
# 5. Local project headers (quoted)
- Regex: '^"geodex/'
Priority: 4
# 6. Relative local headers (quoted, no path prefix)
- Regex: '^"'
Priority: 5
37 changes: 37 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,43 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## Released

### [0.1.1] - 2026-04-23

#### Added - new major features
- Discrete geodesic interpolation algorithm (`discrete_geodesic`).
- New collision checking module: smooth-SDF primitives (`CircleSmoothSDF`, `RectangleSmoothSDF`), `GridSDF`, `PolygonFootprint`, `FootprintGridChecker`.
- `SDFConformalMetric` — turns any base metric into an obstacle-aware metric via a smooth SDF callable.
- `smooth_path()` - metric-aware shortcutting and collision-constrained L-BFGS energy minimization.
- `SE2LeftInvariantMetric::car_like(radius, lateral_penalty)` static factory for turning-radius-constrained SE(2) planning.
- n-dimensional Sphere
- Sphere<Dim> now supports any dimensions
- OMPL integration
- GeodexStateSpace<Manifold> adapts any RiemannianManifold to OMPL's StateSpace.
- GeodexOptimizationObjective<Manifold, Heuristic> for geodesic distance cost + admissible heuristic.
- GeodexDirectInfSampler<Manifold, Heuristic> for informed sampling (PHS for Euclidean heuristic, rejection otherwise).
- GeodexValidityChecker for OMPL motion validation.
- `Sampler` concept with `StochasticSampler` and `HaltonSampler`; all manifolds take a `SamplerT` template parameter.
- CMake install targets and find_package(geodex) support
- New python bindings and tests
- Examples: `sphere_interpolation` (C++ and Python), `se2_tutorial` (holonomic / diff-drive / clearance / parking on a real costmap), `minimum_energy_planning` (planar arm under KE and Jacobi metrics).
- Documentation updates
- New SE2 planning tutorial
- Minimum energy planning tutorial now includes planning with OMPL section
- New concept page for discrete geodesic interpolation algorithm
- Redesigned landing page, and vendored MathJax for offline builds.

#### Changed
- `SE2` sampling bounds unified into `lo`/`hi` `Vector3d` over `(x, y, θ)`; default θ bounds `[−π, π)`.
- `injectivity_radius()` moved from metrics onto manifolds.
- `Sphere` exp/log/distance parameterized on the metric (was round-metric-only).
- Composable metric refactors
- WeightedMetric — uniform scalar (or configuration-dependent callable) scaling wrapper around any base metric.
- JacobiMetric — now composed over KineticEnergyMetric + WeightedMetric; static_assert callability checks on construction.
- SE2LeftInvariantMetric — composed over WeightedMetric + ConstantSPDMetric.
- `type_name<T>()` moved to `core/debug.hpp`; `MetricHasInnerMatrix` concept and `is_riemannian_log()` resolver added in `core/metric.hpp`.
- All manifolds preallocate a sample_buf_ for random_point() (no per-call allocation)
- clang-format applied repo-wide

### [0.1.0] - 2026-04-02

Initial public release.
Expand Down
52 changes: 43 additions & 9 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
cmake_minimum_required(VERSION 3.20)
project(geodex VERSION 0.1.0 LANGUAGES CXX)
project(geodex VERSION 0.1.1 LANGUAGES CXX)

set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)

include(GNUInstallDirs)
include(CMakePackageConfigHelpers)
include(FetchContent)

# Eigen3
Expand All @@ -14,24 +16,19 @@ FetchContent_Declare(
GIT_TAG 5.0.0
GIT_SHALLOW TRUE
)
set(EIGEN_BUILD_DOC OFF CACHE BOOL "" FORCE)
set(EIGEN_BUILD_TESTING OFF CACHE BOOL "" FORCE)
set(BUILD_TESTING_SAVE ${BUILD_TESTING})
set(BUILD_TESTING OFF CACHE BOOL "" FORCE)
FetchContent_GetProperties(eigen)
if(NOT eigen_POPULATED)
FetchContent_Populate(eigen)
add_subdirectory(${eigen_SOURCE_DIR} ${eigen_BINARY_DIR} EXCLUDE_FROM_ALL)
endif()
set(BUILD_TESTING ${BUILD_TESTING_SAVE} CACHE BOOL "" FORCE)

# Header-only interface library
add_library(geodex INTERFACE)
add_library(geodex::geodex ALIAS geodex)
target_include_directories(geodex INTERFACE
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
$<INSTALL_INTERFACE:include>
$<BUILD_INTERFACE:${eigen_SOURCE_DIR}>
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
)
target_link_libraries(geodex INTERFACE Eigen3::Eigen)
target_compile_features(geodex INTERFACE cxx_std_20)

# Tests
Expand Down Expand Up @@ -75,3 +72,40 @@ if(BUILD_DOCS)
VERBATIM)
endif()
endif()

# Install
install(TARGETS geodex
EXPORT geodexTargets
)

install(DIRECTORY include/
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
)

install(DIRECTORY ${eigen_SOURCE_DIR}/Eigen
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
)

install(EXPORT geodexTargets
FILE geodexTargets.cmake
NAMESPACE geodex::
DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/geodex
)

configure_package_config_file(
cmake/geodexConfig.cmake.in
${CMAKE_CURRENT_BINARY_DIR}/geodexConfig.cmake
INSTALL_DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/geodex
)

write_basic_package_version_file(
${CMAKE_CURRENT_BINARY_DIR}/geodexConfigVersion.cmake
VERSION ${PROJECT_VERSION}
COMPATIBILITY SameMajorVersion
)

install(FILES
${CMAKE_CURRENT_BINARY_DIR}/geodexConfig.cmake
${CMAKE_CURRENT_BINARY_DIR}/geodexConfigVersion.cmake
DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/geodex
)
16 changes: 11 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,14 +29,20 @@ All installation instructions, C++/Python tutorials, and API references are avai

geodex accompanies the paper "[Geometry-Aware Sampling-Based Motion Planning on Riemannian Manifolds](https://arxiv.org/abs/2602.00992)" accepted to [WAFR 2026](https://algorithmic-robotics.org/):
```bibtex
@article{kyaw2026geometry,
title={Geometry-Aware Sampling-Based Motion Planning on Riemannian Manifolds},
author={Kyaw, Phone Thiha and Kelly, Jonathan},
journal={arXiv preprint arXiv:2602.00992},
year={2026}
@inproceedings{kyaw2026geometry,
address = {Oulu, Finland},
author = {Phone Thiha Kyaw and Jonathan Kelly},
booktitle = {Proceedings of the 17th World Symposium on the Algorithmic Foundations of Robotics {(WAFR)}},
date = {2026-06-15/2026-06-17},
month = {Jun. 15--17},
title = {Geometry-Aware Sampling-Based Motion Planning on {Riemannian} Manifolds},
url = {https://arxiv.org/abs/2602.00992},
year = {2026}
}
```

## License

Copyright © 2026 Space and Terrestrial Autonomous Robotic Systems (STARS) Lab.

geodex is licensed under the [Apache License 2.0](LICENSE).
34 changes: 34 additions & 0 deletions benchmarks/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
include(FetchContent)

FetchContent_Declare(
googlebenchmark
GIT_REPOSITORY https://github.com/google/benchmark.git
GIT_TAG v1.9.1
GIT_SHALLOW TRUE
)
set(BENCHMARK_ENABLE_TESTING OFF CACHE BOOL "" FORCE)
set(BENCHMARK_ENABLE_INSTALL OFF CACHE BOOL "" FORCE)
set(BENCHMARK_INSTALL_DOCS OFF CACHE BOOL "" FORCE)
FetchContent_MakeAvailable(googlebenchmark)

add_executable(bench_manifold_ops bench_manifold_ops.cpp)
target_link_libraries(bench_manifold_ops PRIVATE geodex benchmark::benchmark benchmark::benchmark_main)

add_executable(bench_algorithms bench_algorithms.cpp)
target_link_libraries(bench_algorithms PRIVATE geodex benchmark::benchmark benchmark::benchmark_main)
target_include_directories(bench_algorithms PRIVATE ${CMAKE_SOURCE_DIR}/tests/fixtures)

add_executable(bench_metrics bench_metrics.cpp)
target_link_libraries(bench_metrics PRIVATE geodex benchmark::benchmark benchmark::benchmark_main)
target_include_directories(bench_metrics PRIVATE ${CMAKE_SOURCE_DIR}/tests/fixtures)

add_executable(bench_retractions bench_retractions.cpp)
target_link_libraries(bench_retractions PRIVATE geodex benchmark::benchmark benchmark::benchmark_main)

add_executable(bench_collision bench_collision.cpp)
target_link_libraries(bench_collision PRIVATE geodex benchmark::benchmark benchmark::benchmark_main)

if(TARGET ompl::ompl)
add_executable(bench_ompl_interpolation bench_ompl_interpolation.cpp)
target_link_libraries(bench_ompl_interpolation PRIVATE geodex benchmark::benchmark benchmark::benchmark_main ompl::ompl)
endif()
Loading
Loading