Browse by type
DynoSAM is a Stereo/RGB-D Visual Odometry pipeline for Dynamic SLAM and estiamtes camera poses, object motions/poses as well as static background and temporal dynamic object maps.
DynoSAM current provides full-batch and sliding-window optimisation procedures and is integrated with ROS2.
The offical code used for our paper: - Jesse Morris, Yiduo Wang, Mikolaj Kliniewski, Viorela Ila, DynoSAM: Open-Source Smoothing and Mapping Framework for Dynamic SLAM, Arxiv. Submitted Transactions on Robotics (T-RO) Visual SLAM Special Issue (2025).
This code now also contains the code for our new work - J.Morris, Y. Wang, V. Ila. Online Dynamic SLAM with Incremental Smoothing and Mapping, Arxiv. Submitted RA-L (2025)
We kindly ask to cite our papers if you find these works useful:
@misc{morris2025dynosam,
title={DynoSAM: Open-Source Smoothing and Mapping Framework for Dynamic SLAM},
author={Jesse Morris and Yiduo Wang and Mikolaj Kliniewski and Viorela Ila},
year={2025},
eprint={2501.11893},
archivePrefix={arXiv},
primaryClass={cs.RO},
url={https://arxiv.org/abs/2501.11893},
}
@article{morris2025online,
title={Online Dynamic SLAM with Incremental Smoothing and Mapping},
author={Morris, Jesse and Wang, Yiduo and Ila, Viorela},
journal={arXiv preprint arXiv:2509.08197},
year={2025}
}
DynoSAM was build as a culmination of several works:
Example output running on the Oxford Multimotion Dataset (OMD, swinging_4_unconstrained).

NOTE: this visualisation was generated using playback and is does not reflect the realtime output of our system.
Tested on Ubuntu 20.04
External dependancies (for visualization) not required for compilation.
- rviz_dynamic_slam_plugins (Plugin to display custom dynamic_slam_interfaces messages which are advertised by default.)
DynoSAM is currently built within the ROS2 infrastructure (if there is enough interest I will split out each component into ROS and non-ROS modules.)
We provide a development Dockerfile that will install all dependancies but expects DynoSAM to be cloned locally. The associated container creation will then mount the local DynoSAM folder into the container along with local results/dataset folders.
NOTE: there are some minor issues with the current dockerfile which will be fixed intime.
The general ROS2 build procedure holds as all relevant subfolders in DynoSAM are built as packages.
More detailed instructions are found here: Insallation instructions
# Finally compile
cd ros_ws && colcon build
# Refresh workspace
source ~/ros_ws/install/setup.bash
dynamic_slam_interfaces is a require dependacy by default. This package is used to include custom messages that represet the state of each dynamic object per frame and is used by the ROS publishers.
To disable this dependancy compile the code as
colcon build --cmake-args -DENABLE_DYNAMIC_SLAM_INTERFACES=OFF
By default ENABLE_DYNAMIC_SLAM_INTERFACES=ON in the CMakeLists.txt. This CMake option will additionally change the visualisation (and the output topics) used by DynoSAM. See the ROS Visualisation section below.
We auto generate Doxygen code docs for all classes in DynoSAM. The code docs are up-to-date with the main branch.
DynoSAM uses a combination of yaml files and GFLAGS (these are being simplified but GFLAGS allows an easier way to programatically set variables over cmd-line) to configure the system. ROS params are used sparingly and are only used to set input file paths.
All .yaml and .flag files should be placed in the same params folder, which is specified by the command line.
To specify the dataset loader, the GFLAG --data_provider_type should be set (see pipeline.flags). Eventually, this will also include the option to take data live from a sensor. For data providers that are specific to each dataset used for evaluation, a dataset path must also be set.
DynoSAM will also log all output configuration to an output-folder specified by --output_path (see pipeline.flags).
Data will only be logged if this folder exists.
The DynoSAM pipeline can be launched via launch file:
ros2 launch dynosam_ros dyno_sam_launch.py params_path:=<value> dataset_path:=<> v:=<>
The launch file will load all the GFLAG's from all .flag files found in the params folder.
For evaluation and more refined control over the input to the system we also provide an evaluation launch script and can be run as:
ros2 run dynosam_utils eval_launch.py
--dataset_path <Path to dataset>
--params_path <Absolute path to the params folder to run dynosam with>
--launch_file <Wich dynosam launch file to run with!>
--output_path <Specifies the output path, overwritting the one set by pipeline.flags>
--name <Name of the experiment to run. This will be appended to the output_path file such that the ouput file path will be output_path/name>
--run_pipeline <if present, the full visual odometry pipeline will run>
--run_analysis <if present, the evaluation script will run using the output found in the full output path>
*args...
This script automated the process of running the evaluation suite (ie. --run_analysis_) and set all rosparams/re-direct input and output paths (e.g. --output_path, name, etc...).
In addition to these arguments, this script takes all additional cmd-line arguments and parses them to the DynoSAM node, allowing any GFLAGS to be overwritten directly by specifying them in the commandline. e.g the dataset provider type can be specified as:
ros2 run dynosam_utils eval_launch.py --output_path=/path/to/results --name test --run_pipeline --data_provider_type=2
This script will also construct the corresponding output folder (e.g. ouput_path/name) and make it, if it does not exist. In the aboce example, the program will make the folder '/path/to/results/test/' and deposit all output logs in that folder.
NOTE: for all evaluations and metrics, this script was used to run the program.
All the cmdline functionality can be replicated programtically using python in order to run experiments and evaluations. See run_experiments_tro.py for examples.
Most of the research here is associated with different backend formulations.
To run the different backends set --backend_updater_enum
NOTE: this enum value is mapped to the enum RGBDFormulationType
backend_updater_enum=0) and WCPE(backend_updater_enum=1) are from TRO-2025, ICRA 2024 and previous worksbackend_updater_enum=2) and PARALLEL_HYBRID (backend_updater_enum=3) are from RA-L 2025All others are internal/experimental.
We use gtest for unit testing. This is installed automagically. When building with ROS, all tests will go into the install folder.
To run the unit tests: build the code, navigate inside the install folder and run the tests. Both dynosam and dynosam_ros packages come with unit tests.
We provide a useful script to make running tests easier. Run
ros2 run dynosam_ros run_dynosam_gtest.py
from anywhere on the system to run tests. The unit tests for a particular package (ie. dynosam and dynosam_ros) can be specified using the --package argumement. This script forwards all arguments to the test executable so that GFLAGS can still be used e.g.
run dynosam_ros run_dynosam_gtest.py --package=dynosam_ros --gtest_filter=TestConcepts*
We provide a number of data providers which process datasets into the input format specified by DynoSAM which includes input images for the pipeline and ground truth data for evaluation.
Download processed version of the KITTI tracking and OMD sequences. The other sequences were used in their raw form.
We use a modified version of the KITTI tracking dataset which includes ground truth motion data, as well dense optical-flow, depth and segmentation masks.
The required dataset loader can be specified by setting --data_provider_type=0
Raw data can be downloaded from the project page. For our 2024 T-RO paper we used a modified version of the dataset which can be downloaded from the above link.
C++ code to parse the raw dataset (although not used) is also provided and the code used to pre-process the dataset (as optical flow and segmentation masks are not provided in the raw dataset) will also be provided soon.
The required dataset loader can be specified by setting --data_provider_type=3
Access raw dataset and download the CARLA-* sequences. No pre-processing is needed on this dataset and the raw data can be parsed by DynoSAM directly.
The required dataset loader can be specified by setting --data_provider_type=2
Access raw dataset and extract in a folder. No pre-processing is needed on this dataset and the raw data can be parsed by DynoSAM directly.
The required dataset loader can be specified by setting --data_provider_type=1
An online data-provider can be specified using the ROS arg online:=True.
This node subscribes to five topics:
- dataprovider/image/camera_info (sensor_msgs.msg.CameraInfo)
- dataprovider/image/rgb (sensor_msgs.msg.Image)
- dataprovider/image/depth (sensor_msgs.msg.Image)
- dataprovider/image/mask (sensor_msgs.msg.Image)
- dataprovider/image/flow (sensor_msgs.msg.Image)
The rgb image is expected to be a valid 8bit image (1, 3 and 4 channel images are accepted). The depth must be a CV_64F image where the value of each pixel represents the metric depth. The mask must be a CV_32SC1 where the static background is of value 0 and all other objects are lablled with a tracking label $j$. The flow must be a CV_32FC2 representing a standard optical-flow image representation.
We also provide a launch file specified for online usage:
ros2 launch dynosam_ros dyno_sam_online_launch.py
NOTE: see the launch file for example topic remapping
All 3D visualisation in DynoSAM is done using RVIZ. Camera pose and point clouds are vizualised using standard ROS messages. Visualising the objects is more complex and we provide two different ways to do this which can be controlled at compile time using the cmake flag -DENABLE_DYNAMIC_SLAM_INTERFACES=ON/OFF
ON, now default) Usage of the custom dynamic_slam_interfaces::msg::ObjectOdometry (in dynamic_slam_interfaces) to publish to current state of the each object per frame. Our custom RVIZ plugin rviz_dynamic_slam_plugins can be used to visualize this message type. The object id, current pose, velocity, path etc... will be shown for each object. See this README.md for more detail.OFF) Instead of using the custom messages, standard ROS visualisation messages are used instead to display the state of each object (object id, current$ claude mcp add DynOSAM \
-- python -m otcore.mcp_server <graph>