Skip to content

Repository files navigation

asm_macvo

AirStack module (macvo, type ros_package, target robot) — MAC-VO learned stereo visual odometry (ICRA 2025 Best Conference Paper / Best Paper on Robot Perception) wrapped for AirStack: the macvo_ros2 node consumes rectified stereo and publishes odometry, a covariance-aware sparse point cloud, and a learned disparity image that the local planner can use for obstacle avoidance in place of classical stereo.

MAC-VO's heavy dependencies — TensorRT, torch, and ~250 MB of model weights — live in this repo's Dockerfile.module (Docker dependency tier 2), keeping AirStack's base robot image slim for everyone who doesn't fly MAC-VO.

/{robot}/sensors/front_stereo/{left,right}/image_rect + right/camera_info
  → macvo_node (MAC-VO network, TensorRT/torch)
  → /{robot}/perception/macvo/{odometry, point_cloud, disparity}
      └─ disparity → local planner (disparity_expansion → DROAN), wired by
         the consuming stack (trunk stacks/full_macvo)

What's inside

Component Path Role
ROS 2 wrapper macvo_ros2/ (ament_python colcon package) macvo_node: stereo-pair sync, MAC-VO inference, odometry/point-cloud/disparity publishers
MAC-VO upstream macvo_ros2/macvo_ros2/macvo/git submoduleMAC-VO/MAC-VO @ 8683b532 The actual network + pipeline code
Module launch file macvo_ros2/launch/macvo.launch.xml The module's interface: every topic endpoint a launch arg with canonical defaults, zero remaps
Dep layer (tier 2) Dockerfile.module TensorRT apt block, torch/torchvision/onnx/tensorrt pips, the 14 MACVO pips, /model_weights
Test stack test_stack/ CI target + living install documentation — trunk's full_macvo wiring with the module's launch include

Submodule note: clone with --recurse-submodules (or run git submodule update --init after). airstack module sync imports with vcs import --recursive, which handles it automatically. The submodule is ~116 MB.

Install

cd ~/AirStack
airstack module add git@github.com:castacks/asm_macvo.git --version <tag-or-sha>
airstack module sync                  # overlay: symlinks macvo_ros2 into robot/ros_ws/src/modules/
airstack module lock --build          # composes the robot image + MAC-VO dep layer (tier 2)

Then bring up the test stack — see test_stack/README.md.

The dependency-tier story (why tier 2, and the tier-3 plan)

module.yaml keeps tier 1 empty on purpose (deps: {apt: [], pip: []}) so the layer story is unambiguous: everything image-level lives in Dockerfile.module (tier 2), one logical RUN per concern, built by airstack module lock --build with BASE_IMAGE = the previous link in the per-host layer chain. Tier 1 lists could not express what MAC-VO needs anyway: the NVIDIA cuda-keyring setup before the TensorRT apt install, the weights bake, and the huggingface_hub/matplotlib-uninstall fix are all imperative steps.

Tier 3 (planned): MAC-VO's multi-GB CUDA/torch layer is exactly the case prebuilt overlays exist for, so the intended end state is a prebuilt overlay — ghcr.io/castacks/asm_macvo-overlay:<airstack_version> built from this same Dockerfile.module (fragment = source of truth, overlay = cache) — that developers pull instead of build. overlay_image stays null until the org settles the registry questions (ghcr.io vs the internal airlab-docker.andrew.cmu.edu registry, which CI job pushes/cosigns overlay images, and how module CI gets push credentials). Tracked in module.yaml.

What trunk provides: the base robot image pins numpy~=1.26.4 in Dockerfile.robot's unconditional pip list. numpy is shared surface for many trunk packages, so the pin is trunk's to own; this module requires numpy<2 and assumes the base image provides it.

Model weights

Two files from the MAC-VO release page, pinned by sha256 in module.yaml assets: (hashes computed from fresh downloads of the exact trunk URLs):

File Size Purpose
MACVO_FrontendCov.pth 74 MB Frontend (matching + covariance) weights
MACVO_posenet.pkl 181 MB Pose network

Dockerfile.module bakes them at /model_weights/ — the path the macvo_ros2 configs expect — so a composed image is self-contained. The assets: list additionally lets airstack sync cache them host-side. No Git LFS anywhere.

Wiring

The module's interface is macvo_ros2/launch/macvo.launch.xml (ros2 launch macvo_ros2 macvo.launch.xml --show-args): stereo/camera-info inputs default to the canonical /$ROBOT_NAME/sensors/front_stereo/... topics, outputs default to relative names that land on /$ROBOT_NAME/perception/macvo/{odometry,point_cloud,disparity} when the stack includes the file under its perception namespace. There are no remaps in the module (single-locus rule): macvo_node takes every topic name as a parameter, including the camera_info subscription.

The canonical consumer is trunk's stacks/full_macvo reference stack, which includes this module's launch file under its perception namespace and feeds /$ROBOT_NAME/perception/macvo/disparity into the local layer (local_disparity_in_topic); this repo's test_stack/ uses the same include.

Image-size note

AirStack's base robot image carries none of MAC-VO's payload — the torch + CUDA wheel stack (~6–8 GB installed), TensorRT apt + python bindings (~1–2 GB), and model weights (250+ MB) enter an image only when a user composes them in via airstack module lock --build (or, later, the tier-3 overlay pull). Everyone else gets the slim base image.

Tests / CI

.github/workflows/ci.yml calls trunk's reusable module-system-tests.yml with marks: "build_docker or build_packages or liveliness" on Isaac Sim. The reusable workflow builds the module's Docker layer chain (airstack module lock --build) before running tests, so Dockerfile.module is exercised, not just schema-validated.

License / maintainer

The module wrapper (this repo: macvo_ros2, Dockerfile.module, test_stack/) is licensed under the BSD 3-Clause Clear License (SPDX: BSD-3-Clause-Clear) — see LICENSE. The MAC-VO git submodule keeps its own upstream license: MIT, Copyright (c) 2025 Carnegie Mellon University (verified at submodule pin 8683b532).

Maintainer: Andrew Jong — ajong@andrew.cmu.edu.

About

AirStack module: MAC-VO learned stereo visual odometry — ROS 2 wrapper + MAC-VO submodule, TensorRT deps as a tier-2 Docker layer (asm_ module per RFC #379)

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages