2. Runtime SDK & Extensions
π Duration: 1-2 hours
πͺ Level: Advanced
Tutorial Overviewβ
In this tutorial you will create custom robot configuration packages, build new Behavior plugins, and learn how to interact with MoveIt Pro through the runtime SDK.
By the end of this tutorial, you should understand:
- How to use the MoveIt Pro SDK Python interface and standard ROS 2 CLI tools to programmatically run Objectives (Behavior Trees) without the GUI.
- How to create and customize robot configuration packages for your own robot (including inheriting from existing configurations).
- How to develop custom Behaviors (plugins)
- How to integrate external ROS 2 interfaces (like topics, services, and actions) into MoveIt Pro Behaviors.
Pre-reqsβ
You should have already installed MoveIt Pro. We will assume you have already completed Tutorial 1 and know how to build Behavior Trees.
This tutorial is also significantly more advanced, and requires you have experience with the Linux command line and code editing. Have your favorite code editor installed, we recommend VS Code.
Command-Line Usageβ
MoveIt Pro provides a command-line tool called moveit_pro
with multiple subcommands (or βverbsβ) to manage the development and runtime environment.
Below is an overview of key moveit_pro commands and how to use them.
moveit_pro runβ
If you've launched MoveIt Pro, you are already familiar with the basic moveit_pro run
command.
Now we'll learn about the additional launch-time arguments:
-w, --user-workspace <PATH>
: Specify a user workspace path to use (overrides the configured default).-c, --config-package <NAME>
: Specify the MoveIt Pro configuration package to launch.-n, --no-drivers
: Do not launch any robot driver containers.-o, --only-drivers
: Only launch the robot driver containers.-h, --headless
: Run in headless mode (no GUI front-end).-v, --verbose
: Enable verbose output for debugging.--no-browser
: Prevent automatically opening the web UI in your browser.
For example, to run MoveIt Pro in verbose mode without opening the browser:
moveit_pro run -v --no-browser
moveit_pro --helpβ
As a quick reference to get general information about the CLI, you can run:
moveit_pro --help
You can also run moveit_pro COMMAND --help
for more details of a specific command line verb.
Try moveit_pro run --help
to see the above argument options directly in the terminal!
moveit_pro configureβ
The moveit_pro configure
command will prompt you with several configuration options to set up your environment.
The first time you run MoveIt Pro it will automatically ask you which robot config to choose from a list.
Thereafter, to change the robot config used when launching MoveIt Pro you can run the configuration utility, or change it directly with the -c run argument:
moveit_pro run -c lab_sim
moveit_pro buildβ
The moveit_pro build
command compiles and builds any customizations you make to the robot workspace, in particular plugin extensions you develop.
Several options are available:
moveit_pro build
: Build everything (Underlying MoveIt Pro Docker images and your user workspace code). Use this if you've made underlying changes to Pro (such as installing a new version), or as a default option if you are unsure of what to rebuild.moveit_pro build user_image
: Build only the MoveIt Pro Docker overlay (user) images. MoveIt Pro uses three main Docker images (named agent_bridge, drivers, and frontend), which are built from the Dockerfile in your user workspace and share a common base image. Use this when you have modified the Dockerfile or added new system dependencies (e.g. via package.xml dependencies) that require rebuilding the containers.moveit_pro build user_workspace
: Build only your ROS workspace packages (your robotβs configuration package, additional ROS packages and source code dependencies, and any custom behaviors). This is fastest if you've only changed your code.
You can pass additional colcon arguments to skip or select certain packages using:
moveit_pro build user_workspace --colcon-args "--packages-select my_package"
moveit_pro rvizβ
You can use your own RViz configuration and run it on your host system or inside a MoveIt Pro image. For an RViz configuration that we recommend, you can load our example using:
moveit_pro rviz
Much of RViz's visualization functionality exists natively in MoveIt Pro, such as viewing the planning scene and collision objects. However, we still offer Rviz integration as an additional tool, which can be helpful for certain tasks such as viewing the TF tree, and using the MoveIt Motion Planning Task plugin, as we'll see in Tutorial 3.
moveit_pro logsβ
To inspect console logs and output, you can launch the ROS 2 default logging interface (rqt_console
):
moveit_pro logs
To export logs to a file (for example, to share with the MoveIt Pro support team), you can use:
moveit_pro export_logs
Other Useful moveit_pro Commandsβ
- moveit_pro down β Stops and shuts down MoveIt Pro and all services.
- moveit_pro test β Build and run colcon tests for in user workspace.
- moveit_pro shell β Open a shell inside the MoveIt Pro runtime Docker container.
- moveit_pro dev β Open a dev container that persists when not running MoveIt Pro.
Docker Container Interactionsβ
There are three main ways to interact with the MoveIt Pro Docker containers:
- moveit_pro shell β Use for runtime interactions, such as echoing topics. MoveIt Pro must be running (
moveit_pro run
ormoveit_pro dev
). - moveit_pro dev β Use for iterative developer interactions, such as writing, building, and testing C++ code with your preferred IDE. This container can be used standalone, and will not execute your robot configuration launch files.
- Direct Dockerfile modifications - use for permanently installing dependencies (packages installed in
moveit_pro shell
ormoveit_pro dev
will not persist when you close the container). docker compose
- Using the command line or other tools, adocker compose
command can be used to start the MoveIt Pro runtime for those who do not wish to use themoveit_pro
launcher.
Several additional dependencies are needed for this tutorial. To ensure they are persistent, install them in your production image now by adding to your Dockerfile:
Edit moveit_pro_example_ws/Dockerfile
, and find the TWO identical sections beginning with # Install additional dependencies.
Systems with discrete GPUs that support CUDA require additional Dockerfile steps to support hardware acceleration. The Dockerfile stages with -gpu
in their name are only used on systems with discrete NVIDIA graphics.
Install the dependencies by replacing --ignore-src
with the following lines (in both places!):
--ignore-src && \
apt-get install -y --no-install-recommends \
ros-humble-examples-rclcpp-minimal-service ros-humble-ros2action
Both sections should now look like this:
Click to expand
RUN --mount=type=cache,target=/var/cache/apt,sharing=locked \
--mount=type=cache,target=/var/lib/apt,sharing=locked \
--mount=type=bind,target=${USER_WS}/,source=. \
. /opt/overlay_ws/install/setup.sh && \
apt-get update && \
rosdep install -q -y \
--from-paths src \
--ignore-src && \
apt-get install -y --no-install-recommends \
ros-humble-examples-rclcpp-minimal-service ros-humble-ros2action
Don't forget to moveit_pro build user_image
after modifying the Dockerfile!
Programmatic SDK Controlβ
MoveIt Pro can run as a standalone application with its own UI, or as a runtime API. Many users integrate MoveIt Pro into their own framework with their application acting as the overarching coordinator.
While the MoveIt Pro UI is useful for building, editing, and executing Objectives, it is by no means required. MoveIt Pro can be run headless and its Objectives can be launched and communicated from external processes through ROS interfaces.
Using the MoveIt Pro SDK to Start Objectivesβ
In this section, we will use the SDK to remotely start an Objective without the UI. As an example, we will trigger the 3 Waypoints Pick and Place
Objective that ships in lab_sim
. While you can do this with Python, in this example we will use the command line.
First we need to add the MoveIt Pro SDK repository as a git submodule
to the moveit_pro_example_ws
that you already have downloaded:
cd ~/moveit_pro/moveit_pro_example_ws/src/external_dependencies
git submodule add https://github.com/PickNikRobotics/moveit_studio_sdk.git
Then we will build our user image and launch MoveIt Pro:
moveit_pro build
moveit_pro run -c lab_sim
From a separate terminal window, first open a shell inside the container:
moveit_pro shell
Then start the Objective using a ROS service:
ros2 service call /execute_objective moveit_studio_sdk_msgs/srv/ExecuteObjective "{objective_name: '3 Waypoints Pick and Place'}"
To cancel a running Objective, for example an Objective that loops forever like 3 Waypoints Pick and Place
, run:
ros2 service call /cancel_objective moveit_studio_sdk_msgs/srv/CancelObjective
Calling a new Objective while one is already running will also cancel the running Objective, and start the new one.
We are using command line examples here, but calling the SDK directly from Python is also supported.
Checking Objective Status and Heartbeatβ
MoveIt Pro publishes a heartbeat signal to the /objective_server_heartbeat ROS topic with the currently running process runtime, current objective name, and the status of the objective. This topic publishes the moveit_studio_agent_msgs/msg/ObjectiveServerStatus message.
Using the MoveIt Pro SDK to Execute Behavior Tree XMLβ
MoveIt Pro also supports your external application programmatically generating your own Behavior Tree XML, and then sending it to the MoveIt Pro runtime to execute it. You can send the entire XML contents programmatically via an action server.
First, start MoveIt Pro and in a separate terminal enter a shell (moveit_pro shell
):
Confirm that our previous Dockerfile update installed the action client interface by running:
ros2 action --help
Which should return a list of available ros2 action subcommands.
Temporarily install ros2 action
If you did not modify the Dockerfile, you can install it temporarily in the open container with the following command:
sudo apt update && sudo apt install ros-humble-ros2action
Send the action request with a trivial Behavior Tree XML example:
ros2 action send_goal
ros2 action send_goal /do_objective moveit_studio_sdk_msgs/action/DoObjectiveSequence '
objective_xml_string: |
<root BTCPP_format="4" main_tree_to_execute="test simple">
<BehaviorTree ID="test simple">
<Control ID="Sequence" name="TopLevelSequence">
<Action ID="AlwaysSuccess"/>
</Control>
</BehaviorTree>
</root>
'
You should get the following result from the action, indicating it was successful:
Goal finished with status: SUCCEEDED
Waiting for an action server to become available...
Sending goal:
objective_name: ''
objective_xml_string: "<root BTCPP_format=\"4\" main_tree_to_execute=\"test simple\">\n <BehaviorTree ID=\"test simple\">\n <Control ID=\"Sequence\" name=\"TopLevelSequence\">\n <Action ID=\"AlwaysSuccess\"/>\n </Control>\n </BehaviorTree>\n</root>\n"
parameter_overrides: []
Goal accepted with ID: d5f48811588240f19a3ab303ccdc78ce
Result:
error_code:
val: 1
message: ''
source: ''
error_message: ''
Goal finished with status: SUCCEEDED
Advanced Exercise
For a more interesting example, try copying and running the XML code from an existing Objective (such as from _Scan Scene
from lab_sim/objectives/_scan_scene.xml
).
Be sure to match the above example action request formatting: the extra indentation of the XML matters, and don't forget the closing apostrophe (') on the final line.
Understanding MoveIt Pro Workspacesβ
In MoveIt Pro, all robot configurations, Behaviors, and external code are represented as
ROS 2 packages in a ROS workspace.
This is where the moveit_pro
launcher will look to build and run your robot configuration.
Below is an example of a typical MoveIt Pro workspace:
moveit_pro_example_ws/
βββ Dockerfile
βββ docker-compose.yaml
βββ colcon-defaults.yaml
βββ src/
βββ lab_sim/
β βββ config/
β βββ launch/
β βββ objectives/
β βββ src/
β βββ package.xml
β βββ CMakeLists.txt
βββ additional_configuration_packages/
βββ external_dependencies/
An empty workspace is provided as a starting point, called moveit_pro_empty_ws, which you can fork and add your own robot configuration package to. If there are changes or additions to our recommended configuration, your fork will nudge you to sync the upstream changes.
User Workspacesβ
In production systems, it is often desirable to have a customized Docker build and bring-up procedure specific to that hardware. The MoveIt Pro Runtime is distributed through Docker images. When the robot starts, Docker services will launch the MoveIt Pro runtime, drivers, developer platform user interface, and/or additional Docker containers using your user image. A user image is built using the base MoveIt Pro image, your ROS 2 workspace, and MoveIt Pro configuration packages according to the steps in your Dockerfile.
The following diagram illustrates how a production system would share and build packages in the MoveIt Pro runtime:
The ROS 2 workspace can be built into the image as part of the Docker build context, mounted at runtime, or some combination of both. See our Docker Containerization page for more detail.
Robot Configuration Packagesβ
A robot configuration package is a ROS 2 package that describes your robot and its capabilities.
It defines:
- Robot and environment (URDF and MJCF) models
- Planner settings (motion planners, inverse kinematics solvers, allowable collisions, etc.)
- Real-time Controller settings
- Camera settings
- Objectives (Applications)
- Saved waypoints
- Launch files: To start drivers/simulators, additional ROS nodes/processes, etc.
- Custom Behaviors (C++ source files)
Creating a New Robot Configurationβ
Creating a custom robot configuration package from scratch is a huge topic covered in this how to guide, but it is outside the scope of this tutorial. Instead we will "fork" an existing package through inheritance.
Inherited Robot Configuration Packagesβ
Package inheritance is a powerful tool that allows you to create base robot configuration packages that contain a generic configuration of your robot, then use inherited robot config packages to add or override certain aspects.
Some example use cases for inherited packages:
- Minor hardware differences
- Differences in end effectors (lacks a gripper, or the robot has multiple end-effectors to choose from)
- IP addresses, serial numbers, specific kinematic calibrations, or other unique details
- Additional Objectives, Behaviors, or sensors
- Mobile base and navigation Behaviors
- Perception and ML Behaviors
An example inheritance structure:
Create a new robot config based on an existing configβ
In the following we will create a robot configuration package (called example_config
) that will be built on an existing base robot config package (in this case, lab_sim
):
mkdir -p ~/moveit_pro/moveit_pro_example_ws/src/example_config/
cd ~/moveit_pro/moveit_pro_example_ws/src/example_config/
We will assume your user workspace is located at the standard ~/moveit_pro/moveit_pro_example_ws
location. You can modify the paths for any location, however.
-
First we begin with a
config.yaml
. Create it inside aconfig
subfolder, since that is where MoveIt Pro expects to find it:mkdir -p config
touch config/config.yaml -
In the editor of your choice, add the following to
config/config.yaml
:based_on_package: lab_sim
-
Navigate to the top level of your package
cd ~/moveit_pro/moveit_pro_example_ws/src/example_config
-
Add three files:
CMakeLists.txt
,package.xml
, andlaunch/agent_bridge.launch.xml
with the following contents: (Noting that agent_bridge.launch.xml must be in alaunch
subfolder, similar to config/config.yaml)CMakeLists.txt
cmake_minimum_required(VERSION 3.8)
project(example_config)
find_package(ament_cmake REQUIRED)
# Add waypoints, Objectives, and other folders here if you want to override them
install(DIRECTORY config launch DESTINATION share/${PROJECT_NAME})
ament_package()package.xml
<?xml version="1.0"?>
<package format="3">
<name>example_config</name>
<version>0.1.0</version>
<description>Example derived MoveIt Pro config package</description>
<maintainer email="support@picknik.ai">MoveIt Pro Maintainer</maintainer>
<license>BSD-3-Clause</license>
<buildtool_depend>ament_cmake</buildtool_depend>
<exec_depend>lab_sim</exec_depend>
<export>
<build_type>ament_cmake</build_type>
</export>
</package>launch/agent_bridge.launch.xml
<?xml version="1.0" encoding="UTF-8" ?>
<launch>
<include file="$(find-pkg-share moveit_studio_agent)/launch/studio_agent_bridge.launch.xml"/>
</launch>
After creating your new robot configuration package, you can rebuild and launch using:
moveit_pro build user_workspace
moveit_pro run -c example_config
Override the Objectives folderβ
In order to create new Objectives specifically in this example_config
, we first need to override that folder:
- Create the
objectives
folder:
mkdir -p ~/moveit_pro/moveit_pro_example_ws/src/example_config/objectives
- Add to your
config.yaml
:
config.yaml
objectives:
objective_library_paths:
example_objective:
package_name: "example_config"
relative_path: "objectives"
- Update the
install
statement in yourCMakeLists.txt
to look like this:
CMakeLists.txt
install(DIRECTORY config launch objectives DESTINATION share/${PROJECT_NAME})
The ROS build system Colcon won't build and symlink your objectives
folder to your install folder if it is empty, so add a dummy file to it:
touch ~/moveit_pro/moveit_pro_example_ws/src/example_config/objectives/.keep
Now run MoveIt Pro and create an Objective in the UI, then see that it is saved in your example_config/Objectives
folder.
Developing Custom Behavior Pluginsβ
Next we will build some example Behaviors plugins in our example_config
.
In the Creating Custom Behaviors how to guide, more details for creating MoveIt Pro Behaviors are covered.
-
Using the graphical interface, create a new Behavior named
my_behavior
(so that it matches the example code blocks) and select theAsyncBehavior
type. -
Build your new Behavior with
moveit_pro build user_workspace
, -
Then run its default test with
moveit_pro test --colcon-args="--packages-select my_behavior
. For more information on testing Behaviors, see here. -
Open your new Behavior's
.cpp
file and modify itsdoWork()
method with this implementation:
doWork()
tl::expected<bool,std::string> MyBehavior::doWork() {
auto ports = moveit_studio::behaviors::getRequiredInputs(getInput<int>("int_1"),
getInput<int>("int_2"));
if (!ports.has_value()) {
return tl::make_unexpected("Missing inputs: "+ports.error());
}
const auto& [a,b] = ports.value();
setOutput<int>("int_out", a + b);
return { true };
}
- In the
providePorts()
function add input and output ports to the Behavior:
providedPorts()
BT::PortsList MyBehavior::providedPorts(){
return {
BT::InputPort<int>("int_1",0,"The first number"),
BT::InputPort<int>("int_2",0,"The second number"),
BT::OutputPort<int>("int_out","The result")
};
}
- Now, run the Behavior by adding it into our Objective from the previous step, and it will add two integers for us.
Try out blackboard introspection to see your result!
Adding Multiple Behavior Plugins in a Single Packageβ
By default, each new Behavior gets put into its own ROS package, but it is often more convenient to have a collection of associated Behavior plugins in the same ROS package. In this section we walk you through manually adding a new Behavior.
To add additional Behaviors to your package, we must create the relevant .cpp
and .hpp
files and register the Behavior in register_behaviors.cpp
.
Lets create a new Behavior to add two blackboard values using an external ROS service:
service_client.hpp
#pragma once
#include <example_interfaces/srv/add_two_ints.hpp>
#include <moveit_studio_behavior_interface/service_client_behavior_base.hpp>
using moveit_studio::behaviors::BehaviorContext;
using moveit_studio::behaviors::ServiceClientBehaviorBase;
using AddTwoInts = example_interfaces::srv::AddTwoInts;
namespace my_behavior
{
class MyAddTwoIntsServiceClient final : public ServiceClientBehaviorBase<AddTwoInts>
{
public:
MyAddTwoIntsServiceClient(const std::string& name, const BT::NodeConfiguration& config,
const std::shared_ptr<BehaviorContext>& shared_resources);
/** @brief Implementation of the required providedPorts() function for the hello_world Behavior. */
static BT::PortsList providedPorts();
/**
* @brief Implementation of the metadata() function for displaying metadata, such as Behavior description and
* subcategory, in the MoveIt Studio Developer Tool.
* @return A BT::KeyValueVector containing the Behavior metadata.
*/
static BT::KeyValueVector metadata();
private:
/** @brief User-provided function to get the name of the service when initializing the service client. */
tl::expected<std::string, std::string> getServiceName() override;
/**
* @brief User-provided function to create the service request.
* @return Returns a service request message. If not successful, returns an error message. Note that the criteria for
* success or failure is defined by the user's implementation of this function.
*/
tl::expected<AddTwoInts::Request, std::string> createRequest() override;
/** @brief Optional user-provided function to process the service response after the service has finished. */
tl::expected<bool, std::string> processResponse(const AddTwoInts::Response& response) override;
/** @brief Classes derived from AsyncBehaviorBase must implement getFuture() so that it returns a shared_future class member */
std::shared_future<tl::expected<bool, std::string>>& getFuture() override
{
return future_;
}
/** @brief Classes derived from AsyncBehaviorBase must have this shared_future as a class member */
std::shared_future<tl::expected<bool, std::string>> future_;
};
} // namespace my_behavior
service_client.cpp
#include <my_behavior/service_client.hpp>
// Include the template implementation for GetMessageFromTopicBehaviorBase<T>.
#include <moveit_studio_behavior_interface/impl/service_client_behavior_base_impl.hpp>
namespace my_behavior
{
MyAddTwoIntsServiceClient::MyAddTwoIntsServiceClient(
const std::string& name, const BT::NodeConfiguration& config,
const std::shared_ptr<moveit_studio::behaviors::BehaviorContext>& shared_resources)
: ServiceClientBehaviorBase<example_interfaces::srv::AddTwoInts>(name, config, shared_resources)
{
}
BT::PortsList MyAddTwoIntsServiceClient::providedPorts()
{
// This node has three input ports and one output port
return BT::PortsList({
BT::InputPort<std::string>("service_name", "/add_two_ints", "The name of the service to call."),
BT::InputPort<int>("addend1", "The first int to add to the other."),
BT::InputPort<int>("addend2", "The second int to add to the other."),
BT::OutputPort<int>("result", "{result}", "Result of the AddTwoInts service."),
});
}
BT::KeyValueVector MyAddTwoIntsServiceClient::metadata()
{
return { { "subcategory", "Example Behaviors" },
{ "description", "Calls a service to add two integers and makes the result available on an output port." } };
}
tl::expected<std::string, std::string> MyAddTwoIntsServiceClient::getServiceName()
{
const auto service_name = getInput<std::string>("service_name");
if (const auto error = moveit_studio::behaviors::maybe_error(service_name))
{
return tl::make_unexpected("Failed to get required value from input data port: " + error.value());
}
return service_name.value();
}
tl::expected<AddTwoInts::Request, std::string> MyAddTwoIntsServiceClient::createRequest()
{
const auto a = getInput<int>("addend1");
const auto b = getInput<int>("addend2");
if (const auto error = moveit_studio::behaviors::maybe_error(a, b))
{
return tl::make_unexpected("Failed to get required value from input data port: " + error.value());
}
return example_interfaces::build<AddTwoInts::Request>().a(a.value()).b(b.value());
}
tl::expected<bool, std::string> MyAddTwoIntsServiceClient::processResponse(const AddTwoInts::Response& response)
{
setOutput<int>("result", response.sum);
return { true };
}
} // namespace my_behavior
To publish a toast message with your result, add the following to your processResponse()
method:
shared_resources_->logger->publishInfoMessage("Sum:", std::to_string(response.sum));
Include and register the Behavior in register_behaviors.cpp
:
#include <my_behavior/service_client.hpp>
moveit_studio::behaviors::registerBehavior<MyAddTwoIntsServiceClient>(factory, "MyAddTwoIntsServiceClient", shared_resources);
Click to reference the full register_behaviors.cpp
#include <behaviortree_cpp/bt_factory.h>
#include <moveit_studio_behavior_interface/behavior_context.hpp>
#include <moveit_studio_behavior_interface/shared_resources_node_loader.hpp>
#include <my_behavior/my_behavior.hpp>
#include <my_behavior/service_client.hpp>
#include <pluginlib/class_list_macros.hpp>
namespace my_behavior
{
class MyBehaviorBehaviorsLoader : public moveit_studio::behaviors::SharedResourcesNodeLoaderBase
{
public:
void registerBehaviors(BT::BehaviorTreeFactory& factory,
[[maybe_unused]] const std::shared_ptr<moveit_studio::behaviors::BehaviorContext>& shared_resources) override
{
moveit_studio::behaviors::registerBehavior<MyBehavior>(factory, "MyBehavior", shared_resources);
moveit_studio::behaviors::registerBehavior<MyAddTwoIntsServiceClient>(factory, "MyServiceClient", shared_resources);
}
};
} // namespace my_behavior
PLUGINLIB_EXPORT_CLASS(my_behavior::MyBehaviorBehaviorsLoader,
moveit_studio::behaviors::SharedResourcesNodeLoaderBase);
Update CMakeLists.txt
to build your new Behavior by adding the example_interfaces
dependency and linking src/service_client.cpp
:
set(THIS_PACKAGE_INCLUDE_DEPENDS moveit_studio_behavior_interface pluginlib example_interfaces)
add_library(
my_behavior
SHARED
src/my_behavior.cpp
src/service_client.cpp
src/register_behaviors.cpp)
Click to reference the full CMakeLists.txt
cmake_minimum_required(VERSION 3.22)
project(my_behavior CXX)
find_package(moveit_studio_common REQUIRED)
moveit_studio_package()
set(THIS_PACKAGE_INCLUDE_DEPENDS moveit_studio_behavior_interface pluginlib example_interfaces)
foreach(package IN ITEMS ${THIS_PACKAGE_INCLUDE_DEPENDS})
find_package(${package} REQUIRED)
endforeach()
add_library(
my_behavior
SHARED
src/my_behavior.cpp
src/service_client.cpp
src/register_behaviors.cpp)
target_include_directories(
my_behavior
PUBLIC $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
$<INSTALL_INTERFACE:include>)
ament_target_dependencies(my_behavior
${THIS_PACKAGE_INCLUDE_DEPENDS})
# Install Libraries
install(
TARGETS my_behavior
EXPORT my_behaviorTargets
ARCHIVE DESTINATION lib
LIBRARY DESTINATION lib
RUNTIME DESTINATION bin
INCLUDES
DESTINATION include)
if(BUILD_TESTING)
moveit_pro_behavior_test(my_behavior)
endif()
# Export the behavior plugins defined in this package so they are available to
# plugin loaders that load the behavior base class library from the
# moveit_studio_behavior package.
pluginlib_export_plugin_description_file(
moveit_studio_behavior_interface my_behavior_plugin_description.xml)
ament_export_targets(my_behaviorTargets HAS_LIBRARY_TARGET)
ament_export_dependencies(${THIS_PACKAGE_INCLUDE_DEPENDS})
ament_package()
Update package.xml
with our new dependency:
<depend>example_interfaces</depend>
Click to reference the full package.xml
<?xml version="1.0" encoding="utf-8" ?>
<package format="3">
<name>my_behavior</name>
<version>0.0.0</version>
<description>My description</description>
<maintainer email="support@picknik.ai">
MoveIt Pro User
</maintainer>
<author email="support@picknik.ai">
MoveIt Pro User
</author>
<license>TODO</license>
<buildtool_depend>ament_cmake</buildtool_depend>
<build_depend>moveit_studio_common</build_depend>
<depend>moveit_studio_behavior_interface</depend>
<depend>example_interfaces</depend>
<test_depend>ament_lint_auto</test_depend>
<test_depend>ament_cmake_gtest</test_depend>
<export>
<build_type>ament_cmake</build_type>
</export>
<buildtool_depend>python3-colcon-common-extensions</buildtool_depend>
</package>
Communicating With External ROS Interfacesβ
Next we will test out our previously built custom Behavior.
First, start MoveIt Pro, then in a separate terminal enter a shell (moveit_pro shell
):
Confirm that our previous Dockerfile update installed the example service by searching for it:
ros2 pkg list | grep examples_rclcpp_minimal_service
If installed, you should see the package examples_rclcpp_minimal_service in the output.
Temporarily install the example service
If you did not modify the Dockerfile, you can install it temporarily in the open container with the following command:
sudo apt update && sudo apt install ros-humble-examples-rclcpp-minimal-service
Then run in that same shell:
ros2 run examples_rclcpp_minimal_service service_main
Check out the Behavior Specialization section for more examples of specialized Behaviors to communicate with ROS interfaces like topics, services, and actions.
Nice work!
Summaryβ
This tutorial introduced advanced usage of MoveIt Pro for customizing and deploying robotic applications. You learned how to use the moveit_pro CLI, create and extend robot configuration packages, develop custom Behaviors, and integrate with external ROS interfaces. You also saw how to run Objectives programmatically using the MoveIt Pro SDKβequipping you with the tools to build and deploy production-grade robotic systems.