Skip to main content

SRMP is a motion planning software for robotic manipulation, leveraging state-of-the-art search-based algorithms. It ensures consistent and predictable motions, backed by rigorous theoretical guarantees. Additionally, SRMP can efficiently plan for up to dozens of manipulators while guaranteeing collision-free execution—both between robots and with the environment—while maintaining motion consistency and predictability.

Why SRMP?

Existing motion planning frameworks often struggle with the demands of high-stakes applications, where predictability and repeatability are critical. SRMP addresses these challenges by leveraging search-based planning methods, ensuring motions that are both efficient and reliable. Whether you're working on robotic manipulation, industrial automation, or large-scale multi-robot coordination, SRMP provides a powerful solution tailored to your needs.

Key Features

  • Multi-Robot Motion Planning: First-of-its-kind support for planning coordinated motions in multi-manipulator systems.
  • Reliable and Consistent Trajectories: Generates predictable and repeatable motions, making it ideal for high-precision and safety-critical applications.
  • Seamless Integration: Compatible with major simulators, including MuJoCo, Sapien, Genesis, PyBullet and Isaac.
  • Multi-Lingual: Available in both Python and C++ for easy integration into research and industrial workflows.
  • MoveIt! Plugin: Enables deployment on real-world robotic systems with minimal setup.

Getting Started

To get started, check our documentation.

Build and Develop within the Package

The default editable install builds the VAMP SIMD validity-checking backend alongside the coal backend. VAMP is vendored as a git submodule at vamp/ (pinned to the commit this integration expects), exactly like search/ and third_party/pybind11, so the default build needs no install step, no download, and no vamp_DIR — it compiles the in-tree VAMP as a CMake source subproject and links the stock vamp::vamp target:

git submodule update --init --recursive
pip install -e .

VAMP requires CMake 3.16+, a C++17 compiler, and Eigen 3.4+. On x86-64 the result requires AVX2; ARM builds use NEON.

A source build targets the host CPU (-march=native). The PyPI wheels are built for a fixed baseline instead: x86-64-v3 (AVX2/FMA/BMI2, Intel Haswell 2013+ and AMD Excavator/Zen+) on Linux, and Apple M1+ on macOS. import srmp checks for those features on Linux x86-64 and raises an ImportError naming what is missing rather than crashing later with an illegal instruction. On an older CPU, build from source with the coal-only option below, or set SRMP_SKIP_CPU_CHECK=1 to bypass the check. To pin a different baseline for your own wheel, pass --config-settings=cmake.define.IMS_MANIP_VAMP_ARCH_FLAGS=-march=<target>.

Coal-only build

To build without VAMP (for example on an architecture VAMP's SIMD backend does not support, or a checkout where the vamp/ submodule was not initialized), turn the backend off explicitly:

python -m pip install -e . \
  --config-settings=cmake.define.IMS_MANIP_WITH_VAMP=OFF

This uses coal mesh collision checking only; get_available_validity_backends() then reports ['coal'].

VAMP-enabled build details

Restart all running Python and Viser processes after rebuilding, then verify the loaded extension:

python -c "import srmp; p=srmp.PlannerInterface(); print(p.get_available_validity_backends())"
# ['coal', 'vamp']

VAMP resolution order at configure time, first match wins:

  1. An explicitly installed package (find_package(vamp CONFIG)), so pointing at an install with -Dvamp_DIR=<prefix>/share/cmake/vamp still behaves as before.
  2. The in-tree submodule at vamp/ (built as a subproject) — the default.
  3. A download of the pinned fork into ext/vamp when -DIMS_MANIP_FETCH_VAMP=ON and the submodule is absent (fallback for checkouts without submodules).

If none resolve, the configure fails with instructions; the quickest fix is git submodule update --init --recursive vamp.

SRMP uses stock VAMP headers and the stock vamp::vamp target. The vamp-planner Python package is not a substitute for the C++ source or CMake target used here.

Include .[agent] instead of . if the Gemini-backed CLI/Viser agent should be installed at the same time.

A VAMP-enabled extension still defaults to coal, so the same installation supports controlled A/B runs:

from srmp import PlannerInterface

planner = PlannerInterface()
planner.add_robot("panda")
print(planner.get_available_validity_backends())  # ["coal", "vamp"]

print(planner.get_vamp_supported_robots())        # ["fetch", "panda", "ur5"]
print(planner.is_robot_vamp_supported("panda"))   # True

context = {
    "planner_id": "wAstar",
    "heuristic": "bfs",
    "weight": "10",
    "validity_backend": "auto",  # or "coal" / "vamp" explicitly
}
planner.make_planner(["panda"], context)
# "auto" picks VAMP when this build and robot support it, coal otherwise;
# an explicit "vamp" raises instead of falling back.
print(planner.get_active_validity_backend())      # "vamp"

Planners

Single-agent planner_id values: Astar, wAstar, ARAstar, MHAstar, wPASE (parallel), MGS, vamp_rrtc; multi-agent (more than one articulation): ECBS, xECBS. All context values are strings.

vamp_rrtc is VAMP's RRT-Connect run on the VAMP backend's SIMD environment (Halton sampling, deterministic): joint goals only, validity_backend vamp or auto, typically well under a millisecond on uncluttered scenes. Keys: rrtc_range (2.0 rad), rrtc_max_iterations (100000), rrtc_max_samples (100000), rrtc_simplify (true: VAMP's shortcut/B-spline pass). The simplified path goes through the usual shortcutting and time parameterization; stats report rrtc_iterations, rrtc_raw_waypoints, rrtc_waypoints, rrtc_solve_time, rrtc_simplify_time.

MGS (multi-graph search) grows a start graph and, for joint goals, a goal graph, and adds further graphs rooted at IK solutions of the BFS heuristic's workspace attractors when the search stalls, bridging graphs with straight joint-space edges:

context = {
    "planner_id": "MGS",
    "g_num": "10",                  # maximum number of graphs (start, goal, roots)
    "weight": "100",                # suboptimality bound of the anchor (start) graph search
    "heuristic": "joint_steps",     # root-to-root heuristic (joint distance in discretization steps)
    "anchor_heuristic": "bfs",      # goal-distance heuristic for the start graph; "joint_steps" (aimed at the
                                    # goal root for pose goals) is 10x faster through narrow passages, slower on easy scenes
    "graph_growth": "on_stall",     # or "upfront": all g_num - 2 roots before searching
    "stall_window": "50",           # expansions without progress before a root is added
    "root_selection": "frontier_nearest",  # or "sequential"
    "nonblocking_roots": "false",   # "true": never wait for root IK; inject roots as they become ready
    "goal_roots": "1",              # pose goals: goal graphs rooted at IK solutions of the goal pose
    "bridge_nn": "kd_tree",         # bridge partner lookup: k-d tree per graph, or "heuristic" (linear scan)
    "anchor_switch_on_stall": "true",   # at the first stall switch the start graph's anchor to
    "anchor_fallback_heuristic": "joint_steps",  # this heuristic (BFS in the open, joint-space in depressions)
    "root_clearance": "0.05",       # roots retreat from obstacles until the EE has this clearance (m)
    "short_prims_near_start": "false",  # "true": use the short primitives within short_dist of the start too
    "anchor_search": "true",        # continue after the first connection to bound the cost
    "expansion_threads": "12",      # parallel edge checks per expansion (coal backend)
    "snap_ik_seeds": "1",           # IK seeds per snap attempt on pose goals (>1 runs them on the worker pool)
    "ik_dt": "1.0",                 # CLIK step scale (full step); "ik_max_iter": "50", "ik_eps": "1e-5"
    "snap_ik_backoff": "0",         # opt-in: skip 1, 2, 4.. snap IKs after a failure (see design notes)
    "snap_cached_goals": "3",       # goal configurations kept as snap targets
    "vamp_packed_edges": "true",    # VAMP: validate all primitive edges of an expansion in shared SIMD blocks
    "root_ik_threads": "6",         # background root IK threads
    "anchor_orientation_weight": "0",  # cost/rad of EE orientation error in the anchor heuristic
    "time_limit": "10",
}

Mobile manipulators and primitive-file units

A mobile base modelled as ordinary joints of the URDF (x, y prismatic and theta revolute, as in data/ridgeback_ur10e) is part of the move group of its end effector, and the planners treat the joints by kind: the articulation reports get_move_group_joint_types(), prismatic coordinates are never wrapped by 2*pi, and the lattice uses resolution degrees for revolute joints and resolution_prismatic metres (default 0.05) for prismatic ones. A primitive file may declare its units and cost model at the top level:

units: steps    # degrees (default) | radians | meters | steps -- steps: multiples of the joint's discretization
cost: time      # file (default): the listed transition costs | time: duration at the joint velocity limits

With units: steps one file serves any mix of prismatic and revolute joints; with cost: time base, torso and arm motions -- and MGS bridge and snap edges -- are priced in seconds, so the search compares them on one scale.

A composite file assembles the move group from per-group primitive files, each in its own units and magnitudes, padded into the full state (config/ridgeback_ur10e_mprim.yaml):

cost: time
groups:
  - name: base
    joints: [ x, y, theta ]          # move-group joint names (or `dims: [0, 1, 2]`)
    file: omni_base_mprim.yaml       # 0.4 m / 10 deg long steps, 0.1 m / 2 deg short steps, diagonals
  - name: arm
    file: manip_6dof_mprim.yaml      # no joints/dims: the remaining coordinates, in order

Group files are looked up next to the composite. The composite's cost: applies to every group. A mobile manipulator's end effector roams far beyond the default 2 m occupancy grid, so construct the PlannerInterface with a GridConfig that covers the base's workspace (the BFS heuristic reports the goal position and the grid bounds otherwise).

On a mobile manipulator the planners' bfs heuristic is base-aware: besides the end-effector wavefront it runs a 2D wavefront over the floor (obstacles up to base_height, inflated by base_footprint_radius) from the docking region within arm_reach of the goal, and takes the larger of the two, so a knee-high wall the end effector passes over still sends the base around. Under cost: time the cells are priced in seconds (ee_speed, default 1 m/s; base_speed, default the slower base velocity limit) and joint_steps heuristics become joint_time, the straight-move duration at the velocity limits:

context = {
    "planner_id": "wAstar", "heuristic": "bfs", "weight": "50",
    "mprim_path": "config/ridgeback_ur10e_mprim.yaml",
    "resolution": "1",                # degrees, revolute joints
    "resolution_prismatic": "0.05",   # metres, prismatic joints (base x/y, torso)
    "base_footprint_radius": "0.5", "base_height": "0.5", "arm_reach": "1.0",
}

Roots are cached across plans with the same start, goal pose and scene, and get_planning_stats() reports MGS counters (bridge_attempts, graph_merges, num_roots, num_graphs, timings) under bonus_stats. Design notes and measurements: docs/plans/2026-09-03-mgs-followups.md, docs/plans/2026-09-03-mgs-incremental-graphs-design.md.

The occupancy grid (the BFS heuristics' world) defaults to 2 x 2 x 2 m at 2 cm around the origin. Adding a mobile manipulator grows it to the base's x/y limits plus 1.5 m at 5 cm automatically; set_grid(GridConfig) rebuilds it at any time (obstacles are voxelized again, the planner is rebuilt on the next plan) and get_grid_config() reports it. The Viser panel's Occupancy grid folder shows the bounds as an outline in the scene and edits them; the Planner context field takes extra key=value pairs for the next Plan.

A mobile manipulator needs no context at all: with no mprim_path the factories compose omni_base_mprim.yaml with the arm's file (config/mobile_6dof_mprim.yaml, mobile_7dof_mprim.yaml), and bfs is the base-aware heuristic. In the Viser Plan panel tick Goal as EE pose to send the gizmo pose itself and let the planner place the base (off, the panel plans to the IK solution shown as the ghost); to tune, fill viz.plan_context_defaults (e.g. {"weight": "50", "arm_reach": "1.2"}), which every Plan click merges into its make_planner call, the panel's own planner and backend choices winning.

In the Viser Plan panel, select one robot and leave Collision backend on Auto (VAMP when supported) (or pick VAMP (SIMD spheres) explicitly -- the option is offered only when the selected robot has a Robot_Module), position the end-effector goal, and click Plan to goal. The status line reports backend: vamp when VAMP is actually attached to the planner. If the VAMP option is absent, the running process loaded a coal-only extension; repeat the backend verification above and restart Viser. VAMP selection is intentionally limited to single-agent planners until Phase 2 multi-robot verification is complete. A coal-only build advertises only coal and gives a reinstall message if Python requests VAMP directly.

Agentic mode

The default CLI backend is Gemini and uses Google's native google-genai SDK. For a new editable installation, install the agent extra and configure a Google AI Studio API key:

pip install -e ".[agent]"
export GEMINI_API_KEY=...
python -m srmp.agent.cli

The default build already includes VAMP, so no extra CMake flags are needed — just add the [agent] extra:

git submodule update --init --recursive
pip install -e ".[agent]"

You can create a free key at https://aistudio.google.com/app/apikey. To add Gemini to an existing installation without rebuilding SRMP, install only the SDK with Python-compatible pins:

python -m pip install \
  'google-genai==1.47.0; python_version < "3.10"' \
  'google-genai==2.17.0; python_version >= "3.10"'

Other backends have separate dependencies; run python -m srmp.agent.cli --help or select a backend in the GUI for their setup instructions.

Launch the Viser agent interface with:

python -m srmp.agent.gui

Metadata

Release files for srmp 0.1.5

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Built distributions (wheels)

Table of built distributions (wheels) for srmp 0.1.5
File
srmp-0.1.5-cp314-cp314-manylinux_2_35_x86_64.whl CPython 3.14 CPython 3.14 Linux glibc 2.35+ x86-64 Details
srmp-0.1.5-cp314-cp314-macosx_11_0_arm64.whl CPython 3.14 CPython 3.14 macOS 11.0+ ARM64 Details
srmp-0.1.5-cp313-cp313-manylinux_2_35_x86_64.whl CPython 3.13 CPython 3.13 Linux glibc 2.35+ x86-64 Details
srmp-0.1.5-cp313-cp313-macosx_11_0_arm64.whl CPython 3.13 CPython 3.13 macOS 11.0+ ARM64 Details
srmp-0.1.5-cp312-cp312-manylinux_2_35_x86_64.whl CPython 3.12 CPython 3.12 Linux glibc 2.35+ x86-64 Details
srmp-0.1.5-cp312-cp312-macosx_11_0_arm64.whl CPython 3.12 CPython 3.12 macOS 11.0+ ARM64 Details
srmp-0.1.5-cp311-cp311-manylinux_2_35_x86_64.whl CPython 3.11 CPython 3.11 Linux glibc 2.35+ x86-64 Details
srmp-0.1.5-cp311-cp311-macosx_11_0_arm64.whl CPython 3.11 CPython 3.11 macOS 11.0+ ARM64 Details
srmp-0.1.5-cp310-cp310-manylinux_2_35_x86_64.whl CPython 3.10 CPython 3.10 Linux glibc 2.35+ x86-64 Details
srmp-0.1.5-cp310-cp310-macosx_11_0_arm64.whl CPython 3.10 CPython 3.10 macOS 11.0+ ARM64 Details
srmp-0.1.5-cp39-cp39-manylinux_2_35_x86_64.whl CPython 3.9 CPython 3.9 Linux glibc 2.35+ x86-64 Details
srmp-0.1.5-cp39-cp39-macosx_11_0_arm64.whl CPython 3.9 CPython 3.9 macOS 11.0+ ARM64 Details

Total release size: 143.0 MB

Release files / srmp-0.1.5-cp314-cp314-manylinux_2_35_x86_64.whl

Download URL srmp-0.1.5-cp314-cp314-manylinux_2_35_x86_64.whl
Size 12.3 MB
Tags CPython 3.14 Linux glibc 2.35+ x86-64
SHA-256 checksum
How to use checksums
9a025ca6630bb9ac93972568b54a85f891c80d80f8fe341327e7e48290751203
BLAKE2b-256 checksum
How to use checksums
77719a853afae0d4b138a6517d9f836bdd790575eb370bf40a4d90a1e08ff7b2
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.12.14

Release files / srmp-0.1.5-cp314-cp314-macosx_11_0_arm64.whl

Download URL srmp-0.1.5-cp314-cp314-macosx_11_0_arm64.whl
Size 11.6 MB
Tags CPython 3.14 macOS 11.0+ ARM64
SHA-256 checksum
How to use checksums
8d38b8bcaf5429b18d7e014f05e77b0ebb9f888c259792683b0aa6fbab736cdb
BLAKE2b-256 checksum
How to use checksums
057f9c5c34641cbc12c3c88621a77ac8cf688f8c8da4960e385bd64c28b60e18
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.12.14

Release files / srmp-0.1.5-cp313-cp313-manylinux_2_35_x86_64.whl

Download URL srmp-0.1.5-cp313-cp313-manylinux_2_35_x86_64.whl
Size 12.3 MB
Tags CPython 3.13 Linux glibc 2.35+ x86-64
SHA-256 checksum
How to use checksums
12f9767ec2db33b7be5145ef6093b23a9bef3ac352ef46f78a6c0c85594a8894
BLAKE2b-256 checksum
How to use checksums
9c424e8ba6be10dd24d29146f8e376790f7f130e08de011cf42274088c574b63
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.12.14

Release files / srmp-0.1.5-cp313-cp313-macosx_11_0_arm64.whl

Download URL srmp-0.1.5-cp313-cp313-macosx_11_0_arm64.whl
Size 11.6 MB
Tags CPython 3.13 macOS 11.0+ ARM64
SHA-256 checksum
How to use checksums
0666616d26381f200281feaa9498c187928848a4e8554ef5eb6e237ce1bbc90d
BLAKE2b-256 checksum
How to use checksums
5f6d9be5f58963a76cdbac2eff79e5cfdf4ed1de6904c059a3bca1613e29d41c
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.12.14

Release files / srmp-0.1.5-cp312-cp312-manylinux_2_35_x86_64.whl

Download URL srmp-0.1.5-cp312-cp312-manylinux_2_35_x86_64.whl
Size 12.3 MB
Tags CPython 3.12 Linux glibc 2.35+ x86-64
SHA-256 checksum
How to use checksums
e102a844584a5d5b844097f28f0f1666d31228ae5c66b07e945e261462c4bd08
BLAKE2b-256 checksum
How to use checksums
580a11d9e5ed4815dfe984851c1c5343c735c524b37d51015d0f73a7a5dfd14d
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.12.14

Release files / srmp-0.1.5-cp312-cp312-macosx_11_0_arm64.whl

Download URL srmp-0.1.5-cp312-cp312-macosx_11_0_arm64.whl
Size 11.6 MB
Tags CPython 3.12 macOS 11.0+ ARM64
SHA-256 checksum
How to use checksums
fff19be1e19808e982f788c931335126b8df28c8668c577b1b8f595460db234b
BLAKE2b-256 checksum
How to use checksums
51b61d62939df9d7b3605d5b37061a0e5b1c754cbaf1c6890a23cf029559cc15
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.12.14

Release files / srmp-0.1.5-cp311-cp311-manylinux_2_35_x86_64.whl

Download URL srmp-0.1.5-cp311-cp311-manylinux_2_35_x86_64.whl
Size 12.3 MB
Tags CPython 3.11 Linux glibc 2.35+ x86-64
SHA-256 checksum
How to use checksums
1d99bbece98d153df4c17ea4ab5e5984f8480a2f32c0d294966aab054bb71158
BLAKE2b-256 checksum
How to use checksums
57c3f40edcfe1d19c81df5dac21810e33be2ce33b5f94cb04ded9c47f3471478
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.12.14

Release files / srmp-0.1.5-cp311-cp311-macosx_11_0_arm64.whl

Download URL srmp-0.1.5-cp311-cp311-macosx_11_0_arm64.whl
Size 11.6 MB
Tags CPython 3.11 macOS 11.0+ ARM64
SHA-256 checksum
How to use checksums
370bc31d0ac440a791160eb1a631b7ec58b3d102684e3a8f1c1873f31957a17e
BLAKE2b-256 checksum
How to use checksums
49e40e05cff6f4f5b2de894164fdda5191d97b3750c5f48c667e4fa67138436a
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.12.14

Release files / srmp-0.1.5-cp310-cp310-manylinux_2_35_x86_64.whl

Download URL srmp-0.1.5-cp310-cp310-manylinux_2_35_x86_64.whl
Size 12.3 MB
Tags CPython 3.10 Linux glibc 2.35+ x86-64
SHA-256 checksum
How to use checksums
7cd6e0f9c55dc58ab52006bb65eac716416f067119ad85a1984f4590a31b84ae
BLAKE2b-256 checksum
How to use checksums
bfc43dd8b0008e00ff658403148e77ce391463aa2ff63cb4c7b2859dfecac757
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.12.14

Release files / srmp-0.1.5-cp310-cp310-macosx_11_0_arm64.whl

Download URL srmp-0.1.5-cp310-cp310-macosx_11_0_arm64.whl
Size 11.6 MB
Tags CPython 3.10 macOS 11.0+ ARM64
SHA-256 checksum
How to use checksums
282d12503772ef21ccfda15ff1aa559d682748d341ab07d2f8cd505b7f014f30
BLAKE2b-256 checksum
How to use checksums
3d2fd10f4a76e9770056787f507270b4c0df196748061e8da44a340dca55a0bd
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.12.14

Release files / srmp-0.1.5-cp39-cp39-manylinux_2_35_x86_64.whl

Download URL srmp-0.1.5-cp39-cp39-manylinux_2_35_x86_64.whl
Size 12.3 MB
Tags CPython 3.9 Linux glibc 2.35+ x86-64
SHA-256 checksum
How to use checksums
a21a1db916e5ba9f9cccc3240c3ef182973ef900f81e0d1ae9731c5e60412ebf
BLAKE2b-256 checksum
How to use checksums
f00ab761a06276934b0852b974eef9a927b3e32ce01adecc09afd1e0783d6278
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.12.14

Release files / srmp-0.1.5-cp39-cp39-macosx_11_0_arm64.whl

Download URL srmp-0.1.5-cp39-cp39-macosx_11_0_arm64.whl
Size 11.0 MB
Tags CPython 3.9 macOS 11.0+ ARM64
SHA-256 checksum
How to use checksums
9c6e06ffc547041090dd50509533c0f7796944b37ed9f6f0419654fe747975a4
BLAKE2b-256 checksum
How to use checksums
dde6119e61d40fec7f15ce0d8226f61daaa7b221d5d5d110facbf1e70a07ea63
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.12.14
Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page