FixTheRobot Explore Robotics / Systems Engineering / Engineering Guides / Module 16

Engineering Guides · Module 16

Configuring MoveIt 2

Most MoveIt problems are mismatches between the URDF, the planning group, the joint limits and the controllers. Check them against each other.

  • Intermediate
  • Module 16: Manipulation & Robotic Arm Integration
  • Written for ROS 2 Jazzy where ROS 2 is used
  • Sources checked 2026-11-06

Assumptions: Numbers in the examples are illustrative and the code is executed by the site’s tests. Facts taken from a cited source are marked; other statements are general engineering knowledge and must be confirmed on the datasheet of the part you use.

1. Engineering problem

MoveIt plans in the robot model defined by the URDF and SRDF and executes through controllers. If the planning group, joint limits and controller joints disagree, planning fails or executes wrongly.

2. When is this needed?

  • Setting up an arm with MoveIt 2.
  • When planning succeeds and execution fails.
  • After changing the robot description.

3. Selection and design decisions

The MoveIt documentation (read 2026-11-06) describes the MoveIt Setup Assistant (for generating the configuration from a URDF), motion planning through a plugin interface with planners configured for the move_group node (OMPL by default; the Pilz industrial motion planner and CHOMP are also available) and planning request adapters that pre- and post-process requests (for example fixing a start state slightly outside joint limits, and adding time parameterisation). Collisions are checked by default, including self-collisions and attached objects. MoveIt Servo (read 2026-11-06) provides real-time jogging with singularity and collision checking that scale velocities down near singularities or collisions.

Overview
ItemCheck
Planning groupJoints of the chain from the base to the tip, in the SRDF
Joint limitsPosition, velocity and acceleration limits for every planned joint
ControllersThe controller joints match the planning group and the ros2_control hardware
CollisionLink pairs that never collide are disabled in the SRDF; the rest are checked
PlannerPipeline and adapters for your needs
Planning sceneTable, walls and attached objects are included

4. Advantages and disadvantages

  • Sampling planners (OMPL) handle general problems and give variable paths; industrial planners (Pilz) give predictable linear and circular motions.
  • More collision checking is safer and slower.
  • Servo suits teleoperation and visual servoing; planning suits point-to-point moves.

5. Requirements and constraints

  • Descriptions agree: URDF, SRDF, limits, controllers.
  • Collision geometry is a conservative simple shape.
  • Execution is tested at low speed before full speed.

6. Architecture

URDF + SRDF + limits + controllers ─▶ move_group (planners, adapters, scene) ─▶ trajectory ─▶ controller ─▶ arm

7. Implementation

  1. Run the Setup Assistant on the checked URDF.
  2. Check the planning group, limits and controllers against each other (below).
  3. Add the table and other fixed objects to the planning scene.
  4. Plan and execute at low speed and compare the planned and executed trajectories.
  5. Tune planners and limits for the application.
urdf_joints = {"j1": (-3.14, 3.14), "j2": (-1.9, 1.9), "j3": (-2.7, 2.7), "j4": (-3.14, 3.14), "j5": (-2.0, 2.0), "j6": (-3.14, 3.14)}
srdf_group = ["j1", "j2", "j3", "j4", "j5"]
limits = {"j1": {"max_velocity": 2.0, "max_acceleration": 3.0}, "j2": {"max_velocity": 2.0}, "j3": {"max_velocity": 2.0, "max_acceleration": 3.0},
          "j4": {"max_velocity": 3.0, "max_acceleration": 5.0}, "j5": {"max_velocity": 3.0, "max_acceleration": 5.0}, "j6": {}}
controller_joints = ["j1", "j2", "j3", "j4", "j5", "j6"]
out = []
for j in urdf_joints:
    if j not in srdf_group:
        out.append(f"{j} is in the URDF and the controller but not in the planning group (fine if it belongs to another group, such as a gripper)")
for j in srdf_group:
    for k in ("max_velocity", "max_acceleration"):
        if k not in limits.get(j, {}):
            out.append(f"{j}: {k} missing in the joint limits (trajectory time parameterisation uses velocity and acceleration limits: check what your pipeline requires)")
if set(srdf_group) - set(controller_joints):
    out.append("a planning-group joint is not controlled")
print("\n".join(out) or "no findings")

Printed (checked by the site’s tests):

j6 is in the URDF and the controller but not in the planning group (fine if it belongs to another group, such as a gripper)
j2: max_acceleration missing in the joint limits (trajectory time parameterisation uses velocity and acceleration limits: check what your pipeline requires)

Reading it: the example description has six joints; the planning group has five (the sixth, which could be a wrist roll or a gripper joint, belongs elsewhere; the checker only notes it); and two joints lack an acceleration limit. The configuration is an invented example.

8. Real examples

  • 6-axis arm: one group for the arm joints and a second group for the gripper.

9. Failure scenarios

  • A joint missing from the planning group, so the arm cannot reach poses that need it.
  • Limits wider than the hardware’s, so execution faults.
  • No table in the scene, so planned paths hit it.

10. Troubleshooting

  1. Compare the planned and executed joint trajectories.
  2. Check controller state and joint names.
  3. Visualise collisions in RViz.

11. Validation

  • The checker prints the lines shown (executed by the site tests).
  • Plans execute at low and full speed without controller faults.

12. Engineering checklist

13. Further references

  • MoveIt motion planning concepts: moveit.picknik.ai, read 2026-11-06 (planner plugins, OMPL as the default, Pilz and CHOMP also available, planning request adapters).
  • MoveIt Servo tutorial: moveit.picknik.ai, read 2026-11-06 (singularity and collision checking scale velocities down near limits).

Related on FixTheRobot