MoveIt Motion Planning: How OMPL, CHOMP, and PILZ Planners Actually Behave on ROS2

July 16, 2026

Author: Gaurav Gupta

Read time: 4 mins

MoveIt2 is the de facto framework for ROS2 motion planning on robotic arms. Most teams reach it through the move_group node and an RViz panel, and never look closely at the planner that turns a goal pose into a joint trajectory. That planner is where the reliability, speed, and path-quality tradeoffs live. This article stays on the planning algorithms MoveIt exposes and the pipeline around them, on ROS2 Humble; perception, grasping, and full task orchestration are out of scope except where they exist to cover a planner's weakness. It continues a theme we have written about before, in cuRobo vs MoveIt2 and ROS2 MoveIt Servo.

Three branches of planners, three different cores

MoveIt exposes several planner families that solve the problem in fundamentally different ways. Knowing which branch you are on explains most of the behavior you will see.

Sampling-based (OMPL). The default. Planners in the Open Motion Planning Library randomly sample collision-free joint configurations and connect them into a tree until start and goal link. They are probabilistically complete but say nothing about repeatability. RRTConnect grows two Rapidly-exploring Random Trees and returns when they meet: fast, but jagged and non-deterministic run to run. RRT* is asymptotically optimal, rewiring to shorten the path for as long as it is allowed to run, which means it uses its entire time budget.

Trajectory optimization. CHOMP deforms an initial trajectory by covariant gradient descent over a distance field; STOMP does the same with gradient-free sampling. Their cost landscape is non-convex, so a poor initial guess lands in an in-collision local minimum and the planner fails. STOMP's MoveIt2 plugin is not available on ROS2 Humble.

Analytical (PILZ). The PILZ Industrial Motion Planner deterministically generates industrial PTP, LIN, and CIRC motions from kinematic limits. It does not plan around clutter, so we describe it but leave it out of the benchmark: in these obstacle scenes it would refuse or drive into an obstacle, and its behavior is known by construction.

Why your MoveIt2 arm moves badly when the plan looks fine

The planner is one stage in a pipeline that reshapes its output. move_group owns the planning scene (robot model plus perception), runs pre-planning adapters to fix the start state, calls the planner plugin, then runs post-planning adapters that time-parameterize the path with TOTG or Ruckig for jerk-limited smoothing. The key model: OMPL returns a path, not a trajectory. Velocity, acceleration, and jerk limits are added afterward, so much of "the arm moves badly" is an adapter problem, not a planner problem.

Configuration decides the rest. The most consequential OMPL parameter is allowed_planning_time on the request: a ceiling RRTConnect rarely hits, but effectively the runtime for RRT*. The CHOMP planner is tuned separately through ridge_factor, learning_rate, and clearance parameters that determine whether it converges or stalls in a local minimum.

Moveit2 Planning Pipeline

What breaks first: benchmarks on ROS2 Humble

We benchmarked RRTConnect, RRTStar, and CHOMP on ROS2 Humble across a table use case (a pick query), a box scene (easy and hard pairs), and a cage scene with tight obstacles, over three runs each with a 10s budget, measuring planning time and joint-space path length (Jlen, in radians).

Motion Plans using RRTConnect
Motion Plans using RRT*

Motion Planner Benchmark

Small sample (3 runs per scene), 10s planning budget. The table use case reports the pick query only. Numbers are averaged over successful runs; "n/a" means no successful plan was produced.

Three patterns matter:

  • RRT* always spends its full budget. Its planning time sits near 10s in every scene because it keeps optimizing until told to stop. It often returns the shortest Jlen, but you pay the full budget every time.
  • CHOMP failed in every scene. Seeded with a naive guess, it fell into in-collision local minima, which is why it is normally paired with a sampling-based pre-seed rather than run standalone.
  • RRTConnect is the most reliable but wildly variable. It solved box-hard in 0.10s and dropped to 33% on box-easy: a start state near a collision boundary can make an easy query fail while a harder one succeeds.

The real takeaway is variance, and hardware widens it. Raw OMPL paths are jerky without Ruckig smoothing, non-repeatability erodes trust in human-centric cells, and end-effector constraints rely on rejection sampling that balloons planning time.

Making MoveIt planners production-grade

Motion planning using MoveIt gives you broad planner coverage but weak guarantees. OMPL is complete but non-deterministic and slow under constraints, trajectory optimizers are smooth but fragile without a seed, and PILZ is deterministic but not collision-aware. None is production-grade out of the box. The engineering work is the layer around the planner: start-state hygiene, planner choice per query, jerk-limited time parameterization, constraint-aware seeding, and task-level sequencing with MoveIt Task Constructor. Where CPU planning cannot keep up, GPU approaches like cuRobo are the next step.

That gap between a tutorial planner and a manipulation stack that runs reliably in a real cell is the work we do at Black Coffee Robotics. If you are hitting the reliability, constraint, or path-quality walls here, reach out to us. We build and deploy robotics in the real world.

Media & source credits

  • MoveIt2, OMPL, CHOMP, STOMP, PILZ, and Ruckig documentation and papers are linked inline and belong to their respective authors.
  • Benchmark figures and scene visuals are from BCR's internal RRTConnect / RRTStar / CHOMP runs on ROS2 Humble across the box, table, and cage scenes.

Want to reduce costs and time to market for your autonomous robots?