MoveIt 2 does not plan because your robot description is wrong, not because the planner is bad. A missing collision geometry, a mismatched planning group or a controller name that does not exist will stop it before OMPL ever runs.
This guide covers what MoveIt 2 actually does, how to generate a configuration with the Setup Assistant, how planning and execution are separated, and the errors that account for most failed first attempts.
What MoveIt 2 is responsible for
MoveIt 2 is a motion planning framework, not a robot driver. It takes a robot description, builds a planning scene, finds a collision-free path and sends joint trajectories to a controller. Each of those steps can fail on its own.
- Robot model: URDF for geometry, SRDF for planning groups and collision rules.
- Planning scene: the robot plus the world, including attached objects.
- Kinematics: inverse kinematics solvers per planning group.
- Planner: OMPL by default, with Pilz and CHOMP as alternatives.
- Execution: a controller from
ros2_controlthat accepts a joint trajectory. - Visualisation: RViz with the Motion Planning display.
If any one of the six is misconfigured, the symptom appears at a different place. That is why “MoveIt does not work” is almost never a useful bug report.
Generate a configuration first
The Setup Assistant reads your URDF and writes a moveit_config package containing the SRDF, kinematics, joint limits, controllers and launch files. Do not hand-write this on a first project; generate it, then edit.
ros2 launch moveit_setup_assistant setup_assistant.launch.py- Load the URDF or xacro output, not the xacro source.
- Generate a self-collision matrix; it takes a minute and prevents false collisions.
- Define one planning group per arm, and a separate group for the gripper.
- Pick a kinematic solver and give it a timeout.
- Set the controller names to match your
ros2_controlconfiguration exactly. - Save the package into your workspace and build it.
The generated launch file starts move_group, RViz and, depending on the template, a fake controller or your real one. Start with the fake controller until planning works, then switch to hardware. Debugging planning and hardware at the same time doubles the work.
The SRDF decides more than people expect
The SRDF is where you tell MoveIt which joints form a group, which pairs can never collide, and which named poses exist. A planning group with the wrong joints produces strange IK results or refuses to move a joint you expected.
| SRDF element | What it controls | Typical mistake |
|---|---|---|
| Planning group | Which joints move together | Gripper joints left inside the arm group |
| Virtual joint | How the robot attaches to the world | Missing fixed base, so the robot floats |
| Disabled collisions | Pairs that are allowed to overlap | Adjacent links flagged, blocking every plan |
| Group state | Named poses such as home | Pose outside joint limits |
| End effector | Tool used for grasping | Tool not attached, so grasp poses are wrong |
Planning is not execution
move_group produces a trajectory. A controller executes it. In RViz you can plan and preview without any hardware, which is useful, but it also hides execution problems until later. When the ghost robot moves and the real one does not, the plan was fine and the controller side is broken.
ros2 control list_controllers
ros2 control list_hardware_interfaces
ros2 topic echo /joint_states --onceThose three commands answer most execution questions. No active controller, no command interface, or no joint states means MoveIt has nothing to talk to. The controller name in the moveit_config must match the name in the ros2_control YAML, character for character.
Choosing a planner
OMPL’s default RRTConnect is a good general planner for free-space motion. It is fast and reliable but produces paths that look inelegant and do not follow straight lines. For process motion, use the Pilz industrial motion planner, which offers PTP, LIN and CIRC moves that behave like industrial robot instructions.
- RRTConnect: default for reaching a pose in a cluttered cell.
- RRTstar: slower, shorter paths, useful when path length matters.
- PRM: good for repeated queries in a static environment.
- Pilz PTP/LIN/CIRC: deterministic process motion.
- CHOMP and STOMP: optimisation-based, useful for smooth trajectories.
Planning time is a parameter, not a fixed cost. A two-second allowance on a simple pick is wasteful; a 100 ms allowance on a tight cell produces failures that look random. Set it per request.
Collision checking that tells the truth
MoveIt checks the collision geometry in the URDF, not the visual meshes. If your collision meshes are simplified boxes, the plan is only as accurate as those boxes. If they are full visual meshes, planning becomes slow and may report collisions inside the gripper.
- Use simple primitives or convex hulls for collision geometry.
- Disable collisions between adjacent links that always touch.
- Add the fixture and the machine to the planning scene, not just the robot.
- Attach grasped objects so the planner accounts for them.
- Allow collision with the object you are about to grasp, then attach it.
Errors you will meet in the first week
| Symptom | Likely cause |
|---|---|
| No kinematic solver loaded | Plugin missing or wrong group name in kinematics.yaml |
| Every plan fails instantly | Start state in collision, often the home pose |
| Plan succeeds, robot does not move | Controller inactive or name mismatch |
| Robot moves in RViz only | Fake controller still selected |
| Planning takes many seconds | Mesh collision geometry or a large scene |
| IK fails near a reachable pose | Joint limits or a solver timeout that is too short |
| Robot drifts after execution | Joint state source not the real hardware |
A debugging order that works
- Confirm the URDF loads and the TF tree is complete.
- Open RViz, check the robot model matches the real robot.
- Move joints with the sliders before planning anything.
- Plan to a nearby pose with no obstacles.
- Add the fixture and plan again.
- Switch from the fake controller to hardware and execute a short trajectory.
- Only then tune planners and velocities.
This order separates model, kinematics, planning, scene and execution. Each step gives a clear yes or no, which is far faster than changing five parameters and hoping.
Related: URDF for ROS 2, ros2_control tutorial, TF2 tutorial, robot arm kinematics, Gazebo simulation.
What is MoveIt 2 used for?
Motion planning, collision checking, inverse kinematics and trajectory execution for robot arms in ROS 2. It plans a path and hands it to a ros2_control controller.
Do I need MoveIt 2 for a mobile robot?
No. MoveIt 2 is for manipulators. Mobile robots use Nav2 for path planning; a mobile manipulator uses both.
Why does MoveIt 2 fail to plan?
Usually a start state in collision, missing collision geometry, a wrong planning group, or joint limits that make the goal unreachable. Check the start state first.
What is the difference between URDF and SRDF?
The URDF describes links and joints. The SRDF adds planning groups, disabled collision pairs, named poses and end effectors that MoveIt needs.
Can MoveIt 2 run without hardware?
Yes, with a fake controller and simulated joint states. Plan in RViz first, then switch to the real controller.
Execution reaches the motors through ros2_control, covered in the hardware interface tutorial.
A working URDF starts with sane geometry, and the robot arm design guide covers joint limits and cable routing.
It helps to solve a two-link arm by hand first; the worked example shows what the solver is doing.
MoveIt 2 expects a working desktop install, and the Windows WSL2 route is the shortest path for students without a spare Ubuntu machine.
Sources and further reading
- MoveIt 2 documentation — tutorials, Setup Assistant and planner configuration.
- ROS 2 documentation — ros2_control and TF reference.
- OMPL — motion planning algorithms used by MoveIt.
- MoveIt 2 source — issue tracker and release notes.


