Skip to main content
Version: 10

Whole-Body Motion on Mobile Bases

Whole-body motion is coordinated motion of a mobile base and an arm as one kinematic system: a single planned trajectory that moves the wheels and the arm joints together, on one timeline. It is what lets an arm reach past its own workspace by moving the base forward as the end effector approaches, or backing the base up while pulling a door open.

This page describes the model used by the mobile manipulation robot configuration packages, such as hangar_sim. It assumes you understand Objectives, motion planning, and ros2_control in MoveIt Pro at a high level.

Scope

This page is about short-range coordinated motion: the base is already roughly in position and moves in support of the arm's reachability. Driving the robot from one place to another is navigation's job — see Nav2 Mobile Navigation.

Looking ahead

Whole-body motion is being redesigned to make configuration simpler and to support a wider range of base types, including differential drive. This page describes the model that ships today.

The base as three virtual joints

MoveIt plans for joints. To let a planner move the base, the mobile manipulation robot configuration packages give the base three ordinary URDF joints, chained off a world root link through two empty intermediate links:

These three joints are sometimes called virtual rails. They carry no hardware and no geometry; they exist so that the base pose appears to MoveIt as joint positions. Both prismatic joints declare travel limits, and those limits describe the area the robot is expected to work in rather than a physical end stop.

The three base joints are then listed in the same SRDF planning group as the arm. A planner asked to solve for that group treats X, Y, yaw and the six arm joints as nine joints of one mechanism, and returns a single trajectory spanning all nine.

Base pose as joint states

The three base joints have no hardware, so no driver publishes joint states for them. The robot configuration package runs a small bridge node that subscribes to the base's /odom topic, converts each odometry message into linear_x_joint, linear_y_joint and rotational_yaw_joint positions, and republishes them on /joint_states. A static identity transform from odom to world places the planning root underneath the odometry frame so the two agree.

The bridge is not an odometry source and performs no estimation of its own.

How a whole-body trajectory executes

The nine-joint trajectory reaches hardware that has no X, Y or yaw actuator — it has wheels. MoveIt Pro bridges that gap with chained controllers.

The upstream joint_trajectory_controller (JTC) claims all nine joints. For the six arm joints it writes to the arm's own hardware interfaces. For the three base joints it writes instead to reference interfaces exported by the base drive controller, which converts the commanded planar velocity into the four wheel velocities. Chaining is what turns the three virtual joints into wheel motion.

hangar_sim loads the clearpath_mecanum_drive_controller/MecanumDriveController plugin from a version of that package vendored in the robot configuration workspace. Upstream, the controller exports its reference interfaces under fixed Twist-component names (linear/x/velocity, linear/y/velocity, angular/z/velocity) and commands in the base's body frame; the vendored version adds a reference_joint_names parameter, which hangar_sim sets to the virtual joint names so the JTC's command_joints entries resolve, and an optional world-to-body rotation driven by the yaw joint, read as an additional state interface.

What the model requires of the control stack

Command interfaces are shared controller-wide

A joint_trajectory_controller's command_interfaces setting applies to every joint the controller claims, not to each joint individually. The base joints are commanded in velocity, because that is what the drive controller's reference interfaces accept. The six arm joints are therefore also commanded in velocity, using per-joint proportional gains set in the robot configuration package.

This determines which controller executes whole-body motion. MoveIt Pro's Joint Trajectory Admittance Controller (JTAC) commands joint position, so arm-only trajectories use JTAC while whole-body trajectories use JTC. The capabilities available follow from that:

CapabilityArm-only motion (JTAC)Whole-body motion (JTC)
Cartesian admittance and force complianceYesNo
Trajectory time scalingYesNo
JTAC's controlled stopYesNo

Objectives choose the controller explicitly, through the execution_pipeline port on the ExecuteTrajectory Behavior: jtac is the default, so a whole-body Objective sets execution_pipeline to jtc along with the matching controller_action_name, /joint_trajectory_controller/follow_joint_trajectory.

One controller at a time

Only one controller may command a given hardware interface, so the whole-body joint_trajectory_controller and the navigation velocity controller are active one at a time. Objectives switch between them explicitly, which is why running a navigation Objective activates the navigation controller in place of the whole-body controller, and vice versa. Nav2 Mobile Navigation describes that switch.

Supported base types

This model represents a base that can translate freely in X and Y while rotating independently — a holonomic base, such as a mecanum drive. Use a holonomic base for whole-body motion.

The reason lies in the joint chain. Modelling the base as an X joint, a Y joint and a yaw joint states that those three degrees of freedom are independent, and every planner samples and interpolates them accordingly. A mecanum base meets that description: it is holonomic at the velocity level, with the wheel kinematics handled inside the drive controller.

A differential-drive, Ackermann, or other nonholonomic base does not meet it, and cannot be represented in this model. Such a base cannot translate sideways — its wheels only roll along the heading they are pointed in. That rolling constraint couples the three degrees of freedom, and three joints declared independent provide no way to express a coupling between them. A planner can return a base path that translates the robot sideways, and the hardware cannot execute it.

MoveIt's planar joint type is a separate mechanism, declared as an SRDF virtual_joint and described in Mobile Base Control Setup. It carries a motion_model property with a diff_drive setting that affects interpolation and distance in the robot model. That is a different representation from the virtual-joint chain described on this page, and it is not the representation the mobile manipulation robot configuration packages use for whole-body motion.

Using whole-body motion

The hangar_sim robot configuration package plans and executes coordinated base and arm motion through this model, and it is the mechanism behind the whole-body portion of the motion planning tutorial. Start there to see it working, and use hangar_sim as the reference when building a robot configuration package of your own. Mobile Base Control Setup covers MoveIt's planar joint, the other representation described above.