Skip to content

Commit d7e28b2

Browse files
committed
Merge branch 'develop' of github.com:borglab/gtsam into develop
2 parents 2c97752 + a22b8db commit d7e28b2

File tree

186 files changed

+18196
-2206
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

186 files changed

+18196
-2206
lines changed

.github/workflows/build-special.yml

Lines changed: 23 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -180,9 +180,8 @@ jobs:
180180
run: |
181181
sudo apt-get install libeigen3-dev
182182
echo "GTSAM_USE_SYSTEM_EIGEN=ON" >> $GITHUB_ENV
183-
# TODO(dellaert): This does not work yet?
184-
# sudo apt-get install metis
185-
# echo "GTSAM_USE_SYSTEM_METIS=ON" >> $GITHUB_ENV
183+
sudo apt-get install libmetis-dev
184+
echo "GTSAM_USE_SYSTEM_METIS=ON" >> $GITHUB_ENV
186185
187186
- name: Turn off boost
188187
if: matrix.flag == 'no_boost'
@@ -197,11 +196,28 @@ jobs:
197196
echo "GTSAM_BUILD_UNSTABLE=OFF" >> $GITHUB_ENV
198197
echo "GTSAM 'unstable' will not be built."
199198
200-
- name: Set Swap Space
199+
- name: Create swap (Linux only)
201200
if: runner.os == 'Linux'
202-
uses: pierotofy/set-swap-space@master
203-
with:
204-
swap-size-gb: 8
201+
shell: bash
202+
run: |
203+
# Attempts to create and enable a swap file at /mnt/swapfile.
204+
# It tries different sizes (8G, 4G, 2G, 1G) until successful.
205+
set -euo pipefail
206+
SWAP=/mnt/swapfile
207+
sudo swapoff $SWAP 2>/dev/null || true
208+
sudo rm -f $SWAP
209+
210+
for SIZE in 8 4 2 1; do
211+
if sudo fallocate -l ${SIZE}G $SWAP; then
212+
sudo chmod 600 $SWAP
213+
sudo mkswap $SWAP
214+
sudo swapon $SWAP && break
215+
fi
216+
sudo rm -f $SWAP
217+
done
218+
219+
# Displays active swap spaces at the end.
220+
swapon --show
205221
206222
- name: Build & Test
207223
run: |

.github/workflows/vcpkg.yml

Lines changed: 168 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,168 @@
1+
name: vcpkg
2+
on:
3+
pull_request:
4+
5+
# Every time you make a push to your PR, it cancel immediately the previous checks,
6+
# and start a new one. The other runner will be available more quickly to your PR.
7+
concurrency:
8+
group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }}
9+
cancel-in-progress: true
10+
11+
jobs:
12+
build:
13+
name: ${{ matrix.os }}
14+
runs-on: ${{ matrix.os }}
15+
strategy:
16+
fail-fast: false
17+
matrix:
18+
include:
19+
- os: windows-latest
20+
triplet: x64-windows-release
21+
build_type: Release
22+
test_target: RUN_TESTS
23+
binary_cache: C:\Users\runneradmin\AppData\Local\vcpkg\archives
24+
python: python
25+
# check_constraint_program fail on windows. should fix it for windows.
26+
# Remove this excluded test when you fix it for windows.
27+
ctest_extra_flags: -E check_constraint_program
28+
- os: ubuntu-latest
29+
triplet: x64-linux-release
30+
build_type: Release
31+
test_target: test
32+
binary_cache: /home/runner/.cache/vcpkg/archives
33+
cxxflags: -DCMAKE_CXX_FLAGS="-Wno-error=nonnull -Wno-error=maybe-uninitialized"
34+
python: python3
35+
- os: macos-latest
36+
triplet: arm64-osx-release
37+
build_type: Release
38+
test_target: test
39+
binary_cache: /Users/runner/.cache/vcpkg/archives
40+
python: python3
41+
steps:
42+
- name: Checkout
43+
uses: actions/checkout@v4
44+
45+
- name: Restore cache dependencies
46+
uses: actions/cache/restore@v3
47+
with:
48+
path: ${{ matrix.binary_cache }}
49+
key: ${{ matrix.os }}
50+
restore-keys: ${{ matrix.os }}
51+
52+
- name: Setup msbuild
53+
if: runner.os == 'Windows'
54+
uses: ilammy/msvc-dev-cmd@v1
55+
with:
56+
arch: x64
57+
toolset: 14.40
58+
59+
- name: cl version
60+
if: runner.os == 'Windows'
61+
shell: cmd
62+
run: cl
63+
64+
- name: Install vcpkg python dependencies
65+
if: runner.os == 'Linux'
66+
shell: bash
67+
run: |
68+
sudo apt-get install autoconf automake autoconf-archive
69+
70+
- name: Install vcpkg python dependencies
71+
if: runner.os == 'macOS'
72+
shell: bash
73+
run: |
74+
brew install autoconf automake autoconf-archive
75+
76+
- name: "Install dependencies"
77+
run: >
78+
vcpkg x-set-installed --triplet ${{ matrix.triplet }} --host-triplet ${{ matrix.triplet }}
79+
boost-assign
80+
boost-bimap
81+
boost-chrono
82+
boost-date-time
83+
boost-filesystem
84+
boost-format
85+
boost-graph
86+
boost-math
87+
boost-program-options
88+
boost-regex
89+
boost-serialization
90+
boost-system
91+
boost-thread
92+
boost-timer
93+
eigen3
94+
metis
95+
tbb
96+
pybind11
97+
geographiclib
98+
99+
- name: copy files for hash
100+
shell: bash
101+
run: |
102+
VCPKG_BASH_PATH=${VCPKG_INSTALLATION_ROOT//\\//}
103+
echo $VCPKG_BASH_PATH
104+
mkdir -p vcpkg-info
105+
find $VCPKG_BASH_PATH/installed/ -type f -name 'vcpkg_abi_info.txt' | \
106+
while read filepath; do
107+
triplet=$(echo "$filepath" | awk -F/ '{print $(NF-3)}')
108+
port=$(echo "$filepath" | awk -F/ '{print $(NF-1)}')
109+
cp "$filepath" "vcpkg-info/${triplet}_${port}.txt"
110+
done
111+
112+
- name: Save cache dependencies
113+
uses: actions/cache/save@v4
114+
with:
115+
path: ${{ matrix.binary_cache }}
116+
key: ${{ matrix.os }}-${{ hashFiles('vcpkg-info/*') }}
117+
118+
- name: Install python packages
119+
shell: bash
120+
run: |
121+
$VCPKG_INSTALLATION_ROOT/installed/${{ matrix.triplet }}/tools/python3/${{ matrix.python }} -m ensurepip --upgrade
122+
$VCPKG_INSTALLATION_ROOT/installed/${{ matrix.triplet }}/tools/python3/${{ matrix.python }} -m pip install -r python/dev_requirements.txt
123+
124+
- name: cmake config
125+
if: success()
126+
shell: bash
127+
run: |
128+
export CL=-openmp:experimental
129+
130+
# This is due an error in linux:
131+
# error: argument 2 null where non-null expected [-Werror=nonnull]
132+
# return __builtin_memcmp(__first1, __first2, sizeof(_Tp) * __num);
133+
# Remove `${{ matrix.cxxflags }}` when the compilation error solved
134+
135+
cmake . -B build -G Ninja \
136+
-DCMAKE_TOOLCHAIN_FILE=$VCPKG_INSTALLATION_ROOT/scripts/buildsystems/vcpkg.cmake \
137+
-DVCPKG_INSTALLED_DIR=$VCPKG_INSTALLATION_ROOT/installed \
138+
-DVCPKG_TARGET_TRIPLET=${{ matrix.triplet }} \
139+
-DVCPKG_HOST_TRIPLET=${{ matrix.triplet }} \
140+
-DCMAKE_BUILD_TYPE=Release \
141+
-DGTSAM_BUILD_EXAMPLES_ALWAYS=ON \
142+
-DGTSAM_ROT3_EXPMAP=ON \
143+
-DGTSAM_POSE3_EXPMAP=ON \
144+
-DGTSAM_BUILD_PYTHON=ON \
145+
-DGTSAM_BUILD_TESTS=ON \
146+
-DGTSAM_BUILD_UNSTABLE=OFF \
147+
-DGTSAM_USE_SYSTEM_EIGEN=ON \
148+
-DGTSAM_USE_SYSTEM_METIS=ON \
149+
-DGTSAM_USE_SYSTEM_PYBIND=ON \
150+
-DGTSAM_SUPPORT_NESTED_DISSECTION=ON \
151+
-DCTEST_EXTRA_ARGS="${{ matrix.ctest_extra_flags }}" \
152+
${{ matrix.cxxflags }}
153+
154+
- name: cmake build
155+
shell: bash
156+
run: |
157+
cmake --build build --config Release
158+
159+
- name: Run Python tests
160+
shell: bash
161+
run: |
162+
cmake --build build --target python-install
163+
cmake --build build --target python-test
164+
165+
- name: Run tests
166+
shell: bash
167+
run: |
168+
cmake --build build --target check

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,3 +23,5 @@ xcode/
2323

2424
# MyST build outputs
2525
_build
26+
GEMINI.md
27+
doc/#*.lyx#

CMakeLists.txt

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,37 @@ set (CMAKE_PROJECT_VERSION_PATCH ${GTSAM_VERSION_PATCH})
4040
###############################################################################
4141
# Gather information, perform checks, set defaults
4242

43+
# Option to enable AddressSanitizer
44+
option(GTSAM_ENABLE_ASAN "Enable AddressSanitizer for memory error detection" OFF)
45+
46+
if (GTSAM_ENABLE_ASAN)
47+
message(STATUS "Enabling AddressSanitizer (ASan)")
48+
if (MSVC)
49+
# MSVC-specific ASan flags
50+
# /fsanitize=address enables ASan
51+
# /Zi is for debug information (PDB files)
52+
# /Od is for disabling optimization (Debug builds)
53+
# /MD is for linking with the DLL version of the C runtime library
54+
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /fsanitize=address /Zi /Od")
55+
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /fsanitize=address /Zi /Od")
56+
57+
# Linker flags for MSVC ASan
58+
# /fsanitize=address enables ASan linking
59+
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /fsanitize=address")
60+
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} /fsanitize=address")
61+
set(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} /fsanitize=address")
62+
else()
63+
# Clang/GCC ASan flags (already there)
64+
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address -fno-omit-frame-pointer")
65+
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=address -fno-omit-frame-pointer")
66+
67+
# Linker flags
68+
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fsanitize=address")
69+
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -fsanitize=address")
70+
set(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} -fsanitize=address")
71+
endif()
72+
endif()
73+
4374
if(MSVC)
4475
set(MSVC_LINKER_FLAGS "/FORCE:MULTIPLE")
4576
set(CMAKE_EXE_LINKER_FLAGS ${MSVC_LINKER_FLAGS})

DEVELOP.md

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,32 @@
88

99
### Header-Wrapper Parameter Name Matching
1010

11-
If you add a C++ function to a `.i` file to expose it to the wrapper, you must ensure that the parameter names match exactly between the declaration in the header file and the declaration in the `.i`. Similarly, if you change any parameter names in a wrapped function in a header file, or change any parameter names in a `.i` file, you must change the corresponding function in the other file to reflect those changes.
11+
If you add a C++ function to a `.i` file to expose it to the wrapper, you must ensure that the parameter names match exactly between the declaration in the header file and the declaration in the `.i`. Similarly, if you change any parameter names in a wrapped function in a header file, or change any parameter names in a `.i` file, you must change the corresponding function in the other file to reflect those changes.
12+
13+
This includes inherited functions wrapped in `.i` files. If `Pose2` inherits `logmap` from `LieGroup` (in `Lie.h`) and wraps `logmap`, `Pose2.logmap` in the `.i` needs to have the same parameter names as the function definition in `Lie.h`.
1214

1315
> [!IMPORTANT]
1416
> The Doxygen documentation from the C++ will not carry over into the Python docstring if the parameter names do not match exactly!
1517
1618
If you encounter any functions that do not meet this criterion, please submit a PR to make them match.
1719

20+
## Wrapper Maintenance: How to fix C++ GTSAM functions not showing up in Python
21+
22+
The GTSAM Python wrapper is created using the [wrap](https://github.com/borglab/wrap) library ([docs](https://github.com/borglab/wrap/blob/master/DOCS.md)). The following brief guide is intended to help users extend the GTSAM wrapper themselves if necessary.
23+
24+
The Python wrapper for a class is defined in the `*.i` interface file present in the same directory as the class. For example, the wrapper for `gtsam/geometry/Pose3.h` is defined in `gtsam/geometry/geometry.i`; for `gtsam/navigation/ImuFactor.h`, it's `gtsam/navigation/navigation.i`, etc. With that knowledge and following these steps, you can manipulate your local clone of GTSAM and rebuild the Python package with your custom extended bindings.
25+
26+
1. Follow steps to clone, build, and install GTSAM with Python bindings on your OS, to be sure that you can do so before changing the source code. See [INSTALL.md](INSTALL.md) and the [Python README.md](python/README.md).
27+
2. Identify which folder your problem class is in and the corresponding interface file.
28+
3. Edit the interface file to include your desired functions from C++. Largely, this consists of simply copying the function signature into the appropriate class of the `.i`, but you also must make sure that everything is explicitly referenced (e.g. with `gtsam::`, `Eigen::`). In some cases, such as with Vectors or Jacobians, you may have to change a return type or argument type. In such situations, let the similar code in the `.i` be your guide. Commonly, `VectorN` can be changed to `gtsam::Vector`.
29+
4. Rebuild GTSAM with Python bindings and reinstall the Python package.
30+
5. At this point, your function should be available after `import gtsam`.
31+
32+
### Possible remaining issues
33+
34+
- If the source compiled fine, any build issues will be a consequence of errors in your new wrapper code. Look closely for missing namespaces, semicolons, types, etc. See the [wrap docs](https://github.com/borglab/wrap/blob/master/DOCS.md) for syntax guidelines.
35+
- If the new function won't show up in Python, make sure you have properly reinstalled the Python package. You might need to `pip uninstall` before reinstalling. On Windows, you might need to recopy the `.pyd` files and then rebuild as mentioned in the Windows installation instructions.
36+
1837
## Windows
1938

2039
On Windows it is necessary to explicitly export all functions from the library which should be externally accessible. To do this, include the macro `GTSAM_EXPORT` in your class or function definition.

cmake/GtsamTesting.cmake

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,8 @@ mark_as_advanced(GTSAM_SINGLE_TEST_EXE)
101101

102102
# Enable make check (http://www.cmake.org/Wiki/CMakeEmulateMakeCheck)
103103
if(GTSAM_BUILD_TESTS)
104-
add_custom_target(check COMMAND ${CMAKE_CTEST_COMMAND} -C $<CONFIGURATION> --output-on-failure)
104+
separate_arguments(CTEST_EXTRA_ARGS_LIST UNIX_COMMAND "${CTEST_EXTRA_ARGS}")
105+
add_custom_target(check COMMAND ${CMAKE_CTEST_COMMAND} -C $<CONFIGURATION> --output-on-failure ${CTEST_EXTRA_ARGS_LIST} VERBATIM)
105106
# Also add alternative checks using valgrind.
106107
# We don't look for valgrind being installed in the system, since these
107108
# targets are not invoked unless directly instructed by the user.

cmake/HandleMetis.cmake

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12,22 +12,26 @@ option(GTSAM_USE_SYSTEM_METIS "Find and use system-installed libmetis. If 'off',
1212

1313
if(GTSAM_USE_SYSTEM_METIS)
1414
# Debian package: libmetis-dev
15+
find_package(METIS CONFIG NAMES metis)
16+
if(NOT METIS_FOUND)
17+
find_path(METIS_INCLUDE_DIR metis.h REQUIRED)
18+
find_library(METIS_LIBRARY metis REQUIRED)
19+
if(METIS_INCLUDE_DIR AND METIS_LIBRARY)
20+
set(METIS_FOUND ON)
21+
endif()
22+
endif()
1523

16-
find_path(METIS_INCLUDE_DIR metis.h REQUIRED)
17-
find_library(METIS_LIBRARY metis REQUIRED)
18-
19-
if(METIS_INCLUDE_DIR AND METIS_LIBRARY)
24+
if(METIS_FOUND)
2025
mark_as_advanced(METIS_INCLUDE_DIR)
2126
mark_as_advanced(METIS_LIBRARY)
22-
2327
add_library(metis-gtsam-if INTERFACE)
2428
target_include_directories(metis-gtsam-if BEFORE INTERFACE ${METIS_INCLUDE_DIR}
2529
# gtsam_unstable/partition/FindSeparator-inl.h uses internal metislib.h API
2630
# via extern "C"
2731
$<BUILD_INTERFACE:${GTSAM_SOURCE_DIR}/gtsam/3rdparty/metis/libmetis>
2832
$<BUILD_INTERFACE:${GTSAM_SOURCE_DIR}/gtsam/3rdparty/metis/GKlib>
2933
)
30-
target_link_libraries(metis-gtsam-if INTERFACE ${METIS_LIBRARY})
34+
target_link_libraries(metis-gtsam-if INTERFACE ${METIS_LIBRARY} metis)
3135
endif()
3236
else()
3337
# Bundled version:

0 commit comments

Comments
 (0)