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.

Separately, 9.4.2 and 10.0 use stable host hardware to identify each computer for licensing. This is not a workspace change, but it can affect activation and prevent startup. Read Check Your License Identity below and Configure Licensing before upgrading.

Required Migration Changes

Check Your License Identity

MoveIt Pro 9.4.2 and 10.0 identify a computer by its TPM security chip, or by the MAC address of a permanent hardware network interface when no TPM is available. MoveIt Pro 9.4.1 and earlier used the MAC address of the interface named eth0, which was missing on some hardware and could be identical across a fleet.

When upgrading directly from 9.4.1 or earlier, the license identity changes even when the same network interface is selected. An online installation re-activates on first start when it can reach the license server. An explicitly offline installation needs a new request and response because its existing offline response remains bound to the previous identity. An installation already running 9.4.2 retains its identity when the pinned source and persistent data remain available.

For an air-gapped installation, plan the license exchange as part of the maintenance window. Before generating the new request, move the pre-upgrade offlineRequest_*.dat and offlineResponse_*.dat files out of ~/.local/share/moveit_pro/. Keep them only as archived support evidence; do not copy them back or reuse them. Install 10.0, generate a new offline request, obtain the corresponding response on a connected computer, and apply it before returning the installation to service.

Stop MoveIt Pro cleanly before upgrading, then start 10.0. A clean shutdown releases a hosted-floating seat, but it does not remove a node-locked activation. The new identity can use another allowed activation, so contact support@picknik.ai before upgrading if the key has no recovery capacity.

warning

Contact support@picknik.ai before upgrading a fleet.

If computers running 9.4.1 or earlier shared one license identity — most likely if their network interfaces are not named eth0, such as on NVIDIA Jetson carrier boards — they were consuming a single activation between them. Stable fingerprinting identifies each computer separately, so each one needs its own activation. Without an adjustment to the license first, the fleet will not start after the upgrade.

An unclean shutdown, such as power loss or docker kill, can leave a hosted-floating seat held until its lease expires. A node-locked activation remains registered regardless of shutdown method. Support can review either type before the fleet upgrade.

If MoveIt Pro Will Not Start After Upgrading

MoveIt Pro 9.4.2 and 10.0 refuse to start rather than fall back to an identity that a fleet could share. If no TPM and no permanent hardware network interface can be found, startup fails with:

No machine-unique hardware identity is available, so this license cannot be bound to this machine.

This normally means the container cannot see the host's real hardware. Check that you are using the 10.0 Compose files rather than a modified copy carried over from 9.x — they grant the runtime and drivers services the access this needs.

Changing a Computer's Hardware

After activation, MoveIt Pro records which hardware source it used in ~/.local/share/moveit_pro/licensing/fingerprint_pin (under $MOVEIT_HOST_DATA_DIR if you set it) and keeps using that source. This is deliberate: silently switching sources would change the computer's identity and consume another activation.

If the selected network card or TPM is replaced, startup fails with a message naming that file. Restore access to the original source when possible. Otherwise, contact support@picknik.ai to review or clear the existing activation before removing the pin and activating against new hardware. This can consume another activation.

Copying fingerprint_pin to another computer grants nothing — it records which hardware source to read, not the identity itself, and the second computer derives a different value from its own hardware.

Migrate Custom View Panes

MoveIt Pro 10.0 isolates custom panes from the application and its credentials. Check every custom pane before upgrading:

MoveIt Pro 9.x paneMoveIt Pro 10.0 migration
./..., ../..., or another root-relative URLInstall the files under <config_package>/web/ and use /api/packages/<config_package>/web/<file>.
Absolute URL on another hostnameServe it from the desktop client computer or the connected Runtime computer. The hostname must match one of those hosts.
HTTP pane with ROS accessServe it over HTTPS, or disable ROS access.
web_bridge_url in frontend_settings.yamlRemove it. Set enable_web_bridge: true only when the pane needs ROS topics.
rosbridge or an older copy of iframe-ros-client.jsUse the 10.0 IframeROSClient and enable ROS access for the pane.
Direct access to frontend storage or the frontend keyUnsupported. Use the parent-frame Web bridge for ROS topics.
Form submission, popups, clipboard, or media-device permissionsUnsupported inside the pane sandbox.

Panes saved only in 9.x browser storage are not migrated. Re-add them through Add/Edit Panes after updating their URLs. See Creating Custom View Panes for the supported hosting options and URL rules.

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-runtime
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.

Rename the agent_bridge Service to runtime

MoveIt Pro 10.0 renames the agent_bridge Docker Compose service to runtime to match the product terminology. Update your user workspace:

  • Compose files: rename the agent_bridge: service to runtime: in your docker-compose.yaml (and any overlay Compose files), and update every reference to it (for example depends_on: entries).

  • Config package launch file: rename launch/agent_bridge.launch.xml in your robot configuration package to launch/runtime.launch.xml. The file's contents are unchanged — it still includes studio_agent_bridge.launch.xml from moveit_studio_agent (a legacy package name that is intentionally not renamed).

  • Runtime launch configuration: add runtime_launch_file to the resolved robot configuration. Add it once to the inherited base configuration when every derived configuration uses the same launch file; otherwise add or override it in each robot configuration package. The runtime service launches the configured package and path, rather than assuming a launch filename.

    runtime_launch_file:
    package: "my_robot_config"
    path: "launch/runtime.launch.xml"

    launch/runtime.launch.xml is the standard example, not an implicit runtime-service convention. The configured file may instead use another path or a Python launch file.

  • CLI and scripts: replace agent_bridge with runtime where you target the service by name, for example moveit_pro shell -s agent_bridge … becomes moveit_pro shell -s runtime ….

Find candidates with:

grep -RIn --exclude-dir=.git 'agent_bridge' .

The Docker image is renamed to match the service, from moveit-pro-agent-bridge to moveit-pro-runtime (see the image table above); rebuild or re-pull the 10.0 images so the runtime service finds it.

Remove the web_ui Service

In MoveIt Pro 10.0 the interface is the separately installed MoveIt Pro Desktop App, so the 10.0 Compose files no longer define a web_ui service. The 9.0 migration had you mirror it in your workspace docker-compose.yaml. A service that now exists only there has no image and no build context, so Compose rejects the merged project:

service "web_ui" has neither an image nor a build context specified: invalid compose project

Every moveit_pro command loads that merged project, so run, build, shell, and down all fail until the entry is gone. Delete it from your docker-compose.yaml and any overlay Compose files, along with references to it such as depends_on entries:

# Delete these lines.
# Starts the web UI frontend.
web_ui: {}

Nothing in Compose replaces it. The Desktop App is a host application, frequently on a different computer from the Runtime, and is installed and opened separately. moveit_pro run publishes the running Runtime for the app to find — see Connect with the MoveIt Pro Desktop App.

Replace moveit_studio_common

The deprecated moveit_studio_common compatibility package has been removed. Update custom packages that still depend on it:

  • Replace <depend>moveit_studio_common</depend> with <depend>moveit_pro_common</depend> when using the shared utility library. In CMakeLists.txt, replace find_package(moveit_studio_common REQUIRED) with find_package(moveit_pro_common REQUIRED).
  • Replace moveit_studio_common/... includes with moveit_pro_common/.... Code using the old namespace aliases must also replace moveit_studio::common with moveit_pro::common.
  • For CMake helpers, replace <build_depend>moveit_studio_common</build_depend> with <buildtool_depend>moveit_pro_package</buildtool_depend> in package.xml and call find_package(moveit_pro_package REQUIRED). Replace moveit_studio_package() with moveit_pro_package() and moveit_studio_behavior_test() with moveit_pro_behavior_test(); the target_package_dependencies() name is unchanged.
  • If MOVEIT_PRO_PACKAGE() from moveit_pro_common was your only use of that package, remove its <depend> entry. Use moveit_pro_package() from moveit_pro_package instead; its C++20 and -Werror defaults may expose diagnostics that the removed compatibility macro did not.

Search for remaining uses with:

grep -RInE --exclude-dir=.git 'moveit_studio_common|moveit_studio::common|moveit_studio_package|moveit_studio_behavior_test|MOVEIT_PRO_PACKAGE|find_package[[:space:]]*\(moveit_pro_common' .

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.

Consolidate the hardware launch-file keys

10.0 replaces three hardware launch-file keys with two that are always included, and removes the separate hardware.simulated mode flag, so launch files no longer depend on a simulated flag:

  • robot_driver_persist_launch_file and simulated_robot_driver_persist_launch_fileadditional_driver_launch_file (included with the robot driver process, which persists across Agent restarts and runs in --only-drivers mode).
  • simulated_hardware_launch_fileadditional_agent_launch_file (included with the Agent process, which runs in --no-drivers mode).
  • hardware.simulated is removed. Choose simulation vs. real hardware through your xacro use_fake_hardware parameter and ros_global_params.use_sim_time.

If any value in your config referenced hardware.simulated through the %>> template syntax — for example use_fake_hardware: "%>> hardware.simulated" under robot_description.urdf_params — replace it with the literal true or false it resolved to, since the referenced key no longer exists.

Unlike the other removed config keys above, these are not silently ignored: a configuration that still sets any removed hardware key — one of the three launch-file keys or hardware.simulatedfails to load with an error naming the key and how to migrate it.

If a base configuration previously carried both a real and a simulated driver launch file and children flipped simulated, set the launch file that should run by default on additional_driver_launch_file in the base, and override it in the mode-specific child. When switching a child to real hardware, also override additional_agent_launch_file back to a blank launch file if the base used it to launch a simulator, so the simulator does not start on the real robot.

See the config.yaml reference for the full key descriptions.

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 web-bridge 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.

Remove Deprecated ProRRT Orientation Ports

The ProRRT planning Behaviors (PlanToJointGoal, SetupMTCConnectWithProRRT, SetupMTCPlanToPose, SetupMTCPlanToRobotState) previously exposed three scalar orientation ports: keep_orientation, keep_orientation_tolerance, and keep_orientation_link_names. These are removed in 10.0. Orientation constraints now go through the single typed orientation_constraint port (moveit_studio_msgs::msg::OrientationConstraint), matching how joint_range_constraint already works. Editing the port in the UI opens a dialog for adding links and setting each link's tolerance.

An Objective that references any of the removed ports fails to load until those attributes are removed. Migration is mechanical, and which case you are in is easy to tell:

  • No orientation constraint (keep_orientation unset or "false"): delete the three keep_orientation* attributes and add nothing. An absent orientation_constraint plans exactly as before, with no orientation constraint applied.
  • Orientation constrained (keep_orientation="true"): replace the three attributes with a single orientation_constraint whose value is a YAML sequence of per-link maps — one entry per link that was listed in keep_orientation_link_names, each carrying what was the shared keep_orientation_tolerance:
<!-- Before (removed) -->
<Action ID="PlanToJointGoal" keep_orientation="true" keep_orientation_tolerance="0.05" keep_orientation_link_names="grasp_link" ... />

<!-- After -->
<Action ID="PlanToJointGoal" orientation_constraint="[{link_name: grasp_link, angle_tolerance: 0.05}]" ... />

Multiple links (previously semicolon-separated in keep_orientation_link_names) become additional entries in the sequence. Each entry now carries its own tolerance, so you can tighten or loosen individual links — previously every link shared the single keep_orientation_tolerance:

orientation_constraint="[{link_name: grasp_link, angle_tolerance: 0.05}, {link_name: tool0, angle_tolerance: 0.1}]"

Leave the port empty for no orientation constraint — both "" and [] (an empty sequence, the value the shipped Objectives default to) are accepted and mean the same thing.

Migrate via the UI instead of hand-editing XML

If you prefer to migrate your Objectives via the UI, open the Objective in the Behavior editor and edit the Behavior's orientation_constraint port — a dialog lets you add each link and set its tolerance, and writes the value for you.

Restrict Eigen to Its MPL-2.0 Modules

MoveIt Pro 10.0 compiles with EIGEN_MPL2_ONLY and propagates that definition to packages that link MoveIt Pro C++ targets, restricting Eigen to its MPL-2.0-licensed modules.

Almost every workspace is unaffected. With Eigen 3.4, which is what MoveIt Pro builds against, this excludes exactly two symbols, both from unsupported/Eigen/IterativeSolvers: Eigen::constrained_cg() and Eigen::IterationController. Everything else still works, including Eigen/Sparse, SimplicialLDLT, AMDOrdering, and IncompleteCholesky, which were relicensed to MPL-2.0 in Eigen 3.4.

If your workspace uses one of the two, replace it. constrained_cg solves a bound-constrained problem, so an unconstrained Eigen::ConjugateGradient solve followed by clamping is an approximation, not a drop-in equivalent: validate it against your own tolerances, or move to a constraint-aware solver such as a projected-gradient or active-set method. IterationController is only convergence bookkeeping, so track iteration count and residual directly.

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.

Action required: public members renamed to drop the trailing underscore

Public data members no longer end in _ — that suffix is now reserved for private members. Members that derived classes read or write directly kept their public visibility but dropped the underscore. This breaks only if your workspace reads or writes one of these members by name; the fix is a mechanical rename (drop the trailing _).

ClassRenamed members (drop the _)
KinematicsBasenode_, robot_description_, group_name_, base_frame_, tip_frames_, default_timeout_, redundant_joint_indices_, redundant_joint_discretization_, supported_methods_ (and robot_model_private, use getRobotModel())
JointModeltype_, variable_names_, local_variable_names_, variable_bounds_, variable_index_map_ (used when authoring a custom joint model)
VariableBoundsmin_position_, max_position_, position_bounded_, and the velocity/acceleration/jerk equivalents
World::Objectid_, pose_, shapes_, shape_poses_, global_shape_poses_, subframe_poses_, global_subframe_poses_
CollisionData, FCLObject, FCLGeometry, FCLManagerreq_, res_, acm_, done_, active_components_only_, collision_geometry_, collision_objects_, object_, manager_
DistanceFieldsize_x_/size_y_/size_z_, origin_x_/origin_y_/origin_z_, resolution_
OccupancyMapUpdatermonitor_, type_, tree_, transform_provider_callback_, transform_cache_, debug_info_
MoveGroupCapabilitycapability_name_, context_
MoveGroupContextmoveit_cpp_, debug_
SensorModel::Parameterswidth_, height_, near_clipping_plane_distance_, far_clipping_plane_distance_
CuboidGraspCandidateConfig, CuboidGraspDatagenerate_x_axis_grasps_, generate_y_axis_grasps_, generate_z_axis_grasps_, samples_per_quadrant_, grasp_min_depth_, grasp_max_depth_, max_grasp_width_, tform_eef_mount_to_tcp_
LineGraspCandidateConfig, LineGraspDatanormalized_lengths_along_line_, num_radial_samples_, sample_symmetric_grasps_, tform_eef_mount_to_tcp_
VacuumGraspCandidateConfig, VacuumGraspDatagenerate_centroid_grasps_, padding_dimension_, samples_per_plane_, num_orientation_samples_, tform_eef_mount_to_tcp_
BaseTrajectoryExecutornode_, callback_group_, action_client_, active_goal_handle_, current_action_name_, goal_mutex_

Exception: the planning_scene_monitor_ members of MoveGroupContext and the LockedPlanningScene* lock helpers keep the trailing underscore, because a member named planning_scene_monitor would collide with the planning_scene_monitor namespace. No action is needed for those.

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.

Rename process_attached_collision_object in the Python PlanningScene API

PlanningScene.process_attached_collision_object (in moveit_pro_base.core.planning_scene) is renamed to apply_attached_collision_object_msg, matching the C++ API. Instead of logging the error and returning False, the new method returns None and raises ValueError naming the reason when the operation cannot be applied, so replace any check of the returned bool with exception handling.

MoveIt Pro Core C++ API: Robot State and Model Value Types Use Eigen

MoveIt Pro 10.0 modernizes the value-passing APIs of the MoveIt Pro Core robot model and state — RobotState, RobotModel, JointModelGroup, and JointModel — to take Eigen types (Eigen::Ref<const Eigen::VectorXd>, Eigen::VectorXd, std::span<double>) instead of raw double* and std::vector<double> buffers. This matches the Eigen storage the state already holds and removes a class of unchecked-pointer bugs.

This is a MoveIt Pro Core C++ API change, not a Behavior API change. Behavior Trees, Objective XML, Behavior ports, and the blackboard are unaffected — no Objective needs editing. It affects only custom C++ Behaviors (or custom kinematics / joint-model plugins) that call these Core methods directly, and most workspaces drive the state through the shipped Behaviors and need no changes.

To pass existing std::vector<double> or pointer data into the new Eigen parameters without copying, include <moveit_pro_base/utils/eigen_conversions.hpp> and wrap the argument with moveit_pro::base::toEigen():

#include <moveit_pro_base/utils/eigen_conversions.hpp>

// joint_values is a std::vector<double>, e.g. from a ROS message
robot_state.setJointGroupPositions(group, moveit_pro::base::toEigen(joint_values));
// a pointer + length (or a single scalar) also works:
robot_state.setJointPositions(joint, moveit_pro::base::toEigen(&value, 1));

RobotState value setters take Eigen

The RobotState value setters now take const Eigen::Ref<const Eigen::VectorXd>&. The raw double* overloads still compile but are deprecated (they log a compiler warning), and the std::vector<double> overloads of the group setters (setJointGroup{Positions,Velocities,Accelerations}) are removed.

// Before
state.setJointGroupPositions(group, joint_values); // joint_values is std::vector<double> — no longer compiles
state.setVariablePositions(positions_ptr); // positions_ptr is double* — now deprecated

// After
state.setJointGroupPositions(group, moveit_pro::base::toEigen(joint_values));
state.setVariablePositions(moveit_pro::base::toEigen(positions_ptr, count));

copyJointGroupPositions keeps a std::vector<double>& output overload alongside the new Eigen::VectorXd& one, so read-back code that fills a std::vector is unaffected.

RobotModel, JointModelGroup, and JointModel state methods take Eigen / std::span

The distance, interpolation, and bounds methods no longer take double*:

ClassMethodsNew parameter type
RobotModel (whole robot state)distance, interpolate, enforcePositionBounds, satisfiesPositionBounds, updateMimicJoints, getVariableRandomPositions, getVariableDefaultPositionsconst Eigen::VectorXd& (reads) / Eigen::VectorXd& (writes)
JointModelGroup (group state)distance, interpolate, enforcePositionBounds, satisfiesPositionBoundsEigen::Ref<const Eigen::VectorXd> / Eigen::Ref<Eigen::VectorXd>; the resize-and-fill getVariableRandomPositions / getVariableDefaultPositions take Eigen::VectorXd&
JointModel (single joint)distance, interpolate, enforcePositionBounds, satisfiesPositionBounds, getVariableRandomPositions, getVariableDefaultPositions, computeTransform, computeVariablePositionsstd::span<double> / std::span<const double>

The per-joint JointModel methods keep contiguous buffers as std::span because they operate on partial views into a larger state; the whole-state RobotModel / JointModelGroup methods take Eigen because callers already hold Eigen vectors. This only affects a workspace that authors a custom JointModel subclass (override the std::span virtuals) or calls these state methods directly.

Removed: the ROS-message joint-bounds API

JointModel::getVariableBoundsMsg(), JointModel::setVariableBounds(const std::vector<moveit_msgs::msg::JointLimits>&), and computeVariableBoundsMsg() are removed. Use the native Bounds API instead:

  • Read bounds with getVariableBounds(), which returns the internal JointModel::Bounds. Its fields (min_position, max_position, position_bounded, and the velocity / acceleration / jerk equivalents — see the underscore-drop rename above) carry the same values the message did.
  • Set bounds with setVariableBounds(const Bounds&), which replaces every variable's bounds and throws if the count does not match the joint's variable count.

Removed: getVariableRandomPositionsNearBy and getMissingVariableNames

  • getVariableRandomPositionsNearBy (on both JointModel and JointModelGroup) is removed. Sample with getVariableRandomPositions and clamp to your own window if you need bounded-neighborhood sampling.
  • RobotModel::getMissingVariableNames is removed; it had no callers.