Usage
Installation
SRMP supports Ubuntu>=22.04 and Python 3.9, 3.10, 3.11, 3.12, and 3.13.
To use SRMP, first install it using pip:
(.venv) $ pip install srmp
Note
If you encounter installation issues, see the Troubleshooting Installation section below.
Then, import it in your script and follow the instructions on the docs:
import srmp
import numpy as np
Basic Single Robot Planning
Note
You can download pre-configured robot models (URDF/SRDF files) from our Data Downloads page.
Create a planner interface:
planner = srmp.PlannerInterface()
Add a robot model to the world:
Note
The srdf_path argument is optional. If you don’t have an SRDF file, omit the argument or pass an empty string (srdf_path=””).
# With SRDF (recommended when semantic info is available)
planner.add_articulation(name="panda",
end_effector="panda_hand",
urdf_path="/path/to/panda.urdf",
srdf_path="/path/to/panda.srdf")
# Or without SRDF (URDF only)
planner.add_articulation(name="panda",
end_effector="panda_hand",
urdf_path="/path/to/panda.urdf")
Add objects to the environment:
# Add a box obstacle
obstacle_pose = srmp.Pose()
obstacle_pose.p = np.array([0.5, 0.2, 0.4])
obstacle_size = np.array([0.1, 0.1, 0.4])
planner.add_box("box", obstacle_size, obstacle_pose)
# Add a mesh
mesh_pose = srmp.Pose()
mesh_pose.p = np.array([0.3, 0.3, 0.5])
planner.add_mesh("mesh_object", mesh_path="/path/to/mesh.stl",
scale=np.array([1.0, 1.0, 1.0]), pose=mesh_pose)
# Add a point cloud
# Generate sample point cloud data (Nx3 array)
point_cloud = np.random.rand(1000, 3) * 0.5 + np.array([0.2, 0.2, 0.3])
planner.add_point_cloud("point_cloud_obstacle", point_cloud, resolution=0.02)
Define the start configuration:
start_state = np.array([50, 47, -10, -35, -22, 93, 39])
start_state = np.radians(start_state)
Define goal constraints:
# Goal as joint angles
goal_state = np.array([21, 29, -30, -104, -162, 52, -118])
goal_state = np.radians(goal_state)
goal_joints = srmp.GoalConstraint(srmp.GoalType.JOINTS, [goal_state])
# Goal as end-effector pose
goal_pose = srmp.Pose()
goal_pose.p = np.array([0.642, -0.068, 0.505])
goal_pose.q = np.array([0.0, 0.0, 0.0, 1.0]) # normalized quaternion
goal_ee = srmp.GoalConstraint(srmp.GoalType.POSE, [goal_pose])
Configure the planner:
# Available planners and configurations
planner.print_available_planners()
# wAstar planner with BFS heuristic
planner.make_planner(["panda"], {"planner_id": "wAstar",
"heuristic": "bfs",
"weight": "10."})
# ARA* planner with parameters
planner.make_planner(["panda"], {"planner_id": "ARAstar",
"heuristic": "bfs",
"weight": "10.",
"weight_delta": "1.",
"final_weight": "1."})
# PA*SE
planner.make_planner(["panda"], {"planner_id": "wPASE",
"heuristic": "bfs", "weight": "50.", "time_limit": "5.",
"num_threads": "8"})
Compute a trajectory:
trajectory = planner.plan(start_state, goal_joints)
# or
trajectory = planner.plan(start_state, goal_ee)
# Access trajectory data
print(f"Trajectory length: {len(trajectory.positions)}")
for i, position in enumerate(trajectory.positions):
print(f"Step {i}: {position}")
Multi-Robot Planning
Note
Multi-robot URDF/SRDF configurations are available for download on the Data Downloads page.
Add multiple robots to the world:
planner = srmp.PlannerInterface()
# Add first robot
planner.add_articulation(
name="panda0",
end_effector="panda0_hand",
urdf_path="/path/to/panda0.urdf",
srdf_path="/path/to/panda0.srdf"
)
# Add second robot
planner.add_articulation(
name="panda1",
end_effector="panda1_hand",
urdf_path="/path/to/panda1.urdf",
srdf_path="/path/to/panda1.srdf"
)
Set base poses for robots:
# Set base pose for panda0
pose0 = srmp.Pose()
pose0.p = np.array([-0.5, 0.5, 0])
pose0.q = np.array([1, 0, 0, 0])
planner.set_base_pose("panda0", pose0)
# Set base pose for panda1
pose1 = srmp.Pose()
pose1.p = np.array([0.5, 0.3, 0])
pose1.q = np.array([0, 0, 0, 1])
planner.set_base_pose("panda1", pose1)
Configure multi-robot planner:
articulation_names = ["panda0", "panda1"]
planner_context = {
"planner_id": "xECBS",
"weight_low_level_heuristic": "55.0",
"high_level_focal_suboptimality": "1.8",
"low_level_focal_suboptimality": "1.0",
"heuristic_panda0": "joint_euclidean_remove_time",
"heuristic_panda1": "joint_euclidean_remove_time",
}
# Add robot-specific parameters similar to test_mramp.py
for name in articulation_names:
planner_context[f"heuristic_{name}"] = "joint_euclidean_remove_time"
planner_context[f"mprim_path_{name}"] = "/path/to/config/manip_7dof_timed_mprim.yaml"
planner.make_planner(articulation_names=articulation_names, planner_context=planner_context)
Define start and goal states for multiple robots:
start_states = {
"panda0": np.radians([-40, 0, 0, -85, 0, 57, 0]),
"panda1": np.radians([-40, 0, 0, -85, 0, 57, 0])
}
goal_states = {
"panda0": np.radians([40, 0, 0, -70, 0, 50, 0]),
"panda1": np.radians([40, 0, 0, -95, 0, 67, 0])
}
# Create goal constraints
goal_constraints = {}
for art_name in goal_states.keys():
goal_constraints[art_name] = srmp.GoalConstraint(srmp.GoalType.JOINTS, [goal_states[art_name]])
Plan for multiple robots:
trajectories = planner.plan_multi(start_states, goal_constraints)
# Access individual robot trajectories
for robot_name, trajectory in trajectories.items():
print(f"Robot {robot_name}: {len(trajectory.positions)} waypoints")
Simulator Integration
SRMP supports integration with multiple simulators. The planner can automatically read collision objects from the simulation environment:
Genesis Integration:
import genesis as gs
# Create Genesis scene
scene = gs.Scene()
# ... add objects to scene ...
# Read objects from Genesis
planner.read_sim(scene, "genesis")
PyBullet Integration:
import pybullet as p
# Create PyBullet simulation
physics_client = p.connect(p.GUI)
# ... add objects to simulation ...
# Read objects from PyBullet (exclude articulated bodies)
planner.read_sim(physics_client, "pybullet", articulations=["panda"])
SAPIEN Integration:
import sapien
# Create SAPIEN scene
scene = sapien.Scene()
# ... add objects to scene ...
# Read objects from SAPIEN
planner.read_sim(scene, "sapien")
Available Planners
SRMP provides several search-based planning algorithms:
wAstar: Weighted A* - Fast single-goal planning
ARAstar: Anytime Repairing A* - Iteratively improves solution quality
MHAstar: Multi-heuristic A* - Uses multiple heuristics for better performance
wPASE: Weighted PASE - Parallel search for improved performance
Astar: Standard A* - Optimal but potentially slower
E-CBS: Enhanced Conflict-Based Search - For multi-robot coordination
xECBS: Experience Accelerated Conflict-Based Search - For multi-robot coordination
You can view available planners programmatically:
planner.print_available_planners()
Environment Management
Remove objects from the environment:
planner.remove_object("box")
Supported geometric primitives:
Boxes: add_box(name, size, pose)
Spheres: add_sphere(name, radius, pose)
Cylinders: add_cylinder(name, radius, height, pose)
Meshes: add_mesh(name, mesh_path, scale, pose)
Point Clouds: add_point_cloud(name, vertices, resolution)
See the API for detailed method signatures and additional functionality.
Troubleshooting Installation
Conda Environment Issues
If you’re using conda and encounter C++ library compatibility issues:
$ conda install -c conda-forge libstdcxx-ng
Missing NumPy
If you get import errors related to NumPy:
$ pip install numpy