dim_slam: cuVSLAM+fusion - #3632
Conversation
Greptile SummaryThis change adds the Rust-backed dimSLAM module, a RealSense stereo demo, odometry-path visualization, and supporting registration. The infrared-only demo can fail to initialize visual odometry on a RealSense profile without a discoverable depth stream because camera-frame transforms are withheld even though the infrared streams are enabled. Confidence Score: 4/5The infrared-only RealSense demo is not reliable across supported camera profiles until its transform origin can be selected from an enabled stream. The camera transform builder unconditionally selects a depth profile as its origin. When that profile is unavailable, it returns without publishing the infrared transforms required by dimSLAM. Files Needing Attention: dimos/hardware/sensors/camera/realsense/camera.py
What T-Rex did
|
Codecov Report❌ Patch coverage is
@@ Coverage Diff @@
## jeff/feat/cuvslam #3632 +/- ##
=====================================================
+ Coverage 77.55% 77.78% +0.22%
=====================================================
Files 1293 1293
Lines 123802 123829 +27
Branches 10850 10851 +1
=====================================================
+ Hits 96017 96322 +305
+ Misses 24662 24366 -296
- Partials 3123 3141 +18
Flags with carried forward coverage won't be shown. Click here to find out more.
... and 13 files with indirect coverage changes 🚀 New features to boost your workflow:
|
b0c4f8e to
8ff0d69
Compare
The Rust filter shipped in the same derivation as cuvslam_odometry but had no Python side, so nothing in dimos could run it. Every source publishes onto one sources port and is told apart by header.frame_id, which makes adding a source a config change rather than a port change. imu_init_samples carries the weight here: on a 517 s Alfred drive, leaving the raw gyro bias in costs 19.8 m of final error against 1.6 m with it removed, which is worse than fusing no IMU at all.
The Rust filter gained a use_imu switch so it can be seeded level from the first source message and coast between measurements rather than propagating on IMU. `#[native_config]` supplies no defaults and rejects unknown keys, so the Python config has to carry the field for the module to start at all. Off is worth having on Alfred: measured against point-lio over the 517 s drive, wheel and cuVSLAM fused without the IMU lands at 3.53 m, while the same pair with the IMU added lands at 71.32 m.
The native module publishes a range-gated depth_cloud and takes the gate from two
config fields. `#[native_config]` supplies no defaults and rejects unknown keys, and
the runtime rejects a module whose declared ports do not match the binary's, so
without both the field pair and the port the process died on startup every run:
failed to deserialize config: missing field `depth_cloud_min_range`
topics do not match module ports: missing ["depth_cloud"]
That killed CuvslamOdometry silently in alfred-mls-nav — the stack came up, the
remaining modules ran, and the fusion filter simply never saw a visual source. With
both in place cuvslam publishes odometry at 30 Hz on Alfred.
dimSLAM merged its two binaries into one dim_slam executable that feeds the tracker's pose into the fusion filter in-process, so the two wrapper modules collapse into one DimSlam module with the flat union of both configs. The internal visual odometry stream no longer crosses the wire; external sources still arrive on the sources input, told apart by header.frame_id.
k x k block median decimation of the published depth cloud; <= 1 off.
… instead of a pinned rev (cherry picked from commit 8cc5734)
…efaults The noise figures are a property of the part, so the module has no sane default; use_imu now requires all four above zero.
The filter needed four datasheet noise figures at construction or it raised, so every blueprint without an IMU had to opt out by hand.
The depth scale note claimed rgbd only, which the cloud path does not gate on.
Pairs with dimSLAM's max_position_m, which holds the last pose instead of publishing a diverged one. Also trims four comments back to the part the code does not already say.
The dimSLAM repo now exports only the library (cuVSLAM tracking + fusion filter); the LCM module binary moves here. The crate converts LCM messages to and from the library's plain types and builds through a flake whose sdk-<variant> packages come from cu_vslam_rs, so the python build_command selects the variant the host actually has.
CI clippy-checks every Cargo.lock directory on runners with no SDK; cu_vslam_rs 0.1.2 compiles as a non-linking stub when CUVSLAM_SDK_DIR is absent, the re-pinned dim_slam library skips its rpath then, and so does this build script. Nix builds still set the SDK and are unchanged.
clippy 1.98 (CI stable) denies chunks_exact with a constant size, and as_chunks yields [f64; 6] directly so the try_into fallibility disappears.
8ff0d69 to
12af282
Compare
| use lcm_msgs::std_msgs::Header; | ||
|
|
||
| #[derive(Debug, Clone, Default, PartialEq)] | ||
| pub struct ImuInfo { |
There was a problem hiding this comment.
Should eventually put this in some kind of shared message thing. For now I'm trying to not modify stuff outside of dim_slam
| speed_gate_max_angular: f64, | ||
| /// cuVSLAM's own inertial mode, separate from the filter's use_imu. | ||
| cuvslam_enable_imu: bool, | ||
| depth_units_per_meter: f64, |
There was a problem hiding this comment.
Config needs to be redone to support multi-camera
| } | ||
|
|
||
| async fn report(&mut self) { | ||
| if let Some(vo) = &self.vo { |
There was a problem hiding this comment.
I prefer that only fusion reports, will change
Odom fusion with cuVSLAM
next PR lets us run it on alfred