pyorbslam3 0.1.1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (37) hide show
  1. pyorbslam3-0.1.1/.dockerignore +8 -0
  2. pyorbslam3-0.1.1/.github/workflows/wheels.yml +48 -0
  3. pyorbslam3-0.1.1/.gitignore +12 -0
  4. pyorbslam3-0.1.1/BENCHMARKS.md +139 -0
  5. pyorbslam3-0.1.1/CMakeLists.txt +192 -0
  6. pyorbslam3-0.1.1/Dockerfile +79 -0
  7. pyorbslam3-0.1.1/PKG-INFO +327 -0
  8. pyorbslam3-0.1.1/README.md +312 -0
  9. pyorbslam3-0.1.1/build.sh +9 -0
  10. pyorbslam3-0.1.1/cmake/deps/CMakeLists.txt +106 -0
  11. pyorbslam3-0.1.1/configs/euroc/mono.yaml +78 -0
  12. pyorbslam3-0.1.1/configs/euroc/mono_inertial.yaml +84 -0
  13. pyorbslam3-0.1.1/configs/euroc/stereo.yaml +96 -0
  14. pyorbslam3-0.1.1/configs/euroc/stereo_inertial.yaml +114 -0
  15. pyorbslam3-0.1.1/configs/kitti/mono_2011_09_26.yaml +64 -0
  16. pyorbslam3-0.1.1/configs/kitti/stereo_2011_09_26.yaml +63 -0
  17. pyorbslam3-0.1.1/configs/tum_rgbd/mono_fr1.yaml +65 -0
  18. pyorbslam3-0.1.1/configs/tum_rgbd/mono_fr3.yaml +64 -0
  19. pyorbslam3-0.1.1/configs/tum_rgbd/rgbd_fr1.yaml +71 -0
  20. pyorbslam3-0.1.1/configs/tum_rgbd/rgbd_fr3.yaml +70 -0
  21. pyorbslam3-0.1.1/configs/tumvi/mono.yaml +64 -0
  22. pyorbslam3-0.1.1/configs/tumvi/mono_inertial.yaml +83 -0
  23. pyorbslam3-0.1.1/configs/tumvi/stereo.yaml +96 -0
  24. pyorbslam3-0.1.1/configs/tumvi/stereo_inertial.yaml +113 -0
  25. pyorbslam3-0.1.1/docker/patches/0001-cmake-static-pic-modern-targets.patch +789 -0
  26. pyorbslam3-0.1.1/docker/patches/0002-localmapping-keyframeculling-guards.patch +39 -0
  27. pyorbslam3-0.1.1/docker/patches/README.md +14 -0
  28. pyorbslam3-0.1.1/docs/benchmarks_header.md +47 -0
  29. pyorbslam3-0.1.1/docs/benchmarks_notes.md +40 -0
  30. pyorbslam3-0.1.1/examples/benchmark.py +388 -0
  31. pyorbslam3-0.1.1/examples/make_report.py +94 -0
  32. pyorbslam3-0.1.1/examples/run_tumvi.py +188 -0
  33. pyorbslam3-0.1.1/pyorbslam3/__init__.py +24 -0
  34. pyorbslam3-0.1.1/pyorbslam3/slam.py +216 -0
  35. pyorbslam3-0.1.1/pyorbslam3/vocab.py +70 -0
  36. pyorbslam3-0.1.1/pyproject.toml +56 -0
  37. pyorbslam3-0.1.1/src/orbslam3_pybind.cpp +432 -0
@@ -0,0 +1,8 @@
1
+ build/
2
+ results/
3
+ vocabulary/
4
+ *.so
5
+ __pycache__/
6
+ *.pyc
7
+ *.egg-info/
8
+ .git/
@@ -0,0 +1,48 @@
1
+ name: wheels
2
+
3
+ on:
4
+ push:
5
+ tags: ["v*"]
6
+ workflow_dispatch:
7
+
8
+ jobs:
9
+ sdist:
10
+ runs-on: ubuntu-latest
11
+ steps:
12
+ - uses: actions/checkout@v4
13
+ - uses: actions/setup-python@v5
14
+ with: { python-version: "3.12" }
15
+ - run: pip install build && python -m build --sdist
16
+ - uses: actions/upload-artifact@v4
17
+ with: { name: sdist, path: dist/*.tar.gz }
18
+
19
+ wheels:
20
+ runs-on: ubuntu-latest
21
+ timeout-minutes: 300
22
+ steps:
23
+ - uses: actions/checkout@v4
24
+ - uses: pypa/cibuildwheel@v2.22.0
25
+ - uses: actions/upload-artifact@v4
26
+ with: { name: wheels, path: wheelhouse/*.whl }
27
+
28
+ github-release:
29
+ needs: [sdist, wheels]
30
+ if: startsWith(github.ref, 'refs/tags/v')
31
+ runs-on: ubuntu-latest
32
+ permissions: { contents: write }
33
+ steps:
34
+ - uses: actions/download-artifact@v4
35
+ with: { path: dist, merge-multiple: true }
36
+ - uses: softprops/action-gh-release@v2
37
+ with: { files: dist/* }
38
+
39
+ pypi:
40
+ needs: [sdist, wheels]
41
+ if: startsWith(github.ref, 'refs/tags/v')
42
+ runs-on: ubuntu-latest
43
+ environment: pypi
44
+ permissions: { id-token: write } # PyPI trusted publishing (no token stored)
45
+ steps:
46
+ - uses: actions/download-artifact@v4
47
+ with: { path: dist, merge-multiple: true }
48
+ - uses: pypa/gh-action-pypi-publish@release/v1
@@ -0,0 +1,12 @@
1
+ build/
2
+ *.so
3
+ __pycache__/
4
+ *.pyc
5
+ *.egg-info/
6
+ vocabulary/ORBvoc.txt
7
+ results/*
8
+ !results/benchmarks.jsonl
9
+ !results/traj_*.txt
10
+ !results/kf_traj_*.txt
11
+ dist/
12
+ wheelhouse/
@@ -0,0 +1,139 @@
1
+ # pyorbslam3 benchmarks
2
+
3
+ Results of running the bindings on public datasets with `examples/benchmark.py`.
4
+ Every row is one full sequence run; the raw records are in
5
+ `results/benchmarks.jsonl` and the trajectories in `results/`. Regenerate this
6
+ file with `python3 examples/make_report.py -o BENCHMARKS.md --header docs/benchmarks_header.md --footer docs/benchmarks_notes.md`.
7
+
8
+ ## Setup
9
+
10
+ * Machine: Intel Core i5-1035G1 (4 cores / 8 threads, 1.0 GHz base), 15 GB RAM,
11
+ Ubuntu 22.04, Python 3.10, OpenCV 4.5.4. No GPU is used by ORB-SLAM3.
12
+ * Bindings linked against ORB-SLAM3 upstream commit `4452a3c4` with the two
13
+ patches in `docker/patches/`. Viewer off.
14
+ * Settings files: the stock ORB-SLAM3 examples for each dataset
15
+ (`configs/<dataset>/`), with two corrections: the TUM-VI stereo file's
16
+ `Camera.overlapping*` keys renamed to `Camera1.*` (the upstream spelling is
17
+ ignored by the parser), and the KITTI stereo file rewritten as two identical
18
+ `PinHole` cameras instead of `Camera.type: "Rectified"`, which crashes in the
19
+ settings printer upstream.
20
+ * Frames are fed sequentially as fast as tracking allows (no real-time pacing),
21
+ so `fps` is the throughput on this CPU, not a dataset rate. `track ms` is the
22
+ median wall time of one track call.
23
+
24
+ ## Metrics
25
+
26
+ * **Tracked OK** — frames for which ORB-SLAM3 reported `TrackingState.OK`. In
27
+ inertial modes the frames before IMU initialization count as not OK, which is
28
+ why mono-inertial rates sit below the non-inertial ones.
29
+ * **IMU init** — seconds of sequence time until `imu_initialized()` turned true.
30
+ * **ATE sim(3)** — RMSE of position error after a similarity (Umeyama) alignment
31
+ of the estimated trajectory to ground truth, over the poses that associate to
32
+ a ground-truth sample within 20 ms. **scale** is the similarity scale found by
33
+ that alignment: 1.0 means the estimate is already metric. For monocular runs
34
+ the scale is arbitrary by construction; for stereo, RGB-D and inertial runs it
35
+ should be close to 1.0.
36
+ * **ATE SE(3)** — the same error with scale fixed at 1 (rigid alignment only).
37
+ This is the number that matters for a metric system; it is meaningless for
38
+ plain monocular runs.
39
+
40
+ Ground truth: TUM-VI mocap (`mocap0`), EuRoC `state_groundtruth_estimate0`,
41
+ TUM RGB-D `groundtruth.txt`, KITTI raw OXTS GPS/INS converted to a local metric
42
+ frame (the odometry-benchmark drives with published poses are not in the raw
43
+ download set, so GPS/INS is used; its accuracy is at the decimetre level, which
44
+ sets a floor on the KITTI numbers).
45
+
46
+ ORB-SLAM3 is multi-threaded and not deterministic; repeated runs of the same
47
+ sequence vary by a few percent in tracked frames and ATE.
48
+
49
+
50
+ ### TUM-VI
51
+
52
+ | Sequence | Mode | Frames | Tracked OK | IMU init | ATE sim(3) | scale | ATE SE(3) | fps | track ms |
53
+ |---|---|---:|---:|---:|---:|---:|---:|---:|---:|
54
+ | room1 (run 1) | mono | 2821 | 2724 (96.6%) | n/a | 7.29 cm | 1.785 | n/a | 7.1 | 67.0 |
55
+ | room1 (run 2) | mono | 2821 | 2724 (96.6%) | n/a | 97.42 cm | 8.485 | n/a | 17.7 | 45.8 |
56
+ | room1 (run 1) | mono-imu | 2821 | 2700 (95.7%) | 8.4 s | 1.22 cm | 1.000 | 1.22 cm | 3.3 | 56.7 |
57
+ | room1 (run 2) | mono-imu | 2821 | 2700 (95.7%) | 8.4 s | 1.28 cm | 0.998 | 1.30 cm | 19.0 | 43.3 |
58
+ | room1 (run 1) | stereo | 2821 | 2821 (100.0%) | n/a | 7.15 cm | 0.974 | 7.62 cm | 4.9 | 102.9 |
59
+ | room1 (run 2) | stereo | 2821 | 2821 (100.0%) | n/a | 7.16 cm | 0.975 | 7.60 cm | 9.8 | 84.1 |
60
+ | room1 | stereo-imu | 2821 | 2746 (97.3%) | 2.5 s | 0.76 cm | 1.005 | 0.90 cm | 6.7 | 86.0 |
61
+
62
+ ### EuRoC MAV
63
+
64
+ | Sequence | Mode | Frames | Tracked OK | IMU init | ATE sim(3) | scale | ATE SE(3) | fps | track ms |
65
+ |---|---|---:|---:|---:|---:|---:|---:|---:|---:|
66
+ | V1_01_easy | mono | 2912 | 2802 (96.2%) | n/a | 8.87 cm | 2.058 | n/a | 25.8 | 30.2 |
67
+ | V1_01_easy | mono-imu | 2911 | 2798 (96.1%) | 7.9 s | 3.25 cm | 1.011 | 3.83 cm | 24.3 | 32.3 |
68
+ | V1_01_easy | stereo | 2912 | 2912 (100.0%) | n/a | 8.82 cm | 1.005 | 8.86 cm | 16.6 | 53.5 |
69
+ | V1_01_easy | stereo-imu | 2911 | 2864 (98.4%) | 2.5 s | 3.45 cm | 1.009 | 3.83 cm | 12.7 | 68.1 |
70
+ | V1_02_medium | mono | 1710 | 1531 (89.5%) | n/a | 9.40 cm | 0.216 | n/a | 29.1 | 24.8 |
71
+ | V1_02_medium | mono-imu | 1709 | 1594 (93.3%) | 11.0 s | 1.94 cm | 1.004 | 2.06 cm | 27.8 | 26.5 |
72
+ | V1_02_medium | stereo | 1710 | 1710 (100.0%) | n/a | 8.10 cm | 1.008 | 8.22 cm | 17.5 | 51.2 |
73
+ | V1_02_medium | stereo-imu | 1709 | 1687 (98.7%) | 2.4 s | 1.41 cm | 1.007 | 1.90 cm | 15.1 | 60.9 |
74
+ | V1_03_difficult | mono | 2149 | 1737 (80.8%) | n/a | 13.34 cm | 3.806 | n/a | 31.5 | 22.7 |
75
+ | V1_03_difficult | mono-imu | 2149 | 1790 (83.3%) | 9.8 s | 2.17 cm | 1.015 | 2.83 cm | 29.9 | 24.1 |
76
+ | V1_03_difficult | stereo | 2149 | 2149 (100.0%) | n/a | 15.12 cm | 1.018 | 15.38 cm | 18.7 | 48.4 |
77
+ | V1_03_difficult | stereo-imu | 2149 | 2071 (96.4%) | 2.4 s | 1.99 cm | 1.013 | 2.79 cm | 16.7 | 56.2 |
78
+
79
+ ### KITTI raw
80
+
81
+ | Sequence | Mode | Frames | Tracked OK | IMU init | ATE sim(3) | scale | ATE SE(3) | fps | track ms |
82
+ |---|---|---:|---:|---:|---:|---:|---:|---:|---:|
83
+ | 2011_09_26_drive_0036 (run 1) | mono | 803 | 802 (99.9%) | n/a | 801.9 cm | 12.176 | n/a | 18.4 | 41.0 |
84
+ | 2011_09_26_drive_0036 (run 2) | mono | 803 | 802 (99.9%) | n/a | 895.0 cm | 12.781 | n/a | 19.8 | 38.1 |
85
+ | 2011_09_26_drive_0036 | stereo | 803 | 803 (100.0%) | n/a | 85.59 cm | 1.007 | 151.4 cm | 6.0 | 88.9 |
86
+ | 2011_09_26_drive_0101 | mono | 936 | 845 (90.3%) | n/a | 2602.1 cm | 117.2 | n/a | 6.4 | 39.7 |
87
+ | 2011_09_26_drive_0101 | stereo | 936 | 936 (100.0%) | n/a | 107.7 cm | 1.000 | 107.8 cm | 4.5 | 117.4 |
88
+
89
+ ### TUM RGB-D
90
+
91
+ | Sequence | Mode | Frames | Tracked OK | IMU init | ATE sim(3) | scale | ATE SE(3) | fps | track ms |
92
+ |---|---|---:|---:|---:|---:|---:|---:|---:|---:|
93
+ | fr1_desk | mono | 596 | 492 (82.6%) | n/a | 1.50 cm | 1.043 | n/a | 17.9 | 34.8 |
94
+ | fr1_desk | rgbd | 596 | 596 (100.0%) | n/a | 1.60 cm | 0.996 | 1.64 cm | 6.5 | 60.4 |
95
+ | fr3_long_office (run 1) | mono | 2488 | 2463 (99.0%) | n/a | 105.6 cm | 2.715 | n/a | 15.7 | 41.0 |
96
+ | fr3_long_office (run 2) | mono | 2488 | 2463 (99.0%) | n/a | 2.60 cm | 2.435 | n/a | 18.5 | 34.5 |
97
+ | fr3_long_office | rgbd | 2488 | 2488 (100.0%) | n/a | 1.65 cm | 0.986 | 3.44 cm | 12.6 | 59.4 |
98
+
99
+ ## Reading the results
100
+
101
+ * **Inertial modes recover metric scale.** Across all eight inertial runs
102
+ (TUM-VI room1, EuRoC V1_01–V1_03) the similarity-alignment scale lies within
103
+ 1.5 % of 1.0 and the ATE is 0.8–3.5 cm. Stereo-inertial initializes the IMU in
104
+ about 2.5 s on every sequence; mono-inertial needs 8–11 s of motion.
105
+ * **Stereo tracks every frame.** 100 % of frames `OK` on all seven stereo
106
+ sequences, scale 0.97–1.02 without any IMU. Indoor ATE is 7–15 cm; the KITTI
107
+ drives give about 1 m over 800–940 frames of driving against GPS/INS ground
108
+ truth, whose own accuracy is at the decimetre level.
109
+ * **RGB-D** tracks every frame on both TUM sequences with 1.6 cm ATE and metric
110
+ scale.
111
+ * **Plain monocular is the least repeatable mode.** Scale is arbitrary by
112
+ construction, and whenever ORB-SLAM3 re-initializes a map mid-sequence the
113
+ saved trajectory contains segments with different scales, which a single
114
+ similarity alignment cannot undo. That is what the paired runs show: room1 mono
115
+ 7 cm in one run and 97 cm in the next, fr3_long_office 106 cm and then 2.6 cm,
116
+ with identical tracking rates. On the KITTI driving sequences monocular drifts
117
+ in scale by one to two orders of magnitude (no loop closures on these drives),
118
+ which is expected and why the ORB-SLAM3 authors report KITTI with stereo only.
119
+ For anything that needs a usable trajectory, use stereo, RGB-D or an inertial
120
+ mode.
121
+ * **Throughput.** On this 1.0 GHz laptop CPU the bindings run EuRoC (752×480)
122
+ at 13–29 fps and TUM-VI (512×512 fisheye) at 10–19 fps depending on mode. The
123
+ "run 1" TUM-VI rows were measured while a Docker image was compiling on the
124
+ same machine; the "run 2" rows of the same modes show the uncontended speed.
125
+ The Python layer adds no measurable overhead: the median track-call time is
126
+ the ORB-SLAM3 tracking thread's own frame time.
127
+
128
+ Where a mode was run twice, `results/` holds the trajectory of the later run
129
+ (the `_run2` files for the two repeats that were run into a separate folder,
130
+ otherwise the file was overwritten); the JSONL keeps both sets of metrics.
131
+
132
+ ## Not covered here
133
+
134
+ * Real-camera results (ZED 2i, RealSense D435i) live in the `orbulation` ROS 2
135
+ package's user guide. D435i stereo-inertial is configured but still needs a
136
+ handheld test with motion.
137
+ * TUM-VI corridor/magistrale/outdoor sequences, EuRoC machine hall and
138
+ vicon_room2, and the KITTI odometry benchmark proper were not run.
139
+
@@ -0,0 +1,192 @@
1
+ cmake_minimum_required(VERSION 3.16)
2
+ project(pyorbslam3 LANGUAGES CXX)
3
+
4
+ if(NOT CMAKE_BUILD_TYPE)
5
+ set(CMAKE_BUILD_TYPE Release)
6
+ endif()
7
+ set(CMAKE_CXX_STANDARD 17)
8
+ set(CMAKE_CXX_STANDARD_REQUIRED ON)
9
+
10
+ # ---------------------------------------------------------------------------
11
+ # Where does ORB-SLAM3 come from? Three options, tried in this order:
12
+ #
13
+ # (a) ORBSLAM3_ROOT (+ optional ORBSLAM3_BUILD_DIR, default <root>/build):
14
+ # a standalone ORB_SLAM3 source tree already built as static libraries,
15
+ # with Pangolin discoverable through find_package(Pangolin) / Pangolin_DIR.
16
+ # Also read from the environment, so `ORBSLAM3_ROOT=... pip install .` works.
17
+ # (b) ORBSLAM_DEPS: legacy — the _deps dir of a PRBonn ORB-SLAM-Python build.
18
+ # (c) PYORBSLAM3_FETCH_DEPS=ON (automatic when neither of the above exists):
19
+ # download and compile Pangolin + ORB-SLAM3 (cmake/deps). Slow (30–60 min)
20
+ # but needs nothing beyond the system packages listed in the README.
21
+ # ---------------------------------------------------------------------------
22
+ set(ORBSLAM3_ROOT "$ENV{ORBSLAM3_ROOT}" CACHE PATH "Standalone ORB_SLAM3 source tree")
23
+ set(ORBSLAM3_BUILD_DIR "" CACHE PATH "Build dir of ORBSLAM3_ROOT (default <root>/build)")
24
+ set(ORBSLAM_DEPS
25
+ "${CMAKE_CURRENT_SOURCE_DIR}/../ORB-SLAM-Python/build/cp310-cp310-linux_x86_64/_deps"
26
+ CACHE PATH "Legacy: _deps dir of an ORB-SLAM-Python build")
27
+ option(PYORBSLAM3_FETCH_DEPS "Download and build Pangolin + ORB-SLAM3" OFF)
28
+ # Self-contained: also build a static minimal OpenCV and Eigen, so the module
29
+ # does not depend on the system OpenCV (used for the manylinux wheels).
30
+ if(DEFINED ENV{PYORBSLAM3_SELF_CONTAINED} AND NOT "$ENV{PYORBSLAM3_SELF_CONTAINED}" STREQUAL "" AND NOT "$ENV{PYORBSLAM3_SELF_CONTAINED}" STREQUAL "0")
31
+ set(_default_self_contained ON)
32
+ else()
33
+ set(_default_self_contained OFF)
34
+ endif()
35
+ option(PYORBSLAM3_SELF_CONTAINED "Bundle OpenCV + Eigen in the dependency build" ${_default_self_contained})
36
+ if(PYORBSLAM3_SELF_CONTAINED)
37
+ set(PYORBSLAM3_FETCH_DEPS ON)
38
+ endif()
39
+ # Where the dependency build lives (shared between Python versions in CI).
40
+ set(PYORBSLAM3_DEPS_DIR "$ENV{PYORBSLAM3_DEPS_DIR}" CACHE PATH "Directory for the dependency superbuild")
41
+ if(DEFINED ENV{PYORBSLAM3_JOBS} AND NOT "$ENV{PYORBSLAM3_JOBS}" STREQUAL "")
42
+ set(_default_jobs "$ENV{PYORBSLAM3_JOBS}")
43
+ else()
44
+ set(_default_jobs 2)
45
+ endif()
46
+ set(PYORBSLAM3_JOBS "${_default_jobs}" CACHE STRING "Parallel jobs for the dependency build")
47
+ if(PYORBSLAM3_JOBS STREQUAL "")
48
+ set(PYORBSLAM3_JOBS 2)
49
+ endif()
50
+
51
+ if(ORBSLAM3_ROOT STREQUAL "" AND NOT PYORBSLAM3_FETCH_DEPS
52
+ AND EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/../ORB_SLAM3/build/libORB_SLAM3.a")
53
+ set(ORBSLAM3_ROOT "${CMAKE_CURRENT_SOURCE_DIR}/../ORB_SLAM3")
54
+ endif()
55
+ if(ORBSLAM3_ROOT STREQUAL "" AND NOT PYORBSLAM3_FETCH_DEPS
56
+ AND NOT EXISTS "${ORBSLAM_DEPS}/orb_slam3-build/libORB_SLAM3.a")
57
+ set(PYORBSLAM3_FETCH_DEPS ON)
58
+ endif()
59
+
60
+ if(PYORBSLAM3_FETCH_DEPS)
61
+ if(PYORBSLAM3_DEPS_DIR STREQUAL "")
62
+ set(_deps "${CMAKE_BINARY_DIR}/deps")
63
+ else()
64
+ set(_deps "${PYORBSLAM3_DEPS_DIR}")
65
+ endif()
66
+ message(STATUS "pyorbslam3: building Pangolin + ORB-SLAM3 from source in ${_deps} "
67
+ "(jobs=${PYORBSLAM3_JOBS}, self-contained=${PYORBSLAM3_SELF_CONTAINED}; this takes a while)")
68
+ # Generator, make program and compilers are passed explicitly so that a
69
+ # dependency build cached from an earlier pip run (whose temporary build
70
+ # environment is gone) is refreshed instead of pointing at stale paths.
71
+ execute_process(
72
+ COMMAND ${CMAKE_COMMAND} -S "${CMAKE_CURRENT_SOURCE_DIR}/cmake/deps" -B "${_deps}"
73
+ -G "${CMAKE_GENERATOR}" "-DCMAKE_MAKE_PROGRAM=${CMAKE_MAKE_PROGRAM}"
74
+ "-DCMAKE_C_COMPILER=${CMAKE_C_COMPILER}" "-DCMAKE_CXX_COMPILER=${CMAKE_CXX_COMPILER}"
75
+ -DJOBS=${PYORBSLAM3_JOBS} -DSELF_CONTAINED=${PYORBSLAM3_SELF_CONTAINED}
76
+ RESULT_VARIABLE _rc)
77
+ if(NOT _rc EQUAL 0)
78
+ message(FATAL_ERROR "configuring the dependency superbuild failed")
79
+ endif()
80
+ execute_process(COMMAND ${CMAKE_COMMAND} --build "${_deps}" RESULT_VARIABLE _rc)
81
+ if(NOT _rc EQUAL 0)
82
+ message(FATAL_ERROR "building Pangolin / ORB-SLAM3 failed (see output above)")
83
+ endif()
84
+ set(ORBSLAM3_ROOT "${_deps}/orbslam3-src")
85
+ set(ORBSLAM3_BUILD_DIR "${_deps}/orbslam3-build")
86
+ set(Pangolin_DIR "${_deps}/pangolin-install/lib/cmake/Pangolin" CACHE PATH "" FORCE)
87
+ if(PYORBSLAM3_SELF_CONTAINED)
88
+ # prepend so the bundled OpenCV/Eigen win over any system copies
89
+ list(PREPEND CMAKE_PREFIX_PATH "${_deps}/opencv-install" "${_deps}/eigen-install")
90
+ endif()
91
+ endif()
92
+
93
+ find_package(Python COMPONENTS Interpreter Development.Module REQUIRED)
94
+ find_package(pybind11 CONFIG REQUIRED)
95
+ find_package(OpenCV 4.4 REQUIRED)
96
+ find_package(Eigen3 REQUIRED)
97
+ # Boost.Serialization is linked shared on purpose: distribution static builds
98
+ # are usually not -fPIC (manylinux's is not), and auditwheel bundles the .so.
99
+ find_package(Boost REQUIRED COMPONENTS serialization)
100
+ find_package(OpenSSL REQUIRED)
101
+
102
+ pybind11_add_module(_core MODULE src/orbslam3_pybind.cpp)
103
+
104
+ if(PYORBSLAM3_SELF_CONTAINED)
105
+ set(_win_uri "x11") # manylinux builds have no Wayland
106
+ else()
107
+ set(_win_uri "wayland")
108
+ endif()
109
+ target_compile_definitions(
110
+ _core PRIVATE HAVE_GLEW HAVE_EIGEN _LINUX_ PANGO_DEFAULT_WIN_URI="${_win_uri}"
111
+ BOOST_ALL_NO_LIB BOOST_SERIALIZATION_DYN_LINK)
112
+
113
+ if(NOT ORBSLAM3_ROOT STREQUAL "")
114
+ # ---- (a)/(c) standalone tree ---------------------------------------------
115
+ if(ORBSLAM3_BUILD_DIR STREQUAL "")
116
+ set(ORBSLAM3_BUILD_DIR "${ORBSLAM3_ROOT}/build")
117
+ endif()
118
+ if(NOT EXISTS "${ORBSLAM3_BUILD_DIR}/libORB_SLAM3.a")
119
+ message(FATAL_ERROR "libORB_SLAM3.a not found in ${ORBSLAM3_BUILD_DIR}; build ORB_SLAM3 first.")
120
+ endif()
121
+ find_package(Pangolin REQUIRED)
122
+ message(STATUS "pyorbslam3: linking ORB_SLAM3 from ${ORBSLAM3_ROOT} (build ${ORBSLAM3_BUILD_DIR})")
123
+
124
+ target_include_directories(
125
+ _core SYSTEM
126
+ PRIVATE "${ORBSLAM3_ROOT}"
127
+ "${ORBSLAM3_ROOT}/include"
128
+ "${ORBSLAM3_ROOT}/include/CameraModels"
129
+ "${ORBSLAM3_ROOT}/Thirdparty/Sophus"
130
+ ${Pangolin_INCLUDE_DIRS}
131
+ ${OpenCV_INCLUDE_DIRS})
132
+
133
+ target_link_libraries(
134
+ _core
135
+ PRIVATE
136
+ -Wl,--start-group
137
+ "${ORBSLAM3_BUILD_DIR}/libORB_SLAM3.a"
138
+ "${ORBSLAM3_BUILD_DIR}/Thirdparty/DBoW2/libDBoW2.a"
139
+ "${ORBSLAM3_BUILD_DIR}/Thirdparty/g2o/libg2o.a"
140
+ ${Pangolin_LIBRARIES}
141
+ -Wl,--end-group
142
+ Eigen3::Eigen
143
+ ${OpenCV_LIBS}
144
+ Boost::serialization
145
+ OpenSSL::Crypto)
146
+ else()
147
+ # ---- (b) legacy ORB-SLAM-Python _deps tree ------------------------------
148
+ set(ORBSLAM_SRC "${ORBSLAM_DEPS}/orb_slam3-src")
149
+ set(ORBSLAM_BUILD "${ORBSLAM_DEPS}/orb_slam3-build")
150
+ set(PANGOLIN_SRC "${ORBSLAM_DEPS}/pangolin-src")
151
+ set(PANGOLIN_BUILD "${ORBSLAM_DEPS}/pangolin-build")
152
+ message(STATUS "pyorbslam3: linking legacy ORB-SLAM-Python deps at ${ORBSLAM_DEPS}")
153
+
154
+ file(GLOB PANGOLIN_COMPONENT_INCLUDES "${PANGOLIN_SRC}/components/*/include")
155
+ file(GLOB PANGOLIN_LIBS "${PANGOLIN_BUILD}/libpango_*.a")
156
+
157
+ target_include_directories(
158
+ _core SYSTEM
159
+ PRIVATE "${ORBSLAM_SRC}"
160
+ "${ORBSLAM_SRC}/include"
161
+ "${ORBSLAM_SRC}/include/CameraModels"
162
+ "${ORBSLAM_SRC}/Thirdparty/Sophus"
163
+ ${PANGOLIN_COMPONENT_INCLUDES}
164
+ "${PANGOLIN_BUILD}/include"
165
+ ${OpenCV_INCLUDE_DIRS})
166
+
167
+ target_link_libraries(
168
+ _core
169
+ PRIVATE
170
+ -Wl,--start-group
171
+ "${ORBSLAM_BUILD}/libORB_SLAM3.a"
172
+ "${ORBSLAM_BUILD}/Thirdparty/DBoW2/libDBoW2.a"
173
+ "${ORBSLAM_BUILD}/Thirdparty/g2o/libg2o.a"
174
+ ${PANGOLIN_LIBS}
175
+ "${PANGOLIN_BUILD}/libtinyobj.a"
176
+ -Wl,--end-group
177
+ Eigen3::Eigen
178
+ ${OpenCV_LIBS}
179
+ Boost::serialization
180
+ OpenSSL::Crypto
181
+ GLEW OpenGL GLX GLU EGL SM ICE X11 Xext
182
+ wayland-client wayland-egl wayland-cursor xkbcommon rt)
183
+ endif()
184
+
185
+ if(SKBUILD)
186
+ # pip / scikit-build-core: the module goes into the wheel's package dir.
187
+ install(TARGETS _core LIBRARY DESTINATION pyorbslam3)
188
+ else()
189
+ # ./build.sh: drop the built module straight into the source package.
190
+ set_target_properties(_core PROPERTIES
191
+ LIBRARY_OUTPUT_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/pyorbslam3")
192
+ endif()
@@ -0,0 +1,79 @@
1
+ # syntax=docker/dockerfile:1
2
+ # pyorbslam3 — self-contained image: Pangolin v0.9 + ORB-SLAM3 (patched) + Python bindings.
3
+ #
4
+ # docker build -t pyorbslam3 . # ~30-60 min, needs ~6 GB RAM at JOBS=3
5
+ # docker run --rm -it -v /path/to/datasets:/data pyorbslam3 \
6
+ # python3 examples/benchmark.py --dataset tumvi --root /data/dataset-room1_512_16 --mode stereo-imu
7
+ #
8
+ # Build parallelism is capped (ARG JOBS) because a few ORB-SLAM3 translation
9
+ # units need ~2 GB each to compile.
10
+
11
+ ARG UBUNTU=22.04
12
+
13
+ # ---------------------------------------------------------------------------
14
+ FROM ubuntu:${UBUNTU} AS builder
15
+ ARG JOBS=3
16
+ ARG ORBSLAM3_COMMIT=4452a3c4ab75b1cde34e5505a36ec3f9edcdc4c4
17
+ ARG PANGOLIN_VERSION=0.9
18
+ ENV DEBIAN_FRONTEND=noninteractive
19
+
20
+ RUN apt-get update && apt-get install -y --no-install-recommends \
21
+ build-essential git ca-certificates pkg-config wget \
22
+ python3-dev python3-pip python3-numpy \
23
+ libopencv-dev libeigen3-dev libboost-serialization-dev libssl-dev \
24
+ libglew-dev libgl1-mesa-dev libegl1-mesa-dev libglu1-mesa-dev \
25
+ libwayland-dev libxkbcommon-dev wayland-protocols \
26
+ libx11-dev libxext-dev libsm-dev libice-dev \
27
+ && rm -rf /var/lib/apt/lists/* \
28
+ && pip3 install --no-cache-dir "cmake>=3.25,<4" "pybind11>=2.10" # ORB-SLAM3 needs CMake >= 3.25
29
+
30
+ # ---- Pangolin (static, PIC, viewer only) ----------------------------------
31
+ RUN wget -qO- https://github.com/stevenlovegrove/Pangolin/archive/refs/tags/v${PANGOLIN_VERSION}.tar.gz \
32
+ | tar xz -C /opt \
33
+ && cmake -S /opt/Pangolin-${PANGOLIN_VERSION} -B /opt/Pangolin-${PANGOLIN_VERSION}/build \
34
+ -DCMAKE_BUILD_TYPE=Release -DBUILD_SHARED_LIBS=OFF \
35
+ -DCMAKE_POSITION_INDEPENDENT_CODE=ON \
36
+ -DBUILD_TOOLS=OFF -DBUILD_EXAMPLES=OFF -DBUILD_TESTS=OFF \
37
+ -DBUILD_PANGOLIN_PYTHON=OFF -DBUILD_PANGOLIN_VIDEO=OFF \
38
+ && cmake --build /opt/Pangolin-${PANGOLIN_VERSION}/build -j${JOBS} \
39
+ && cmake --install /opt/Pangolin-${PANGOLIN_VERSION}/build \
40
+ && rm -rf /opt/Pangolin-${PANGOLIN_VERSION}
41
+
42
+ # ---- ORB-SLAM3 (pinned commit + patches) ----------------------------------
43
+ COPY docker/patches /tmp/patches
44
+ RUN git init -q /opt/ORB_SLAM3 && cd /opt/ORB_SLAM3 \
45
+ && git remote add origin https://github.com/UZ-SLAMLab/ORB_SLAM3.git \
46
+ && git fetch -q --depth 1 origin ${ORBSLAM3_COMMIT} \
47
+ && git checkout -q FETCH_HEAD \
48
+ && git apply --whitespace=nowarn /tmp/patches/0001-*.patch /tmp/patches/0002-*.patch \
49
+ && rm -rf .git Examples_old Examples/*/TUM_IMU \
50
+ && tar -xzf Vocabulary/ORBvoc.txt.tar.gz -C Vocabulary
51
+ RUN cmake -S /opt/ORB_SLAM3 -B /opt/ORB_SLAM3/build -DCMAKE_BUILD_TYPE=Release \
52
+ && cmake --build /opt/ORB_SLAM3/build -j${JOBS}
53
+
54
+ # ---- pyorbslam3 (PEP 517 build against the tree above) ---------------------
55
+ COPY . /src/pyorbslam3
56
+ RUN cd /src/pyorbslam3 \
57
+ && ORBSLAM3_ROOT=/opt/ORB_SLAM3 pip3 install --no-cache-dir --no-deps --target /opt/pyinstall . \
58
+ && python3 -c "import sys; sys.path.insert(0, '/opt/pyinstall'); import pyorbslam3"
59
+
60
+ # ---------------------------------------------------------------------------
61
+ FROM ubuntu:${UBUNTU}
62
+ ENV DEBIAN_FRONTEND=noninteractive
63
+ RUN apt-get update && apt-get install -y --no-install-recommends \
64
+ python3 python3-numpy python3-opencv \
65
+ libboost-serialization1.74.0 libssl3 libglew2.2 libgl1 libglx0 libopengl0 libegl1 libglu1-mesa \
66
+ libwayland-client0 libwayland-egl1 libwayland-cursor0 libxkbcommon0 \
67
+ libx11-6 libxext6 libsm6 libice6 \
68
+ && rm -rf /var/lib/apt/lists/*
69
+
70
+ COPY --from=builder /opt/pyinstall/ /usr/local/lib/python3.10/dist-packages/
71
+ COPY --from=builder /opt/ORB_SLAM3/Vocabulary/ORBvoc.txt /opt/pyorbslam3/vocabulary/ORBvoc.txt
72
+ COPY configs /opt/pyorbslam3/configs
73
+ COPY examples /opt/pyorbslam3/examples
74
+ COPY README.md /opt/pyorbslam3/README.md
75
+
76
+ WORKDIR /opt/pyorbslam3
77
+ ENV PYORBSLAM3_VOCAB=/opt/pyorbslam3/vocabulary/ORBvoc.txt
78
+ RUN python3 -c "import pyorbslam3; print('pyorbslam3 OK:', [s.name for s in pyorbslam3.Sensor.__members__.values()])"
79
+ CMD ["python3", "-c", "import pyorbslam3; print('pyorbslam3 ready; see examples/benchmark.py --help')"]