Skip to main content
Version: 10

Migrate User Workspace From 9.x to 10.0

MoveIt Pro 10.0 completes the move to direct controller execution for MoveIt Task Constructor (MTC) solutions that began in 9.0. The legacy MTC execution path is now fully removed: the ExecuteMTCTask Behavior, the /execute_task_solution move_group capability, and the controller_names and trajectory_monitoring ports on InitializeMTCTask that only fed that path. 10.0 also removes the deprecated ExecuteFollowJointTrajectory and ExecuteTrajectoryWithAdmittance Behaviors, which were consolidated into the single ExecuteTrajectory Behavior in 9.0.

If you already completed the 9.0 migration and adopted the Execute MTC Solution Subtree, most of your workspace already uses the new path and the changes below are small.

Migration Summary

These are breaking changes. A Behavior Tree that still references the removed Behavior, ports, or capability will fail to load or run, so complete the Required Migration Changes below. Run the shell commands from the top level of your user workspace (for example ~/moveit_pro/moveit_pro_example_ws/).

10.0 also introduces one non-breaking deprecation — the position_only port on the Cartesian path Behaviors. Existing Objectives keep working, so it is not in the required list; see Replace the Deprecated position_only Port on the Cartesian Path Behaviors below to silence the deprecation warning.

Required Migration Changes

Rename Docker Image References

MoveIt Pro 10.0 renames Docker image repositories from moveit-studio to moveit-pro. This applies to published images and locally built development images. For example:

MoveIt Pro 9.x imageMoveIt Pro 10.0 image
picknikciuser/moveit-studiopicknikciuser/moveit-pro
picknikciuser/moveit-studio-frontendpicknikciuser/moveit-pro-frontend
moveit-studio-devmoveit-pro-dev
moveit-studio-basemoveit-pro-base
moveit-studio-agent-bridgemoveit-pro-agent-bridge
moveit-studio-driversmoveit-pro-drivers
moveit-studio-overlay-devmoveit-pro-overlay-dev

Update custom Dockerfiles, Compose files, CI workflows, deployment scripts, and image-retention rules that name the old repositories. Search the workspace for candidates with:

grep -RIn --exclude-dir=.git 'moveit-studio' .

Review each result rather than replacing the text globally: legacy ROS package and module names that contain moveit_studio are unchanged. After updating the image references, rebuild or pull the 10.0 images. Existing images under the old repository names are not reused automatically.

Remove ExecuteMTCTask

The ExecuteMTCTask Behavior, deprecated in 9.0, has been removed. Execute MTC solutions with the Execute MTC Solution Subtree (or the ExecuteMTCSolution Behavior), which run the solution directly through the JTAC or JTC controllers instead of the MoveIt 2 execution pipeline.

Replace:

<Action ID="ExecuteMTCTask" solution="{solution}" />

With:

<SubTree
ID="Execute MTC Solution"
solution="{solution}"
execution_pipeline="jtac"
controller_names="joint_trajectory_admittance_controller"
controller_action_name="/joint_trajectory_admittance_controller/follow_joint_trajectory"
/>

For a JTC-like controller, set execution_pipeline="jtc" (or use the Execute MTC Solution (JTC) convenience Subtree) and point controller_names and controller_action_name at your controller.

Remove controller_names and trajectory_monitoring From InitializeMTCTask

InitializeMTCTask no longer accepts the controller_names or trajectory_monitoring input ports. Because Behavior Trees reject unknown port attributes at load time, an Objective that still sets either attribute on InitializeMTCTask will fail to load.

Remove both attributes from every InitializeMTCTask Action. For example, change:

<Action
ID="InitializeMTCTask"
task_id="pick_object"
controller_names="joint_trajectory_admittance_controller"
task="{mtc_task}"
trajectory_monitoring="false"
/>

To:

<Action ID="InitializeMTCTask" task_id="pick_object" task="{mtc_task}" />
Only remove these attributes on InitializeMTCTask

controller_names is still a valid input on the Execute MTC Solution Subtree and on core motion Objectives, and many Objectives declare it as a top-level port. Only remove controller_names where it appears as an attribute of an InitializeMTCTask Action — leave every other use in place.

trajectory_monitoring is used only by InitializeMTCTask, so on a Linux workspace you can safely remove it everywhere at once:

find . -name '*.xml' -exec sed -i '/^[[:space:]]*trajectory_monitoring=/d' {} +

Why these ports were removed

Both ports only fed the removed /execute_task_solution execution path:

  • Controller selection is now handled by the Execute MTC Solution Subtree — ExecuteMTCSolution chooses its controller through its own controller_action_name port, and controllers are activated with an explicit SwitchController step.
  • Per-subtrajectory collision monitoring (trajectory_monitoring) is no longer performed automatically during execution. To collision-check a planned trajectory against an updated planning scene, use the ValidateTrajectory Behavior at the Behavior Tree level before executing.

Remove the /execute_task_solution move_group Capability

The ExecuteTaskSolutionCapability move_group capability (the /execute_task_solution action server) has been removed, since ExecuteMTCSolution executes MTC solutions directly through the controllers.

  • Most users: no action needed — this capability was loaded by the default MoveIt Pro configuration, which no longer references it.
  • If your robot configuration overrides the move_group capability list, remove move_group/ExecuteTaskSolutionCapability from it.
  • Custom action clients that sent goals to the /execute_task_solution action must switch to running the Execute MTC Solution Subtree.

Remove the MoveIt Controller-Manager Configuration

10.0 removes the MoveIt controller-manager plugin layer (the MoveItSimpleControllerManager / Ros2ControlManager plugins) that the trajectory execution manager drove. Trajectory execution and controller switching now run entirely through ros2_control controllers driven by the Behavior Tree — controllers are activated with an explicit SwitchController step, and MTC solutions execute directly through the JTAC or JTC controllers.

  • moveit_params.moveit_simple_controller_manager config key: remove it from your robot configuration package. The key is now silently ignored (the config schema drops unknown keys), so a workspace that still sets it loses that functionality with no error. Hardware that is not exposed through ros2_control must now provide a ros2_control interface — the previous "drivers without ros2_control" path is no longer available.
  • SetActiveControllerService move_group capability: removed. Most users need no action (it was loaded by the default configuration). If your robot configuration overrides the move_group capability list, remove move_group/SetActiveControllerService from it.
  • allow_trajectory_execution launch argument: still accepted, but it no longer has any effect. Trajectory execution is now driven by the Behavior Tree. Remove any workflow that relied on it as a runtime toggle.
  • moveit_studio_agent_msgs/srv/SetStringArray SDK message: removed along with the controller-switching service it backed. Any external Behavior, Python, or C++ client that referenced this message type must drop it; controller switching is done with the SwitchController Behavior for ros2_control controllers, or custom Behaviors for custom controllers.
  • moveit_params.trajectory_execution config block: removed. It configured the MoveIt trajectory execution manager, so every field under it (manage_controllers, allowed_execution_duration_scaling, allowed_goal_duration_margin, allowed_start_tolerance, control_multi_dof_joint_variables) is now silently ignored. Remove the block from your robot configuration package.

Remove ExecuteFollowJointTrajectory and ExecuteTrajectoryWithAdmittance

The ExecuteFollowJointTrajectory and ExecuteTrajectoryWithAdmittance Behaviors, deprecated in 9.0, have been removed. Both are replaced by the consolidated ExecuteTrajectory Behavior, which selects the execution interface through its execution_pipeline input port — "jtc" for a standard FollowJointTrajectory controller, "jtac" for the Joint Trajectory Admittance Controller. ExecuteFollowJointTrajectory's execute_follow_joint_trajectory_action_name port is renamed to controller_action_name; ExecuteTrajectoryWithAdmittance already used controller_action_name.

Replace ExecuteFollowJointTrajectory:

<Action
ID="ExecuteFollowJointTrajectory"
execute_follow_joint_trajectory_action_name="{controller_action_server}"
joint_trajectory_msg="{joint_trajectory_msg}"
/>

With:

<Action
ID="ExecuteTrajectory"
execution_pipeline="jtc"
controller_action_name="{controller_action_server}"
joint_trajectory_msg="{joint_trajectory_msg}"
/>

Replace ExecuteTrajectoryWithAdmittance:

<Action
ID="ExecuteTrajectoryWithAdmittance"
controller_action_name="{controller_action_server}"
joint_trajectory_msg="{joint_trajectory_msg}"
admittance_parameters_msg="{admittance_parameters}"
/>

With:

<Action
ID="ExecuteTrajectory"
execution_pipeline="jtac"
controller_action_name="{controller_action_server}"
joint_trajectory_msg="{joint_trajectory_msg}"
admittance_parameters_msg="{admittance_parameters}"
/>

ExecuteTrajectory reads its goal and path tolerances from the controller configuration when the corresponding ports are left unset, rather than applying Behavior-side default tolerances. It has no goal_time_tolerance input port and no trajectory_remainder output port. If you relied on ExecuteFollowJointTrajectory's goal_time_tolerance, configure the equivalent tolerance on your controller.

Remove CreateStampedPose, CreateStampedTwist, and CreateStampedWrench

These three Behaviors were deprecated in favor of CreatePoseStamped, CreateTwistStamped, and CreateWrenchStamped, and are now removed. An Objective that still references a removed name will fail to load.

The replacements take the same input ports; only the output port name changed:

Removed BehaviorReplacementOutput port rename
CreateStampedPoseCreatePoseStampedstamped_posepose_stamped
CreateStampedTwistCreateTwistStampedstamped_twisttwist_stamped
CreateStampedWrenchCreateWrenchStampedstamped_wrenchwrench_stamped

Rename the Action and its output port. For example, change:

<Action ID="CreateStampedPose" reference_frame="world" position_xyz="0.5;0;0.1" orientation_xyzw="0;0;0;1" stamped_pose="{pose}" />

To:

<Action ID="CreatePoseStamped" reference_frame="world" position_xyz="0.5;0;0.1" orientation_xyzw="0;0;0;1" pose_stamped="{pose}" />

The blackboard variable the output writes to ({pose} above) is unchanged, so downstream Actions that read it need no edit. The position and orientation ports also adopt the typed-message form described in Pose and Transform Behaviors Use Typed Orientation and Position Ports below.

Adopt moveit_msgs/RobotState (Retire RobotJointState)

MoveIt Pro 10.0 replaces the custom moveit_studio_agent_msgs/msg/RobotJointState message with the standard moveit_msgs/msg/RobotState everywhere a joint-space robot state is produced or consumed. RobotState is a superset of the old message: it keeps the same joint_state and multi_dof_joint_state fields and adds attached_collision_objects and is_diff. The shipped Behaviors, Objectives, and UI are all updated to the new type, so most workspaces need no changes. The exceptions below apply only if your workspace references the old message type, the renamed service, or the generated converter Behaviors directly.

Port keys are unchanged; seven Behaviors are also renamed. RetrieveWaypoint, SaveRobotJointStateToYaml, and LoadRobotJointStateFromYaml keep both their names and their port keys — only the port type changed from RobotJointState to RobotState. Seven planning Behaviors whose names carried the ambiguous JointState term are additionally renamed so the name matches the type they actually carry (see Planning Behaviors renamed to use RobotState below); their old names keep working as deprecation aliases. In every case the port keys are unchanged, so an Objective that only wires these Behaviors together by name needs no edit; the type break is in custom code that constructs or reads the message with the explicit old type.

Planning Behaviors renamed to use RobotState

Seven planning Behaviors carried the ambiguous JointState term in their names — some producing the composite whole-robot state, one producing a plain sensor_msgs/JointState. They are renamed so the name states the type: RobotState for the whole-robot state, JointState for the single-DOF message.

Old nameNew name
GetRobotJointStateGetJointState
CreateJointStateCreateRobotState
GetTrajectoryStateAtTimeGetRobotStateFromTrajectory
RetrieveJointStateParameterRetrieveRobotStateParameter
SetupMTCPlanToJointStateSetupMTCPlanToRobotState
SetupMTCInterpolateToJointStateSetupMTCInterpolateToRobotState
SetupMTCCartesianMoveToJointStateSetupMTCCartesianMoveToRobotState

The old names are still registered as deprecation aliases, so existing Objectives keep loading unchanged; they will be removed in a future major release. The shipped Objectives already use the new names — update your own Objective XML at your convenience by swapping the ID="…" string.

Update Objectives that use the Pack/Unpack converter Behaviors

The message-conversion Behaviors are generated per message type, so retiring RobotJointState removes PackRobotJointStateMessage and UnpackRobotJointStateMessage; they are replaced by PackRobotStateMessage and UnpackRobotStateMessage. An Objective that references a removed node ID fails to register.

Rename both the node ID and its message port — the message port is named after the message type, so it changes from robot_joint_state to robot_state. The field ports (joint_state, multi_dof_joint_state) are unchanged; the new type simply adds attached_collision_objects and is_diff ports you can ignore. For example, change:

<Action ID="UnpackRobotJointStateMessage" robot_joint_state="{robot_state_msg}" joint_state="{joint_state}" multi_dof_joint_state="{multi_dof}" />

To:

<Action ID="UnpackRobotStateMessage" robot_state="{robot_state_msg}" joint_state="{joint_state}" multi_dof_joint_state="{multi_dof}" />

PackRobotStateMessage changes the same way — its output message port is renamed robot_joint_staterobot_state.

Update custom code that names the old message type or service

  • Custom C++ / Python Behaviors and nodes that reference moveit_studio_agent_msgs::msg::RobotJointState (or moveit_studio_agent_msgs/msg/RobotJointState) must switch to moveit_msgs::msg::RobotState. Field access is unchanged — joint_state and multi_dof_joint_state are the same members — so usually only the type name and include change (#include <moveit_msgs/msg/robot_state.hpp>).
  • The RetrieveJointState service is renamed. moveit_studio_agent_msgs/srv/RetrieveJointState is now RetrieveRobotState, and its response field robot_joint_state is now robot_state (a moveit_msgs/RobotState). The service endpoint name (retrieve_joint_state) is unchanged; the wrapper Behavior is renamed RetrieveJointStateParameterRetrieveRobotStateParameter (old name kept as a deprecation alias — see above). Only a custom client that calls the service with the old .srv type needs updating.
  • Custom rosbridge integrations that publish to /moveit_pro_ui/store_joint_state must send moveit_msgs/msg/RobotState instead of moveit_studio_agent_msgs/msg/RobotJointState.

Set is_diff = false on robot states you build by hand

moveit_msgs/RobotState carries an is_diff flag that RobotJointState did not. The full-state consumers — PlanToJointGoal, the Plan/Interpolate/CartesianMoveTo Joint State MTC setup Behaviors, GeneratePointToPointTrajectory, and SetMujocoState — treat the message as absolute joint values and reject is_diff == true with a clear error ("... must be a complete robot state (is_diff == false), not a diff."). Every shipped producer emits is_diff = false. If your custom Behavior constructs a RobotState to feed one of these consumers, set is_diff = false (the default) and populate the named joints; do not send a differential state.

Saved waypoint YAML files keep working

No action is required for existing saved joint-state files. SaveRobotJointStateToYaml / LoadRobotJointStateFromYaml keep their names and now read and write RobotState, and the YAML loader tolerates the pre-10.0 layout: a file saved as a RobotJointState (only joint_state and multi_dof_joint_state, with no is_diff or attached_collision_objects keys) still loads, with the new fields defaulting (is_diff = false, empty attachments). You do not need to re-save waypoints.

Zero the Force/Torque Sensor Before Executing a Trajectory

MoveIt Pro 10.0 restricts the force/torque tare — the Joint Trajectory Admittance Controller's ~/zero_fts/<sensor_frame> services and the Velocity Force Controller's ~/zero_fts service — to run only while the controller is idle. A tare triggered while the JTAC is executing a goal, or while the VFC is actively streaming a command, is now rejected and the service reply reports success = false. Previously the tare ran mid-execution.

This is disallowed because zeroing the sensor mid-trajectory steps the force offset — introducing a discontinuity in the admittance control signal — and averages a changing load into a meaningless offset.

Refactor any Objective that tares the sensor during execution so the tare runs before the trajectory is sent for execution: sequence the ~/zero_fts CallTriggerService step ahead of the ExecuteTrajectory step instead of running them in parallel or triggering the tare mid-motion. The tare service now also replies only after the averaged offset has been applied, so a step that zeroes the sensor and then commands motion waits for the tare to complete instead of racing it.

Replace the Deprecated position_only Port on the Cartesian Path Behaviors

MoveIt Pro 10.0 adds a cartesian_constraint input port to the PlanCartesianPath and SetupMTCPathIK Behaviors and deprecates their position_only port. Unlike the changes above this is not a breaking change — an Objective that sets position_only still loads and runs — but whenever the position_only port is wired explicitly the Behavior logs a deprecation warning on each run. Migrate to cartesian_constraint to silence the warning and prepare for the port's removal in a future major release.

The two ports are mutually exclusive: setting both on the same Behavior is an error and the Behavior fails to run. Replace an explicit position_only attribute with the equivalent cartesian_constraint value:

Deprecated position_onlyReplacement cartesian_constraint
position_only="false"cartesian_constraint="[{constraint_type: position_and_orientation}]"
position_only="true"cartesian_constraint="[{constraint_type: position_only}]" — or just delete the attribute, since position-only is the default

For example, change (the ... stands for the Behavior's other, unchanged ports):

<Action ID="PlanCartesianPath" ... position_only="false" />

To:

<Action ID="PlanCartesianPath" ... cartesian_constraint="[{constraint_type: position_and_orientation}]" />

An Objective that does not set position_only needs no migration: with neither port wired the Behavior keeps the historical position-only default and logs no warning.

C++ Access Specifier Cleanup: protected Removed

MoveIt Pro 10.0 removes all protected members from its C++ classes. Every class member is now either public or private:

  • Extension points are now public. Members that derived classes are meant to use — virtual hooks you override, base-class state you read, helpers you call — are now public.
  • Implementation details are now private. Members that only the defining class used are now private.

No changes needed for most overrides

If your custom Behaviors derive from the standard base classes and only override subclass hooks, those overrides compile unchanged:

  • AsyncBehaviorBasedoWork(), doHalt(), getFuture(), and notifyCanHalt() are now public.
  • ServiceClientBehaviorBasecreateRequest(), processResponse(), getServiceName(), doHalt(), and the timeout hooks are now public.
  • ActionClientBehaviorBasecreateGoal(), processResult(), processFeedback(), and the message hooks are now public.
  • GetMessageFromTopicBehaviorBase — the timeout hooks are now public.
  • SharedResourcesNode — the shared Behavior context is now exposed through the public getBehaviorContext() accessor. Direct member references require the source update described below.

Your existing overrides keep compiling no matter which access section they sit in: C++ lets a derived class declare an override at any access level. You do not need to move your own protected: overrides — although we recommend adopting the same public/private convention in your workspace.

The same applies to the other customer-facing inheritance hierarchies, whose subclass-facing members are now public: MoveIt Task Constructor stages (Stage, PropagatingEitherWay, Generator, MonitoringGenerator, ContainerBase, GeneratePose), KinematicsBase (custom IK plugins), CollisionEnv, KinematicConstraint, JointModel, PlanningContext, OccupancyMapUpdater, MoveGroupCapability, and the ActionBasedControllerHandle controller-handle bases.

Action required: use getBehaviorContext() for shared Behavior context

SharedResourcesNode now keeps its shared context in a private member named behavior_context_ and exposes it through getBehaviorContext(). Custom Behaviors that directly accessed the old member must update their source code:

// Before
shared_resources_->logger->publishInfoMessage(name(), "message");

// After
getBehaviorContext()->logger->publishInfoMessage(name(), "message");

A mechanical search/replace is usually enough:

grep -RIl 'shared_resources_->' src/ | xargs --no-run-if-empty sed -i 's/shared_resources_->/getBehaviorContext()->/g'

Action required: members that became private

Members that were used only inside their defining class became private. This is a breaking change only if your workspace defines a class that derives from one of the classes below and touches the listed members. Overriding a now-private virtual still compiles — only direct reads, writes, or calls break.

ClassNow-private membersUse instead
RobotModelInternal model state (urdf_, srdf_, link/joint maps, …)Public getters (getURDF(), getSRDF(), getJointModel(), …)
JointModelGroupInternal group state (joint/link vectors, index maps, …)Public getters
RevoluteJointModel, PrismaticJointModelaxis_, continuous_getAxis() / setAxis(), isContinuous(). Note: setAxis() normalizes the axis and recomputes cached rotation products — code that wrote axis_ directly had a latent stale-cache bug that this fixes
PlanningSceneMonitorInternal state (scene_, mutexes, subscribers, …)Public accessors and LockedPlanningSceneRO / LockedPlanningSceneRW
Transformstarget_frame_, transforms_map_getTargetFrame(), getAllTransforms()
PlannerManagerconfig_settings_getPlannerConfigurations() / setPlannerConfigurations()
KinematicConstraintSetConstraint containersgetAllConstraints() and per-type getters
KinematicConstrainttype_, robot_model_, constraint_weight_Pass the constraint type to the two-argument base constructor, use getType() / getRobotModel() / getConstraintWeight(), and apply validated weights with setConstraintWeight()
JointConstraint, OrientationConstraint, PositionConstraint, VisibilityConstraintConstraint state and cached matricesPublic getters; reconfigure via configure()
CollisionEnvrobot_model_getRobotModel()
VoxelGrid<T>Grid data and dimensionsgetSize(), getResolution(), getCell(), …
DistanceFieldinv_twice_resolution_getResolution()
SynchronizedStringParameterNode/publisher internalsPublic getValue() API
ShapeMaskbodies_, bspheres_, transform_callback_addShape() / removeShape() for managed shapes, setTransformCallback() for the callback, and maskContainment() / getMaskContainment() for queries
MTC Connect, MoveTo, MoveRelative, ModifyPlanningScene, ComputeIK, CurrentState, FixedState, FixedCartesianPosesStage-internal state (planner_, upstream_solutions_, …)Goal/group/IK-frame state: stage properties (setGoal(), properties(), …). The planner: keep the solvers::PlannerInterfacePtr you passed to the stage's constructor — the stage never replaces it
TaskSolutionVisualization, TaskSolutionPanel, TrajectoryVisualization, TrajectoryPanel, TrajectoryDisplay, RobotStateDisplayrviz widget/render internalsPublic display API
RRTConnectPlannerPlanner parameters (max_iters_, timeout_s_, seed_, …)Public setters
Concrete (leaf) Behaviors (e.g. the vision Behaviors, ExecuteTrajectory, AddCollisionObjectBase's doWork()/getFuture())doWork(), doHalt(), getFuture(), internal stateDerive from AsyncBehaviorBase (or the relevant base) instead of subclassing a shipped concrete Behavior; AddCollisionObjectBase subclasses override the public buildCollisionObject()

If you hit a compile error on a member not listed here, the pattern is the same: the member moved to private because a public accessor covers it, or the class was not designed for subclassing. Prefer the public API; if no public equivalent exists for something your integration genuinely needs, contact MoveIt Pro support.

Pose and Transform Behaviors Use Typed Orientation and Position Ports

The pose and transform Behaviors now type their orientation and position ports as geometry_msgs messages instead of vector<double>: orientation ports (orientation_xyzw, rotation_xyzw, quaternion_xyzw) take a Quaternion, and position ports (position_xyz, translation_xyz) take a Vector3. This affects CreatePoseStamped, CreateTransform, TransformPose, and OverridePoseOrientation.

  • Literal values in XML need no change. orientation_xyzw="0;0;0;1" and position_xyz="0.5;0.0;0.1" still parse — the semicolon form is read directly into the typed message.
  • Blackboard references must supply the matching type. If a custom Behavior writes a std::vector<double> to the blackboard and wires it in (for example position_xyz="{my_xyz}"), change that Behavior to output a geometry_msgs::msg::Vector3 (or Quaternion for orientation). A vector-typed blackboard entry no longer matches the port, and the tree will fail when the Behavior ticks.
  • Malformed values are now rejected at parse time. The new parser requires exactly the right element count and finite numbers, so nan, inf, and trailing garbage (e.g. 1x) that the old std::vector<double> port silently accepted now fail the Behavior loudly. This is a deliberate tightening; fix any Objective that relied on the old leniency.
  • OverridePoseOrientation near-zero-norm threshold. It now shares the common normalize_orientation() helper (like the other three Behaviors), which rejects a quaternion only when its norm falls below machine epsilon (was 1e-10). A quaternion whose norm sits between epsilon and 1e-10 — almost always noise or user error — now normalizes and succeeds instead of failing.