Skip to content

Software

mod (Maps of Dynamics)

By OrebroUniversity, from github.com/OrebroUniversity/mod (opens in a new tab)

  • Navigation and mapping
  • Library
  • LGPL-3.0-only

A C++ library that lets motion planners follow the flow of people using Maps of Dynamics, with OMPL objectives, informed samplers, a Hybrid A* planner, and a playground for comparing them.

Facts

GitHub stars
0read on 6 Nov 2026
Last update
19 Sept 2026Newest commit on dev
Maintenance
Activea commit in the last 90 days
Difficulty
Advanced
Hardware it needs, as the project states it
A C++17 compiler, CMake 3.16+, OMPL 2.0, Boost, Eigen 3 and nlohmann_json; GoogleTest, GLFW 3.3 with OpenGL and Python 3 are optional. No ROS is required.

Checked on GitHub on 6 Nov 2026.

Licenses

Code
LGPL-3.0-only (opens in a new tab)

Read by Robotheca from LICENSE (opens in a new tab) (LGPL-3.0-only) at commit 57706c1 (opens in a new tab), on 22 Oct 2026.

Commercial use
Yes

Copyleft: Modified source must be published.

Overview

What it does: Robotheca's summary

  • Reads Maps of Dynamics (CLiFF, GMMT and intensity maps) that describe how people move through a place.
  • Provides OMPL optimization objectives that make paths going with the crowd cheap and paths against it expensive.
  • Offers informed samplers that use the same cost to steer sampling towards low-cost solutions.
  • Includes a Hybrid A* planner that optimizes the same cost as the sampling planners.
  • Ships a playground with a headless batch runner, JSON logs, an ImGui app with map overlays, and Python plots.
  • Bundles ready-to-use environments: a shopping centre, a simulated warehouse and a simulated office.

Written by Robotheca from the project's README (opens in a new tab) at commit 57706c1, not by its creator.

The README

The creator's own README, copied as written: README.md by OrebroUniversity, at commit 57706c1, under LGPL-3.0-only (opens in a new tab). The original on GitHub (opens in a new tab).

Read the README here

mod — Maps of Dynamics for motion planning

mod lets a motion planner follow the flow of people instead of only avoiding walls. It reads a Map of Dynamics (MoD) of a place, such as a shopping centre where thousands of pedestrian tracks were recorded, and turns it into a cost that an OMPL (opens in a new tab) planner can optimize: paths that go with the crowd are cheap, paths that cut across it or push upstream are expensive. It also ships informed samplers that use that same cost to steer the planner's sampling towards low-cost solutions, a Hybrid A* planner that optimizes the same cost, and a playground for running and comparing all of this on real maps, with logs and plots.

If you just want to see it work, go to Quick start. If you want the theory, read docs/concepts.md (opens in a new tab) and the papers under Background reading.

Hybrid A* on the ATC map in the playground

What is in the box
PartWhat it doesWhere
MoD map readersCLiFF-map (Gaussian flow field), GMMT-map (Gaussian-mixture trajectory clusters), intensity map (how busy each cell is)include/mod/cliffmap.hpp, gmmtmap.hpp
ObjectivesOMPL optimization objectives: Down-The-CLiFF, upstream criterion (CLiFF or GMMT), intensity, plus plain path lengthinclude/ompl/mod/objectives/
SamplersInformed samplers that bias the planner's sampling with its own cost function: Dijkstra path, intensity map, ellipsoidal heuristic, and their hybridinclude/ompl/mod/samplers/
Hybrid A*Deterministic grid-and-primitive planner over the same maps, footprint and cost as the sampling plannersinclude/mod/planners/hybrid_astar.hpp
PlaygroundHeadless batch runner with JSON logs, an ImGui app with map overlays, and Python plotssrc/playground/, analysis/
MapsReady-to-use environments: the ATC shopping centre, a simulated warehouse and a simulated officemaps/

Everything is a plain C++17 library with a CMake target (mod::mod). No ROS is required, although a package.xml is included for ament_cmake workspaces.

Quick start
1. Build

You need a C++17 compiler, CMake 3.16+, OMPL 2.0, Boost, Eigen 3, nlohmann_json, and for the optional parts GoogleTest (tests), GLFW 3.3 + OpenGL (GUI) and Python 3 with numpy, pandas and matplotlib (plots). Distro package lists are in docs/getting-started.md (opens in a new tab).

git clone --recurse-submodules https://github.com/OrebroUniversity/mod.git
cd mod
cmake -S . -B build
cmake --build build -j
ctest --test-dir build        # optional: 51 tests, about 2 s

The library lands in build/lib/libmod.so, the tools in build/bin/ (run_batch, check_interpolation, mod_playground_gui) and the tests in build/bin/tests/.

2. Plan a path in the GUI
./build/bin/mod_playground_gui --map maps/atc/atc.yaml

Hold S and left-click to place the start, hold G and left-click for the goal (drag while holding to set the heading), pick an objective and its map files with the v pickers, press Solve. Turn on the overlays to see the CLiFF flow arrows, the intensity heat, the planner tree or Hybrid A*'s expanded nodes under the path. Every solve is logged to a run folder. Full tour: docs/gui.md (opens in a new tab).

3. Run an experiment headlessly
./build/bin/run_batch maps/atc/batch_atc_smoke.json --threads 4
python3 analysis/runs.py runs/atc_smoke              # table of every run
python3 analysis/plot_success.py runs/atc_smoke -o success.png
python3 analysis/plot_cost.py runs/atc_smoke -o cost.png

A batch JSON is the product scenarios × planners × samplers × objectives × repeats; each run writes config.json and solution.json into its own folder. Format and fields: docs/batch-and-logs.md (opens in a new tab).

4. Use it from your own code
#include <ompl/mod/objectives/UpstreamCriterionOptimizationObjective.h>

MoD::OptObjParameters obj;                 // defaults are the published settings
obj.type = MoD::ObjectiveType::cliff;
obj.cliff_map_file = "maps/atc/atc_cliff.xml";
obj.intensity_map_file = "maps/atc/atc_intensity1m.xml";
obj.w_c = 0.1;
MoD::SamplerParameters smp;
smp.type = MoD::SamplerType::dijkstra;

auto objective = std::make_shared<ompl::MoD::UpstreamCriterionOptimizationObjective>(si, obj, smp);
objective->setCostStep(0.05);              // metres between cost points along an edge
pdef->setOptimizationObjective(objective); // RRT*, AIT*, ... now optimize the MoD cost

Link mod::mod (via find_package(mod) after cmake --install, or add_subdirectory). The objective allocates the informed sampler the planner asks for. More in docs/library.md (opens in a new tab).

How it works in one paragraph

An MoD stores, per location, how people move there: a CLiFF-map keeps a mixture of Gaussians over (heading, speed); a GMMT-map keeps clusters of typical trajectories; an intensity map keeps how often the cell is visited. The objectives integrate a cost along every planner edge at a fixed step: the steering distance, a small heading term, and the MoD term evaluated at each point for the direction the robot moves (not the way it faces, so reversing is costed like driving). The samplers do not look for where people walk: they use the planner's own cost function to concentrate samples where a low-cost solution is likely (cells of a Dijkstra path under the MoD cost, cells weighted by the intensity map, or the ellipse defined by the best cost so far), which is what makes RRT* and AIT* converge fast. Hybrid A* expands short arcs on a grid, costs them with the identical objective and uses an MoD-aware Dijkstra cost-to-go as its heuristic, so its single deterministic answer is directly comparable with the sampling planners. Details, formulas and defaults: docs/concepts.md (opens in a new tab) and docs/parameters.md (opens in a new tab).

Documentation
PageFor
docs/getting-started.md (opens in a new tab)Installing dependencies, building, installing, troubleshooting
docs/concepts.md (opens in a new tab)Maps, objectives, samplers, planners, footprint and cost definition
docs/gui.md (opens in a new tab)The playground app: controls, panels, overlays, command line
docs/batch-and-logs.md (opens in a new tab)Batch JSON, run folders, config.json / solution.json / samples.json, plots
docs/parameters.md (opens in a new tab)Every parameter, its default and its meaning
docs/library.md (opens in a new tab)C++ API: maps, objectives, samplers, Hybrid A*, thread safety
maps/README.md (opens in a new tab)The bundled environments and their scenario files
analysis/README.md (opens in a new tab)The Python scripts
docs/development.md (opens in a new tab)Code layout, tests, style, plans, how to add an objective / sampler / planner
CHANGELOG.rst (opens in a new tab)What changed per version, including the ATC comparison results
Background readingThe papers behind the objectives, samplers and maps
Results at a glance

On the six ATC scenarios with the four MoD objectives (30 s budget, 10 repeats), Hybrid A* solved every run in under a second with a cost equal to or lower than RRT*'s and AIT*'s best after 30 s. The full table is in CHANGELOG.rst (opens in a new tab), and the batch that produced it is maps/atc/batch_atc_hybrid.json.

Background reading

The objectives and samplers in mod are the ones proposed and evaluated in these papers (Papers I, III and IV of the author's thesis); the maps come from the referenced representations.

  • Down-The-CLiFF objective and intensity-map sampling. C. S. Swaminathan, T. P. Kucner, M. Magnusson, L. Palmieri, A. J. Lilienthal, Down the CLiFF: Flow-Aware Trajectory Planning under Motion Pattern Uncertainty, IEEE/RSJ IROS 2018.
  • Benchmarking the objectives (upstream criterion on CLiFF and GMMT maps, DTC, intensity) with simulated pedestrians. C. S. Swaminathan, T. P. Kucner, M. Magnusson, L. Palmieri, S. Molina, A. Mannucci, F. Pecora, A. J. Lilienthal, Benchmarking the Utility of Maps of Dynamics for Human-Aware Motion Planning, Frontiers in Robotics and AI 9, 916153, 2022.
  • The samplers (Dijkstra, intensity, hybrid) and the ATC experiments this playground reproduces. C. S. Swaminathan, T. P. Kucner, A. J. Lilienthal, M. Magnusson, Sampling Functions for Global Motion Planning Using Maps of Dynamics for Mobile Robots, Robotics and Autonomous Systems 194, 105117, 2025, doi:10.1016/j.robot.2025.105117 (opens in a new tab).
  • CLiFF-map. T. P. Kucner, M. Magnusson, E. Schaffernicht, V. Hernandez Bennetts, A. J. Lilienthal, Enabling Flow Awareness for Mobile Robots in Partially Observable Environments, IEEE RA-L 2(2), 2017.
  • GMMT-map. M. Bennewitz, W. Burgard, G. Cielniak, S. Thrun, Learning Motion Patterns of People for Compliant Robot Motion, IJRR 24(1), 2005.
  • The Dijkstra-graph sampling idea the Dijkstra sampler extends. L. Palmieri, T. P. Kucner, M. Magnusson, A. J. Lilienthal, K. O. Arras, Kinodynamic Motion Planning on Gaussian Mixture Fields, IEEE ICRA 2017.
  • Maps of Dynamics in general. T. P. Kucner, A. J. Lilienthal, M. Magnusson, L. Palmieri, C. S. Swaminathan, Probabilistic Mapping of Spatial Motion Patterns for Mobile Robots, Springer, 2020; and T. P. Kucner et al., Survey of Maps of Dynamics for Mobile Robots, IJRR 42(11), 2023.
  • ATC dataset (the bundled real map). D. Brščić, T. Kanda, T. Ikeda, T. Miyashita, Person Tracking in Large Public Spaces Using 3-D Range Sensors, IEEE THMS 3(6), 2013.
For developers

The short version; the long one is docs/development.md (opens in a new tab).

  • Layout. include/mod (maps, parameters, Hybrid A*, grid Dijkstra), include/ompl/mod (objectives, samplers), src/ (implementations), src/playground/{core,tools,gui}, test/ (GoogleTest), analysis/ (Python), maps/ (data), AI-PLANS/ (the implementation plans with their settled decisions).
  • Build options. MOD_BUILD_TESTS and MOD_BUILD_PLAYGROUND (both ON); CMAKE_BUILD_TYPE defaults to Release. -DMOD_BUILD_PLAYGROUND=OFF needs neither GLFW nor the ImGui submodule.
  • Conventions. C++17, .clang-format (Google, 120 columns), -Wall -Wextra clean. Console logging is one macro, MOD_LOG, that prints [mod] ... to stderr. New code lives in namespace MoD (a global mod namespace collides with Boost.Geometry). Objectives and samplers hold no mutable per-call state; maps are shared as shared_ptr<const>, so one planner per thread is safe.
  • Tests. ctest --test-dir build. Test data is maps/ (through MOD_TEST_DATA_DIR); synthetic maps are built in-memory in the tests themselves.
  • Plans and changelog. Every feature was planned in AI-PLANS/*.md with a settled-decisions table; the decisions there are binding. Record user-visible changes in CHANGELOG.rst; bump the version in CMakeLists.txt and package.xml together.
  • Attribution. Borrowed code carries its licence header in-file and a row in 3rd_party_licenses.md; design-only borrowings (bench-mr, Nav2) are noted in the files that follow them.
Acknowledgements and licence

The experiment pipeline follows bench-mr (opens in a new tab) (MIT, Eric Heiden and contributors) and the MoD additions in ksatyaki/bench-mr (opens in a new tab), which ran the published experiments; no bench-mr source is included, but the maps, start/goal pairs, objective wiring, solution timing, batch expansion and figure design are derived from it and marked as such. The Hybrid A* planner follows the design description of Nav2's SmacPlannerHybrid (Apache-2.0, Steve Macenski et al.); no Nav2 code is included. The ATC occupancy map comes from the ATC pedestrian dataset (Brščić, Kanda, Ikeda, Miyashita, IEEE THMS 2013). The GUI uses Dear ImGui (MIT).

mod is LGPL-3.0 (LICENSE). Third-party code and data are listed with their licences in 3rd_party_licenses.md (opens in a new tab). Maintained by Chittaranjan Swaminathan, Örebro University.

Files and versions

Facts read at commit 57706c1

Robotheca never hosts the code: each link goes to the creator's own page.

Use it

How to install it, in the creator's words: The project's README (opens in a new tab)

Robotheca doesn't review code. Read it before running it.

Robotheca lists software as a reference: nothing is hosted or run here, and every fact links to where it was read.