# collections

id: c502b221-cbba-48f5-9f57-26dfa50f986e
name: langchain
database_id: 00000000-0000-0000-0000-000000000000
config_json_str:
{"hnsw_configuration": {"space": "l2", "ef_construction": 100, "ef_search": 10, "num_threads": 8, "M": 16, "resize_factor": 1.2, "batch_size": 100, "sync_threshold": 1000, "_type": "HNSWConfigurationInternal"}, "_type": "CollectionConfigurationInternal"}


# embedding_metadata

key: chroma:document
string_value:
Title: Getting Started

URL: https://moveit.picknik.ai/main/doc/tutorials/getting_started/getting_started.html

Section: index.html

--------------------------------------------------------------------------------

## Install ROS 2 and colcon

MoveIt 2 currently supports multiple versions of ROS.

Install whichever version you prefer.

We primarily support ROS installed on Ubuntu 22.04 or 24.04 but other methods and platforms may work with small changes to the instructions listed below.

If you are just getting started, we recommend you use the latest stable version of ROS (Jazzy) on Ubuntu 24.04 for the most seamless experience.

It is easy to miss steps when going through the ROS 2 installation tutorial.

If you run into errors in the next few steps, a good place to start is to go back and make sure you have installed ROS 2 correctly.

One that users commonly forget is to source the ROS 2 install itself.

Note to source the version of ROS you installed.

Installrosdepto install system dependencies :


key: chroma:document
string_value:
Installrosdepto install system dependencies :

Once you have ROS 2 installed, make sure you have the most up to date packages:

InstallColconthe ROS 2 build system withmixin:

Installvcstool:

## Create A Colcon Workspace and Download Tutorials

For tutorials you will need to have acolconworkspace setup.

## Download Source Code of MoveIt and the Tutorials

Move into your Colcon workspace and pull the MoveIt tutorials source, where<branch>can be e.g.humblefor ROS Humble, ormainfor the latest version of the tutorials :

Next we will download the source code for the rest of MoveIt:

The import command may ask for your GitHub credentials.

You can just press Enter until it moves on (ignore the “Authentication failed” error).

## Build your Colcon Workspace

First remove all previously installed moveit binaries:

The following will install from Debian any package dependencies not already in your workspace.

This is the step that will install MoveIt and all of its dependencies:


key: chroma:document
string_value:
The next command will configure your Colcon workspace:

This build command will likely take a long time (20+ minutes) depending on your computer speed and amount of RAM available (we recommend 32 GB).

If everything goes well, you should see the message “Summary: X packages finished” where X might be 50. If you have problems, try re-checking yourROS Installation.

## Setup Your Colcon Workspace

Source the Colcon workspace:

Optional: add the previous command to your.bashrc:

## Next Step

Nice job!

Next, we willVisualize a robot with the interactive motion planning plugin for RViz

Code Examples:

Language: unknown

```

source

/

opt

/

ros

/

jazzy

/

setup

.

bash

```

Language: unknown

File: .bashrc

```

sudo

apt

install

python3

rosdep

```

Language: unknown

File: .bashrc

```

sudo

rosdep

init

rosdep

update

sudo

apt

update

sudo

apt

dist

upgrade

```

Language: unknown

File: .bashrc

```

sudo

apt

install

python3

colcon

common

extensions

sudo

apt

install

python3


key: chroma:document
string_value:
colcon

common

extensions

sudo

apt

install

python3

colcon

mixin

colcon

mixin

add

default

https

:

//

raw

.

githubusercontent

.

com

/

colcon

/

colcon

mixin

repository

/

master

/

index

.

yaml

colcon

mixin

update

default

```

Language: unknown

File: .bashrc

```

sudo

apt

install

python3

vcstool

```

Language: unknown

File: .bashrc

```

mkdir

p

~/

ws_moveit

/

src

```

Language: unknown

File: main

```

cd

~/

ws_moveit

/

src

git

clone

b

<

branch

>

https

:

//

github

.

com

/

moveit

/

moveit2_tutorials

```

Language: unknown

File: main

```

vcs

import

--

recursive

<

moveit2_tutorials

/

moveit2_tutorials

.

repos

```

Language: unknown

File: main

```

sudo apt remove ros-$ROS_DISTRO-moveit*

```

Language: unknown

File: main

```

sudo apt update && rosdep install -r --from-paths . --ignore-src --rosdistro $ROS_DISTRO -y

```

Language: unknown

File: main

```

cd

~/

ws_moveit

colcon

build

--

mixin

release

```


key: chroma:document
string_value:
```

cd

~/

ws_moveit

colcon

build

--

mixin

release

```

Language: unknown

File: MAKEFLAGS="-j4-l1"colconbuild--executorsequential

```

source

~/

ws_moveit

/

install

/

setup

.

bash

```

Language: unknown

File: .bashrc

```

echo

'source ~/ws_moveit/install/setup.bash'

>>

~/.

bashrc

```


key: chroma:document
string_value:
Title: Python API Documentation

URL: https://moveit.picknik.ai/main/doc/api/python_api/api.html

Section: index.html

--------------------------------------------------------------------------------


key: chroma:document
string_value:
Title: Planning Scene Monitor

URL: https://moveit.picknik.ai/main/doc/concepts/planning_scene_monitor.html

Section: index.html

--------------------------------------------------------------------------------

## World Geometry Monitor The world geometry monitor builds world geometry using information from the sensors on the robot such as LIDARs or depth cameras and from user input. It uses theoccupancymapmonitordescribed below to build a 3D representation of the environment around the robot and augments that with information on theplanning_scenetopic for adding object information.

## 3D Perception 3D perception in MoveIt is handled by theoccupancymapmonitor. The occupancy map monitor uses a plugin architecture to handle different kinds of sensor input as shown in the Figure above. In particular, MoveIt has inbuilt support for handling two kinds of inputs: Note that you can add your own types of updaters as a plugin to the occupancy map monitor.


key: chroma:document
string_value:
## Octomap The Occupancy map monitor uses anOctomapto maintain the occupancy map of the environment. The Octomap can actually encode probabilistic information about individual cells although this information is not currently used in MoveIt. The Octomap can directly be passed into FCL, the collision checking library that MoveIt uses.

## Depth Image Occupancy Map Updater The depth image occupancy map updater includes its ownself-filter, i.e. it will remove visible parts of the robot from the depth map. It uses current information about the robot (the robot state) to carry out this operation.


key: chroma:document
string_value:
Title: How to Cross

Reference Content

URL: https://moveit.picknik.ai/main/doc/how_to_contribute/how_to_cross_reference.html

Section: index.html

--------------------------------------------------------------------------------

## Learning Objectives


key: chroma:document
string_value:
## Learning Objectives

## Linking to other Documents and Sections Sphinx provides the:doc:and:ref:roles forcross-referencing contentand it’s best to stick to them to ensure compatibility with other Sphinx extensions and multi-distro support. For linking to other documents, you can use the:doc:role like this:Getting Started(:doc:`/doc/tutorials/getting_started/getting_started`). The:ref:role accepts ids that link to explicit targets on a page. For convenience, we have enabled the Sphinx extensionautosectionlabelwhich creates unique and human-readable reference targets for all sections. Sections in all documents can be linked by providing the document path and the section titlelike this(:ref:`likethis<doc/tutorials/getting_started/getting_started:InstallROS2andColcon>`). Note that the:doc:role requires absolute paths to start with a/while theautosectionlabelextension builds:refpath labels without it.


key: chroma:document
string_value:
## Referencing the API Documentation The API pages are generated using Doxygen and not Sphinx which means that:doc:and:ref:roles are not able to find any API pages. We are usingdoxylinkand the custom:cpp_api:role for generating links to the API pages from symbols. Here are some examples, take note that some links use titles and some not: If you are unsure about how to link certain symbols, you can find all Doxygen references inside theMoveIt.tagfile. The file is located insidebuild/html/api/orbuild/html/<branch>/api/depending on the build type.

## Do’s and Don’ts

Pleasedo:

Pleasedon’t:

## Further Reading


key: chroma:document
string_value:
Title: How

To Guides

URL: https://moveit.picknik.ai/main/doc/how_to_guides/how_to_guides.html

Section: doc/how_to_guides/how_to_guides.html

--------------------------------------------------------------------------------


key: chroma:document
string_value:
Title: API Documentation

URL: https://moveit.picknik.ai/main/doc/api/api.html

Section: index.html

--------------------------------------------------------------------------------


key: chroma:document
string_value:
Title: MoveIt Task Constructor

URL: https://moveit.picknik.ai/main/doc/concepts/moveit_task_constructor/moveit_task_constructor.html

Section: index.html

--------------------------------------------------------------------------------

## What is MoveIt Task Constructor?

## MTC Stages There are three possible stages relating to the result flow:

## Generator Stage

## Propagating Stage

## Connecting Stage

## Wrapper

## MTC Containers

Currently available containers:

## Serial Container

## Parallel Container Parallel containers combine a set of stages to allow planning alternate solutions.

## Initializing a MTC Task The top-level planning problem is specified as a MTC Task and the subproblems which are specified by Stages are added to the MTC task object.

## Adding containers and stages to a MTC Task Adding a stage to MTC task Containers derive from Stage and hence containers can be added to MTC task similarly


key: chroma:document
string_value:
## Setting planning solvers Stages that do motion planning need solver information. Solvers available in MTC Code Example on how to initialize the solver These solvers will be passed into stages likeMoveTo,MoveRelative, andConnect.

## Setting Properties

## Cost calculator for Stages CostTerm is the basic interface to compute costs for solutions for MTC stages. CostTerm implementations available in MTC Example code on how to set CostTerm usingLambdaCostTerm All stages provided by MTC have default cost terms. Stages which produce trajectories as solutions usually use path length to calculate cost.


key: chroma:document
string_value:
## Planning and Executing a MTC Task Planning an MTC task will return aMoveItErrorCode. Referhereto identity the different error types. If planning succeeds, you can expect the plan function to returnmoveit_msgs::msg::MoveItErrorCodes::SUCCESS. After planning, extract the first successful solution and pass it to the execute function. This will create anexecute_task_solutionaction client. The action server resides in theexecute_task_solution_capabilityplugin provided by MTC. The plugin extendsMoveGroupCapability. It constructs aMotionPlanRequestfrom the MTC solution and uses MoveIt’sPlanExecutionto actuate the robot.

## Links to Additional Information Here is atutorialon how to create a Pick and Place pipeline using MTC. The links listed below contain more information on stages and containers provided by MTC

Code Examples:


key: chroma:document
string_value:
Code Examples:

Language: unknown File: GeneratePose ``` auto node = std :: make_shared < rclcpp :: Node > (); auto task = std :: make_unique < moveit :: task_constructor :: Task > (); task -> loadRobotModel ( node ); // Set controllers used to execute robot motion. If not set, MoveIt has controller discovery logic. task -> setProperty ( "trajectory_execution_info" , "joint_trajectory_controller gripper_controller" ); ```

Language: unknown

File: GeneratePose

```

auto

current_state

=

std

::

make_unique

<

moveit

::

task_constructor

::

stages

::

CurrentState

>

(

"current_state"

);

task

>

add

(

std

::

move

(

current_state

));

```

Language: unknown File: GeneratePose ``` auto container = std :: make_unique < moveit :: task_constructor :: SerialContainer > ( "Pick Object" ); // TODO: Add stages to the container before adding the container to MTC task task -> add ( std :: move ( container )); ```

Language: unknown

File: CartesianPath

```

const

auto

mtc_pipeline_planner

=


key: chroma:document
string_value:
File: CartesianPath

```

const

auto

mtc_pipeline_planner

=

std

::

make_shared

<

moveit

::

task_constructor

::

solvers

::

PipelinePlanner

>

(

node

,

"ompl"

,

"RRTConnectkConfigDefault"

);

const

auto

mtc_joint_interpolation_planner

=

std

::

make_shared

<

moveit

::

task_constructor

::

solvers

::

JointInterpolationPlanner

>

();

const

auto

mtc_cartesian_planner

=

std

::

make_shared

<

moveit

::

task_constructor

::

solvers

::

CartesianPath

>

();

```

Language: unknown

File: Connect

```

void

setProperty

(

const

std

::

string

&

name

,

const

boost

::

any

&

value

);

```

Language: unknown

File: LambdaCostTerm

```

stage

>

setCostTerm

(

moveit

::

task_constructor

::

LambdaCostTerm

(

[](

const

moveit

::

task_constructor

::

SubTrajectory

&

traj

)

{

return

100

traj

.

cost

();

}));

```

Language: unknown

File: moveit_msgs::msg::MoveItErrorCodes::SUCCESS

```

auto

error_code

=

task

.

plan

()

```


key: chroma:document
string_value:
```

auto

error_code

=

task

.

plan

()

```

Language: unknown

File: PlanExecution

```

auto

result

=

task

.

execute

(

task

.

solutions

().

front

());

```


key: chroma:document
string_value:
Title: MoveIt Quickstart in RViz URL: https://moveit.picknik.ai/main/doc/tutorials/quickstart_in_rviz/quickstart_in_rviz_tutorial.html Section: index.html --------------------------------------------------------------------------------

## Getting Started If you haven’t already done so, make sure you’ve completed the steps inGetting Startedor ourDocker Guide. If you followed the Docker Guide, also follow theCreate A Colcon Workspace and Download Tutorialsguide onwards to set up the tutorials.

## Step 1: Launch the Demo and Configure the Plugin

## Step 2: Play with the Visualized Robots There are four different overlapping visualizations: The display states for each of these visualizations can be toggled on and off using checkboxes:


key: chroma:document
string_value:
## Step 3: Interact with the Kinova Gen 3 For the next steps we will want only the scene robot, start state and goal state: There should now be two interactive markers. One marker corresponding to the orange colored arm will be used to set the “Goal State” for motion planning and the other marker corresponding to a green colored arm are used to set the “Start State” for motion planning. If you don’t see the interactive markers pressInteractin the top menu of RViz (Note: some tools may be hidden, press“+”in the top menu to add theInteracttool as shown below). You should now be able to use these markers to drag the arm around and change its orientation. Try it!


key: chroma:document
string_value:
## Moving into collision For this section, hide the planned path and the goal state: Now, only the Start State (the green colored arm) should be visible.  Try to move the arm into a configuration where two of its links are in collision with each other.  (If you find this difficult, make sure the “Use Collision-Aware IK” checkbox under the Planning tab of the MotionPlanning plugin is un-checked.)  Once you do this, the links that are in collision will turn red. Now, check the “Use Collision-Aware IK” checkbox, and try again to move two of the links into collision with each other.  When the checkbox is ticked, the IK solver will keep attempting to find a collision-free solution for the desired end-effector pose. When it is not checked, the solver will allow collisions to happen in the solution. The links in collision will always still be visualized in red, regardless of the state of the checkbox.


key: chroma:document
string_value:
## Moving out of Reachable Workspace Note what happens when you try to move an end-effector out of its reachable workspace. Before moving onto the next section, re-enable the planned path and the goal state:

## Moving Joints or in Null Space You can use theJointstab to move single joints and the redundant joints of 7-DOF robots. Try moving the “null space exploration” slider as shown in the animation below.

## Step 4: Use Motion Planning with the Kinova Gen 3

## Introspecting Trajectory Waypoints You can visually introspect trajectories point by point in RViz. Note: Once you placed your end-effector to a new goal, be sure to runPlanbefore runningPlay– otherwise you’ll see the waypoints for the previous goal if available.

## Plan Cartesian motions If the “Use Cartesian Path” checkbox is activated, the robot will attempt to move the end effector linearly in cartesian space.


key: chroma:document
string_value:
## Executing Trajectories, Adjusting Speed Clicking “Plan & Execute” or “Execute” after a successful plan will send the trajectory to the robot - in this tutorial, since you usedkinova_demo.launch, the robot is only simulated. Initially, the default velocity and acceleration are scaled to 10% (0.1) of the robot’s maximum. You can change these scaling factors in the Planning tab shown below, or change these default values in themoveit_configof your robot (injoint_limits.yaml).

## Next Steps

## RViz Visual Tools Many of the tutorials usemoveit_visual_toolsto step through a demo. Before continuing on to the next tutorials it is a good idea to enable theRvizVisualToolsGui. From “Panels” menu, select “Add New Panels”. From the menu, select “RvizVisualToolsGui” and click OK. You’ll see the new panel added to RViz.


key: chroma:document
string_value:
## Saving Your Configuration RViz enables you to save your configuration underFile->SaveConfig. You should do this before continuing on to the next tutorials. If you choose to save your configuration under a new name, you can useFile->SaveConfigAsand refer to your configuration file using: Replaceyour_rviz_config.rvizwith the name of the file you saved tomoveit2_tutorials/doc/tutorials/quickstart_in_rviz/launch/and build the workspace so it can be found.

## Next Tutorial InYour First MoveIt Project, you will create a C++ program using MoveIt to plan and execute moves.

Code Examples:

Language: unknown

```

ros2

launch

moveit2_tutorials

demo

.

launch

.

py

```

Language: unknown

File: File

>SaveConfigAs

```

ros2

launch

moveit2_tutorials

demo

.

launch

.

py

rviz_config

:=

your_rviz_config

.

rviz

```


key: chroma:document
string_value:
Title: Visualizing In RViz

URL: https://moveit.picknik.ai/main/doc/tutorials/visualizing_in_rviz/visualizing_in_rviz.html

Section: index.html

--------------------------------------------------------------------------------

## Prerequisites

If you haven’t already done so, make sure you’ve completed the steps inYour First Project.

This project assumes you are starting with thehello_moveitproject, where the previous tutorial left off.

## Steps

## 1 Add the dependency moveit_visual_tools

Add this line to yourpackage.xmlin thehello_moveitproject after the other<depend>statements:

Then in yourCMakeLists.txtadd this line to the section offind_packagestatements:

Further down in the file extend theament_target_dependenciesmacro call to include the new dependency like this:

To verify that you added the dependency correctly, add the required include to your source filehello_moveit.cpp:


key: chroma:document
string_value:
To test that this all worked, open a terminal in the workspace directory (remembering to source your ROS install in opt) and then build with colcon:

## 2 Create a ROS executor and spin the node on a thread

Before we can initialize MoveItVisualTools, we need to have a executor spinning on our ROS node.

This is necessary because of how MoveItVisualTools interacts with ROS services and topics. First, add the threading library to your includes at the top.

By creating and naming loggers, we are able to keep our program logs organized.

Next, add your executor before creating the MoveIt MoveGroup Interface.

Finally, make sure to join the thread before exiting.

After making these changes, rebuild your workspace to make sure you don’t have any syntax errors.

## 3 Create and Initialize MoveItVisualTools

Next, we will construct and initialize MoveItVisualTools after the construction of MoveGroupInterface.


key: chroma:document
string_value:
We pass the following into the constructor: the ROS node, the base link of the robot, the marker topic to use (more on this later), and the robot model (which we get from the move_group_interface).

Next, we make a call to delete all the markers. This clears any rendered state out of RViz that we have left over from previous runs.

Lastly, we load remote control.

Remote control is a really simple plugin that lets us have a button in RViz to interact with our program.

## 4 Write closures for visualizations

After we’ve constructed and initialized, we now create some closures (function objects that have access to variables in our current scope) that we can use later in our program to help render visualizations in RViz.

Each of the three closures capturemoveit_visual_toolsby reference and the last one captures a pointer to the joint model group object we are planning with.

Each of these call a function onmoveit_visual_toolsthat changes something in RViz.


key: chroma:document
string_value:
You might be asking yourself why we would create lambdas like this, and the reason is simply to make the code that comes later easier to read and understand.

As your write software, it is often helpful to break up your functionality into named functions which can be easily reused and tested on their own.

You will see in the next section how we use these functions we created.

## 5 Visualize the steps of your program

Now we’ll augment the code in the middle of your program.

Update your code for planning and executing to include these new features:

One thing you’ll quickly notice is that we have to call a method calledtriggeronmoveit_visual_toolsafter each call to change something rendered in RViz.

The reason for this is that messages sent to RViz are batched up and sent when you calltriggerto reduce bandwidth of the marker topics.

Lastly, build your project again to make sure all the code additions are correct.

## 6 Enable visualizations in RViz


key: chroma:document
string_value:
## 6 Enable visualizations in RViz

Open a new terminal, source the workspace, and then start the demo launch file that opens RViz.

Uncheck “MotionPlanning” in the “Displays” tab to hide it.

We aren’t going to be using the “MotionPlanning” plugin for this next part.

To add the buttons to interact with the prompts we added to our program open the dialog with the “Panels/Add New Panel” menu:

Then selectRvizVisualToolsGuiand click OK.

This will create a new panel on the bottom left with aNextbutton we’ll use later.

Finally, we need to add aMarkerArrayto render the visualizations we’ve added.

Click on the “Add” Button in the “Displays” panel.

SelectMarkerArrayand clickOK.

Scroll to the bottom of the items in the Displays panel and edit the topic that the new Marker Array is using to/rviz_visual_tools.

You are now ready to run your new program with visualizations.

## 7 Run the Program

In a new terminal, go to the workspace, source the workspace, and runhello_moveit:


key: chroma:document
string_value:
You’ll notice that your program has stopped with a log that looks like this:

Click theNextbutton in RViz and see your application advance.

You’ll see after you clicked the next button, your application planned, added a title above the robot, and drew a line representing the tool path.

To continue, pressNextagain to see your robot execute the plan.

## Summary

You extended the program you wrote with MoveIt to interact with the Gui in RViz, allowing you to step through your program with a button, render some text above the robot, and display the tool path that you planned.

## Further Reading

## Next Step

In the next tutorialPlanning Around Objects, you will expand on the program you built here to add to the collision environment and see the robot plan with these changes.

Code Examples:

Language: unknown

File: <depend>

```

<depend>

moveit_visual_tools

</depend>

```

Language: unknown

File: find_package

```

find_package

(

moveit_visual_tools

REQUIRED

)

```

Language: unknown


key: chroma:document
string_value:
(

moveit_visual_tools

REQUIRED

)

```

Language: unknown

File: ament_target_dependencies

```

ament_target_dependencies

(

hello_moveit

"moveit_ros_planning_interface"

"moveit_visual_tools"

"rclcpp"

)

```

Language: unknown

File: hello_moveit.cpp

```

#include

<moveit_visual_tools/moveit_visual_tools.h>

```

Language: unknown

File: hello_moveit.cpp

```

cd

~/ws_moveit

colcon

build

--mixin

debug

```

Language: unknown

File: hello_moveit.cpp

```

#include

<thread>

// <---- add this to the set of includes at the top

```

Language: unknown

File: hello_moveit.cpp

```

// Create a ROS logger

auto

const

logger

=

rclcpp

::

get_logger

(

"hello_moveit"

);

```

Language: unknown

File: hello_moveit.cpp

```

// Spin up a SingleThreadedExecutor for MoveItVisualTools to interact with ROS

rclcpp

::

executors

::

SingleThreadedExecutor

executor

;

executor

.

add_node

(

node

);

auto

spinner

=

std

::

thread

([

&

executor

]()

{

executor

.

spin

();

});


key: chroma:document
string_value:
thread

([

&

executor

]()

{

executor

.

spin

();

});

// Create the MoveIt MoveGroup Interface

...

```

Language: unknown

File: hello_moveit.cpp

```

// Shutdown ROS

rclcpp

::

shutdown

();

// <--- This will cause the spin function in the thread to return

spinner

.

join

();

// <--- Join the thread before exiting

return

0

;

```

Language: unknown

File: hello_moveit.cpp

```

// Create the MoveIt MoveGroup Interface

using

moveit

::

planning_interface

::

MoveGroupInterface

;

auto

move_group_interface

=

MoveGroupInterface

(

node

,

"manipulator"

);

// Construct and initialize MoveItVisualTools

auto

moveit_visual_tools

=

moveit_visual_tools

::

MoveItVisualTools

{

node

,

"base_link"

,

rviz_visual_tools

::

RVIZ_MARKER_TOPIC

,

move_group_interface

.

getRobotModel

()};

moveit_visual_tools

.

deleteAllMarkers

();

moveit_visual_tools

.

loadRemoteControl

();

```

Language: unknown

File: hello_moveit.cpp

```

// Create closures for visualization


key: chroma:document
string_value:
```

// Create closures for visualization

auto

const

draw_title

=

[

&

moveit_visual_tools

](

auto

text

)

{

auto

const

text_pose

=

[]

{

auto

msg

=

Eigen

::

Isometry3d

::

Identity

();

msg

.

translation

().

z

()

=

1.0

;

// Place text 1m above the base link

return

msg

;

}();

moveit_visual_tools

.

publishText

(

text_pose

,

text

,

rviz_visual_tools

::

WHITE

,

rviz_visual_tools

::

XLARGE

);

};

auto

const

prompt

=

[

&

moveit_visual_tools

](

auto

text

)

{

moveit_visual_tools

.

prompt

(

text

);

};

auto

const

draw_trajectory_tool_path

=

[

&

moveit_visual_tools

,

jmg

=

move_group_interface

.

getRobotModel

()

>

getJointModelGroup

(

"manipulator"

)](

auto

const

trajectory

)

{

moveit_visual_tools

.

publishTrajectoryLine

(

trajectory

,

jmg

);

};

```

Language: unknown

File: next

```

// Set a target Pose

auto

const

target_pose

=

[]

{

geometry_msgs

::

msg

::

Pose

msg

;

msg

.

orientation

.

w

=


key: chroma:document
string_value:
::

msg

::

Pose

msg

;

msg

.

orientation

.

w

=

1.0

;

msg

.

position

.

x

=

0.28

;

msg

.

position

.

y

=

0.2

;

msg

.

position

.

z

=

0.5

;

return

msg

;

}();

move_group_interface

.

setPoseTarget

(

target_pose

);

// Create a plan to that target pose

prompt

(

"Press 'Next' in the RvizVisualToolsGui window to plan"

);

draw_title

(

"Planning"

);

moveit_visual_tools

.

trigger

();

auto

const

[

success

,

plan

]

=

[

&

move_group_interface

]

{

moveit

::

planning_interface

::

MoveGroupInterface

::

Plan

msg

;

auto

const

ok

=

static_cast

<

bool

>

(

move_group_interface

.

plan

(

msg

));

return

std

::

make_pair

(

ok

,

msg

);

}();

// Execute the plan

if

(

success

)

{

draw_trajectory_tool_path

(

plan

.

trajectory

);

moveit_visual_tools

.

trigger

();

prompt

(

"Press 'Next' in the RvizVisualToolsGui window to execute"

);

draw_title

(

"Executing"

);

moveit_visual_tools

.

trigger

();


key: chroma:document
string_value:
(

"Executing"

);

moveit_visual_tools

.

trigger

();

move_group_interface

.

execute

(

plan

);

}

else

{

draw_title

(

"Planning Failed!"

);

moveit_visual_tools

.

trigger

();

RCLCPP_ERROR

(

logger

,

"Planning failed!"

);

}

```

Language: unknown

File: trigger

```

cd

~/ws_moveit

source

/opt/ros/rolling/setup.bash

colcon

build

--mixin

debug

```

Language: unknown

File: trigger

```

cd

~/ws_moveit

source

install/setup.bash

ros2

launch

moveit2_tutorials

demo.launch.py

```

Language: unknown

File: hello_moveit

```

cd

~/ws_moveit

source

install/setup.bash

ros2

run

hello_moveit

hello_moveit

```

Language: unknown

File: hello_moveit

```

[

INFO

]

[

1652822889.492940200

]

[

hello_moveit

.

remote_control

]:

Waiting

to

continue

:

Press

'Next'

in

the

RvizVisualToolsGui

window

to

plan

```


key: chroma:document
string_value:
Title: MoveIt 2 Documentation

URL: https://moveit.picknik.ai/main/index.html

Section: index.html

--------------------------------------------------------------------------------

## How

To Use This Website

## Table Of Contents

## Attribution Some major past contributors to the MoveIt tutorials are listed in chronological order: Sachin Chitta, Dave Hershberger, Acorn Pooley, Dave Coleman, Michael Goerner, Francisco Suarez, Mike Lautman, Tyler Weaver, David Lu!!, Vatan Tezer, and Andy Zelenak. These are just some of the46+ Contributors over the yearswho have a big impact on this documentation. Help us improve these docs and we’ll be happy to include you here also!

## Corporate Sponsorship


key: chroma:document
string_value:
Title: How to Write a MoveIt How-To Guide URL: https://moveit.picknik.ai/main/doc/how_to_contribute/how_to_write_how_to_guides.html Section: index.html --------------------------------------------------------------------------------

## Learning Objectives

## Requirements

## Steps

## Template

## Further Reading

Code Examples:

Language: unknown

File: .rst

```

<

Title

>

------

<

Brief

description

of

the

How

To

Guide

with

image

or

GIF

showing

the

outcome

.>

Learning

Objectives

------------------

<

List

of

things

the

user

will

learn

.>

Requirements

---------

<

Explanation

of

what

the

user

should

understand

.

Unlike

a

tutorial

,

these

guides

stand

alone

and

can

assume

the

user

has

much

more

background

.>

Steps

----

<

A

list

of

steps

to

take

to

solve

the

problem

.>

Further

Reading

--------------

<

A

list

of

links

to

related

content

on

and

off

this

website

.>

```


key: chroma:document
string_value:
Title: Concepts

URL: https://moveit.picknik.ai/main/doc/concepts/concepts.html

Section: doc/concepts/concepts.html

--------------------------------------------------------------------------------


key: chroma:document
string_value:
Title: Hybrid Planning

URL: https://moveit.picknik.ai/main/doc/concepts/hybrid_planning/hybrid_planning.html

Section: index.html

--------------------------------------------------------------------------------


key: chroma:document
string_value:
## What is Hybrid Planning? Hybrid Planning is a term for a motion planning method that combines heterogeneous motion planners to produce more robust or reactive solutions. The general approach is already very established in the Navigation community and successfully implemented in popular projects like navigation2. MoveIt’s Hybrid Planning architecture combines a pair of global and local planners that run in parallel and recurrently with different planning speeds and problem scopes. The global planner has the task to solve a global motion planning problem very akin to the planners used in a “Sense-Plan-Act” application. The used planner algorithm should be complete and is therefore assumed to be relatively slow in terms of computation time. Furthermore, the global planner is not required to be real-time safe, meaning that there are no guarantees that the planner finds a solution within a specific deadline. Depending on the planner implementation, the global planner may generate one initial solution or


key: chroma:document
string_value:
the global planner may generate one initial solution or iteratively optimized solutions during the execution. The local planner is running continuously during execution and produces iterative robot commands for following the global trajectory. In a way, the local planner resembles a controller, only that the architecture allows for solving more complicated problems and constraints. The idea is that the planner is able to reason about the world and to have an internal state. That property makes it very versatile and as it can be used for solving combinations of arbitrary local planning problems, as for example: In order to enable solving these local problems the local planner must be fast, able to react to sensor feedback and in many cases real-time safe. Also, it should be deterministic in order to avoid jerky or unpredictable motions. In general, the local planner relies on the reference trajectory produced by the global planner so that it doesn’t get stuck in a local minimum. Since local minima sometimes


key: chroma:document
string_value:
get stuck in a local minimum. Since local minima sometimes still can’t be ruled out, it can be required that the global planner is triggered for a replan in order to still reach the desired goal. This behavior requires a certain way to communicate planner events and to process them accordingly. For that purpose the Hybrid Planning architecture allows implementing an event-based logic that can be customized for the specific use case and planner types. Hybrid Planning can be useful in a broad range of use cases. Most of the applications can be grouped into the following three scenarios.


key: chroma:document
string_value:
## The Hybrid Planning Architecture The diagram below depicts the fundamental plugin types and ROS interfaces that make up the Hybrid Planning architecture. The architecture is structured in three ROS component nodes: The architecture components are designed to be generic and highly customizable. Since the components only interact via ROS 2 message interfaces, it’s very easy to replace implementations of each of the architecture’s components or plugins. The plugin interfaces are designed to be minimal and to abstract from the actual algorithm implementation as much as possible. That allows the developer to fully focus on the isolated logic or solvers without having to implement any parts of the infrastructure. This also allows reusing the same components for different setups or planning problems.


key: chroma:document
string_value:
## Hybrid Planning Manager This component is “The Brain” of the architecture. Its main purpose is to process HybridPlanner action  requests and to coordinate the motion planning and execution process based on the planning logic plugin. The planning logic is implemented in the PlanningLogic plugin and is event-driven by design. Events are defined by string identifiers and may trigger action calls or cancellations targeting the global or local planners. An example event log for a simple planning logic is shown in the diagram below: Events are triggered by the Hybrid Planning action request and by both of the global and local planners action feedback messages. In this example, the Hybrid Planning Manager starts the global planner after the hybrid planning request is received. Upon arrival of the global trajectory the local planner is started and when the local planner is finished the Hybrid Planning Manager returns a Hybrid Planning response. A custom implementation of the Planning Logic plugin supports


key: chroma:document
string_value:
A custom implementation of the Planning Logic plugin supports mapping generic events to available actions provided by the architecture like “Start global planning”, “Stop trajectory execution”, or “Switch to local planner constraint x”. With this, the motion planning behavior becomes highly customizable and adaptable.


key: chroma:document
string_value:
## Global Planner The Global Planner is the simplest component of the architecture. It provides an action server that processes GlobalPlanner requests. These requests include common MotionPlanRequests, which are processed by the Global Planner plugin. By default, this is simply MoveIt’s planning pipeline, but any kind of planner or even MTC could technically be used here. The planning result is reported using the action feedback and the solution trajectory is published to the Local Planner for further processing.


key: chroma:document
string_value:
## Local Planner The Local Planner also runs an action server that handles requests from the Hybrid Planning Manager. The action is used for starting and stopping execution and may also configure runtime parameters like constraints or solver types. The local planner implementation is based on two plugins: The diagram below shows an example loop cycle of the Local Planner upon action request by the Hybrid Planning Manager: Each iteration the local planner requests the current planning scene and matches the current robot state within the reference trajectory. If the goal is reached, the local planning action successfully finishes. Otherwise, the current local planning problem is identified based on the current robot state and solved afterwards. Finally, the resulting control commands are published to the robot controller.


key: chroma:document
string_value:
## How does it work? The runtime behavior of a Hybrid Planner can best be understood by drawing a workflow diagram that visualizes the communication channels and events of the different components. Below is a diagram that shows the runtime logic of a successful trajectory execution. The planner is invoked by a hybrid planning request which is also the first event the Hybrid Planning Manager reacts to. In this example, the planner logic simply runs both planners in sequence. After the initial hybrid planning request, the Hybrid Planning Manager invokes the global planner. The global planner computes and publishes a trajectory which is received by the Hybrid Planning Manager and the Local Planner Component. Important to notice is, that the Local Planner Component just processes the new trajectory and does not start executing until it is invoked by the Hybrid Planning Manager. Once requested by the Hybrid Planning Manager, the Local Planner Component starts unwinding the reference trajectory and returns the


key: chroma:document
string_value:
starts unwinding the reference trajectory and returns the action response successfully when it reaches the final state. After that, the Hybrid Planning Manager returns a successful HybridPlanningResponse. Now let’s consider a more difficult scenario where the hybrid planner is designed to avoid an obstacle during execution by replanning. The animation below shows a simple motion that is being fixed at runtime because of changing collision objects. Here, the collision object present during the global planning process disappears after the global trajectory is computed. Instead two new collision objects appear that invalidate the initial global trajectory. The local planner detects the imminent collision and pauses the execution until the global planner has provided an updated collision free trajectory. Below you can see the workflow of the described behavior. The startup is the same as in the first example, but during unwinding the reference trajectory the local planner detects a collision. Here, the planner


key: chroma:document
string_value:
the local planner detects a collision. Here, the planner logic reacts by re-invoking the global planner. During the calculation of the new global solution, the local planner must prevent the robot from colliding with the collision object i.e. by keeping its current position. After the global planner finishes its calculation, the new global solution is published to the local planner and the local planner’s Trajectory Operator Plugin blends the update into the reference trajectory. Afterwards, the Local Planner Component continues to follow the reference trajectory as the updated solution enables it to steer around the collision object. If you want to use Hybrid Planning in your application or just want to experiment with it, check out theHybrid Planning Example Tutorial.


key: chroma:document
string_value:
Title: Pick and Place with MoveIt Task Constructor

URL: https://moveit.picknik.ai/main/doc/tutorials/pick_and_place_with_moveit_task_constructor/pick_and_place_with_moveit_task_constructor.html

Section: index.html

--------------------------------------------------------------------------------

## 1 Basic Concepts

The fundamental idea of MTC is that complex motion planning problems can be composed into a set of simpler subproblems.

The top-level planning problem is specified as aTaskwhile all subproblems are specified byStages.

Stages can be arranged in any arbitrary order and hierarchy only limited by the individual stages types.

The order in which stages can be arranged is restricted by the direction in which results are passed.

There are three possible stages relating to the result flow: generator, propagator, and connector stages:

Generatorscompute their results independently of their neighbor stages and pass them in both directions, backwards and forwards.


key: chroma:document
string_value:
An example is an IK sampler for geometric poses where approaching and departing motions (neighbor stages) depend on the solution.

Propagatorsreceive the result of one neighbor stage, solve a subproblem and then propagate their result to the neighbor on the opposite site.

Depending on the implementation, propagating stages can pass solutions forward, backward or in both directions separately.

An example is a stage that computes a Cartesian path based on either a start or a goal state.

Connectorsdo not propagate any results, but rather attempt to bridge the gap between the resulting states of both neighbors.

An example is the computation of a free-motion plan from one given state to another.

Additional to the order types, there are different hierarchy types allowing to encapsulate subordinate stages.

Stages without subordinate stages are calledprimitive stages, higher-level stages are calledcontainer stages.

There are three container types:


key: chroma:document
string_value:
There are three container types:

Wrappersencapsulate a single subordinate stage and modify or filter the results.

For example, a filter stage that only accepts solutions of its child stage that satisfy a certain constraint can be realized as a wrapper.

Another standard use of this type includes the IK wrapper stage, which generates inverse kinematics solutions based on planning scenes annotated with a pose target property.

Serial Containershold a sequence of subordinate stages and only consider end-to-end solutions as results.

An example is a picking motion that consists of a sequence of coherent steps.

Parallel Containerscombine set of subordinate stages and can be used for passing the best of alternative results, running fallback solvers or for merging multiple independent solutions.

Examples are running alternative planners for a free-motion plan, picking objects with the right hand or with the left hand as a fallback, or moving the arm and opening the gripper at the same time.


key: chroma:document
string_value:
Stages not only support solving motion planning problems.

They can also be used for all kinds of state transitions, as for instance modifying the planning scene.

Combined with the possibility of using class inheritance it is possible to construct very complex behavior while only relying on a well-structured set of primitive stages.

More detailed information on MTC can be found in theMoveIt Task Constructor concepts page

## 2 Getting Started

If you haven’t already done so, make sure you’ve completed the steps inGetting Started.

Move into your colcon workspace and pull the MoveIt Task Constructor source, where<branch>can be e.g.humblefor ROS Humble, orros2for the latest version compatible with MoveIt 2main:

Install missing packages with rosdep:

Build the workspace:

## 3 Trying It Out

The MoveIt Task Constructor package contains several basic examples and a pick-and-place demo.

For all demos you should launch the basic environment:

Subsequently, you can run the individual demos:


key: chroma:document
string_value:
Subsequently, you can run the individual demos:

On the right side you should see theMotion Planning Taskspanel outlining the hierarchical stage structure of the tasks.

When you select a particular stage, the list of successful and failed solutions will be

shown in the right-most window. Selecting one of those solutions will start its visualization.

## 4 Setting up a Project with MoveIt Task Constructor

This section walks through the steps required to build a simple task with MoveIt Task Constructor.

## 4.1 Create a New Package

Create a new package with the following command:

This will create a new package and folder calledmtc_tutorialwith a dependency onmoveit_task_constructor_coreas well as a hello world example insrc/mtc_node.

## 4.2 The Code

Openmtc_node.cppin your editor of choice, and paste in the following code.

## 4.3 Code Breakdown

The top of the code includes the ROS and MoveIt Libraries that this package uses.


key: chroma:document
string_value:
The next line gets a logger for our new node. We also create a namespace alias formoveit::task_constructorfor convenience.

We start by defining a class that will contain the main MoveIt Task Constructor functionality.  We also declare the MoveIt Task Constructor task object as a member variable for our class: this isn’t strictly necessary for a given application, but it helps save the task for later visualization purposes. We will explore each function individually below.

These lines initialize the node with specified options (it is the constructor of ourMTCTaskNodeclass).

These next lines define a getter function to get the node base interface, which will be used for the executor later.

This class method is used to set up the planning scene that is used in the example. It creates a cylinder with dimensions specified byobject.primitives[0].dimensionsand position specified bypose.position.xandpose.position.y.


key: chroma:document
string_value:
You can try changing these numbers to resize and move the cylinder around. If we move the cylinder out of the robot’s reach, planning will fail.

This function interfaces with the MoveIt Task Constructor task object. It first creates a task, which includes setting some properties and adding stages. This will be discussed further in thecreateTaskfunction definition. Next,task.init()initializes the task andtask.plan(5)generates a plan, stopping after 5 successful plans are found. The next line publishes the solution to be visualized in RViz - this line can be removed if you don’t care for visualization. Finally,task.execute()executes the plan. Execution occurs via an action server interface with the RViz plugin.


key: chroma:document
string_value:
As mentioned above, this function creates a MoveIt Task Constructor object and sets some initial properties. In this case, we set the task name to “demo_task”, load the robot model, define the names of some useful frames, and set those frame names as properties of the task withtask.setProperty(property_name,value). The next few code blocks will fill out this function body.

Now, we add an example stage to the node. The first line setscurrent_state_ptrtonullptr; this creates a pointer to a stage such that we can reuse stage information in specific scenarios. This line is not used at this moment, but will be used later when more stages are added to the task. Next, we make acurrent_statestage (a generator stage) and add it to our task - this starts the robot off in its current state. Now that we’ve created theCurrentStatestage, we save a pointer to it in thecurrent_state_ptrfor later use.

Solvers are used to define the type of robot motion. MoveIt Task Constructor has three options for solvers:


key: chroma:document
string_value:
Feel free to try out the different solvers and see how the robot motion changes. For the first stage we will use the Cartesian planner, which requires the following properties to be set:

Now that we added in the planners, we can add a stage that will move the robot.

The following lines use aMoveTostage (a propagator stage). Since opening the hand is a relatively simple movement, we can use the joint interpolation planner.

This stage plans a move to the “open hand” pose, which is a named pose defined in theSRDFfor the Panda robot.

We return the task and finish with thecreateTask()function.

Finally, we havemain: the following lines create a node using the class defined above, and calls the class methods to set up and execute a basic MTC task. In this example, we do not cancel the executor once the task has finished executing to keep the node alive to inspect the solutions in RViz.

## 5 Running the Demo

## 5.1 Launch Files


key: chroma:document
string_value:
## 5 Running the Demo

## 5.1 Launch Files

We will need a launch file to launch themove_group,ros2_control,static_tf,robot_state_publisher, andrviznodes that provide us the environment to run the demo. The one we will use for this example can be foundhere.

To run the MoveIt Task Constructor node, we will use a second launch file to start themtc_tutorialexecutable with the proper parameters. Here we can load URDF, SRDF, and OMPL parameters, or use MoveIt Configs Utils to do so. Your launch file should look something like the one found in this tutorial packagehere(pay close attention to thepackageandexecutablearguments below as they are different from the launch file linked) :

Save a launch file aspick_place_demo.launch.pyor download one to the package’s launch directory. Make sure to edit theCMakeLists.txtso it includes the launch folder by adding the following lines:

Now we can build and source the colcon workspace.


key: chroma:document
string_value:
Now we can build and source the colcon workspace.

Start by launching the first launch file. If you want to use the one provided by the tutorials:

RViz will now load. If you’re using your own launch file and haven’t included an rviz configsuch as this, you will need to configure RViz before you see anything displayed. If you’re using the launch file from the tutorials package, RViz will already be configured for you and you can jump to the end of the next section.

## 5.2 RViz Configuration

If you are not using the RViz configuration provided, we’ll have to make some changes to the RViz configuration to see your robot and the MoveIt Task Constructor solutions. First, start RViz. The following steps will cover how to set up RViz for MoveIt Task Constructor solution visualization.


key: chroma:document
string_value:
You should see the panda arm in the main view with Motion Planning Tasks display open in the bottom left and nothing in it. Your MTC task will show up in this panel once you launch themtc_tutorialnode. If you’re usingmtc_demo.launch.pyfrom the tutorials, jump back in here.

## 5.3 Launching the Demo

Launch themtc_tutorialnode with

You should see the arm execute the task with the single stage to open the hand, with the cylinder in green in front of it. It should look something like this:

If you haven’t made your own package, but still want to see what this looks like, you can launch this file from the tutorials:

## 6 Adding Stages

So far, we’ve walked through creating and executing a simple task, which runs but does not do much. Now, we will start adding the pick-and-place stages to the task. The image below shows an outline of the stages we will use in our task.

We will start adding stages after our existing open hand stage. Openmtc_node.cppand locate the following lines:

## 6.1 Pick Stages


key: chroma:document
string_value:
## 6.1 Pick Stages

We need to move the arm to a position where we can pick up our object. This is done with aConnectstage, which as its name implies, is a Connector stage. This means that it tries to bridge between the results of the stage before and after it. This stage is initialized with a name,move_to_pick, and aGroupPlannerVectorthat specifies the planning group and the planner. We then set a timeout for the stage, set the properties for the stage, and add it to our task.

Next, we create a pointer to a MoveIt Task Constructor stage object, and set it tonullptrfor now. Later, we will use this to save a stage.

This next block of code creates aSerialContainer.

This is a container that can be added to our task and can hold several substages.

In this case, we create a serial container that will contain the stages relevant to the picking action.


key: chroma:document
string_value:
Instead of adding the stages to the task, we will add the relevant stages to the serial container. We useexposeTo()to declare the task properties from the parent task in the new serial container, and useconfigureInitFrom()to initialize them.

This allows the contained stages to access these properties.

We then create a stage to approach the object. This stage is aMoveRelativestage, which allows us to specify a relative movement from our current position.MoveRelativeis a propagator stage: it receives the solution from its neighbouring stages and propagates it to the next or previous stage. Usingcartesian_plannerfinds a solution that involves moving the end effector in a straight line. We set the properties, and set the minimum and maximum distance to move. Now we create aVector3Stampedmessage to indicate the direction we want to move - in this case, in the Z direction from the hand frame. Finally, we add this stage to our serial container

Now, create a stage to generate the grasp pose.


key: chroma:document
string_value:
Now, create a stage to generate the grasp pose.

This is a generator stage, so it computes its results without regard to the stages before and after it.

The first stage,CurrentStateis a generator stage as well - to connect the first stage and this stage, a connecting stage must be used, which we already created above.

This code sets the stage properties, sets the pose before grasping, the angle delta, and the monitored stage.

Angle delta is a property of theGenerateGraspPosestage that is used to determine the number of poses to generate; when generating solutions, MoveIt Task Constructor will try to grasp the object from many different orientations, with the difference between the orientations specified by the angle delta. The smaller the delta, the closer together the grasp orientations will be. When defining the current stage, we setcurrent_state_ptr, which is now used to forward information about the object pose and shape to the inverse kinematics solver.


key: chroma:document
string_value:
This stage won’t be directly added to the serial container like previously, as we still need to do inverse kinematics on the poses it generates.

Before we compute inverse kinematics for the poses generated above, we first need to define the frame. This can be done with aPoseStampedmessage fromgeometry_msgsor in this case, we define the transform using Eigen transformation matrix and the name of the relevant link. Here, we define the transformation matrix.


key: chroma:document
string_value:
Now, we create theComputeIKstage, and give it the namegenerateposeIKas well as thegenerategraspposestage defined above. Some robots have multiple inverse kinematics solutions for a given pose - we set the limit on the amount of solutions to solve for up to 8. We also set the minimum solution distance, which is a threshold on how different solutions must be: if the joint positions in a solution are too similar to a previous solution, it will be marked as invalid. Next, we configure some additional properties, and add theComputeIKstage to the serial container.

To pick up the object, we must allow collision between the hand and the object. This can be done with aModifyPlanningScenestage. TheallowCollisionsfunction lets us specify which collisions to disable.allowCollisionscan be used with a container of names, so we can usegetLinkModelNamesWithCollisionGeometryto get all the names of links with collision geometry in the hand group.


key: chroma:document
string_value:
With collisions allowed, we now can close the hand. This is done with aMoveTostage, similarly to theopenhandstage from above, except moving to thecloseposition as defined in the SRDF.

We now use aModifyPlanningScenestage again, this time to attach the object to the hand usingattachObject. Similarly to what we did with thecurrent_state_ptr, we get a pointer to this stage for later use when generating the place pose for the object.

Next, we lift the object with aMoveRelativestage, similarly to theapproach_objectstage.

With this, we have all the stages needed to pick the object. Now, we add the serial container (with all its substages) to the task. If you build the package as-is, you can see the robot plan to pick up the object.

To test out the newly created stage, build the code and execute:

## 6.2 Place Stages


key: chroma:document
string_value:
## 6.2 Place Stages

Now that the stages that define the pick are complete, we move on to defining the stages for placing the object. Picking up where we left off, we add aConnectstage to connect the two, as we will soon be using a generator stage to generate the pose for placing the object.

We also create a serial container for the place stages. This is done similarly to the pick serial container.

The next stages will be added to the serial container rather than the task.

This next stage generates the poses used to place the object and compute the inverse kinematics for those poses - it is somewhat similar to thegenerategraspposestage from the pick serial container.

We start by creating a stage to generate the poses and inheriting the task properties.

We specify the pose where we want to place the object with aPoseStampedmessage fromgeometry_msgs- in this case, we choosey=0.5in the"object"frame.

We then pass the target pose to the stage withsetPose.


key: chroma:document
string_value:
We then pass the target pose to the stage withsetPose.

Next, we usesetMonitoredStageand pass it the pointer to theattach_objectstage from earlier.

This allows the stage to know how the object is attached.

We then create aComputeIKstage and pass it ourGeneratePlacePosestage - the rest follows the same logic as above with the pick stages.

Now that we’re ready to place the object, we open the hand withMoveTostage and the joint interpolation planner.

We also can re-enable collisions with the object now that we no longer need to hold it.

This is done usingallowCollisionsalmost exactly the same way as disabling collisions, except setting the last argument tofalserather thantrue.

Now, we can detach the object usingdetachObject.

We retreat from the object using aMoveRelativestage, which is done similarly to theapproachobjectandliftobjectstages.

We finish our place serial container and add it to the task.


key: chroma:document
string_value:
We finish our place serial container and add it to the task.

The final step is to return home: we use aMoveTostage and pass it the goal pose ofready, which is a pose defined in the Panda SRDF.

All these stages should be added above these lines.

Congratulations! You’ve now defined a pick and place task using MoveIt Task Constructor! To try it out, build the code and execute:

## 7 Further Discussion

The task with each comprising stage is shown in the Motion Planning Tasks pane. Click on a stage and additional information about the stage will show up to the right. The right pane shows different solutions as well as their associated costs. Depending on the stage type and the robot configuration, there may only be one solution shown.

Click one of the solution costs to see an animation of the robot following the plan for that stage. Click the “Exec” button in the upper-right portion of the pane to execute the motion.

To run the complete MoveIt Task Constructor example included with the MoveIt tutorials:


key: chroma:document
string_value:
And in a second terminal:

## 7.1 Debugging Information Printed to the Terminal

When running MTC, it prints a diagram like this to terminal:

This example^ shows two stages. The first stage (“initial_state”) is aCurrentStatetype of stage, which initializes aPlanningSceneand captures any collision objects that are present at that moment.

A pointer to this stage can be used to retrieve the state of the robot.

SinceCurrentStateinherits fromGenerator, it propagates solutions both forward and backward.

This is denoted by the arrows in both directions.

The second stage (“move_to_home”) is aMoveTotype of stage. It inherits its propagation direction from the previous stage, so both arrows point forward. The0’s indicate that this stage failed completely. From left to right, the0’s mean:

In this case, we could tell that “move_to_home” was the root cause of the failure. The problem was a home state that was in collision. Defining a new, collision-free home position fixed the issue.

## 7.2 Stages


key: chroma:document
string_value:
## 7.2 Stages

Information about individual stages can be retrieved from the task. For example, here we retrieve the unique ID for a stage:

ACurrentStatetype stage does not just retrieve the current state of the robot.

It also initializes aPlanningSceneobject, capturing any collision objects that are present at that moment.

MTC stages can be propagated in forward and backward order.

You can easily check which direction a stage propagates by the arrow in the RViz GUI.

When propagating backwards, the logic of many operations is reversed.

For example, to allow collisions with an object in aModifyPlanningScenestage, you would callallowCollisions(false)rather thanallowCollisions(true). There is a discussion to be readhere.

Code Examples:

Language: unknown

File: main

```

cd

~/

ws_moveit

/

src

git

clone

b

<

branch

>

https

:

//

github

.

com

/

moveit

/

moveit_task_constructor

.

git

```

Language: unknown

File: main

```


key: chroma:document
string_value:
.

git

```

Language: unknown

File: main

```

rosdep install --from-paths . --ignore-src --rosdistro $ROS_DISTRO

```

Language: unknown

File: main

```

cd

~/

ws_moveit

colcon

build

--

mixin

release

```

Language: unknown

File: main

```

ros2

launch

moveit_task_constructor_demo

demo

.

launch

.

py

```

Language: unknown

File: main

```

ros2

launch

moveit_task_constructor_demo

run

.

launch

.

py

exe

:=

cartesian

ros2

launch

moveit_task_constructor_demo

run

.

launch

.

py

exe

:=

modular

ros2

launch

moveit_task_constructor_demo

run

.

launch

.

py

exe

:=

pick_place_demo

```

Language: unknown

File: main

```

ros2

pkg

create

\

--

build

type

ament_cmake

\

--

dependencies

moveit_task_constructor_core

rclcpp

\

--

node

name

mtc_node

mtc_tutorial

```

Language: unknown

File: mtc_node.cpp

```

#include

<rclcpp/rclcpp.hpp>

#include

<moveit/planning_scene/planning_scene.h>

#include


key: chroma:document
string_value:
#include

<moveit/planning_scene/planning_scene.h>

#include

<moveit/planning_scene_interface/planning_scene_interface.h>

#include

<moveit/task_constructor/task.h>

#include

<moveit/task_constructor/solvers.h>

#include

<moveit/task_constructor/stages.h>

#if __has_include(<tf2_geometry_msgs/tf2_geometry_msgs.hpp>)

#include

<tf2_geometry_msgs/tf2_geometry_msgs.hpp>

#else

#include

<tf2_geometry_msgs/tf2_geometry_msgs.h>

#endif

#if __has_include(<tf2_eigen/tf2_eigen.hpp>)

#include

<tf2_eigen/tf2_eigen.hpp>

#else

#include

<tf2_eigen/tf2_eigen.h>

#endif

static

const

rclcpp

::

Logger

LOGGER

=

rclcpp

::

get_logger

(

"mtc_tutorial"

);

namespace

mtc

=

moveit

::

task_constructor

;

class

MTCTaskNode

{

public

:

MTCTaskNode

(

const

rclcpp

::

NodeOptions

&

options

);

rclcpp

::

node_interfaces

::

NodeBaseInterface

::

SharedPtr

getNodeBaseInterface

();

void

doTask

();

void

setupPlanningScene

();

private

:

// Compose an MTC task from a series of stages.


key: chroma:document
string_value:
private

:

// Compose an MTC task from a series of stages.

mtc

::

Task

createTask

();

mtc

::

Task

task_

;

rclcpp

::

Node

::

SharedPtr

node_

;

};

MTCTaskNode

::

MTCTaskNode

(

const

rclcpp

::

NodeOptions

&

options

)

:

node_

{

std

::

make_shared

<

rclcpp

::

Node

>

(

"mtc_node"

,

options

)

}

{

}

rclcpp

::

node_interfaces

::

NodeBaseInterface

::

SharedPtr

MTCTaskNode

::

getNodeBaseInterface

()

{

return

node_

>

get_node_base_interface

();

}

void

MTCTaskNode

::

setupPlanningScene

()

{

moveit_msgs

::

msg

::

CollisionObject

object

;

object

.

id

=

"object"

;

object

.

header

.

frame_id

=

"world"

;

object

.

primitives

.

resize

(

1

);

object

.

primitives

[

0

].

type

=

shape_msgs

::

msg

::

SolidPrimitive

::

CYLINDER

;

object

.

primitives

[

0

].

dimensions

=

{

0.1

,

0.02

};

geometry_msgs

::

msg

::

Pose

pose

;

pose

.

position

.

x

=

0.5

;

pose

.

position

.

y

=

0.25

;

pose


key: chroma:document
string_value:
.

x

=

0.5

;

pose

.

position

.

y

=

0.25

;

pose

.

orientation

.

w

=

1.0

;

object

.

pose

=

pose

;

moveit

::

planning_interface

::

PlanningSceneInterface

psi

;

psi

.

applyCollisionObject

(

object

);

}

void

MTCTaskNode

::

doTask

()

{

task_

=

createTask

();

try

{

task_

.

init

();

}

catch

(

mtc

::

InitStageException

&

e

)

{

RCLCPP_ERROR_STREAM

(

LOGGER

,

e

);

return

;

}

if

(

!

task_

.

plan

(

5

))

{

RCLCPP_ERROR_STREAM

(

LOGGER

,

"Task planning failed"

);

return

;

}

task_

.

introspection

().

publishSolution

(

task_

.

solutions

().

front

());

auto

result

=

task_

.

execute

(

task_

.

solutions

().

front

());

if

(

result

.

val

!=

moveit_msgs

::

msg

::

MoveItErrorCodes

::

SUCCESS

)

{

RCLCPP_ERROR_STREAM

(

LOGGER

,

"Task execution failed"

);

return

;

}

return

;

}

mtc

::

Task

MTCTaskNode

::

createTask

()

{

mtc

::

Task

task

;

task

.

stages

()

>

setName

(


key: chroma:document
string_value:
{

mtc

::

Task

task

;

task

.

stages

()

>

setName

(

"demo task"

);

task

.

loadRobotModel

(

node_

);

const

auto

&

arm_group_name

=

"panda_arm"

;

const

auto

&

hand_group_name

=

"hand"

;

const

auto

&

hand_frame

=

"panda_hand"

;

// Set task properties

task

.

setProperty

(

"group"

,

arm_group_name

);

task

.

setProperty

(

"eef"

,

hand_group_name

);

task

.

setProperty

(

"ik_frame"

,

hand_frame

);

// Disable warnings for this line, as it's a variable that's set but not used in this example

#pragma GCC diagnostic push

#pragma GCC diagnostic ignored "-Wunused-but-set-variable"

mtc

::

Stage

current_state_ptr

=

nullptr

;

// Forward current_state on to grasp pose generator

#pragma GCC diagnostic pop

auto

stage_state_current

=

std

::

make_unique

<

mtc

::

stages

::

CurrentState

>

(

"current"

);

current_state_ptr

=

stage_state_current

.

get

();

task

.

add

(

std

::

move

(

stage_state_current

));

auto


key: chroma:document
string_value:
.

add

(

std

::

move

(

stage_state_current

));

auto

sampling_planner

=

std

::

make_shared

<

mtc

::

solvers

::

PipelinePlanner

>

(

node_

);

auto

interpolation_planner

=

std

::

make_shared

<

mtc

::

solvers

::

JointInterpolationPlanner

>

();

auto

cartesian_planner

=

std

::

make_shared

<

mtc

::

solvers

::

CartesianPath

>

();

cartesian_planner

>

setMaxVelocityScalingFactor

(

1.0

);

cartesian_planner

>

setMaxAccelerationScalingFactor

(

1.0

);

cartesian_planner

>

setStepSize

(

.01

);

auto

stage_open_hand

=

std

::

make_unique

<

mtc

::

stages

::

MoveTo

>

(

"open hand"

,

interpolation_planner

);

stage_open_hand

>

setGroup

(

hand_group_name

);

stage_open_hand

>

setGoal

(

"open"

);

task

.

add

(

std

::

move

(

stage_open_hand

));

return

task

;

}

int

main

(

int

argc

,

char

**

argv

)

{

rclcpp

::

init

(

argc

,

argv

);

rclcpp

::

NodeOptions

options

;

options

.


key: chroma:document
string_value:
,

argv

);

rclcpp

::

NodeOptions

options

;

options

.

automatically_declare_parameters_from_overrides

(

true

);

auto

mtc_task_node

=

std

::

make_shared

<

MTCTaskNode

>

(

options

);

rclcpp

::

executors

::

MultiThreadedExecutor

executor

;

auto

spin_thread

=

std

::

make_unique

<

std

::

thread

>

([

&

executor

,

&

mtc_task_node

]()

{

executor

.

add_node

(

mtc_task_node

>

getNodeBaseInterface

());

executor

.

spin

();

executor

.

remove_node

(

mtc_task_node

>

getNodeBaseInterface

());

});

mtc_task_node

>

setupPlanningScene

();

mtc_task_node

>

doTask

();

spin_thread

>

join

();

rclcpp

::

shutdown

();

return

0

;

}

```

Language: unknown

File: tf2_eigen/tf2_eigen.hpp

```

#include

<rclcpp/rclcpp.hpp>

#include

<moveit/planning_scene/planning_scene.h>

#include

<moveit/planning_scene_interface/planning_scene_interface.h>

#include

<moveit/task_constructor/task.h>

#include

<moveit/task_constructor/solvers.h>

#include


key: chroma:document
string_value:
#include

<moveit/task_constructor/solvers.h>

#include

<moveit/task_constructor/stages.h>

#if __has_include(<tf2_geometry_msgs/tf2_geometry_msgs.hpp>)

#include

<tf2_geometry_msgs/tf2_geometry_msgs.hpp>

#else

#include

<tf2_geometry_msgs/tf2_geometry_msgs.h>

#endif

#if __has_include(<tf2_eigen/tf2_eigen.hpp>)

#include

<tf2_eigen/tf2_eigen.hpp>

#else

#include

<tf2_eigen/tf2_eigen.h>

#endif

```

Language: unknown

File: moveit::task_constructor

```

static

const

rclcpp

::

Logger

LOGGER

=

rclcpp

::

get_logger

(

"mtc_tutorial"

);

namespace

mtc

=

moveit

::

task_constructor

;

```

Language: unknown

File: moveit::task_constructor

```

class

MTCTaskNode

{

public

:

MTCTaskNode

(

const

rclcpp

::

NodeOptions

&

options

);

rclcpp

::

node_interfaces

::

NodeBaseInterface

::

SharedPtr

getNodeBaseInterface

();

void

doTask

();

void

setupPlanningScene

();

private

:

// Compose an MTC task from a series of stages.

mtc

::

Task

createTask

();

mtc

::

Task


key: chroma:document
string_value:
mtc

::

Task

createTask

();

mtc

::

Task

task_

;

rclcpp

::

Node

::

SharedPtr

node_

;

};

```

Language: unknown

File: MTCTaskNode

```

MTCTaskNode

::

MTCTaskNode

(

const

rclcpp

::

NodeOptions

&

options

)

:

node_

{

std

::

make_shared

<

rclcpp

::

Node

>

(

"mtc_node"

,

options

)

}

{

}

```

Language: unknown

File: MTCTaskNode

```

rclcpp

::

node_interfaces

::

NodeBaseInterface

::

SharedPtr

MTCTaskNode::getNodeBaseInterface

()

{

return

node_

>

get_node_base_interface

();

}

```

Language: unknown

File: pose.position.y

```

void

MTCTaskNode::setupPlanningScene

()

{

moveit_msgs

::

msg

::

CollisionObject

object

;

object

.

id

=

"object"

;

object

.

header

.

frame_id

=

"world"

;

object

.

primitives

.

resize

(

1

);

object

.

primitives

[

0

].

type

=

shape_msgs

::

msg

::

SolidPrimitive

::

CYLINDER

;

object

.

primitives

[

0

].

dimensions

=

{

0.1

,

0.02

};

geometry_msgs

::

msg

::

Pose

pose

;


key: chroma:document
string_value:
{

0.1

,

0.02

};

geometry_msgs

::

msg

::

Pose

pose

;

pose

.

position

.

x

=

0.5

;

pose

.

position

.

y

=

0.25

;

object

.

pose

=

pose

;

moveit

::

planning_interface

::

PlanningSceneInterface

psi

;

psi

.

applyCollisionObject

(

object

);

}

```

Language: unknown

File: task.execute()

```

void

MTCTaskNode::doTask

()

{

task_

=

createTask

();

try

{

task_

.

init

();

}

catch

(

mtc

::

InitStageException

&

e

)

{

RCLCPP_ERROR_STREAM

(

LOGGER

,

e

);

return

;

}

if

(

!

task_

.

plan

(

5

))

{

RCLCPP_ERROR_STREAM

(

LOGGER

,

"Task planning failed"

);

return

;

}

task_

.

introspection

().

publishSolution

(

task_

.

solutions

().

front

());

auto

result

=

task_

.

execute

(

task_

.

solutions

().

front

());

if

(

result

.

val

!=

moveit_msgs

::

msg

::

MoveItErrorCodes

::

SUCCESS

)

{

RCLCPP_ERROR_STREAM

(

LOGGER

,

"Task execution failed"

);

return

;

}

return

;

}

```

Language: unknown


key: chroma:document
string_value:
);

return

;

}

return

;

}

```

Language: unknown

File: task.setProperty(property_name,value)

```

mtc

::

Task

MTCTaskNode::createTask

()

{

moveit

::

task_constructor

::

Task

task

;

task

.

stages

()

>

setName

(

"demo task"

);

task

.

loadRobotModel

(

node_

);

const

auto

&

arm_group_name

=

"panda_arm"

;

const

auto

&

hand_group_name

=

"hand"

;

const

auto

&

hand_frame

=

"panda_hand"

;

// Set task properties

task

.

setProperty

(

"group"

,

arm_group_name

);

task

.

setProperty

(

"eef"

,

hand_group_name

);

task

.

setProperty

(

"ik_frame"

,

hand_frame

);

```

Language: unknown

File: current_state_ptr

```

mtc

::

Stage

current_state_ptr

=

nullptr

;

// Forward current_state on to grasp pose generator

auto

stage_state_current

=

std

::

make_unique

<

mtc

::

stages

::

CurrentState

>

(

"current"

);

current_state_ptr

=

stage_state_current

.

get

();

task

.

add

(

std

::

move

(

stage_state_current

));

```


key: chroma:document
string_value:
.

add

(

std

::

move

(

stage_state_current

));

```

Language: unknown

File: current_state_ptr

```

auto

sampling_planner

=

std

::

make_shared

<

mtc

::

solvers

::

PipelinePlanner

>

(

node_

);

```

Language: unknown

File: current_state_ptr

```

auto

interpolation_planner

=

std

::

make_shared

<

mtc

::

solvers

::

JointInterpolationPlanner

>

();

```

Language: unknown

File: current_state_ptr

```

auto

cartesian_planner

=

std

::

make_shared

<

mtc

::

solvers

::

CartesianPath

>

();

```

Language: unknown

File: current_state_ptr

```

auto

cartesian_planner

=

std

::

make_shared

<

mtc

::

solvers

::

CartesianPath

>

();

cartesian_planner

>

setMaxVelocityScalingFactor

(

1.0

);

cartesian_planner

>

setMaxAccelerationScalingFactor

(

1.0

);

cartesian_planner

>

setStepSize

(

.01

);

```

Language: unknown

File: createTask()

```

auto

stage_open_hand

=

std

::

make_unique

<

mtc

::

stages

::

MoveTo

>

(

"open hand"

,


key: chroma:document
string_value:
<

mtc

::

stages

::

MoveTo

>

(

"open hand"

,

interpolation_planner

);

stage_open_hand

>

setGroup

(

hand_group_name

);

stage_open_hand

>

setGoal

(

"open"

);

task

.

add

(

std

::

move

(

stage_open_hand

));

return

task

;

}

```

Language: unknown

File: main

```

int

main

(

int

argc

,

char

**

argv

)

{

rclcpp

::

init

(

argc

,

argv

);

rclcpp

::

NodeOptions

options

;

options

.

automatically_declare_parameters_from_overrides

(

true

);

auto

mtc_task_node

=

std

::

make_shared

<

MTCTaskNode

>

(

options

);

rclcpp

::

executors

::

MultiThreadedExecutor

executor

;

auto

spin_thread

=

std

::

make_unique

<

std

::

thread

>

([

&

executor

,

&

mtc_task_node

]()

{

executor

.

add_node

(

mtc_task_node

>

getNodeBaseInterface

());

executor

.

spin

();

executor

.

remove_node

(

mtc_task_node

>

getNodeBaseInterface

());

});

mtc_task_node

>

setupPlanningScene

();

mtc_task_node

>

doTask

();

spin_thread

>


key: chroma:document
string_value:
();

mtc_task_node

>

doTask

();

spin_thread

>

join

();

rclcpp

::

shutdown

();

return

0

;

}

```

Language: unknown

File: executable

```

from

launch

import

LaunchDescription

from

launch_ros.actions

import

Node

from

moveit_configs_utils

import

MoveItConfigsBuilder

def

generate_launch_description

():

moveit_config

=

MoveItConfigsBuilder

(

"moveit_resources_panda"

)

.

to_dict

()

# MTC Demo node

pick_place_demo

=

Node

(

package

=

"mtc_tutorial"

,

executable

=

"mtc_node"

,

output

=

"screen"

,

parameters

=

[

moveit_config

,

],

)

return

LaunchDescription

([

pick_place_demo

])

```

Language: unknown

File: CMakeLists.txt

```

install(DIRECTORY launch

DESTINATION share/${PROJECT_NAME}

)

```

Language: unknown

File: CMakeLists.txt

```

cd

~/

ws_moveit

colcon

build

--

mixin

release

source

~/

ws_moveit

/

install

/

setup

.

bash

```

Language: unknown

File: CMakeLists.txt

```

ros2

launch

moveit2_tutorials

mtc_demo

.


key: chroma:document
string_value:
```

ros2

launch

moveit2_tutorials

mtc_demo

.

launch

.

py

```

Language: unknown

File: mtc_tutorial

```

ros2

launch

mtc_tutorial

pick_place_demo

.

launch

.

py

```

Language: unknown

File: mtc_tutorial

```

ros2

launch

moveit2_tutorials

mtc_demo_minimal

.

launch

.

py

```

Language: unknown

File: mtc_node.cpp

```

auto

stage_open_hand

=

std

::

make_unique

<

mtc

::

stages

::

MoveTo

>

(

"open hand"

,

interpolation_planner

);

stage_open_hand

>

setGroup

(

hand_group_name

);

stage_open_hand

>

setGoal

(

"open"

);

task

.

add

(

std

::

move

(

stage_open_hand

));

// Add the next lines of codes to define more stages here

```

Language: unknown

File: GroupPlannerVector

```

auto

stage_move_to_pick

=

std

::

make_unique

<

mtc

::

stages

::

Connect

>

(

"move to pick"

,

mtc

::

stages

::

Connect

::

GroupPlannerVector

{

{

arm_group_name

,

sampling_planner

}

});

stage_move_to_pick

>

setTimeout

(

5.0

);

stage_move_to_pick


key: chroma:document
string_value:
>

setTimeout

(

5.0

);

stage_move_to_pick

>

properties

().

configureInitFrom

(

mtc

::

Stage

::

PARENT

);

task

.

add

(

std

::

move

(

stage_move_to_pick

));

```

Language: unknown

File: nullptr

```

mtc

::

Stage

attach_object_stage

=

nullptr

;

// Forward attach_object_stage to place pose generator

```

Language: unknown

File: configureInitFrom()

```

{

auto

grasp

=

std

::

make_unique

<

mtc

::

SerialContainer

>

(

"pick object"

);

task

.

properties

().

exposeTo

(

grasp

>

properties

(),

{

"eef"

,

"group"

,

"ik_frame"

});

grasp

>

properties

().

configureInitFrom

(

mtc

::

Stage

::

PARENT

,

{

"eef"

,

"group"

,

"ik_frame"

});

```

Language: unknown

File: Vector3Stamped

```

{

auto

stage

=

std

::

make_unique

<

mtc

::

stages

::

MoveRelative

>

(

"approach object"

,

cartesian_planner

);

stage

>

properties

().

set

(

"marker_ns"

,

"approach_object"

);

stage

>

properties

().

set

(

"link"

,


key: chroma:document
string_value:
);

stage

>

properties

().

set

(

"link"

,

hand_frame

);

stage

>

properties

().

configureInitFrom

(

mtc

::

Stage

::

PARENT

,

{

"group"

});

stage

>

setMinMaxDistance

(

0.1

,

0.15

);

// Set hand forward direction

geometry_msgs

::

msg

::

Vector3Stamped

vec

;

vec

.

header

.

frame_id

=

hand_frame

;

vec

.

vector

.

z

=

1.0

;

stage

>

setDirection

(

vec

);

grasp

>

insert

(

std

::

move

(

stage

));

}

```

Language: unknown

File: current_state_ptr

```

{

// Sample grasp pose

auto

stage

=

std

::

make_unique

<

mtc

::

stages

::

GenerateGraspPose

>

(

"generate grasp pose"

);

stage

>

properties

().

configureInitFrom

(

mtc

::

Stage

::

PARENT

);

stage

>

properties

().

set

(

"marker_ns"

,

"grasp_pose"

);

stage

>

setPreGraspPose

(

"open"

);

stage

>

setObject

(

"object"

);

stage

>

setAngleDelta

(

M_PI

/

12

);

stage

>

setMonitoredStage

(

current_state_ptr

);

// Hook into current state

```


key: chroma:document
string_value:
(

current_state_ptr

);

// Hook into current state

```

Language: unknown

File: geometry_msgs

```

Eigen

::

Isometry3d

grasp_frame_transform

;

Eigen

::

Quaterniond

q

=

Eigen

::

AngleAxisd

(

M_PI

/

2

,

Eigen

::

Vector3d

::

UnitX

())

Eigen

::

AngleAxisd

(

M_PI

/

2

,

Eigen

::

Vector3d

::

UnitY

())

Eigen

::

AngleAxisd

(

M_PI

/

2

,

Eigen

::

Vector3d

::

UnitZ

());

grasp_frame_transform

.

linear

()

=

q

.

matrix

();

grasp_frame_transform

.

translation

().

z

()

=

0.1

;

```

Language: unknown

File: ComputeIK

```

// Compute IK

auto

wrapper

=

std

::

make_unique

<

mtc

::

stages

::

ComputeIK

>

(

"grasp pose IK"

,

std

::

move

(

stage

));

wrapper

>

setMaxIKSolutions

(

8

);

wrapper

>

setMinSolutionDistance

(

1.0

);

wrapper

>

setIKFrame

(

grasp_frame_transform

,

hand_frame

);

wrapper

>

properties

().

configureInitFrom

(

mtc

::

Stage

::

PARENT

,

{

"eef"

,

"group"

});

wrapper

>

properties


key: chroma:document
string_value:
PARENT

,

{

"eef"

,

"group"

});

wrapper

>

properties

().

configureInitFrom

(

mtc

::

Stage

::

INTERFACE

,

{

"target_pose"

});

grasp

>

insert

(

std

::

move

(

wrapper

));

}

```

Language: unknown

File: getLinkModelNamesWithCollisionGeometry

```

{

auto

stage

=

std

::

make_unique

<

mtc

::

stages

::

ModifyPlanningScene

>

(

"allow collision (hand,object)"

);

stage

>

allowCollisions

(

"object"

,

task

.

getRobotModel

()

>

getJointModelGroup

(

hand_group_name

)

>

getLinkModelNamesWithCollisionGeometry

(),

true

);

grasp

>

insert

(

std

::

move

(

stage

));

}

```

Language: unknown

File: close

```

{

auto

stage

=

std

::

make_unique

<

mtc

::

stages

::

MoveTo

>

(

"close hand"

,

interpolation_planner

);

stage

>

setGroup

(

hand_group_name

);

stage

>

setGoal

(

"close"

);

grasp

>

insert

(

std

::

move

(

stage

));

}

```

Language: unknown

File: current_state_ptr

```

{

auto

stage

=

std

::


key: chroma:document
string_value:
File: current_state_ptr

```

{

auto

stage

=

std

::

make_unique

<

mtc

::

stages

::

ModifyPlanningScene

>

(

"attach object"

);

stage

>

attachObject

(

"object"

,

hand_frame

);

attach_object_stage

=

stage

.

get

();

grasp

>

insert

(

std

::

move

(

stage

));

}

```

Language: unknown

File: approach_object

```

{

auto

stage

=

std

::

make_unique

<

mtc

::

stages

::

MoveRelative

>

(

"lift object"

,

cartesian_planner

);

stage

>

properties

().

configureInitFrom

(

mtc

::

Stage

::

PARENT

,

{

"group"

});

stage

>

setMinMaxDistance

(

0.1

,

0.3

);

stage

>

setIKFrame

(

hand_frame

);

stage

>

properties

().

set

(

"marker_ns"

,

"lift_object"

);

// Set upward direction

geometry_msgs

::

msg

::

Vector3Stamped

vec

;

vec

.

header

.

frame_id

=

"world"

;

vec

.

vector

.

z

=

1.0

;

stage

>

setDirection

(

vec

);

grasp

>

insert

(

std

::

move

(

stage

));

}

```

Language: unknown

File: approach_object


key: chroma:document
string_value:
stage

));

}

```

Language: unknown

File: approach_object

```

task

.

add

(

std

::

move

(

grasp

));

}

```

Language: unknown

File: approach_object

```

ros2

launch

mtc_tutorial

pick_place_demo

.

launch

.

py

```

Language: unknown

File: Connect

```

{

auto

stage_move_to_place

=

std

::

make_unique

<

mtc

::

stages

::

Connect

>

(

"move to place"

,

mtc

::

stages

::

Connect

::

GroupPlannerVector

{

{

arm_group_name

,

sampling_planner

},

{

hand_group_name

,

interpolation_planner

}

});

stage_move_to_place

>

setTimeout

(

5.0

);

stage_move_to_place

>

properties

().

configureInitFrom

(

mtc

::

Stage

::

PARENT

);

task

.

add

(

std

::

move

(

stage_move_to_place

));

}

```

Language: unknown

File: Connect

```

{

auto

place

=

std

::

make_unique

<

mtc

::

SerialContainer

>

(

"place object"

);

task

.

properties

().

exposeTo

(

place

>

properties

(),

{

"eef"

,

"group"

,

"ik_frame"

});

place

>

properties


key: chroma:document
string_value:
{

"eef"

,

"group"

,

"ik_frame"

});

place

>

properties

().

configureInitFrom

(

mtc

::

Stage

::

PARENT

,

{

"eef"

,

"group"

,

"ik_frame"

});

```

Language: unknown

File: GeneratePlacePose

```

{

// Sample place pose

auto

stage

=

std

::

make_unique

<

mtc

::

stages

::

GeneratePlacePose

>

(

"generate place pose"

);

stage

>

properties

().

configureInitFrom

(

mtc

::

Stage

::

PARENT

);

stage

>

properties

().

set

(

"marker_ns"

,

"place_pose"

);

stage

>

setObject

(

"object"

);

geometry_msgs

::

msg

::

PoseStamped

target_pose_msg

;

target_pose_msg

.

header

.

frame_id

=

"object"

;

target_pose_msg

.

pose

.

position

.

y

=

0.5

;

target_pose_msg

.

pose

.

orientation

.

w

=

1.0

;

stage

>

setPose

(

target_pose_msg

);

stage

>

setMonitoredStage

(

attach_object_stage

);

// Hook into attach_object_stage

// Compute IK

auto

wrapper

=

std

::

make_unique

<

mtc

::

stages

::

ComputeIK

>

(


key: chroma:document
string_value:
std

::

make_unique

<

mtc

::

stages

::

ComputeIK

>

(

"place pose IK"

,

std

::

move

(

stage

));

wrapper

>

setMaxIKSolutions

(

2

);

wrapper

>

setMinSolutionDistance

(

1.0

);

wrapper

>

setIKFrame

(

"object"

);

wrapper

>

properties

().

configureInitFrom

(

mtc

::

Stage

::

PARENT

,

{

"eef"

,

"group"

});

wrapper

>

properties

().

configureInitFrom

(

mtc

::

Stage

::

INTERFACE

,

{

"target_pose"

});

place

>

insert

(

std

::

move

(

wrapper

));

}

```

Language: unknown

File: MoveTo

```

{

auto

stage

=

std

::

make_unique

<

mtc

::

stages

::

MoveTo

>

(

"open hand"

,

interpolation_planner

);

stage

>

setGroup

(

hand_group_name

);

stage

>

setGoal

(

"open"

);

place

>

insert

(

std

::

move

(

stage

));

}

```

Language: unknown

File: true

```

{

auto

stage

=

std

::

make_unique

<

mtc

::

stages

::

ModifyPlanningScene

>

(

"forbid collision (hand,object)"

);

stage

>

allowCollisions

(

"object"


key: chroma:document
string_value:
);

stage

>

allowCollisions

(

"object"

,

task

.

getRobotModel

()

>

getJointModelGroup

(

hand_group_name

)

>

getLinkModelNamesWithCollisionGeometry

(),

false

);

place

>

insert

(

std

::

move

(

stage

));

}

```

Language: unknown

File: detachObject

```

{

auto

stage

=

std

::

make_unique

<

mtc

::

stages

::

ModifyPlanningScene

>

(

"detach object"

);

stage

>

detachObject

(

"object"

,

hand_frame

);

place

>

insert

(

std

::

move

(

stage

));

}

```

Language: unknown

File: liftobject

```

{

auto

stage

=

std

::

make_unique

<

mtc

::

stages

::

MoveRelative

>

(

"retreat"

,

cartesian_planner

);

stage

>

properties

().

configureInitFrom

(

mtc

::

Stage

::

PARENT

,

{

"group"

});

stage

>

setMinMaxDistance

(

0.1

,

0.3

);

stage

>

setIKFrame

(

hand_frame

);

stage

>

properties

().

set

(

"marker_ns"

,

"retreat"

);

// Set retreat direction

geometry_msgs

::

msg

::

Vector3Stamped

vec

;

vec

.

header


key: chroma:document
string_value:
::

msg

::

Vector3Stamped

vec

;

vec

.

header

.

frame_id

=

"world"

;

vec

.

vector

.

x

=

0.5

;

stage

>

setDirection

(

vec

);

place

>

insert

(

std

::

move

(

stage

));

}

```

Language: unknown

File: liftobject

```

task

.

add

(

std

::

move

(

place

));

}

```

Language: unknown

File: ready

```

{

auto

stage

=

std

::

make_unique

<

mtc

::

stages

::

MoveTo

>

(

"return home"

,

interpolation_planner

);

stage

>

properties

().

configureInitFrom

(

mtc

::

Stage

::

PARENT

,

{

"group"

});

stage

>

setGoal

(

"ready"

);

task

.

add

(

std

::

move

(

stage

));

}

```

Language: unknown

File: ready

```

// Stages all added to the task above this line

return

task

;

}

```

Language: unknown

File: ready

```

ros2

launch

mtc_tutorial

pick_place_demo

.

launch

.

py

```

Language: unknown

File: ready

```

ros2

launch

moveit2_tutorials

mtc_demo

.

launch

.

py

```

Language: unknown

File: ready

```

ros2

launch


key: chroma:document
string_value:
.

py

```

Language: unknown

File: ready

```

ros2

launch

moveit2_tutorials

pick_place_demo

.

launch

.

py

```

Language: unknown

File: ready

```

[

demo_node-1

]

1

←

1

→

0

/

initial_state

[

demo_node-1

]

0

→

0

→

0

/

move_to_home

```

Language: unknown

File: 0

```

uint32_t

const

unique_stage_id

=

task_

.

stages

()

>

findChild

(

stage_name

)

>

introspectionId

();

```


key: chroma:document
string_value:
Title: Examples

URL: https://moveit.picknik.ai/main/doc/examples/examples.html

Section: doc/examples/examples.html

--------------------------------------------------------------------------------


key: chroma:document
string_value:
Title: Contributing

URL: https://moveit.picknik.ai/main/doc/how_to_contribute/how_to_contribute.html

Section: index.html

--------------------------------------------------------------------------------


key: chroma:document
string_value:
Title: How to Write a MoveIt Tutorial

URL: https://moveit.picknik.ai/main/doc/how_to_contribute/how_to_write_tutorials.html

Section: index.html

--------------------------------------------------------------------------------

## Learning Objectives

## Requirements

## Steps

## Template

## Further Reading

Code Examples:

Language: unknown

File: .rst

```

<

Title

>

-------

<

Brief

description

of

the

tutorial

with

image

showing

what

will

be

accomplished

.>

Background

----------

<

Explanation

of

what

the

user

should

have

already

done

before

this

tutorial

.>

Steps

-----

1.

<

First

Step

>

---------------

<

This

should

describe

an

action

that

the

user

should

take

such

as

creating

a

ROS

project

or

typing

up

some

code

.>

1.1

)

<

Explanation

First

Step

>

^^^^^^^^^^^^^^^^^^^^^^^^^^^^

<

Use

sub

steps

like

this

to

walk

the

user

through

an

explanation

of

what

they

did

.>

1.2

)

<

Action

First

step

>


key: chroma:document
string_value:
of

what

they

did

.>

1.2

)

<

Action

First

step

>

^^^^^^^^^^^^^^^^^^^^^^^

<

Use

a

sub

step

like

this

to

describe

running

the

new

code

and

what

the

results

should

be

.>

2.

<

Second

Step

>

----------------

<...>

Conclusion

----------

<

Here

is

where

you

explain

what

the

user

has

read

and

provide

additional

references

.>

Next

Step

---------

<

Link

to

the

next

tutorial

here

.>

```


key: chroma:document
string_value:
Title: Motion Planning

URL: https://moveit.picknik.ai/main/doc/concepts/motion_planning.html

Section: index.html

--------------------------------------------------------------------------------

## The Motion Planning Plugin MoveIt works with motion planners through aplugin interface. This allows MoveIt to communicate with and use different motion planners from multiple libraries, making MoveIt easily extensible. The interface to the motion planners is through a ROS action or service (offered by themove_groupnode). The default motion planners for move_group are configured using OMPL and the MoveIt interface to OMPL by the MoveIt Setup Assistant. Other planners that are available by default are the Pilz industrial motion planner and CHOMP.


key: chroma:document
string_value:
## The Motion Plan Request The motion plan request specifies what you would like the motion planner to do. Typically, you will be asking the motion planner to move an arm to a different location (in joint space) or the end-effector to a new pose. Collisions are checked for by default (including self-collisions and attached objects). You can also specify the planner via theplanning_pipelineandplanner_idparameters, and the constraints for the motion planner to check - the inbuilt constraints provided by MoveIt arekinematicconstraints:

## The Motion Plan Result Themove_groupnode will generate a desired trajectory in response to your motion plan request. This trajectory will move the arm (or any group of joints) to the desired location. Note that the result coming out ofmove_groupis a trajectory and not just a path.move_groupwill use the desired maximum velocities and accelerations (if specified) to generate a trajectory that obeys velocity and acceleration constraints at the joint level.


key: chroma:document
string_value:
## Motion planning adapters The complete motion planning pipeline chains together a motion planner with other components calledplanning request adapters. Planning request adapters allow for pre-processing motion plan requests and post-processing motion plan responses. Pre-processing is useful in several situations, e.g. when a start state for the robot is slightly outside the specified joint limits for the robot. Post-processing is needed for several other operations, e.g. to convert paths generated for a robot into time-parameterized trajectories. MoveIt provides a set of default motion planning adapters that each perform a very specific function.


key: chroma:document
string_value:
## CheckStartStateBounds The fix start state bounds adapter fixes the start state to be within the joint limits specified in the URDF. The need for this adapter arises in situations where the joint limits for the physical robot are not properly configured. The robot may then end up in a configuration where one or more of its joints is slightly outside its joint limits. In this case, the motion planner is unable to plan since it will think that the starting state is outside joint limits. The “CheckStartStateBounds” planning request adapter will “fix” the start state by moving it to the joint limit. However, this is obviously not the right solution every time - e.g. where the joint is really outside its joint limits by a large amount. A parameter for the adapter specifies how much the joint can be outside its limits for it to be “fixable”.


key: chroma:document
string_value:
## ValidateWorkspaceBounds The fix workspace bounds adapter will specify a default workspace for planning: a cube of size 10 m x 10 m x 10 m. This workspace will only be specified if the planning request to the planner does not have these fields filled in.

## CheckStartStateCollision The fix start state collision adapter will attempt to sample a new collision-free configuration near a specified configuration (in collision) by perturbing the joint values by a small amount. The amount that it will perturb the values by is specified by thejiggle_fractionparameter that controls the perturbation as a percentage of the total range of motion for the joint. The other parameter for this adapter specifies how many random perturbations the adapter will sample before giving up.


key: chroma:document
string_value:
## AddTimeParameterization The motion planners will typically generate “kinematic paths”, i.e., paths that do not obey any velocity or acceleration constraints and are not time parameterized. This adapter will “time parameterize” the motion plans by applying velocity and acceleration constraints.

## ResolveConstraintFrames Goal constraints can be set using subframes (e.g. a pose goal in the framecup/handle, wherehandleis a subframe on the objectcup). This adapter changes the frame of constraints to an object or robot frame (e.g.cup).

## OMPL OMPL (Open Motion Planning Library) is an open-source motion planning library that primarily implements randomized motion planners. MoveIt integrates directly with OMPL and uses the motion planners from that library as its primary/default set of planners. The planners in OMPL are abstract; i.e. OMPL has no concept of a robot. Instead, MoveIt configures OMPL and provides the back-end for OMPL to work with problems in Robotics.


key: chroma:document
string_value:
Title: How to Contribute to This Site URL: https://moveit.picknik.ai/main/doc/how_to_contribute/how_to_contribute_to_site.html Section: index.html --------------------------------------------------------------------------------

## Learning Objectives

## Requirements

## Steps

## Further Reading

Code Examples:

Language: unknown

File: ~/ws_moveit/src/moveit2_tutorials

```

make

html

# Or run the following lines if you want to automatically rebuild the website on new changes while inotifywait -re modify,move,create,delete . ; do make html

done

```

Language: unknown

File: ./build/html/index.html

```

xdg

open

./build/html/index.html

```

Language: unknown

File: pip

```

python3

m

venv

.venv

source

.venv/bin/activate

```

Language: unknown

File: pip

```

pip3

install

upgrade

requirement

requirements.txt

```

Language: unknown

File: htmlproofer

```

./htmlproofer.sh

```

Language: unknown

File: htmlproofer

```

python3

m

pip

install

user

pre

commit

```


key: chroma:document
string_value:
```

python3

m

pip

install

user

pre

commit

```

Language: unknown

File: htmlproofer

```

pre

commit

run

all

```

Language: unknown

File: htmlproofer

```

ros2

run

industrial_ci

rerun_ci

src/moveit2_tutorials

\

DOCKER_IMAGE

=

'moveit/moveit2:rolling

source'

\

UPSTREAM_WORKSPACE

=

'moveit2_tutorials.repos'

\

TARGET_CMAKE_ARGS

=

'

DCMAKE_BUILD_TYPE=Release'

\

CCACHE_DIR

=

"

$HOME

/.ccache"

\

CLANG_TIDY

=

'true'

```


key: chroma:document
string_value:
Title: Kinematics

URL: https://moveit.picknik.ai/main/doc/concepts/kinematics.html

Section: index.html

--------------------------------------------------------------------------------

## The Kinematics Plugin MoveIt uses a plugin infrastructure, especially targeted towards allowing users to write their own inverse kinematics algorithms. Forward kinematics and finding Jacobians is integrated within the RobotState class itself. The default inverse kinematics plugin for MoveIt is configured using theKDLnumerical Jacobian-based solver. This plugin is automatically configured by the MoveIt Setup Assistant.

## Collision Checking Collision checking in MoveIt is configured inside a Planning Scene using theCollisionWorldobject. Fortunately, MoveIt is set up so that users never really have to worry about how collision checking is happening. Collision checking in MoveIt is mainly carried out using theFCLpackage - the primary collision checking library of MoveIt.


key: chroma:document
string_value:
## Collision Objects MoveIt supports collision checking for different types of objects including:

## Allowed Collision Matrix (ACM) Collision checking is a very expensive operation often accounting for close to 90% of the computational expense during motion planning. TheAllowedCollisionMatrixorACMencodes a binary value corresponding to the need to check for collision between pairs of bodies (which could be on the robot or in the world). If the value corresponding to two bodies is set totruein the ACM, no collision check between the two bodies will be performed. The collision checking would not be required if, e.g., the two bodies are always so far away that they can never collide with each other. Alternatively, the two bodies could be in contact with each other by default, in which case the collision detection should be disabled for the pair in the ACM.


key: chroma:document
string_value:
Title: Tutorials

URL: https://moveit.picknik.ai/main/doc/tutorials/tutorials.html

Section: doc/tutorials/tutorials.html

--------------------------------------------------------------------------------


key: chroma:document
string_value:
Title: Your First C++ MoveIt Project

URL: https://moveit.picknik.ai/main/doc/tutorials/your_first_project/your_first_project.html

Section: index.html

--------------------------------------------------------------------------------

## Prerequisites

If you haven’t already done so, make sure you’ve completed the steps inGetting Started.

This tutorial assumes you understand the basics of ROS 2.

To prepare yourself for this please complete theOfficial ROS 2 Tutorialsup until “Writing a simple publisher and Subscriber (C++)”.

## Steps

## 1 Create a package

Open a terminal andsource your ROS 2 installationso thatros2commands will work.

Navigate to yourws_moveitdirectory you created in theGetting Started Tutorial.

Change directory into thesrcdirectory, as that is where we put our source code.

Create a new package with the ROS 2 command line tools:

The output of this will show that it created some files in a new directory.

Note that we addedmoveit_ros_planning_interfaceandrclcppas dependencies.


key: chroma:document
string_value:
This will create the necessary changes in thepackage.xmlandCMakeLists.txtfiles so that we can depend on these two packages.

Open the new source file created for you atws_moveit/src/hello_moveit/src/hello_moveit.cppin your favorite editor.

## 2 Create a ROS Node and Executor

This first block of code is a bit of boilerplate but you should be used to seeing this from the ROS 2 tutorials.

## 2.1 Build and Run

We will build and run the program to see that everything is right before we move on.

Change the directory back to the workspace directoryws_moveitand run this command:

After this succeeds,open a new terminal, then source the workspace environment script in that new terminal so that we can run our program.

Run your program and see the output.

The program should run and exit without error.

## 2.2 Examine the code

The headers included at the top are just some standard C++ headers and the headers for ROS and MoveIt that we will use later.


key: chroma:document
string_value:
After that, we have the normal call to initialize rclcpp, and then we create our Node.

The first argument is a string that ROS will use to name a unique node.

The second is needed for MoveIt because of how we use ROS Parameters.

Next, wecreate a loggernamed “hello_moveit” to keep our log outputs organized and configurable.

Lastly, we have the code to shutdown ROS.

## 3 Plan and Execute using MoveGroupInterface

In place of the comment that says “Next step goes here”, add this code:

## 3.1 Build and Run

Just like before, we need to build the code before we can run it.

In the workspace directory,ws_moveit, run this command:

After this succeeds, we need to reuse the demo launch file from the previous tutorial to start RViz and the MoveGroup node.

In a separate terminal, source the workspace and then execute this:

Then in theDisplayswindow underMotionPlanning/PlanningRequest, uncheck the boxQueryGoalState.

In a third terminal, source the workspace and run your program.


key: chroma:document
string_value:
This should cause the robot in RViz to move and end up in this pose:

Note that if you run the nodehello_moveitwithout launching the demo launch file first, it will wait for 10 seconds and then print this error and exit.

This is because thedemo.launch.pylaunch is starting theMoveGroupnode that provides the robot description.

WhenMoveGroupInterfaceis constructed, it looks for a node publishing a topic with the robot description.

If it fails to find that within 10 seconds, it prints this error and terminates the program.

## 3.2 Examine the code

The first thing we do is create theMoveGroupInterface.

This object will be used to interact withmove_group, which allows us to plan and execute trajectories.

Note that this is the only mutable object that we create in this program.

Another thing to take note of is the second argument to theMoveGroupInterfaceobject we are creating here:"manipulator".


key: chroma:document
string_value:
That is the group of joints as defined in the robot description that we are going to operate on with thisMoveGroupInterface.

Then, we set our target pose and plan. Note that only the target pose is set (viasetPoseTarget).

The starting pose is implicitly the position published by the joint state publisher, which could be changed using theMoveGroupInterface::setStartState*family of functions (but is not in this tutorial).

One more thing to note about this next section is the use of lambdas for constructing the message typetarget_poseand planning.

This is a pattern you’ll find in modern C++ codebases that enables writing in a more declarative style.

For more information about this pattern, there are a couple of links at the end of this tutorial.

Finally, we execute our plan if planning is successful, otherwise, we log an error:

## Summary

## Further Reading

## Next Step


key: chroma:document
string_value:
## Summary

## Further Reading

## Next Step

In the next tutorialVisualizing in RViz, you will expand on the program you built here to create visual markers that make it easier to understand what MoveIt is doing.

Code Examples:

Language: unknown

File: src

```

ros2

pkg

create

\

--build-type

ament_cmake

\

--dependencies

moveit_ros_planning_interface

rclcpp

\

--node-name

hello_moveit

hello_moveit

```

Language: unknown

File: ws_moveit/src/hello_moveit/src/hello_moveit.cpp

```

#include

<memory>

#include

<rclcpp/rclcpp.hpp>

#include

<moveit/move_group_interface/move_group_interface.h>

int

main

(

int

argc

,

char

argv

[])

{

// Initialize ROS and create the Node

rclcpp

::

init

(

argc

,

argv

);

auto

const

node

=

std

::

make_shared

<

rclcpp

::

Node

>

(

"hello_moveit"

,

rclcpp

::

NodeOptions

().

automatically_declare_parameters_from_overrides

(

true

)

);

// Create a ROS logger

auto

const

logger

=

rclcpp

::

get_logger

(

"hello_moveit"


key: chroma:document
string_value:
const

logger

=

rclcpp

::

get_logger

(

"hello_moveit"

);

// Next step goes here

// Shutdown ROS

rclcpp

::

shutdown

();

return

0

;

}

```

Language: unknown

File: ws_moveit

```

colcon

build

--mixin

debug

```

Language: unknown

File: ws_moveit

```

cd

~/ws_moveit

source

install/setup.bash

```

Language: unknown

File: ws_moveit

```

ros2

run

hello_moveit

hello_moveit

```

Language: unknown

File: ws_moveit

```

auto

const

node

=

std

::

make_shared

<

rclcpp

::

Node

>

(

"hello_moveit"

,

rclcpp

::

NodeOptions

().

automatically_declare_parameters_from_overrides

(

true

)

);

```

Language: unknown

File: ws_moveit

```

// Create a ROS logger

auto

const

logger

=

rclcpp

::

get_logger

(

"hello_moveit"

);

```

Language: unknown

File: ws_moveit

```

// Shutdown ROS

rclcpp

::

shutdown

();

return

0

;

```

Language: unknown

File: ws_moveit

```

// Create the MoveIt MoveGroup Interface

using

moveit

::

planning_interface

::


key: chroma:document
string_value:
using

moveit

::

planning_interface

::

MoveGroupInterface

;

auto

move_group_interface

=

MoveGroupInterface

(

node

,

"manipulator"

);

// Set a target Pose

auto

const

target_pose

=

[]{

geometry_msgs

::

msg

::

Pose

msg

;

msg

.

orientation

.

w

=

1.0

;

msg

.

position

.

x

=

0.28

;

msg

.

position

.

y

=

0.2

;

msg

.

position

.

z

=

0.5

;

return

msg

;

}();

move_group_interface

.

setPoseTarget

(

target_pose

);

// Create a plan to that target pose

auto

const

[

success

,

plan

]

=

[

&

move_group_interface

]{

moveit

::

planning_interface

::

MoveGroupInterface

::

Plan

msg

;

auto

const

ok

=

static_cast

<

bool

>

(

move_group_interface

.

plan

(

msg

));

return

std

::

make_pair

(

ok

,

msg

);

}();

// Execute the plan

if

(

success

)

{

move_group_interface

.

execute

(

plan

);

}

else

{

RCLCPP_ERROR

(

logger

,

"Planning failed!"

);

}

```

Language: unknown

File: ws_moveit

```

colcon

build


key: chroma:document
string_value:
}

```

Language: unknown

File: ws_moveit

```

colcon

build

--mixin

debug

```

Language: unknown

File: ws_moveit

```

ros2

launch

moveit2_tutorials

demo.launch.py

```

Language: unknown

File: QueryGoalState

```

ros2

run

hello_moveit

hello_moveit

```

Language: unknown

File: hello_moveit

```

[

ERROR

]

[

1644181704

.350825487

]

[

hello_moveit

]

:

Could

not

find

parameter

robot_description

and

did

not

receive

robot_description

via

std_msgs::msg::String

subscription

within

10

.000000

seconds.

```

Language: unknown

File: MoveGroupInterface

```

using

moveit

::

planning_interface

::

MoveGroupInterface

;

auto

move_group_interface

=

MoveGroupInterface

(

node

,

"manipulator"

);

```

Language: unknown

File: target_pose

```

// Set a target Pose

auto

const

target_pose

=

[]{

geometry_msgs

::

msg

::

Pose

msg

;

msg

.

orientation

.

w

=

1.0

;

msg

.

position

.

x

=

0.28

;

msg

.

position

.

y

=

0.2

;

msg

.

position

.


key: chroma:document
string_value:
;

msg

.

position

.

y

=

0.2

;

msg

.

position

.

z

=

0.5

;

return

msg

;

}();

move_group_interface

.

setPoseTarget

(

target_pose

);

// Create a plan to that target pose

auto

const

[

success

,

plan

]

=

[

&

move_group_interface

]{

moveit

::

planning_interface

::

MoveGroupInterface

::

Plan

msg

;

auto

const

ok

=

static_cast

<

bool

>

(

move_group_interface

.

plan

(

msg

));

return

std

::

make_pair

(

ok

,

msg

);

}();

```

Language: unknown

File: target_pose

```

// Execute the plan

if

(

success

)

{

move_group_interface

.

execute

(

plan

);

}

else

{

RCLCPP_ERROR

(

logger

,

"Planning failed!"

);

}

```


key: chroma:document
string_value:
Title: Themove_groupnode

URL: https://moveit.picknik.ai/main/doc/concepts/move_group.html

Section: index.html

--------------------------------------------------------------------------------

## User Interface The users can access the actions and services provided bymove_groupin two ways:

## Configuration move_groupis a ROS node. It uses the ROS param server to get three kinds of information:

## Robot Interface move_grouptalks to the robot through ROS topics and actions. It communicates with the robot to get current state information (positions of the joints, etc.), to get point clouds and other sensor data from the robot sensors and to talk to the controllers on the robot.


key: chroma:document
string_value:
## Joint State Information move_grouplistens on the/joint_statestopic for determining the current state information - i.e. determining where each joint of the robot is.move_groupis capable of listening to multiple publishers on this topic even if they are publishing only partial information about the robot state (e.g. separate publishers may be used for the arm and mobile base of a robot). Note thatmove_groupwill not set up its own joint state publisher - this is something that has to be implemented on each robot.


key: chroma:document
string_value:
## Transform Information move_groupmonitors transform information using the ROS TF library. This allows the node to get global information about the pose of the robot (among other things). For instance, the ROS navigation stack will publish the transform between the map frame and base frame of the robot to TF.move_groupcan use TF to figure out this transform for internal use. Note thatmove_grouponly listens to TF. To publish TF information from your robot, you will need to have arobot_state_publishernode running on your robot.

## Controller Interface move_grouptalks to the controllers on the robot using the FollowJointTrajectoryAction interface. This is a ROS action interface. A server on the robot needs to service this action - this server is not provided bymove_groupitself.move_groupwill only instantiate a client to talk to this controller action server on your robot.


key: chroma:document
string_value:
## Planning Scene move_groupuses the Planning Scene Monitor to maintain aplanning scene, which is a representation of the world and the current state of the robot. The robot state can include any objects attached to (carried by) the robot which are considered to be rigidly attached to the robot. More details on the architecture for maintaining and updating theplanning sceneare outlined in the Planning Scene section below.

## Extensible Capabilities move_groupis structured to be easily extensible. Individual capabilities like pick and place, kinematics, motion planning are actually implemented as separate plugins with a common base class. The plugins are configurable using ROS through a set of ROS yaml parameters and through the use of the ROS pluginlib library. Most users will not have to configure move_group plugins since they come automatically configured in the launch files generated by the MoveIt Setup Assistant.


key: chroma:document
string_value:
Title: Trajectory Processing

URL: https://moveit.picknik.ai/main/doc/concepts/trajectory_processing.html

Section: index.html

--------------------------------------------------------------------------------

## Time parameterization Motion planners typically only generate “paths”, i.e. there is no timing information associated with the paths. MoveIt includes severaltrajectory processingalgorithms that can work on these paths and generate trajectories that are properly time-parameterized accounting for the maximum velocity and acceleration limits imposed on individual joints. These limits are read from a specialjoint_limits.yamlconfiguration file that is specified for each robot. The configuration file is optional and it overrides any velocity or acceleration limits from the URDF. The recommended algorithm as of January 2023 isTimeOptimalTrajectoryGeneration(TOTG). A caveat for this algorithm is that the robot must start and end at rest. By default, the TOTG timestep is 0.1 seconds.


key: chroma:document
string_value:
Title: Planning Around Objects

URL: https://moveit.picknik.ai/main/doc/tutorials/planning_around_objects/planning_around_objects.html

Section: index.html

--------------------------------------------------------------------------------

## Prerequisites

If you haven’t already done so, make sure you’ve completed the steps inVisualizing in RViz.

This project assumes you are starting with thehello_moveitproject, where the previous tutorial left off. If you just want to run the tutorial, you can follow theDocker Guideto start a container with the completed tutorial.

## Steps

## 1 Add include for Planning Scene Interface

At the top of your source file, add this to the list of includes:

## 2 Change the Target Pose

First, update the target pose with the following change to make the robot plan to a different location:

## 3 Create a Collision Object

In the next block of code, we create a collision object.

The first thing to notice is that it is being placed in the coordinate frame of the robot.


key: chroma:document
string_value:
If we had a perception system that reported the location of obstacles in our scene, then this is the sort of message it would build.

Because this is just an example, we are creating it manually.

One thing to notice at the end of this block of code is that we set the operation on this message toADD.

This results in the object getting added to the collision scene.

Place this code block between setting the target pose from the previous step and creating a plan.

## 4 Add the Object to the Planning Scene

Finally, we need to add this object to the collision scene.

To do this, we use an object called thePlanningSceneInterfacethat uses ROS interfaces to communicate changes to the planning scene toMoveGroup.

This code block should directly follow the code block that creates the collision object.

## 5 Run the Program and Observe the Change


key: chroma:document
string_value:
## 5 Run the Program and Observe the Change

Just as we did in the last tutorial, start RViz using thedemo.launch.pyscript and run our program. If you’re using one of the Docker tutorial containers, you can specify a different RViz configuration that already has the RvizVisualToolsGui panel added using:

## Summary

## Further Reading

## Next Step

In the next tutorialPick and Place with MoveIt Task Constructor, you will be introduced to a higher layer tool designed to solve harder motion plans.

In this next tutorial, you will create a program to pick and place an object.

Code Examples:

Language: unknown

File: hello_moveit

```

#include

<moveit/planning_scene_interface/planning_scene_interface.h>

```

Language: unknown

File: hello_moveit

```

// Set a target Pose with updated values !!!

auto

const

target_pose

=

[]

{

geometry_msgs

::

msg

::

Pose

msg

;

msg

.

orientation

.

y

=

0.8

;

msg

.

orientation

.

w

=

0.6

;

msg

.

position

.

x

=

0.1

;

msg

.

position

.


key: chroma:document
string_value:
0.6

;

msg

.

position

.

x

=

0.1

;

msg

.

position

.

y

=

0.4

;

msg

.

position

.

z

=

0.4

;

return

msg

;

}();

move_group_interface

.

setPoseTarget

(

target_pose

);

```

Language: unknown

File: ADD

```

// Create collision object for the robot to avoid

auto

const

collision_object

=

[

frame_id

=

move_group_interface

.

getPlanningFrame

()]

{

moveit_msgs

::

msg

::

CollisionObject

collision_object

;

collision_object

.

header

.

frame_id

=

frame_id

;

collision_object

.

id

=

"box1"

;

shape_msgs

::

msg

::

SolidPrimitive

primitive

;

// Define the size of the box in meters

primitive

.

type

=

primitive

.

BOX

;

primitive

.

dimensions

.

resize

(

3

);

primitive

.

dimensions

[

primitive

.

BOX_X

]

=

0.5

;

primitive

.

dimensions

[

primitive

.

BOX_Y

]

=

0.1

;

primitive

.

dimensions

[

primitive

.

BOX_Z

]

=

0.5

;

// Define the pose of the box (relative to the frame_id)

geometry_msgs

::

msg

::

Pose


key: chroma:document
string_value:
geometry_msgs

::

msg

::

Pose

box_pose

;

box_pose

.

orientation

.

w

=

1.0

;

// We can leave out the x, y, and z components of the quaternion since they are initialized to 0

box_pose

.

position

.

x

=

0.2

;

box_pose

.

position

.

y

=

0.2

;

box_pose

.

position

.

z

=

0.25

;

collision_object

.

primitives

.

push_back

(

primitive

);

collision_object

.

primitive_poses

.

push_back

(

box_pose

);

collision_object

.

operation

=

collision_object

.

ADD

;

return

collision_object

;

}();

```

Language: unknown

File: MoveGroup

```

// Add the collision object to the scene

moveit

::

planning_interface

::

PlanningSceneInterface

planning_scene_interface

;

planning_scene_interface

.

applyCollisionObject

(

collision_object

);

```

Language: unknown

File: demo.launch.py

```

ros2

launch

moveit2_tutorials

demo

.

launch

.

py

rviz_config

:=

kinova_hello_moveit

.

rviz

```


key: chroma:document
string_value:
Title: Installing Gazebo with ROS# URL: https://gazebosim.org/docs/latest/ros_installation Section: ros_installation --------------------------------------------------------------------------------

Code Examples:

Language: unknown

File: noetic

```

sudo

apt

get

install

ros

${

ROS_DISTRO

}

ros

gz

```


key: chroma:document
string_value:
Title: ROS 2 integration overview# URL: https://gazebosim.org/docs/latest/ros2_overview Section: ros2_overview --------------------------------------------------------------------------------


key: chroma:document
string_value:
Title: Ignition Tutorials#

URL: https://gazebosim.org/docs/citadel/tutorials

Section: getstarted

--------------------------------------------------------------------------------


key: chroma:document
string_value:
Title: Gazebo Launch

URL: https://gazebosim.org/api/launch/7/tutorials.html

Section: tutorials

--------------------------------------------------------------------------------


key: chroma:document
string_value:
Title: Ignition Fortress#

URL: https://gazebosim.org/docs/fortress/install

Section: getstarted

--------------------------------------------------------------------------------


key: chroma:document
string_value:
Title: Gazebo Transport

URL: https://gazebosim.org/api/transport/13/tutorials.html

Section: tutorials

--------------------------------------------------------------------------------


key: chroma:document
string_value:
Title: Gazebo Cmake

URL: https://gazebosim.org/api/cmake/3/tutorials.html

Section: tutorials

--------------------------------------------------------------------------------


key: chroma:document
string_value:
Title: Gazebo Common

URL: https://gazebosim.org/api/common/5/tutorials.html

Section: tutorials

--------------------------------------------------------------------------------


key: chroma:document
string_value:
Title: Gazebo Harmonic#

URL: https://gazebosim.org/docs/harmonic/install

Section: getstarted

--------------------------------------------------------------------------------


key: chroma:document
string_value:
Title: Manipulating Models#

URL: https://gazebosim.org/docs/latest/manipulating_models

Section: manipulating_models

--------------------------------------------------------------------------------

Code Examples:

Language: unknown

```

gz

sim

shapes.sdf

```


key: chroma:document
string_value:
Title: Sensors#

URL: https://gazebosim.org/docs/latest/sensors

Section: sensors

--------------------------------------------------------------------------------

Code Examples:

Language: unknown

File: plugin

```

<sdf

version=

'1.9'

>

<world

name=

'demo'

>

<plugin

filename=

"gz-sim-physics-system"

name=

"gz::sim::systems::Physics"

>

</plugin>

<plugin

filename=

"gz-sim-scene-broadcaster-system"

name=

"gz::sim::systems::SceneBroadcaster"

>

</plugin>

<!-- ... -->

```

Language: unknown

File: <world>

```

<plugin

filename=

"gz-sim-imu-system"

name=

"gz::sim::systems::Imu"

>

</plugin>

```

Language: unknown

File: IMU

```

<sensor

name=

"imu_sensor"

type=

"imu"

>

<always_on>

1

</always_on>

<update_rate>

1

</update_rate>

<visualize>

true

</visualize>

<topic>

imu

</topic>

</sensor>

```

Language: unknown

File: contact

```

<model

name=

'wall'

>

<static>

true

</static>

<pose>

5

0

0

0

0

0

</pose>

<!--pose relative to the world-->

<link

name=


key: chroma:document
string_value:
0

0

</pose>

<!--pose relative to the world-->

<link

name=

'box'

>

<visual

name=

'visual'

>

<geometry>

<box>

<size>

0.5

10.0

2.0

</size>

</box>

</geometry>

<!--let's add color to our link-->

<material>

<ambient>

0.0

0.0

1.0

1

</ambient>

<diffuse>

0.0

0.0

1.0

1

</diffuse>

<specular>

0.0

0.0

1.0

1

</specular>

</material>

</visual>

<collision

name=

'collision'

>

<geometry>

<box>

<size>

0.5

10.0

2.0

</size>

</box>

</geometry>

</collision>

</link>

</model>

```

Language: unknown

File: Contact

```

<plugin

filename=

"gz-sim-contact-system"

name=

"gz::sim::systems::Contact"

>

</plugin>

```

Language: unknown

File: wall

```

<sensor

name=

'sensor_contact'

type=

'contact'

>

<contact>

<collision>

collision

</collision>

</contact>

</sensor>

```

Language: unknown

File: wall

```

<plugin

filename=

"gz-sim-touchplugin-system"

name=

"gz::sim::systems::TouchPlugin"

>

<target>

vehicle_blue

</target>

<namespace>

wall

</namespace>


key: chroma:document
string_value:
vehicle_blue

</target>

<namespace>

wall

</namespace>

<time>

0.001

</time>

<enabled>

true

</enabled>

</plugin>

```

Language: unknown

File: TriggeredPublisher

```

<plugin

filename=

"gz-sim-triggered-publisher-system"

name=

"gz::sim::systems::TriggeredPublisher"

>

<input

type=

"gz.msgs.Boolean"

topic=

"/wall/touched"

>

<match>

data:

true

</match>

</input>

<output

type=

"gz.msgs.Twist"

topic=

"/cmd_vel"

>

linear:

{x:

0.0},

angular:

{z:

0.0}

</output>

</plugin>

```

Language: unknown

File: chassis

```

<frame

name=

"lidar_frame"

attached_to=

'chassis'

>

<pose>

0.8

0

0.5

0

0

0

</pose>

</frame>

```

Language: unknown

File: lidar

```

<plugin

filename=

"gz-sim-sensors-system"

name=

"gz::sim::systems::Sensors"

>

<render_engine>

ogre2

</render_engine>

</plugin>

```

Language: unknown

File: lidar

```

<sensor

name=

'gpu_lidar'

type=

'gpu_lidar'

>

"

<pose

relative_to=

'lidar_frame'

>

0

0

0

0

0

0

</pose>

<topic>

lidar


key: chroma:document
string_value:
'lidar_frame'

>

0

0

0

0

0

0

</pose>

<topic>

lidar

</topic>

<update_rate>

10

</update_rate>

<ray>

<scan>

<horizontal>

<samples>

640

</samples>

<resolution>

1

</resolution>

<min_angle>

1.396263

</min_angle>

<max_angle>

1.396263

</max_angle>

</horizontal>

<vertical>

<samples>

1

</samples>

<resolution>

0.01

</resolution>

<min_angle>

0

</min_angle>

<max_angle>

0

</max_angle>

</vertical>

</scan>

<range>

<min>

0.08

</min>

<max>

10.0

</max>

<resolution>

0.01

</resolution>

</range>

</ray>

<always_on>

1

</always_on>

<visualize>

true

</visualize>

</sensor>

```

Language: unknown

File: gztopic-e-t/lidar

```

message

LaserScan

{

Header

header

=

1

;

string

frame

=

2

;

Pose

world_pose

=

3

;

double

angle_min

=

4

;

double

angle_max

=

5

;

double

angle_step

=

6

;

double

range_min

=

7

;

double

range_max

=

8

;

uint32

count

=

9

;

double

vertical_angle_min

=

10

;

double

vertical_angle_max

=

11

;

double


key: chroma:document
string_value:
=

10

;

double

vertical_angle_max

=

11

;

double

vertical_angle_step

=

12

;

uint32

vertical_count

=

13

;

repeated

double

ranges

=

14

;

repeated

double

intensities

=

15

;

}

```

Language: unknown

File: subscriber

```

std

::

string

topic_pub

=

"/cmd_vel"

;

gz

::

transport

::

Node

node

;

auto

pub

=

node

.

Advertise

<

gz

::

msgs

::

Twist

>

(

topic_pub

);

```

Language: unknown

File: cmd_vel

```

void

cb

(

const

gz

::

msgs

::

LaserScan

&

_msg

)

{

gz

::

msgs

::

Twist

data

;

bool

allMore

=

true

;

for

(

int

i

=

0

;

i

<

_msg

.

ranges_size

();

i

++

)

{

if

(

_msg

.

ranges

(

i

)

<

1.0

)

{

allMore

=

false

;

break

;

}

}

if

(

allMore

)

//if all bigger than one

{

data

.

mutable_linear

()

>

set_x

(

0.5

);

data

.

mutable_angular

()

>

set_z

(

0.0

);

}

else

{

data

.

mutable_linear

()

>

set_x

(

0.0

);

data

.

mutable_angular

()

>

set_z

(

0.5

);

}

pub

.


key: chroma:document
string_value:
data

.

mutable_angular

()

>

set_z

(

0.5

);

}

pub

.

Publish

(

data

);

}

```

Language: unknown

File: 1.0

```

int

main

(

int

argc

,

char

**

argv

)

{

std

::

string

topic_sub

=

"/lidar"

;

// Subscribe to a topic by registering a callback.

if

(

!

node

.

Subscribe

(

topic_sub

,

cb

))

{

std

::

cerr

<<

"Error subscribing to topic ["

<<

topic_sub

<<

"]"

<<

std

::

endl

;

return

1

;

}

// Zzzzzz.

gz

::

transport

::

waitForShutdown

();

return

0

;

}

```

Language: unknown

File: build/

```

mkdir

build

cd

build

```

Language: unknown

File: build/

```

cmake

..

make

lidar_node

```

Language: unknown

File: build/

```

./build/lidar_node

```

Language: unknown

File: build/

```

gz

sim

sensor_tutorial.sdf

```

Language: unknown

File: lidar_node

```

<?xml version='1.0'?>

<gz

version=

'1.0'

>

<executable

name=

'sensor-world'

>

<command>

gz

sim

sensor_tutorial.sdf

</command>

</executable>

<executable

name=


key: chroma:document
string_value:
</command>

</executable>

<executable

name=

'lidar_node'

>

<command>

./build/lidar_node

</command>

</executable>

</gz>

```

Language: unknown

File: sensor_launch.gzlaunch

```

gz

launch

sensor_launch.gzlaunch

```


key: chroma:document
string_value:
Title: Ignition Citadel#

URL: https://gazebosim.org/docs/citadel/install

Section: getstarted

--------------------------------------------------------------------------------


key: chroma:document
string_value:
Title: Understanding the GUI#

URL: https://gazebosim.org/docs/latest/gui

Section: gui

--------------------------------------------------------------------------------

Code Examples:

Language: unknown

```

gz

sim

shapes.sdf

```

Language: unknown

File: -

versions

```

9

.0.0

8

.0.0

7

.0.0

6

.0.0

```

Language: unknown

File: -

force

version

```

gz

sim

force

version

9

.0.0

shapes.sdf

```


key: chroma:document
string_value:
Title: Gazebo Ionic#

URL: https://gazebosim.org/docs/ionic/install

Section: getstarted

--------------------------------------------------------------------------------


key: chroma:document
string_value:
Title: Gazebo Utils

URL: https://gazebosim.org/api/utils/2/tutorials.html

Section: tutorials

--------------------------------------------------------------------------------


key: chroma:document
string_value:
Title: Gazebo Fuel_tools

URL: https://gazebosim.org/api/fuel_tools/9/tutorials.html

Section: tutorials

--------------------------------------------------------------------------------


key: chroma:document
string_value:
Title: Getting Started with Gazebo?# URL: https://gazebosim.org/docs/latest/getstarted Section: getstarted --------------------------------------------------------------------------------

Code Examples:

Language: unknown ``` gz sim shapes . sdf # Fortress and Citadel use "ign gazebo" instead of "gz sim" ```

Language: unknown File: -v4 ``` gz sim shapes . sdf - v 4 # Fortress and Citadel use "ign gazebo" instead of "gz sim" ```

Language: unknown File: -s ``` gz sim - s shapes . sdf - v 4 # Fortress and Citadel use "ign gazebo" instead of "gz sim" ```

Language: unknown File: <> ``` # launch server in one terminal

gz sim -v 4 shapes.sdf -s # Fortress and Citadel use "ign gazebo" instead of "gz sim" ```

Language: unknown File: <> ``` # launch gui in a separate terminal

gz sim -v 4 -g # Fortress and Citadel use "ign gazebo" instead of "gz sim" ```


key: chroma:document
string_value:
Title: Binary Installation on MacOS# URL: https://gazebosim.org/docs/fortress/install_osx Section: getstarted --------------------------------------------------------------------------------

Code Examples:

Language: unknown

```

/bin/bash

c

"

$(

curl

fsSL

https://raw.githubusercontent.com/Homebrew/install/master/install.sh

)

"

```

Language: unknown

```

brew

tap

osrf/simulation

brew

install

ignition

fortress

```

Language: unknown

File: igngazebo

s

```

brew

uninstall

ignition

fortress

```


key: chroma:document
string_value:
Title: Binary Installation on MacOS Mojave (10.14)# URL: https://gazebosim.org/docs/citadel/install_osx Section: getstarted --------------------------------------------------------------------------------

Code Examples:

Language: unknown

```

/bin/bash

c

"

$(

curl

fsSL

https://raw.githubusercontent.com/Homebrew/install/master/install.sh

)

"

```

Language: unknown

```

brew

tap

osrf/simulation

brew

install

ignition

citadel

```

Language: unknown

File: igngazebo

```

brew

uninstall

ignition

citadel

```


key: chroma:document
string_value:
Title: SDF worlds#

URL: https://gazebosim.org/docs/latest/sdf_worlds

Section: sdf_worlds

--------------------------------------------------------------------------------

Code Examples:

Language: unknown

```

<?xml version="1.0" ?>

<sdf

version=

"1.8"

>

<world

name=

"world_demo"

>

...

...

</world>

</sdf>

```

Language: unknown

File: <world></world>

```

<physics

name=

"1ms"

type=

"ignored"

>

<max_step_size>

0.001

</max_step_size>

<real_time_factor>

1.0

</real_time_factor>

</physics>

```

Language: unknown

File: <real_time_factor>

```

<plugin

filename=

"gz-sim-physics-system"

name=

"gz::sim::systems::Physics"

>

</plugin>

```

Language: unknown

File: Physics

```

<plugin

filename=

"gz-sim-user-commands-system"

name=

"gz::sim::systems::UserCommands"

>

</plugin>

```

Language: unknown

File: UserCommands

```

<plugin

filename=

"gz-sim-scene-broadcaster-system"

name=

"gz::sim::systems::SceneBroadcaster"

>

</plugin>

```

Language: unknown

File: GUI

```


key: chroma:document
string_value:
>

</plugin>

```

Language: unknown

File: GUI

```

<gui

fullscreen=

"0"

>

...

...

</gui>

```

Language: unknown

File: GUI

```

<!-- 3D scene -->

<plugin

filename=

"MinimalScene"

name=

"3D View"

>

<gz-gui>

<title>

3D

View

</title>

<property

type=

"bool"

key=

"showTitleBar"

>

false

</property>

<property

type=

"string"

key=

"state"

>

docked

</property>

</gz-gui>

<engine>

ogre2

</engine>

<scene>

scene

</scene>

<ambient_light>

0.4

0.4

0.4

</ambient_light>

<background_color>

0.8

0.8

0.8

</background_color>

<camera_pose>

6

0

6

0

0.5

0

</camera_pose>

<camera_clip>

<near>

0.25

</near>

<far>

25000

</far>

</camera_clip>

</plugin>

<plugin

filename=

"GzSceneManager"

name=

"Scene Manager"

>

<gz-gui>

<property

key=

"resizable"

type=

"bool"

>

false

</property>

<property

key=

"width"

type=

"double"

>

5

</property>

<property

key=

"height"

type=

"double"

>

5

</property>

<property

key=

"state"

type=

"string"

>


key: chroma:document
string_value:
5

</property>

<property

key=

"state"

type=

"string"

>

floating

</property>

<property

key=

"showTitleBar"

type=

"bool"

>

false

</property>

</gz-gui>

</plugin>

```

Language: unknown

File: RollPitchYaw

```

<!-- World control -->

<plugin

filename=

"WorldControl"

name=

"World control"

>

<gz-gui>

<title>

World

control

</title>

<property

type=

"bool"

key=

"showTitleBar"

>

false

</property>

<property

type=

"bool"

key=

"resizable"

>

false

</property>

<property

type=

"double"

key=

"height"

>

72

</property>

<property

type=

"double"

key=

"width"

>

121

</property>

<property

type=

"double"

key=

"z"

>

1

</property>

<property

type=

"string"

key=

"state"

>

floating

</property>

<anchors

target=

"3D View"

>

<line

own=

"left"

target=

"left"

/>

<line

own=

"bottom"

target=

"bottom"

/>

</anchors>

</gz-gui>

<play_pause>

true

</play_pause>

<step>

true

</step>

<start_paused>

true

</start_paused>

<service>


key: chroma:document
string_value:
</step>

<start_paused>

true

</start_paused>

<service>

/world/world_demo/control

</service>

<stats_topic>

/world/world_demo/stats

</stats_topic>

</plugin>

```

Language: unknown

File: true

```

<!-- World statistics -->

<plugin

filename=

"WorldStats"

name=

"World stats"

>

<gz-gui>

<title>

World

stats

</title>

<property

type=

"bool"

key=

"showTitleBar"

>

false

</property>

<property

type=

"bool"

key=

"resizable"

>

false

</property>

<property

type=

"double"

key=

"height"

>

110

</property>

<property

type=

"double"

key=

"width"

>

290

</property>

<property

type=

"double"

key=

"z"

>

1

</property>

<property

type=

"string"

key=

"state"

>

floating

</property>

<anchors

target=

"3D View"

>

<line

own=

"right"

target=

"right"

/>

<line

own=

"bottom"

target=

"bottom"

/>

</anchors>

</gz-gui>

<sim_time>

true

</sim_time>

<real_time>

true

</real_time>

<real_time_factor>

true

</real_time_factor>

<iterations>

true

</iterations>


key: chroma:document
string_value:
true

</real_time_factor>

<iterations>

true

</iterations>

<topic>

/world/world_demo/stats

</topic>

</plugin>

```

Language: unknown

File: gztopic-e-t/world/world_demo/stats

```

<!-- Entity tree -->

<plugin

filename=

"EntityTree"

name=

"Entity tree"

>

</plugin>

```

Language: unknown

File: </gui>

```

<light

type=

"directional"

name=

"sun"

>

<cast_shadows>

true

</cast_shadows>

<pose>

0

0

10

0

0

0

</pose>

<diffuse>

0.8

0.8

0.8

1

</diffuse>

<specular>

0.2

0.2

0.2

1

</specular>

<attenuation>

<range>

1000

</range>

<constant>

0.9

</constant>

<linear>

0.01

</linear>

<quadratic>

0.001

</quadratic>

</attenuation>

<direction>

0.5

0.1

0.9

</direction>

</light>

```

Language: unknown

File: </world>

```

<include>

<uri>

https://fuel.gazebosim.org/1.0/OpenRobotics/models/Coke

</uri>

</include>

```

Language: unknown

File: </world>

```

<include>

<uri>

model://Coke

</uri>

</include>

```

Language: unknown

File: GZ_SIM_RESOURCE_PATH

```


key: chroma:document
string_value:
```

Language: unknown

File: GZ_SIM_RESOURCE_PATH

```

world_tutorial<br/>

├── Coke <br/>

└── world_demo.sdf

```

Language: unknown

File: <name>

```

<

include

>

<

name

>

Coke0

</

name

>

<

pose

>

0

0

0

0

0

0

</

pose

>

<

uri

>

https

:

//

fuel

.

gazebosim

.

org

/

1.0

/

OpenRobotics

/

models

/

Coke

</

uri

>

</

include

>

<

include

>

<

name

>

Coke1

</

name

>

<

pose

>

0

0.1

0

0

0

0

</

pose

>

<

uri

>

https

:

//

fuel

.

gazebosim

.

org

/

1.0

/

OpenRobotics

/

models

/

Coke

</

uri

>

</

include

>

```


key: chroma:document
string_value:
Title: Gazebo Physics

URL: https://gazebosim.org/api/physics/7/tutorials.html

Section: tutorials

--------------------------------------------------------------------------------


key: chroma:document
string_value:
Title: Gazebo Garden#

URL: https://gazebosim.org/docs/garden/install

Section: getstarted

--------------------------------------------------------------------------------


key: chroma:document
string_value:
Title: Binary Installation on Ubuntu# URL: https://gazebosim.org/docs/harmonic/install_ubuntu Section: getstarted --------------------------------------------------------------------------------

Code Examples:

Language: unknown

File: gz

harmonic

```

sudo

apt

get

update

sudo

apt

get

install

curl

lsb

release

gnupg

```

Language: unknown

File: gz

harmonic

```

sudo

curl

https://packages.osrfoundation.org/gazebo.gpg

output

/usr/share/keyrings/pkgs

osrf

archive

keyring.gpg

echo

"deb [arch=

$(

dpkg

print

architecture

)

signed

by=/usr/share/keyrings/pkgs

osrf

archive

keyring.gpg] http://packages.osrfoundation.org/gazebo/ubuntu

stable

$(

lsb_release

cs

)

main"

|

sudo

tee

/etc/apt/sources.list.d/gazebo

stable.list

>

/dev/null

sudo

apt

get

update

sudo

apt

get

install

gz

harmonic

```

Language: unknown

File: gzsim

```

sudo

apt

remove

gz

harmonic

&&

sudo

apt

autoremove

```


key: chroma:document
string_value:
Title: Gazebo Sim Architecture#

URL: https://gazebosim.org/docs/latest/architecture

Section: architecture

--------------------------------------------------------------------------------


key: chroma:document
string_value:
Title: Gazebo Tutorials#

URL: https://gazebosim.org/docs/latest/tutorials

Section: tutorials

--------------------------------------------------------------------------------


key: chroma:document
string_value:
Title: Gazebo Rendering

URL: https://gazebosim.org/api/rendering/8/tutorials.html

Section: tutorials

--------------------------------------------------------------------------------


key: chroma:document
string_value:
Title: Actors#

URL: https://gazebosim.org/docs/latest/actors

Section: actors

--------------------------------------------------------------------------------

Code Examples:

Language: unknown

File: actor_walking

```

<actor

name=

"actor_walking"

>

<skin>

<filename>

https://fuel.gazebosim.org/1.0/Mingfei/models/actor/tip/files/meshes/walk.dae

</filename>

<scale>

1.0

</scale>

</skin>

<animation

name=

"walk"

>

<filename>

https://fuel.gazebosim.org/1.0/Mingfei/models/actor/tip/files/meshes/walk.dae

</filename>

<interpolate_x>

true

</interpolate_x>

</animation>

</actor>

```

Language: unknown

File: talk_b.dae

```

<script>

<loop>

true

</loop>

<delay_start>

0.000000

</delay_start>

<auto_start>

true

</auto_start>

```

Language: unknown

File: auto_start

```

<trajectory

id=

"0"

type=

"walk"

tension=

"0.6"

>

<waypoint>

<time>

0

</time>

<pose>

0

0

1.0

0

0

0

</pose>

</waypoint>

<waypoint>

<time>

2

</time>

<pose>

2.0

0

1.0

0

0

0

</pose>


key: chroma:document
string_value:
<time>

2

</time>

<pose>

2.0

0

1.0

0

0

0

</pose>

</waypoint>

<waypoint>

<time>

2.5

</time>

<pose>

2

0

1.0

0

0

1.57

</pose>

</waypoint>

<waypoint>

<time>

4

</time>

<pose>

2

2

1.0

0

0

1.57

</pose>

</waypoint>

<waypoint>

<time>

4.5

</time>

<pose>

2

2

1.0

0

0

3.142

</pose>

</waypoint>

<waypoint>

<time>

6

</time>

<pose>

0

2

1

0

0

3.142

</pose>

</waypoint>

<waypoint>

<time>

6.5

</time>

<pose>

0

2

1

0

0

1.57

</pose>

</waypoint>

<waypoint>

<time>

8

</time>

<pose>

0

0

1.0

0

0

1.57

</pose>

</waypoint>

<waypoint>

<time>

8.5

</time>

<pose>

0

0

1.0

0

0

0

</pose>

</waypoint>

</trajectory>

</script>

```


key: chroma:document
string_value:
Title: Building your own robot#

URL: https://gazebosim.org/docs/latest/building_robot

Section: building_robot

--------------------------------------------------------------------------------

Code Examples:

Language: unknown

File: building_robot.sdf

```

<?xml version="1.0" ?>

<sdf

version=

"1.10"

>

<world

name=

"car_world"

>

<physics

name=

"1ms"

type=

"ignored"

>

<max_step_size>

0.001

</max_step_size>

<real_time_factor>

1.0

</real_time_factor>

</physics>

<plugin

filename=

"gz-sim-physics-system"

name=

"gz::sim::systems::Physics"

>

</plugin>

<plugin

filename=

"gz-sim-user-commands-system"

name=

"gz::sim::systems::UserCommands"

>

</plugin>

<plugin

filename=

"gz-sim-scene-broadcaster-system"

name=

"gz::sim::systems::SceneBroadcaster"

>

</plugin>

<light

type=

"directional"

name=

"sun"

>

<cast_shadows>

true

</cast_shadows>

<pose>

0

0

10

0

0

0

</pose>

<diffuse>

0.8

0.8

0.8

1

</diffuse>

<specular>

0.2

0.2

0.2

1

</specular>

<attenuation>


key: chroma:document
string_value:
<specular>

0.2

0.2

0.2

1

</specular>

<attenuation>

<range>

1000

</range>

<constant>

0.9

</constant>

<linear>

0.01

</linear>

<quadratic>

0.001

</quadratic>

</attenuation>

<direction>

0.5

0.1

0.9

</direction>

</light>

<model

name=

"ground_plane"

>

<static>

true

</static>

<link

name=

"link"

>

<collision

name=

"collision"

>

<geometry>

<plane>

<normal>

0

0

1

</normal>

</plane>

</geometry>

</collision>

<visual

name=

"visual"

>

<geometry>

<plane>

<normal>

0

0

1

</normal>

<size>

100

100

</size>

</plane>

</geometry>

<material>

<ambient>

0.8

0.8

0.8

1

</ambient>

<diffuse>

0.8

0.8

0.8

1

</diffuse>

<specular>

0.8

0.8

0.8

1

</specular>

</material>

</visual>

</link>

</model>

</world>

</sdf>

```

Language: unknown

File: </model>

```

<model

name=

'vehicle_blue'

canonical_link=

'chassis'

>

<pose

relative_to=

'world'

>

0

0

0

0

0

0

</pose>

```

Language: unknown

File: joints

```

<link

name=

'chassis'

>

<pose


key: chroma:document
string_value:
File: joints

```

<link

name=

'chassis'

>

<pose

relative_to=

'__model__'

>

0.5

0

0.4

0

0

0

</pose>

```

Language: unknown

File: model

```

<inertial>

<!--inertial properties of the link mass, inertia matix-->

<mass>

1.14395

</mass>

<inertia>

<ixx>

0.095329

</ixx>

<ixy>

0

</ixy>

<ixz>

0

</ixz>

<iyy>

0.381317

</iyy>

<iyz>

0

</iyz>

<izz>

0.476646

</izz>

</inertia>

</inertial>

```

Language: unknown

File: <inertia>

```

<visual

name=

'visual'

>

<geometry>

<box>

<size>

2.0

1.0

0.5

</size>

</box>

</geometry>

<!--let's add color to our link-->

<material>

<ambient>

0.0

0.0

1.0

1

</ambient>

<diffuse>

0.0

0.0

1.0

1

</diffuse>

<specular>

0.0

0.0

1.0

1

</specular>

</material>

</visual>

```

Language: unknown

File: <specular>

```

<collision

name=

'collision'

>

<geometry>

<box>

<size>

2.0

1.0

0.5

</size>

</box>

</geometry>

</collision>

</link>

</model>

```

Language: unknown

File: </model>

```

<link

name=

'left_wheel'


key: chroma:document
string_value:
File: </model>

```

<link

name=

'left_wheel'

>

<pose

relative_to=

"chassis"

>

0.5

0.6

0

1.5707

0

0

</pose>

<inertial>

<mass>

1

</mass>

<inertia>

<ixx>

0.043333

</ixx>

<ixy>

0

</ixy>

<ixz>

0

</ixz>

<iyy>

0.043333

</iyy>

<iyz>

0

</iyz>

<izz>

0.08

</izz>

</inertia>

</inertial>

```

Language: unknown

File: inertia

```

<visual

name=

'visual'

>

<geometry>

<cylinder>

<radius>

0.4

</radius>

<length>

0.2

</length>

</cylinder>

</geometry>

<material>

<ambient>

1.0

0.0

0.0

1

</ambient>

<diffuse>

1.0

0.0

0.0

1

</diffuse>

<specular>

1.0

0.0

0.0

1

</specular>

</material>

</visual>

<collision

name=

'collision'

>

<geometry>

<cylinder>

<radius>

0.4

</radius>

<length>

0.2

</length>

</cylinder>

</geometry>

</collision>

</link>

```

Language: unknown

File: <length>

```

<!--The same as left wheel but with different position-->

<link

name=

'right_wheel'

>

<pose

relative_to=

"chassis"

>

0.5

0.6

0

1.5707

0

0

</pose>


key: chroma:document
string_value:
relative_to=

"chassis"

>

0.5

0.6

0

1.5707

0

0

</pose>

<!--angles are in radian-->

<inertial>

<mass>

1

</mass>

<inertia>

<ixx>

0.043333

</ixx>

<ixy>

0

</ixy>

<ixz>

0

</ixz>

<iyy>

0.043333

</iyy>

<iyz>

0

</iyz>

<izz>

0.08

</izz>

</inertia>

</inertial>

<visual

name=

'visual'

>

<geometry>

<cylinder>

<radius>

0.4

</radius>

<length>

0.2

</length>

</cylinder>

</geometry>

<material>

<ambient>

1.0

0.0

0.0

1

</ambient>

<diffuse>

1.0

0.0

0.0

1

</diffuse>

<specular>

1.0

0.0

0.0

1

</specular>

</material>

</visual>

<collision

name=

'collision'

>

<geometry>

<cylinder>

<radius>

0.4

</radius>

<length>

0.2

</length>

</cylinder>

</geometry>

</collision>

</link>

```

Language: unknown

File: attached_to

```

<frame

name=

"caster_frame"

attached_to=

'chassis'

>

<pose>

0.8

0

0.2

0

0

0

</pose>

</frame>

```

Language: unknown

File: chassis

```

<!--caster wheel-->

<link

name=

'caster'

>

<pose

relative_to=

'caster_frame'


key: chroma:document
string_value:
<link

name=

'caster'

>

<pose

relative_to=

'caster_frame'

/>

<inertial>

<mass>

1

</mass>

<inertia>

<ixx>

0.016

</ixx>

<ixy>

0

</ixy>

<ixz>

0

</ixz>

<iyy>

0.016

</iyy>

<iyz>

0

</iyz>

<izz>

0.016

</izz>

</inertia>

</inertial>

<visual

name=

'visual'

>

<geometry>

<sphere>

<radius>

0.2

</radius>

</sphere>

</geometry>

<material>

<ambient>

0.0

1

0.0

1

</ambient>

<diffuse>

0.0

1

0.0

1

</diffuse>

<specular>

0.0

1

0.0

1

</specular>

</material>

</visual>

<collision

name=

'collision'

>

<geometry>

<sphere>

<radius>

0.2

</radius>

</sphere>

</geometry>

</collision>

</link>

```

Language: unknown

File: <joint>

```

<joint

name=

'left_wheel_joint'

type=

'revolute'

>

<pose

relative_to=

'left_wheel'

/>

```

Language: unknown

File: left_wheel

```

<parent>

chassis

</parent>

<child>

left_wheel

</child>

```

Language: unknown

File: left_wheel

```

<axis>

<xyz

expressed_in=

'__model__'

>

0

1

0

</xyz>


key: chroma:document
string_value:
<axis>

<xyz

expressed_in=

'__model__'

>

0

1

0

</xyz>

<!--can be defined as any frame or even arbitrary frames-->

<limit>

<lower>

1.79769e+308

</lower>

<!--negative infinity-->

<upper>

1.79769e+308

</upper>

<!--positive infinity-->

</limit>

</axis>

</joint>

```

Language: unknown

File: chassis

```

<joint

name=

'right_wheel_joint'

type=

'revolute'

>

<pose

relative_to=

'right_wheel'

/>

<parent>

chassis

</parent>

<child>

right_wheel

</child>

<axis>

<xyz

expressed_in=

'__model__'

>

0

1

0

</xyz>

<limit>

<lower>

1.79769e+308

</lower>

<!--negative infinity-->

<upper>

1.79769e+308

</upper>

<!--positive infinity-->

</limit>

</axis>

</joint>

```

Language: unknown

File: type='ball'

```

<joint

name=

'caster_wheel'

type=

'ball'

>

<parent>

chassis

</parent>

<child>

caster

</child>

</joint>

```


key: chroma:document
string_value:
Title: Gazebo Plugin

URL: https://gazebosim.org/api/plugin/2/tutorials.html

Section: tutorials

--------------------------------------------------------------------------------


key: chroma:document
string_value:
Title: Libraries#

URL: https://gazebosim.org/libs

Section: getstarted

--------------------------------------------------------------------------------


key: chroma:document
string_value:
Title: Gazebo Msgs

URL: https://gazebosim.org/api/msgs/10/tutorials.html

Section: tutorials

--------------------------------------------------------------------------------


key: chroma:document
string_value:
Title: Gazebo Gui

URL: https://gazebosim.org/api/gui/8/tutorials.html

Section: tutorials

--------------------------------------------------------------------------------


key: chroma:document
string_value:
Title: Gazebo Sensors

URL: https://gazebosim.org/api/sensors/8/tutorials.html

Section: tutorials

--------------------------------------------------------------------------------


key: chroma:document
string_value:
Title: Moving the robot#

URL: https://gazebosim.org/docs/latest/moving_robot

Section: moving_robot

--------------------------------------------------------------------------------

Code Examples:

Language: unknown

File: vehicle_blue

```

<plugin

filename=

"gz

sim

diff

drive

system"

name=

"gz::sim::systems::DiffDrive"

>

<left_joint>

left_wheel_joint

</left_joint>

<right_joint>

right_wheel_joint

</right_joint>

<wheel_separation>

1.2

</wheel_separation>

<wheel_radius>

0.4

</wheel_radius>

<odom_publish_frequency>

1

</odom_publish_frequency>

<topic>

cmd_vel

</topic>

</plugin>

```

Language: unknown

File: gztopic

e

t/keyboard/keypress

```

$ gz topic

e

t /keyboard/keypress

data: 68

data: 85

data: 72

data: 74

data: 81

data: 16777235

data: 16777234

data: 16777237

data: 16777236

```

Language: unknown

File: <world>

```

<!-

Moving Forward-

>

<plugin

filename=

"gz

sim

triggered

publisher

system"

name=

"gz::sim::systems::TriggeredPublisher"

>

<input


key: chroma:document
string_value:
name=

"gz::sim::systems::TriggeredPublisher"

>

<input

type=

"gz.msgs.Int32"

topic=

"/keyboard/keypress"

>

<match

field=

"data"

>

16777235

</match>

</input>

<output

type=

"gz.msgs.Twist"

topic=

"/cmd_vel"

>

linear:

{x:

0.5},

angular:

{z:

0.0}

</output>

</plugin>

```

Language: unknown

File: Triggeredpublisher

```

<!-

Moving Backward-

>

<plugin

filename=

"gz

sim

triggered

publisher

system"

name=

"gz::sim::systems::TriggeredPublisher"

>

<input

type=

"gz.msgs.Int32"

topic=

"/keyboard/keypress"

>

<match

field=

"data"

>

16777237

</match>

</input>

<output

type=

"gz.msgs.Twist"

topic=

"/cmd_vel"

>

linear:

{x:

0.5},

angular:

{z:

0.0}

</output>

</plugin>

```


key: chroma:document
string_value:
Title: Gazebo Sim

URL: https://gazebosim.org/api/sim/8/tutorials.html

Section: tutorials

--------------------------------------------------------------------------------


key: chroma:document
string_value:
Title: Gazebo Math

URL: https://gazebosim.org/api/math/7/tutorials.html

Section: tutorials

--------------------------------------------------------------------------------


key: chroma:document
string_value:
Title: Gazebo Tools

URL: https://gazebosim.org/api/tools/2/tutorials.html

Section: tutorials

--------------------------------------------------------------------------------


key: chroma:document
string_value:
Title: Building a visual robot model from scratch URL: https://docs.ros.org/en/jazzy/Tutorials/Intermediate/URDF/Building-a-Visual-Robot-Model-with-URDF-from-Scratch.html Section: Installation --------------------------------------------------------------------------------


key: chroma:document
string_value:
Building a visual robot model from scratchGoal:Learn how to build a visual model of a robot that you can view in RvizTutorial level:IntermediateTime:20 minutesContentsOne ShapeMultiple ShapesOriginsMaterial GirlFinishing the ModelNoteThis tutorial assumes you know how to write well-formatted XML codeIn this tutorial, we’re going to build a visual model of a robot that vaguely looks like R2D2. In later tutorials, you’ll learn how toarticulate the model,add in some physical properties, andgenerate neater code with xacro, but for now, we’re going to focus on getting the visual geometry correct.Before continuing, make sure you have thejoint_state_publisherpackage installed. If you installedurdf_tutorialbinaries, this should already be the case. If not, please update your installation to include that package (userosdepto check).All of the robot models mentioned in this tutorial (and the source files) can be found in theurdf_tutorialpackage.One ShapeFirst, we’re just going to explore one simple shape. Here’s


key: chroma:document
string_value:
we’re just going to explore one simple shape. Here’s about as simple as a urdf as you can make.[Source: 01-myfirst.urdf]<?xml version="1.0"?><robotname="myfirst"><linkname="base_link"><visual><geometry><cylinderlength="0.6"radius="0.2"/></geometry></visual></link></robot>To translate the XML into English, this is a robot with the namemyfirst, that contains only one link (a.k.a. part), whose visual component is just a cylinder 0.6 meters long with a 0.2 meter radius. This may seem like a lot of enclosing tags for a simple “hello world” type example, but it will get more complicated, trust me.To examine the model, launch thedisplay.launch.pyfile:ros2 launch urdf_tutorial display.launch.py model:=urdf/01-myfirst.urdfThis does three things:Loads the specified model and saves it as a parameter for therobot_state_publishernode.Runs nodes to publishsensor_msgs/msg/JointStateand transforms (more on these later)Starts Rviz with a configuration fileAfter launchingdisplay.launch.py, you should end up with RViz showing


key: chroma:document
string_value:
launchingdisplay.launch.py, you should end up with RViz showing you the following:Things to note:The fixed frame is the transform frame where the center of the grid is located. Here, it’s a frame defined by our one link, base_link.The visual element (the cylinder) has its origin at the center of its geometry as a default. Hence, half the cylinder is below the grid.Multiple ShapesNow let’s look at how to add multiple shapes/links. If we just add more link elements to the urdf, the parser won’t know where to put them. So, we have to add joints. Joint elements can refer to both flexible and inflexible joints. We’ll start with inflexible, or fixed joints.[Source: 02-multipleshapes.urdf]<?xml version="1.0"?><robotname="multipleshapes"><linkname="base_link"><visual><geometry><cylinderlength="0.6"radius="0.2"/></geometry></visual></link><linkname="right_leg"><visual><geometry><boxsize="0.6 0.1


key: chroma:document
string_value:
0.1 0.2"/></geometry></visual></link><jointname="base_to_right_leg"type="fixed"><parentlink="base_link"/><childlink="right_leg"/></joint></robot>Note how we defined a 0.6m x 0.1m x 0.2m boxThe joint is defined in terms of a parent and a child. URDF is ultimately a tree structure with one root link. This means that the leg’s position is dependent on the base_link’s position.ros2 launch urdf_tutorial display.launch.py model:=urdf/02-multipleshapes.urdfBoth of the shapes overlap with each other, because they share the same origin. If we want them not to overlap we must define more origins.OriginsR2D2’s leg attaches to the top half of his torso, on the side. So that’s where we specify the origin of the JOINT to be. Also, it doesn’t attach to the middle of the leg, it attaches to the upper part, so we must offset the origin for the leg as well. We also rotate the leg so it is upright.[Source: 03-origins.urdf]<?xml


key: chroma:document
string_value:
rotate the leg so it is upright.[Source: 03-origins.urdf]<?xml version="1.0"?><robotname="origins"><linkname="base_link"><visual><geometry><cylinderlength="0.6"radius="0.2"/></geometry></visual></link><linkname="right_leg"><visual><geometry><boxsize="0.6 0.1 0.2"/></geometry><originrpy="0 1.57075 0"xyz="0 0 -0.3"/></visual></link><jointname="base_to_right_leg"type="fixed"><parentlink="base_link"/><childlink="right_leg"/><originxyz="0 -0.22 0.25"/></joint></robot>Let’s start by examining the joint’s origin. It is defined in terms of the parent’s reference frame. So we are -0.22 meters in the y direction (to our left, but to the right relative to the axes) and 0.25 meters in the z direction (up). This means that the origin for the child link will be up and to the right, regardless of the child link’s visual origin tag. Since we didn’t specify a rpy (roll pitch yaw) attribute, the child frame will be default have the same orientation as the parent frame.Now, looking at the leg’s visual origin, it has both a xyz


key: chroma:document
string_value:
looking at the leg’s visual origin, it has both a xyz and rpy offset. This defines where the center of the visual element should be, relative to its origin. Since we want the leg to attach at the top, we offset the origin down by setting the z offset to be -0.3 meters. And since we want the long part of the leg to be parallel to the z axis, we rotate the visual part PI/2 around the Y axis.ros2 launch urdf_tutorial display.launch.py model:=urdf/03-origins.urdfThe launch file runs packages that will create TF frames for each link in your model based on your URDF. Rviz uses this information to figure out where to display each shape.If a TF frame does not exist for a given URDF link, then it will be placed at the origin in white (ref.related question).Material Girl“Alright,” I hear you say. “That’s very cute, but not everyone owns a B21. My robot and R2D2 are not red!” That’s a good point. Let’s take a look at the material tag.[Source: 04-materials.urdf]<?xml


key: chroma:document
string_value:
a look at the material tag.[Source: 04-materials.urdf]<?xml version="1.0"?><robotname="materials"><materialname="blue"><colorrgba="0 0 0.8 1"/></material><materialname="white"><colorrgba="1 1 1 1"/></material><linkname="base_link"><visual><geometry><cylinderlength="0.6"radius="0.2"/></geometry><materialname="blue"/></visual></link><linkname="right_leg"><visual><geometry><boxsize="0.6 0.1 0.2"/></geometry><originrpy="0 1.57075 0"xyz="0 0 -0.3"/><materialname="white"/></visual></link><jointname="base_to_right_leg"type="fixed"><parentlink="base_link"/><childlink="right_leg"/><originxyz="0 -0.22 0.25"/></joint><linkname="left_leg"><visual><geometry><boxsize="0.6 0.1 0.2"/></geometry><originrpy="0 1.57075 0"xyz="0 0 -0.3"/><materialname="white"/></visual></link><jointname="base_to_left_leg"type="fixed"><parentlink="base_link"/><childlink="left_leg"/><originxyz="0 0.22 0.25"/></joint></robot>The body is now blue. We’ve defined a new material called “blue”, with the red, green, blue and alpha channels defined as


key: chroma:document
string_value:
“blue”, with the red, green, blue and alpha channels defined as 0,0,0.8 and 1 respectively. All of the values can be in the range [0,1]. This material is then referenced by the base_link’s visual element. The white material is defined similarly.You could also define the material tag from within the visual element, and even reference it in other links. No one will even complain if you redefine it though.You can also use a texture to specify an image file to be used for coloring the objectros2 launch urdf_tutorial display.launch.py model:=urdf/04-materials.urdfFinishing the ModelNow we finish the model off with a few more shapes: feet, wheels, and head. Most notably, we add a sphere and a some meshes. We’ll also add few other pieces that we’ll use later.[Source: 05-visual.urdf]<?xml version="1.0"?><robotname="visual"><materialname="blue"><colorrgba="0 0 0.8 1"/></material><materialname="black"><colorrgba="0 0 0 1"/></material><materialname="white"><colorrgba="1 1 1


key: chroma:document
string_value:
0 0 1"/></material><materialname="white"><colorrgba="1 1 1 1"/></material><linkname="base_link"><visual><geometry><cylinderlength="0.6"radius="0.2"/></geometry><materialname="blue"/></visual></link><linkname="right_leg"><visual><geometry><boxsize="0.6 0.1 0.2"/></geometry><originrpy="0 1.57075 0"xyz="0 0 -0.3"/><materialname="white"/></visual></link><jointname="base_to_right_leg"type="fixed"><parentlink="base_link"/><childlink="right_leg"/><originxyz="0 -0.22 0.25"/></joint><linkname="right_base"><visual><geometry><boxsize="0.4 0.1 0.1"/></geometry><materialname="white"/></visual></link><jointname="right_base_joint"type="fixed"><parentlink="right_leg"/><childlink="right_base"/><originxyz="0 0 -0.6"/></joint><linkname="right_front_wheel"><visual><originrpy="1.57075 0 0"xyz="0 0 0"/><geometry><cylinderlength="0.1"radius="0.035"/></geometry><materialname="black"/></visual></link><jointname="right_front_wheel_joint"type="fixed"><parentlink="right_base"/><childlink="right_front_wheel"/><originrpy="0 0


key: chroma:document
string_value:
0 0"xyz="0.133333333333 0 -0.085"/></joint><linkname="right_back_wheel"><visual><originrpy="1.57075 0 0"xyz="0 0 0"/><geometry><cylinderlength="0.1"radius="0.035"/></geometry><materialname="black"/></visual></link><jointname="right_back_wheel_joint"type="fixed"><parentlink="right_base"/><childlink="right_back_wheel"/><originrpy="0 0 0"xyz="-0.133333333333 0 -0.085"/></joint><linkname="left_leg"><visual><geometry><boxsize="0.6 0.1 0.2"/></geometry><originrpy="0 1.57075 0"xyz="0 0 -0.3"/><materialname="white"/></visual></link><jointname="base_to_left_leg"type="fixed"><parentlink="base_link"/><childlink="left_leg"/><originxyz="0 0.22 0.25"/></joint><linkname="left_base"><visual><geometry><boxsize="0.4 0.1 0.1"/></geometry><materialname="white"/></visual></link><jointname="left_base_joint"type="fixed"><parentlink="left_leg"/><childlink="left_base"/><originxyz="0 0 -0.6"/></joint><linkname="left_front_wheel"><visual><originrpy="1.57075 0 0"xyz="0 0


key: chroma:document
string_value:
0 0"xyz="0 0 0"/><geometry><cylinderlength="0.1"radius="0.035"/></geometry><materialname="black"/></visual></link><jointname="left_front_wheel_joint"type="fixed"><parentlink="left_base"/><childlink="left_front_wheel"/><originrpy="0 0 0"xyz="0.133333333333 0 -0.085"/></joint><linkname="left_back_wheel"><visual><originrpy="1.57075 0 0"xyz="0 0 0"/><geometry><cylinderlength="0.1"radius="0.035"/></geometry><materialname="black"/></visual></link><jointname="left_back_wheel_joint"type="fixed"><parentlink="left_base"/><childlink="left_back_wheel"/><originrpy="0 0 0"xyz="-0.133333333333 0 -0.085"/></joint><jointname="gripper_extension"type="fixed"><parentlink="base_link"/><childlink="gripper_pole"/><originrpy="0 0 0"xyz="0.19 0 0.2"/></joint><linkname="gripper_pole"><visual><geometry><cylinderlength="0.2"radius="0.01"/></geometry><originrpy="0 1.57075 0 "xyz="0.1 0 0"/></visual></link><jointname="left_gripper_joint"type="fixed"><originrpy="0 0 0"xyz="0.2 0.01


key: chroma:document
string_value:
0 0"xyz="0.2 0.01 0"/><parentlink="gripper_pole"/><childlink="left_gripper"/></joint><linkname="left_gripper"><visual><originrpy="0.0 0 0"xyz="0 0 0"/><geometry><meshfilename="package://urdf_tutorial/meshes/l_finger.dae"/></geometry></visual></link><jointname="left_tip_joint"type="fixed"><parentlink="left_gripper"/><childlink="left_tip"/></joint><linkname="left_tip"><visual><originrpy="0.0 0 0"xyz="0.09137 0.00495 0"/><geometry><meshfilename="package://urdf_tutorial/meshes/l_finger_tip.dae"/></geometry></visual></link><jointname="right_gripper_joint"type="fixed"><originrpy="0 0 0"xyz="0.2 -0.01 0"/><parentlink="gripper_pole"/><childlink="right_gripper"/></joint><linkname="right_gripper"><visual><originrpy="-3.1415 0 0"xyz="0 0 0"/><geometry><meshfilename="package://urdf_tutorial/meshes/l_finger.dae"/></geometry></visual></link><jointname="right_tip_joint"type="fixed"><parentlink="right_gripper"/><childlink="right_tip"/></joint><linkname="right_tip"><visual><originrpy="-3.1415 0 0"xyz="0.09137 0.00495


key: chroma:document
string_value:
0 0"xyz="0.09137 0.00495 0"/><geometry><meshfilename="package://urdf_tutorial/meshes/l_finger_tip.dae"/></geometry></visual></link><linkname="head"><visual><geometry><sphereradius="0.2"/></geometry><materialname="white"/></visual></link><jointname="head_swivel"type="fixed"><parentlink="base_link"/><childlink="head"/><originxyz="0 0 0.3"/></joint><linkname="box"><visual><geometry><boxsize="0.08 0.08 0.08"/></geometry><materialname="blue"/></visual></link><jointname="tobox"type="fixed"><parentlink="head"/><childlink="box"/><originxyz="0.1814 0 0.1414"/></joint></robot>ros2 launch urdf_tutorial display.launch.py model:=urdf/05-visual.urdfHow to add the sphere should be fairly self explanatory:<linkname="head"><visual><geometry><sphereradius="0.2"/></geometry><materialname="white"/></visual></link>The meshes here were borrowed from the PR2. They are separate files which you have to specify the path for. You should use thepackage://NAME_OF_PACKAGE/pathnotation. The meshes for this tutorial are located within


key: chroma:document
string_value:
The meshes for this tutorial are located within theurdf_tutorialpackage, in a folder called meshes.<linkname="left_gripper"><visual><originrpy="0.0 0 0"xyz="0 0 0"/><geometry><meshfilename="package://urdf_tutorial/meshes/l_finger.dae"/></geometry></visual></link>The meshes can be imported in a number of different formats. STL is fairly common, but the engine also supports DAE, which can have its own color data, meaning you don’t have to specify the color/material. Often these are in separate files. These meshes reference the.tiffiles also in the meshes folder.Meshes can also be sized using relative scaling parameters or a bounding box size.We could have also referred to meshes in a completely different package.There you have it. A R2D2-like URDF model. Now you can continue on to the next step,making it move.


key: chroma:document
string_value:
Code Examples:

Language: unknown

<?xml version="1.0"?><robotname="myfirst"><linkname="base_link"><visual><geometry><cylinderlength="0.6"radius="0.2"/></geometry></visual></link></robot>

Language: unknown ros2 launch urdf_tutorial display.launch.py model:=urdf/01-myfirst.urdf

Language: unknown

<?xml version="1.0"?><robotname="multipleshapes"><linkname="base_link"><visual><geometry><cylinderlength="0.6"radius="0.2"/></geometry></visual></link><linkname="right_leg"><visual><geometry><boxsize="0.6 0.1 0.2"/></geometry></visual></link><jointname="base_to_right_leg"type="fixed"><parentlink="base_link"/><childlink="right_leg"/></joint></robot>

Language: unknown ros2 launch urdf_tutorial display.launch.py model:=urdf/02-multipleshapes.urdf


key: chroma:document
string_value:
Language: unknown <?xml version="1.0"?><robotname="origins"><linkname="base_link"><visual><geometry><cylinderlength="0.6"radius="0.2"/></geometry></visual></link><linkname="right_leg"><visual><geometry><boxsize="0.6 0.1 0.2"/></geometry><originrpy="0 1.57075 0"xyz="0 0 -0.3"/></visual></link><jointname="base_to_right_leg"type="fixed"><parentlink="base_link"/><childlink="right_leg"/><originxyz="0 -0.22 0.25"/></joint></robot>

Language: unknown ros2 launch urdf_tutorial display.launch.py model:=urdf/03-origins.urdf


key: chroma:document
string_value:
Language: unknown <?xml version="1.0"?><robotname="materials"><materialname="blue"><colorrgba="0 0 0.8 1"/></material><materialname="white"><colorrgba="1 1 1 1"/></material><linkname="base_link"><visual><geometry><cylinderlength="0.6"radius="0.2"/></geometry><materialname="blue"/></visual></link><linkname="right_leg"><visual><geometry><boxsize="0.6 0.1 0.2"/></geometry><originrpy="0 1.57075 0"xyz="0 0 -0.3"/><materialname="white"/></visual></link><jointname="base_to_right_leg"type="fixed"><parentlink="base_link"/><childlink="right_leg"/><originxyz="0 -0.22 0.25"/></joint><linkname="left_leg"><visual><geometry><boxsize="0.6 0.1 0.2"/></geometry><originrpy="0 1.57075 0"xyz="0 0 -0.3"/><materialname="white"/></visual></link><jointname="base_to_left_leg"type="fixed"><parentlink="base_link"/><childlink="left_leg"/><originxyz="0 0.22 0.25"/></joint></robot>

Language: unknown ros2 launch urdf_tutorial display.launch.py model:=urdf/04-materials.urdf


key: chroma:document
string_value:
Language: unknown <?xml version="1.0"?><robotname="visual"><materialname="blue"><colorrgba="0 0 0.8 1"/></material><materialname="black"><colorrgba="0 0 0 1"/></material><materialname="white"><colorrgba="1 1 1 1"/></material><linkname="base_link"><visual><geometry><cylinderlength="0.6"radius="0.2"/></geometry><materialname="blue"/></visual></link><linkname="right_leg"><visual><geometry><boxsize="0.6 0.1 0.2"/></geometry><originrpy="0 1.57075 0"xyz="0 0 -0.3"/><materialname="white"/></visual></link><jointname="base_to_right_leg"type="fixed"><parentlink="base_link"/><childlink="right_leg"/><originxyz="0 -0.22 0.25"/></joint><linkname="right_base"><visual><geometry><boxsize="0.4 0.1 0.1"/></geometry><materialname="white"/></visual></link><jointname="right_base_joint"type="fixed"><parentlink="right_leg"/><childlink="right_base"/><originxyz="0 0 -0.6"/></joint><linkname="right_front_wheel"><visual><originrpy="1.57075 0 0"xyz="0 0


key: chroma:document
string_value:
0 0"xyz="0 0 0"/><geometry><cylinderlength="0.1"radius="0.035"/></geometry><materialname="black"/></visual></link><jointname="right_front_wheel_joint"type="fixed"><parentlink="right_base"/><childlink="right_front_wheel"/><originrpy="0 0 0"xyz="0.133333333333 0 -0.085"/></joint><linkname="right_back_wheel"><visual><originrpy="1.57075 0 0"xyz="0 0 0"/><geometry><cylinderlength="0.1"radius="0.035"/></geometry><materialname="black"/></visual></link><jointname="right_back_wheel_joint"type="fixed"><parentlink="right_base"/><childlink="right_back_wheel"/><originrpy="0 0 0"xyz="-0.133333333333 0 -0.085"/></joint><linkname="left_leg"><visual><geometry><boxsize="0.6 0.1 0.2"/></geometry><originrpy="0 1.57075 0"xyz="0 0 -0.3"/><materialname="white"/></visual></link><jointname="base_to_left_leg"type="fixed"><parentlink="base_link"/><childlink="left_leg"/><originxyz="0 0.22 0.25"/></joint><linkname="left_base"><visual><geometry><boxsize="0.4 0.1


key: chroma:document
string_value:
0.1 0.1"/></geometry><materialname="white"/></visual></link><jointname="left_base_joint"type="fixed"><parentlink="left_leg"/><childlink="left_base"/><originxyz="0 0 -0.6"/></joint><linkname="left_front_wheel"><visual><originrpy="1.57075 0 0"xyz="0 0 0"/><geometry><cylinderlength="0.1"radius="0.035"/></geometry><materialname="black"/></visual></link><jointname="left_front_wheel_joint"type="fixed"><parentlink="left_base"/><childlink="left_front_wheel"/><originrpy="0 0 0"xyz="0.133333333333 0 -0.085"/></joint><linkname="left_back_wheel"><visual><originrpy="1.57075 0 0"xyz="0 0 0"/><geometry><cylinderlength="0.1"radius="0.035"/></geometry><materialname="black"/></visual></link><jointname="left_back_wheel_joint"type="fixed"><parentlink="left_base"/><childlink="left_back_wheel"/><originrpy="0 0 0"xyz="-0.133333333333 0 -0.085"/></joint><jointname="gripper_extension"type="fixed"><parentlink="base_link"/><childlink="gripper_pole"/><originrpy="0 0 0"xyz="0.19 0


key: chroma:document
string_value:
0 0"xyz="0.19 0 0.2"/></joint><linkname="gripper_pole"><visual><geometry><cylinderlength="0.2"radius="0.01"/></geometry><originrpy="0 1.57075 0 "xyz="0.1 0 0"/></visual></link><jointname="left_gripper_joint"type="fixed"><originrpy="0 0 0"xyz="0.2 0.01 0"/><parentlink="gripper_pole"/><childlink="left_gripper"/></joint><linkname="left_gripper"><visual><originrpy="0.0 0 0"xyz="0 0 0"/><geometry><meshfilename="package://urdf_tutorial/meshes/l_finger.dae"/></geometry></visual></link><jointname="left_tip_joint"type="fixed"><parentlink="left_gripper"/><childlink="left_tip"/></joint><linkname="left_tip"><visual><originrpy="0.0 0 0"xyz="0.09137 0.00495 0"/><geometry><meshfilename="package://urdf_tutorial/meshes/l_finger_tip.dae"/></geometry></visual></link><jointname="right_gripper_joint"type="fixed"><originrpy="0 0 0"xyz="0.2 -0.01 0"/><parentlink="gripper_pole"/><childlink="right_gripper"/></joint><linkname="right_gripper"><visual><originrpy="-3.1415 0 0"xyz="0 0


key: chroma:document
string_value:
0 0"xyz="0 0 0"/><geometry><meshfilename="package://urdf_tutorial/meshes/l_finger.dae"/></geometry></visual></link><jointname="right_tip_joint"type="fixed"><parentlink="right_gripper"/><childlink="right_tip"/></joint><linkname="right_tip"><visual><originrpy="-3.1415 0 0"xyz="0.09137 0.00495 0"/><geometry><meshfilename="package://urdf_tutorial/meshes/l_finger_tip.dae"/></geometry></visual></link><linkname="head"><visual><geometry><sphereradius="0.2"/></geometry><materialname="white"/></visual></link><jointname="head_swivel"type="fixed"><parentlink="base_link"/><childlink="head"/><originxyz="0 0 0.3"/></joint><linkname="box"><visual><geometry><boxsize="0.08 0.08 0.08"/></geometry><materialname="blue"/></visual></link><jointname="tobox"type="fixed"><parentlink="head"/><childlink="box"/><originxyz="0.1814 0 0.1414"/></joint></robot>


key: chroma:document
string_value:
Language: unknown ros2 launch urdf_tutorial display.launch.py model:=urdf/05-visual.urdf

Language: unknown

<linkname="head"><visual><geometry><sphereradius="0.2"/></geometry><materialname="white"/></visual></link>

Language: unknown <linkname="left_gripper"><visual><originrpy="0.0 0 0"xyz="0 0 0"/><geometry><meshfilename="package://urdf_tutorial/meshes/l_finger.dae"/></geometry></visual></link>


key: chroma:document
string_value:
Title: Writing a simple publisher and subscriber (C++) URL: https://docs.ros.org/en/jazzy/Tutorials/Beginner-Client-Libraries/Writing-A-Simple-Cpp-Publisher-And-Subscriber.html Section: Installation --------------------------------------------------------------------------------


key: chroma:document
string_value:
Writing a simple publisher and subscriber (C++)Goal:Create and run a publisher and subscriber node using C++.Tutorial level:BeginnerTime:20 minutesContentsBackgroundPrerequisitesTasks1 Create a package2 Write the publisher node3 Write the subscriber node4 Build and runSummaryNext stepsRelated contentBackgroundNodesare executable processes that communicate over the ROS graph. In this tutorial, the nodes will pass information in the form of string messages to each other over atopic. The example used here is a simple “talker” and “listener” system; one node publishes data and the other subscribes to the topic so it can receive that data.The code used in these examples can be foundhere.PrerequisitesIn previous tutorials, you learned how tocreate a workspaceandcreate a package.Tasks1 Create a packageOpen a new terminal andsource your ROS 2 installationso thatros2commands will work.Navigate into theros2_wsdirectory created in aprevious tutorial.Recall that packages should be created in thesrcdirectory, not


key: chroma:document
string_value:
that packages should be created in thesrcdirectory, not the root of the workspace. So, navigate intoros2_ws/src, and run the package creation command:ros2 pkg create --build-type ament_cmake --license Apache-2.0 cpp_pubsubYour terminal will return a message verifying the creation of your packagecpp_pubsuband all its necessary files and folders.Navigate intoros2_ws/src/cpp_pubsub/src. Recall that this is the directory in any CMake package where the source files containing executables belong.2 Write the publisher nodeDownload the example talker code by entering the following command:LinuxmacOSWindowswget -O publisher_lambda_function.cpp https://raw.githubusercontent.com/ros2/examples/jazzy/rclcpp/topics/minimal_publisher/lambda.cppwget -O publisher_lambda_function.cpp https://raw.githubusercontent.com/ros2/examples/jazzy/rclcpp/topics/minimal_publisher/lambda.cppIn a Windows command line prompt:curl -sk https://raw.githubusercontent.com/ros2/examples/jazzy/rclcpp/topics/minimal_publisher/lambda.cpp -o


key: chroma:document
string_value:
-o publisher_lambda_function.cppOr in powershell:curl https://raw.githubusercontent.com/ros2/examples/jazzy/rclcpp/topics/minimal_publisher/lambda.cpp -o publisher_lambda_function.cppNow there will be a new file namedpublisher_lambda_function.cpp. Open the file using your preferred text editor.#include<chrono>#include<memory>#include<string>#include"rclcpp/rclcpp.hpp"#include"std_msgs/msg/string.hpp"usingnamespacestd::chrono_literals;/* This example creates a subclass of Node and uses a fancy C++11 lambda* function to shorten the callback syntax, at the expense of making the* code somewhat more difficult to understand at first glance. */classMinimalPublisher:publicrclcpp::Node{public:MinimalPublisher():Node("minimal_publisher"),count_(0){publisher_=this->create_publisher<std_msgs::msg::String>("topic",10);autotimer_callback=[this]()->void{automessage=std_msgs::msg::String();message.data="Hello, world! "+std::to_string(this->count_++);RCLCPP_INFO(this->get_logger(),"Publishing:


key: chroma:document
string_value:
'%s'",message.data.c_str());this->publisher_->publish(message);};timer_=this->create_wall_timer(500ms,timer_callback);}private:rclcpp::TimerBase::SharedPtrtimer_;rclcpp::Publisher<std_msgs::msg::String>::SharedPtrpublisher_;size_tcount_;};intmain(intargc,char*argv[]){rclcpp::init(argc,argv);rclcpp::spin(std::make_shared<MinimalPublisher>());rclcpp::shutdown();return0;}2.1 Examine the codeThe top of the code includes the standard C++ headers you will be using. After the standard C++ headers is therclcpp/rclcpp.hppinclude which allows you to use the most common pieces of the ROS 2 system. Last isstd_msgs/msg/string.hpp, which includes the built-in message type you will use to publish data.#include<chrono>#include<memory>#include<string>#include"rclcpp/rclcpp.hpp"#include"std_msgs/msg/string.hpp"usingnamespacestd::chrono_literals;These lines represent the node’s dependencies. Recall that dependencies have to be added topackage.xmlandCMakeLists.txt, which you’ll do in the next section.The next line creates the


key: chroma:document
string_value:
which you’ll do in the next section.The next line creates the node classMinimalPublisherby inheriting fromrclcpp::Node. Everythisin the code is referring to the node.classMinimalPublisher:publicrclcpp::NodeThe public constructor names the nodeminimal_publisherand initializescount_to 0. Inside the constructor, the publisher is initialized with theStringmessage type, the topic nametopic, and the required queue size to limit messages in the event of a backup. Next, alambda functioncalledtimer_callbackis declared. It performs a by-reference capture of the current objectthis, takes no input arguments and returns void. Thetimer_callbackfunction creates a new message of typeString, sets its data with the desired string and publishes it. TheRCLCPP_INFOmacro ensures every published message is printed to the console. At last,timer_is initialized, which causes thetimer_callbackfunction to be executed twice a


key: chroma:document
string_value:
which causes thetimer_callbackfunction to be executed twice a second.public:MinimalPublisher():Node("minimal_publisher"),count_(0){publisher_=this->create_publisher<std_msgs::msg::String>("topic",10);autotimer_callback=[this]()->void{automessage=std_msgs::msg::String();message.data="Hello, world! "+std::to_string(this->count_++);RCLCPP_INFO(this->get_logger(),"Publishing: '%s'",message.data.c_str());this->publisher_->publish(message);};timer_=this->create_wall_timer(500ms,timer_callback);}In the bottom of the class is the declaration of the timer, publisher, and counter fields.private:rclcpp::TimerBase::SharedPtrtimer_;rclcpp::Publisher<std_msgs::msg::String>::SharedPtrpublisher_;size_tcount_;Following theMinimalPublisherclass ismain, where the node actually executes.rclcpp::initinitializes ROS 2, andrclcpp::spinstarts processing data from the node, including callbacks from the


key: chroma:document
string_value:
processing data from the node, including callbacks from the timer.intmain(intargc,char*argv[]){rclcpp::init(argc,argv);rclcpp::spin(std::make_shared<MinimalPublisher>());rclcpp::shutdown();return0;}2.2 Add dependenciesNavigate one level back to theros2_ws/src/cpp_pubsubdirectory, where theCMakeLists.txtandpackage.xmlfiles have been created for you.Openpackage.xmlwith your text editor.As mentioned in theprevious tutorial, make sure to fill in the<description>,<maintainer>and<license>tags:<description>Examplesofminimalpublisher/subscriberusingrclcpp</description><maintaineremail="you@email.com">YourName</maintainer><license>Apache-2.0</license>Add a new line after theament_cmakebuildtool dependency and paste the following dependencies corresponding to your node’s include statements:<depend>rclcpp</depend><depend>std_msgs</depend>This declares the package needsrclcppandstd_msgswhen its code is built and executed.Make sure to save the file.2.3 CMakeLists.txtNow open theCMakeLists.txtfile. Below the existing


key: chroma:document
string_value:
open theCMakeLists.txtfile. Below the existing dependencyfind_package(ament_cmakeREQUIRED), add the lines:find_package(rclcpp REQUIRED)find_package(std_msgs REQUIRED)After that, add the executable and name ittalkerso you can run your node usingros2run:add_executable(talker src/publisher_lambda_function.cpp)ament_target_dependencies(talker rclcpp std_msgs)Finally, add theinstall(TARGETS...)section soros2runcan find your executable:install(TARGETStalkerDESTINATION lib/${PROJECT_NAME})You can clean up yourCMakeLists.txtby removing some unnecessary sections and comments, so it looks like this:cmake_minimum_required(VERSION 3.5)project(cpp_pubsub)#DefaulttoC++14if(NOT CMAKE_CXX_STANDARD)set(CMAKE_CXX_STANDARD 14)endif()if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang")add_compile_options(-Wall -Wextra -Wpedantic)endif()find_package(ament_cmake REQUIRED)find_package(rclcpp REQUIRED)find_package(std_msgs REQUIRED)add_executable(talker


key: chroma:document
string_value:
REQUIRED)find_package(std_msgs REQUIRED)add_executable(talker src/publisher_lambda_function.cpp)ament_target_dependencies(talker rclcpp std_msgs)install(TARGETStalkerDESTINATION lib/${PROJECT_NAME})ament_package()You could build your package now, source the local setup files, and run it, but let’s create the subscriber node first so you can see the full system at work.3 Write the subscriber nodeReturn toros2_ws/src/cpp_pubsub/srcto create the next node. Enter the following code in your terminal:LinuxmacOSWindowswget -O subscriber_lambda_function.cpp https://raw.githubusercontent.com/ros2/examples/jazzy/rclcpp/topics/minimal_subscriber/lambda.cppwget -O subscriber_lambda_function.cpp https://raw.githubusercontent.com/ros2/examples/jazzy/rclcpp/topics/minimal_subscriber/lambda.cppIn a Windows command line prompt:curl -sk https://raw.githubusercontent.com/ros2/examples/jazzy/rclcpp/topics/minimal_subscriber/lambda.cpp -o subscriber_lambda_function.cppOr in powershell:curl


key: chroma:document
string_value:
-o subscriber_lambda_function.cppOr in powershell:curl https://raw.githubusercontent.com/ros2/examples/jazzy/rclcpp/topics/minimal_subscriber/lambda.cpp -o subscriber_lambda_function.cppCheck to ensure that these files exist:publisher_lambda_function.cpp  subscriber_lambda_function.cppOpen thesubscriber_lambda_function.cppwith your text editor.#include<memory>#include"rclcpp/rclcpp.hpp"#include"std_msgs/msg/string.hpp"classMinimalSubscriber:publicrclcpp::Node{public:MinimalSubscriber():Node("minimal_subscriber"){autotopic_callback=[this](std_msgs::msg::String::UniquePtrmsg)->void{RCLCPP_INFO(this->get_logger(),"I heard: '%s'",msg->data.c_str());};subscription_=this->create_subscription<std_msgs::msg::String>("topic",10,topic_callback);}private:rclcpp::Subscription<std_msgs::msg::String>::SharedPtrsubscription_;};intmain(intargc,char*argv[]){rclcpp::init(argc,argv);rclcpp::spin(std::make_shared<MinimalSubscriber>());rclcpp::shutdown();return0;}3.1 Examine the codeThe subscriber node’s code is nearly


key: chroma:document
string_value:
Examine the codeThe subscriber node’s code is nearly identical to the publisher’s. Now the node is namedminimal_subscriber, and the constructor uses the node’screate_subscriptionfunction to execute the callback.There is no timer because the subscriber simply responds whenever data is published to thetopictopic.Thetopic_callbackfunction receives the string message data published over the topic, and simply writes it to the console using theRCLCPP_INFOmacro.Recall from thetopic tutorialthat the topic name and message type used by the publisher and subscriber must match to allow them to communicate.public:MinimalSubscriber():Node("minimal_subscriber"){autotopic_callback=[this](std_msgs::msg::String::UniquePtrmsg)->void{RCLCPP_INFO(this->get_logger(),"I heard: '%s'",msg->data.c_str());};subscription_=this->create_subscription<std_msgs::msg::String>("topic",10,topic_callback);}The only field declaration in this class is the


key: chroma:document
string_value:
only field declaration in this class is the subscription.private:rclcpp::Subscription<std_msgs::msg::String>::SharedPtrsubscription_;Themainfunction is exactly the same, except now it spins theMinimalSubscribernode. For the publisher node, spinning meant starting the timer, but for the subscriber it simply means preparing to receive messages whenever they come.Since this node has the same dependencies as the publisher node, there’s nothing new to add topackage.xml.3.2 CMakeLists.txtReopenCMakeLists.txtand add the executable and target for the subscriber node below the publisher’s entries.add_executable(listenersrc/subscriber_lambda_function.cpp)ament_target_dependencies(listenerrclcppstd_msgs)install(TARGETStalkerlistenerDESTINATIONlib/${PROJECT_NAME})Make sure to save the file, and then your pub/sub system should be ready.4 Build and runYou likely already have therclcppandstd_msgspackages installed as part of your ROS 2 system. It’s good practice to runrosdepin the root of your workspace (ros2_ws) to


key: chroma:document
string_value:
practice to runrosdepin the root of your workspace (ros2_ws) to check for missing dependencies before building:LinuxmacOSWindowsrosdep install -i --from-path src --rosdistro jazzy -yrosdep only runs on Linux, so you can skip ahead to next step.rosdep only runs on Linux, so you can skip ahead to next step.Still in the root of your workspace,ros2_ws, build your new package:LinuxmacOSWindowscolcon build --packages-select cpp_pubsubcolcon build --packages-select cpp_pubsubcolcon build --merge-install --packages-select cpp_pubsubOpen a new terminal, navigate toros2_ws, and source the setup files:LinuxmacOSWindows. install/setup.bash. install/setup.bashcall install/setup.batNow run the talker node:ros2 run cpp_pubsub talkerThe terminal should start publishing info messages every 0.5 seconds, like so:[INFO] [minimal_publisher]: Publishing: "Hello World: 0"[INFO] [minimal_publisher]: Publishing: "Hello World: 1"[INFO] [minimal_publisher]: Publishing: "Hello World: 2"[INFO] [minimal_publisher]: Publishing: "Hello


key: chroma:document
string_value:
"Hello World: 2"[INFO] [minimal_publisher]: Publishing: "Hello World: 3"[INFO] [minimal_publisher]: Publishing: "Hello World: 4"Open another terminal, source the setup files from insideros2_wsagain, and then start the listener node:ros2 run cpp_pubsub listenerThe listener will start printing messages to the console, starting at whatever message count the publisher is on at that time, like so:[INFO] [minimal_subscriber]: I heard: "Hello World: 10"[INFO] [minimal_subscriber]: I heard: "Hello World: 11"[INFO] [minimal_subscriber]: I heard: "Hello World: 12"[INFO] [minimal_subscriber]: I heard: "Hello World: 13"[INFO] [minimal_subscriber]: I heard: "Hello World: 14"EnterCtrl+Cin each terminal to stop the nodes from spinning.SummaryYou created two nodes to publish and subscribe to data over a topic. Before compiling and running them, you added their dependencies and executables to the package configuration files.Next stepsNext you’ll create another simple ROS 2 package using the service/client model. Again, you


key: chroma:document
string_value:
simple ROS 2 package using the service/client model. Again, you can choose to write it in eitherC++orPython.Related contentThere are several ways you could write a publisher and subscriber in C++; check out theminimal_publisherandminimal_subscriberpackages in theros2/examplesrepo.


key: chroma:document
string_value:
Code Examples:

Language: unknown

ros2 pkg create -

build

type ament_cmake -

license Apache

2.0 cpp_pubsub

Language: unknown

wget

O publisher_lambda_function.cpp https://raw.githubusercontent.com/ros2/examples/jazzy/rclcpp/topics/minimal_publisher/lambda.cpp

Language: unknown

wget

O publisher_lambda_function.cpp https://raw.githubusercontent.com/ros2/examples/jazzy/rclcpp/topics/minimal_publisher/lambda.cpp

Language: unknown

curl

sk https://raw.githubusercontent.com/ros2/examples/jazzy/rclcpp/topics/minimal_publisher/lambda.cpp

o publisher_lambda_function.cpp

Language: unknown

curl https://raw.githubusercontent.com/ros2/examples/jazzy/rclcpp/topics/minimal_publisher/lambda.cpp

o publisher_lambda_function.cpp


key: chroma:document
string_value:
Language: unknown #include<chrono>#include<memory>#include<string>#include"rclcpp/rclcpp.hpp"#include"std_msgs/msg/string.hpp"usingnamespacestd::chrono_literals;/* This example creates a subclass of Node and uses a fancy C++11 lambda* function to shorten the callback syntax, at the expense of making the* code somewhat more difficult to understand at first glance. */classMinimalPublisher:publicrclcpp::Node{public:MinimalPublisher():Node("minimal_publisher"),count_(0){publisher_=this->create_publisher<std_msgs::msg::String>("topic",10);autotimer_callback=[this]()->void{automessage=std_msgs::msg::String();message.data="Hello, world! "+std::to_string(this->count_++);RCLCPP_INFO(this->get_logger(),"Publishing:


key: chroma:document
string_value:
'%s'",message.data.c_str());this->publisher_->publish(message);};timer_=this->create_wall_timer(500ms,timer_callback);}private:rclcpp::TimerBase::SharedPtrtimer_;rclcpp::Publisher<std_msgs::msg::String>::SharedPtrpublisher_;size_tcount_;};intmain(intargc,char*argv[]){rclcpp::init(argc,argv);rclcpp::spin(std::make_shared<MinimalPublisher>());rclcpp::shutdown();return0;}


key: chroma:document
string_value:
Language: unknown

#include<chrono>#include<memory>#include<string>#include"rclcpp/rclcpp.hpp"#include"std_msgs/msg/string.hpp"usingnamespacestd::chrono_literals;

Language: unknown

classMinimalPublisher:publicrclcpp::Node

Language: unknown

public:MinimalPublisher():Node("minimal_publisher"),count_(0){publisher_=this

>create_publisher<std_msgs::msg::String>("topic",10);autotimer_callback=[this]()

>void{automessage=std_msgs::msg::String();message.data="Hello, world! "+std::to_string(this

>count_++);RCLCPP_INFO(this

>get_logger(),"Publishing: '%s'",message.data.c_str());this

>publisher_

>publish(message);};timer_=this

>create_wall_timer(500ms,timer_callback);}

Language: unknown

private:rclcpp::TimerBase::SharedPtrtimer_;rclcpp::Publisher<std_msgs::msg::String>::SharedPtrpublisher_;size_tcount_;

Language: unknown

intmain(intargc,char

argv[]){rclcpp::init(argc,argv);rclcpp::spin(std::make_shared<MinimalPublisher>());rclcpp::shutdown();return0;}

Language: unknown


key: chroma:document
string_value:
Language: unknown

<description>Examplesofminimalpublisher/subscriberusingrclcpp</description><maintaineremail="you@email.com">YourName</maintainer><license>Apache

2.0</license>

Language: unknown

<depend>rclcpp</depend><depend>std_msgs</depend>

Language: unknown

find_package(rclcpp REQUIRED)find_package(std_msgs REQUIRED)

Language: unknown

add_executable(talker src/publisher_lambda_function.cpp)ament_target_dependencies(talker rclcpp std_msgs)

Language: unknown

install(TARGETStalkerDESTINATION lib/${PROJECT_NAME})


key: chroma:document
string_value:
install(TARGETStalkerDESTINATION lib/${PROJECT_NAME})

Language: unknown cmake_minimum_required(VERSION 3.5)project(cpp_pubsub)#DefaulttoC++14if(NOT CMAKE_CXX_STANDARD)set(CMAKE_CXX_STANDARD 14)endif()if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang")add_compile_options(-Wall -Wextra -Wpedantic)endif()find_package(ament_cmake REQUIRED)find_package(rclcpp REQUIRED)find_package(std_msgs REQUIRED)add_executable(talker src/publisher_lambda_function.cpp)ament_target_dependencies(talker rclcpp std_msgs)install(TARGETStalkerDESTINATION lib/${PROJECT_NAME})ament_package()

Language: unknown

wget

O subscriber_lambda_function.cpp https://raw.githubusercontent.com/ros2/examples/jazzy/rclcpp/topics/minimal_subscriber/lambda.cpp

Language: unknown

wget

O subscriber_lambda_function.cpp https://raw.githubusercontent.com/ros2/examples/jazzy/rclcpp/topics/minimal_subscriber/lambda.cpp

Language: unknown

curl


key: chroma:document
string_value:
Language: unknown

curl

sk https://raw.githubusercontent.com/ros2/examples/jazzy/rclcpp/topics/minimal_subscriber/lambda.cpp

o subscriber_lambda_function.cpp

Language: unknown

curl https://raw.githubusercontent.com/ros2/examples/jazzy/rclcpp/topics/minimal_subscriber/lambda.cpp

o subscriber_lambda_function.cpp

Language: unknown

publisher_lambda_function.cpp  subscriber_lambda_function.cpp

Language: unknown

#include<memory>#include"rclcpp/rclcpp.hpp"#include"std_msgs/msg/string.hpp"classMinimalSubscriber:publicrclcpp::Node{public:MinimalSubscriber():Node("minimal_subscriber"){autotopic_callback=[this](std_msgs::msg::String::UniquePtrmsg)

>void{RCLCPP_INFO(this

>get_logger(),"I heard: '%s'",msg

>data.c_str());};subscription_=this

>create_subscription<std_msgs::msg::String>("topic",10,topic_callback);}private:rclcpp::Subscription<std_msgs::msg::String>::SharedPtrsubscription_;};intmain(intargc,char


key: chroma:document
string_value:
argv[]){rclcpp::init(argc,argv);rclcpp::spin(std::make_shared<MinimalSubscriber>());rclcpp::shutdown();return0;}

Language: unknown

public:MinimalSubscriber():Node("minimal_subscriber"){autotopic_callback=[this](std_msgs::msg::String::UniquePtrmsg)

>void{RCLCPP_INFO(this

>get_logger(),"I heard: '%s'",msg

>data.c_str());};subscription_=this

>create_subscription<std_msgs::msg::String>("topic",10,topic_callback);}

Language: unknown

private:rclcpp::Subscription<std_msgs::msg::String>::SharedPtrsubscription_;

Language: unknown

add_executable(listenersrc/subscriber_lambda_function.cpp)ament_target_dependencies(listenerrclcppstd_msgs)install(TARGETStalkerlistenerDESTINATIONlib/${PROJECT_NAME})

Language: unknown

rosdep install

i -

from

path src -

rosdistro jazzy

y

Language: unknown

colcon build -

packages

select cpp_pubsub

Language: unknown

colcon build -

packages

select cpp_pubsub

Language: unknown

colcon build -

merge

install -

packages

select cpp_pubsub

Language: unknown


key: chroma:document
string_value:
install -

packages

select cpp_pubsub

Language: unknown

. install/setup.bash

Language: unknown

. install/setup.bash

Language: unknown

call install/setup.bat

Language: unknown

ros2 run cpp_pubsub talker

Language: unknown [INFO] [minimal_publisher]: Publishing: "Hello World: 0"[INFO] [minimal_publisher]: Publishing: "Hello World: 1"[INFO] [minimal_publisher]: Publishing: "Hello World: 2"[INFO] [minimal_publisher]: Publishing: "Hello World: 3"[INFO] [minimal_publisher]: Publishing: "Hello World: 4"

Language: unknown

ros2 run cpp_pubsub listener

Language: unknown [INFO] [minimal_subscriber]: I heard: "Hello World: 10"[INFO] [minimal_subscriber]: I heard: "Hello World: 11"[INFO] [minimal_subscriber]: I heard: "Hello World: 12"[INFO] [minimal_subscriber]: I heard: "Hello World: 13"[INFO] [minimal_subscriber]: I heard: "Hello World: 14"


key: chroma:document
string_value:
Title: Usingcolconto build packages

URL: https://docs.ros.org/en/jazzy/Tutorials/Beginner

Client

Libraries/Colcon

Tutorial.html

Section: Installation

--------------------------------------------------------------------------------


key: chroma:document
string_value:
Usingcolconto build packagesTable of ContentsBackgroundPrerequisitesInstall colconInstall ROS 2BasicsCreate a workspaceAdd some sourcesSource an underlayBuild the workspaceRun testsSource the environmentTry a demoCreate your own packageSetupcolcon_cdSetupcolcontab completionTipsGoal:Build a ROS 2 workspace withcolcon.Tutorial level:BeginnerTime:20 minutesThis is a brief tutorial on how to create and build a ROS 2 workspace withcolcon. It is a practical tutorial and not designed to replace the core documentation.Backgroundcolconis an iteration on the ROS build toolscatkin_make,catkin_make_isolated,catkin_toolsandament_tools. For more information on the design of colcon seethis document.The source code can be found in thecolcon GitHub organization.PrerequisitesInstall colconLinuxmacOSWindowssudoaptinstallpython3-colcon-common-extensionspython3-mpipinstallcolcon-common-extensionspipinstall-Ucolcon-common-extensionsInstall ROS 2To build the samples, you will need to install ROS 2.Follow theinstallation


key: chroma:document
string_value:
samples, you will need to install ROS 2.Follow theinstallation instructions.AttentionIf installing from deb packages, this tutorial requires thedesktop installation.BasicsA ROS workspace is a directory with a particular structure. Commonly there is asrcsubdirectory. Inside that subdirectory is where the source code of ROS packages will be located. Typically the directory starts otherwise empty.colcon does out of source builds. By default it will create the following directories as peers of thesrcdirectory:Thebuilddirectory will be where intermediate files are stored. For each package a subfolder will be created in which e.g. CMake is being invoked.Theinstalldirectory is where each package will be installed to. By default each package will be installed into a separate subdirectory.Thelogdirectory contains various logging information about each colcon invocation.NoteCompared to catkin there is nodeveldirectory.Create a workspaceFirst, create a directory (ros2_ws) to contain our


key: chroma:document
string_value:
a workspaceFirst, create a directory (ros2_ws) to contain our workspace:LinuxmacOSWindowsmkdir-p~/ros2_ws/srccd~/ros2_wsmkdir-p~/ros2_ws/srccd~/ros2_wsmd\dev\ros2_ws\srccd\dev\ros2_wsAt this point the workspace contains a single empty directorysrc:. └──src1directory,0filesAdd some sourcesLet’s clone theexamplesrepository into thesrcdirectory of the workspace:gitclonehttps://github.com/ros2/examplessrc/examples-bjazzyNow the workspace should have the source code to the ROS 2 examples:. └──src└──examples├──CONTRIBUTING.md├──LICENSE├──rclcpp├──rclpy└──README.md4directories,3filesSource an underlayIt is important that we have sourced the environment for an existing ROS 2 installation that will provide our workspace with the necessary build dependencies for the example packages. This is achieved by sourcing the setup script provided by a binary installation or a source installation, ie. another colcon workspace (seeInstallation). We call this environment anunderlay.Our workspace,ros2_ws, will be anoverlayon


key: chroma:document
string_value:
anunderlay.Our workspace,ros2_ws, will be anoverlayon top of the existing ROS 2 installation. In general, it is recommended to use an overlay when you plan to iterate on a small number of packages, rather than putting all of your packages into the same workspace.Build the workspaceAttentionTo build packages on Windows you need to be in a Visual Studio environment, seeBuilding the ROS 2 Codefor more details.In the root of the workspace, runcolconbuild. Since build types such asament_cmakedo not support the concept of thedevelspace and require the package to be installed, colcon supports the option--symlink-install. This allows the installed files to be changed by changing the files in thesourcespace (e.g. Python files or other non-compiled resources) for faster iteration.LinuxmacOSWindowscolcon build --symlink-installcolcon build --symlink-installcolcon build --symlink-install --merge-installWindows doesn’t allow long paths, somerge-installwill combine all the paths into theinstalldirectory.After the build


key: chroma:document
string_value:
combine all the paths into theinstalldirectory.After the build is finished, we should see thebuild,install, andlogdirectories:. ├──build ├──install ├──log └──src4directories,0filesRun testsTo run tests for the packages we just built, run the following:LinuxmacOSWindowscolcon testcolcon testRemember to use ax64NativeToolsCommandPromptforVS2019for executing the following command, as we are going to build a workspace.colcon test --merge-installYou also need to specify--merge-installhere since we used it for building above.Source the environmentWhen colcon has completed building successfully, the output will be in theinstalldirectory. Before you can use any of the installed executables or libraries, you will need to add them to your path and library paths. colcon will have generated bash/bat files in theinstalldirectory to help set up the environment. These files will add all of the required elements to your path and library paths as well as provide any bash or shell commands exported by


key: chroma:document
string_value:
paths as well as provide any bash or shell commands exported by packages.LinuxmacOSWindowssourceinstall/setup.bash.install/setup.bashcallinstall\setup.batOr with Powershell:install\setup.ps1Try a demoWith the environment sourced, we can run executables built by colcon. Let’s run a subscriber node from the examples:ros2runexamples_rclcpp_minimal_subscribersubscriber_member_functionIn another terminal, let’s run a publisher node (don’t forget to source the setup script):ros2runexamples_rclcpp_minimal_publisherpublisher_member_functionYou should see messages from the publisher and subscriber with numbers incrementing.Create your own packagecolcon uses thepackage.xmlspecification defined inREP 149(format 2is also supported).colcon supports multiple build types. The recommended build types areament_cmakeandament_python. Also supported are purecmakepackages.An example of anament_pythonbuild is theament_index_python package, where the setup.py is the primary entry point for building.A package such


key: chroma:document
string_value:
setup.py is the primary entry point for building.A package such asdemo_nodes_cppuses theament_cmakebuild type, and uses CMake as the build tool.For convenience, you can use the toolros2pkgcreateto create a new package based on a template.NoteForcatkinusers, this is the equivalent ofcatkin_create_package.Setupcolcon_cdThe commandcolcon_cdallows you to quickly change the current working directory of your shell to the directory of a package. As an examplecolcon_cdsome_ros_packagewould quickly bring you to the directory~/ros2_ws/src/some_ros_package.LinuxmacOSWindowsecho "source /usr/share/colcon_cd/function/colcon_cd.sh" >> ~/.bashrcecho "export _colcon_cd_root=/opt/ros/jazzy/" >> ~/.bashrcecho "source /usr/local/share/colcon_cd/function/colcon_cd.sh" >> ~/.bashrcecho "export _colcon_cd_root=~/ros2_install" >> ~/.bashrcNot yet availableDepending on the way you installedcolcon_cdand where your workspace is, the instructions above may vary, please refer tothe documentationfor more details. To undo this in Linux


key: chroma:document
string_value:
tothe documentationfor more details. To undo this in Linux and macOS, locate your system’s shell startup script and remove the appended source and export commands.Setupcolcontab completionThecolconcommand supports command completion for bash and bash-like shells. Thecolcon-argcompletepackage must be installed, andsome setup may be requiredto make it work.TipsIf you do not want to build a specific package place an empty file namedCOLCON_IGNOREin the directory and it will not be indexed.If you want to avoid configuring and building tests in CMake packages you can pass:--cmake-args-DBUILD_TESTING=0.If you want to run a single particular test from a package:colcontest--packages-selectYOUR_PKG_NAME--ctest-args-RYOUR_TEST_IN_PKG


key: chroma:document
string_value:
Code Examples:

Language: unknown

sudoaptinstallpython3

colcon

common

extensions

Language: unknown

python3

mpipinstallcolcon

common

extensions

Language: unknown

pipinstall

Ucolcon

common

extensions

Language: unknown

mkdir

p~/ros2_ws/srccd~/ros2_ws

Language: unknown

mkdir

p~/ros2_ws/srccd~/ros2_ws

Language: unknown

md\dev\ros2_ws\srccd\dev\ros2_ws

Language: unknown

.

└──src1directory,0files

Language: unknown

gitclonehttps://github.com/ros2/examplessrc/examples

bjazzy

Language: unknown

.

└──src└──examples├──CONTRIBUTING.md├──LICENSE├──rclcpp├──rclpy└──README.md4directories,3files

Language: unknown

colcon build -

symlink

install

Language: unknown

colcon build -

symlink

install

Language: unknown

colcon build -

symlink

install -

merge

install

Language: unknown

.

├──build

├──install

├──log

└──src4directories,0files

Language: unknown

colcon test

Language: unknown

colcon test

Language: unknown

colcon test -

merge

install

Language: unknown


key: chroma:document
string_value:
colcon test -

merge

install

Language: unknown

sourceinstall/setup.bash

Language: unknown

.install/setup.bash

Language: unknown

callinstall\setup.bat

Language: unknown

install\setup.ps1

Language: unknown

ros2runexamples_rclcpp_minimal_subscribersubscriber_member_function

Language: unknown

ros2runexamples_rclcpp_minimal_publisherpublisher_member_function

Language: unknown echo "source /usr/share/colcon_cd/function/colcon_cd.sh" >> ~/.bashrcecho "export _colcon_cd_root=/opt/ros/jazzy/" >> ~/.bashrc

Language: unknown echo "source /usr/local/share/colcon_cd/function/colcon_cd.sh" >> ~/.bashrcecho "export _colcon_cd_root=~/ros2_install" >> ~/.bashrc

Language: unknown

colcontest-

packages

selectYOUR_PKG_NAME-

ctest

args

RYOUR_TEST_IN_PKG


key: chroma:document
string_value:
Title: Migrating C++ Packages Reference URL: https://docs.ros.org/en/jazzy/How-To-Guides/Migrating-from-ROS1/Migrating-CPP-Packages.html Section: Installation --------------------------------------------------------------------------------


key: chroma:document
string_value:
Migrating C++ Packages ReferenceTable of ContentsBuild toolUpdate yourCMakeLists.txtto useament_cmakeRequire a newer version of CMakeSet the build type to ament_cmakeAdd a call toament_package()Updatefind_package()callsUse modern CMake targetsReplacecatkin_package()with various ament_cmake callsGenerate messagesRemove references to the devel spaceUnit testsLintersUpdate source codeMessages, services, and actionsUse of service objectsUsages of ros::TimeUsages of ros::RateBoostThis page shows how to migrate parts of a C++ package from ROS 1 to ROS 2. If this is your first time migrating a C++ package, then read theC++ migration examplefirst. Afterwards, use this page as a reference while you migrate your own packages.Build toolInstead of usingcatkin_make,catkin_make_isolatedorcatkinbuildROS 2 uses the command line toolcolconto build and install a set of packages. See thebeginner tutorialto get started withcolcon.Update yourCMakeLists.txtto useament_cmakeROS 2 C++ packages useCMakewith convenience functions


key: chroma:document
string_value:
2 C++ packages useCMakewith convenience functions provided byament_cmake. Apply the following changes to useament_cmakeinstead ofcatkin.Require a newer version of CMakeROS 2 relies on newer versions of CMake than used by ROS 1. Find the minimum version of CMake used by the ROS distribution you want to support inREP 2000, and use that version at the top of yourCMakeLists.txt. For example,3.14.4 is the minimum recommended support for ROS Humble.cmake_minimum_required(VERSION3.14.4)Set the build type to ament_cmakeRemove any dependencies oncatkinfrom yourpackage.xml# Remove this!<buildtool_depend>catkin</buildtool_depend>Add a new dependency onament_cmake_ros(example):<buildtool_depend>ament_cmake_ros</buildtool_depend>Add an<export>section to yourpackage.xmlif it does not have one already. Set the<build_type>toament_cmake(example)<export><build_type>ament_cmake</build_type></export>Add a call toament_package()Insert a call toament_package()at the bottom of yourCMakeLists.txt(example)# Add this to the bottom


key: chroma:document
string_value:
bottom of yourCMakeLists.txt(example)# Add this to the bottom of your CMakeLists.txtament_package()Updatefind_package()callsReplace thefind_package(catkinCOMPONENTS...)call with individualfind_package()calls (example):For example, change this:find_package(catkinREQUIREDCOMPONENTSfoobarstd_msgs)find_package(bazREQUIRED)To this:find_package(ament_cmake_rosREQUIRED)find_package(fooREQUIRED)find_package(barREQUIRED)find_package(std_msgsREQUIRED)find_package(bazREQUIRED)Use modern CMake targetsPrefer to use per-target CMake functions so that your package can export modern CMake targets.If yourCMakeLists.txtusesinclude_directories(), then delete those calls.# Delete calls to include_directories like this one! include_directories(include ${catkin_INCLUDE_DIRS})Add a calltarget_include_directories()for every library in your pacakage (example).target_include_directories(my_libraryPUBLIC"$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>""$<INSTALL_INTERFACE:include/${PROJECT_NAME}>")Change


key: chroma:document
string_value:
alltarget_link_libraries()calls to use modern CMake targets. For example, if your package in ROS 1 uses old-style standard CMake variables like this.target_link_libraries(my_library ${catkin_LIBRARIES} ${baz_LIBRARIES})Then change it to use specific modern CMake targets instead. Use${package_name_TARGETS}if the package you’re depending on is a message package such asstd_msgs.target_link_libraries(my_libraryPUBLICfoo::foobar::bar${std_msgs_TARGETS}baz::baz)ChoosePUBLICorPRIVATEbased on how the dependency is used by your library (example).UsePUBLICif the dependency is needed by downstream users, for example, your library’s public API uses it.UsePRIVATEif the dependency is only used internally by your library.Replacecatkin_package()with various ament_cmake callsImagine yourCMakeLists.txthas a call tocatkin_packagelike this:catkin_package( INCLUDE_DIRS include LIBRARIES my_library CATKIN_DEPENDS foo bar std_msgs DEPENDS baz )


key: chroma:document
string_value:
install(TARGETS my_library ARCHIVE DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION} LIBRARY DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION} RUNTIME DESTINATION ${CATKIN_GLOBAL_BIN_DESTINATION} )Replacingcatkin_package(INCLUDE_DIRS...)If you’ve used modern CMake targets andtarget_include_directories(), you don’t need to do anything further. Downstream users will get the include directories by depending on your modern CMake targets.Replacingcatkin_package(LIBRARIES...)Useament_export_targets()andinstall(TARGETS...EXPORT...)to replace theLIBRARIESargument.Use theEXPORTkeyword when installing yourmy_librarytarget (example).install(TARGETSmy_libraryEXPORTexport_my_packageARCHIVEDESTINATIONlibLIBRARYDESTINATIONlibRUNTIMEDESTINATIONbin)The above is a good default for library targets. If your package used differentCATKIN_*_DESTINATIONvariables, convert them as


key: chroma:document
string_value:
used differentCATKIN_*_DESTINATIONvariables, convert them as follows:catkinament_cmakeCATKIN_GLOBAL_BIN_DESTINATIONbinCATKIN_GLOBAL_INCLUDE_DESTINATIONincludeCATKIN_GLOBAL_LIB_DESTINATIONlibCATKIN_GLOBAL_LIBEXEC_DESTINATIONlibCATKIN_GLOBAL_SHARE_DESTINATIONshareCATKIN_PACKAGE_BIN_DESTINATIONlib/${PROJECT_NAME}CATKIN_PACKAGE_INCLUDE_DESTINATIONinclude/${PROJECT_NAME}CATKIN_PACKAGE_LIB_DESTINATIONlibCATKIN_PACKAGE_SHARE_DESTINATIONshare/${PROJECT_NAME}Add a call toament_export_targets()with the same name you gave to theEXPORTkeyword (example).ament_export_targets(export_my_package)Replacingcatkin_package(CATKIN_DEPENDS..DEPENDS..)Your package’s users mustfind_package()dependencies used by your package’s public API. In ROS 1 this was done for downstream users with theCATKIN_DEPENDSandDEPENDSarguments. Useament_export_dependenciesto do this in ROS 2.ament_export_dependencies(foobarstd_msgsbaz)Generate messagesIf your package contains both C++ code and ROS message, service, or action definitions, then consider


key: chroma:document
string_value:
and ROS message, service, or action definitions, then consider splitting it into two packages:A package with only the ROS message, service, and/or action definitionsA package with the C++ codeAdd the following dependencies to thepackage.xmlof the package that contains ROS messages:Add a<buildtool_depend>onrosidl_default_generators(example)<buildtool_depend>rosidl_default_generators</buildtool_depend>Add an<exec_depend>onrosidl_default_runtime(example)<exec_depend>rosidl_default_runtime</exec_depend>Add a<member_of_group>tag with the group namerosidl_interface_packages(example)<member_of_group>rosidl_interface_packages</member_of_group>In yourCMakeLists.txt, replace the invocation ofadd_message_files,add_service_filesandgenerate_messageswithrosidl_generate_interfaces. The first argument must be${PROJECT_NAME}due tothis bug.For example, if your ROS 1 package looks like


key: chroma:document
string_value:
tothis bug.For example, if your ROS 1 package looks like this:add_message_files(DIRECTORYmsgFILESFooBar.msgBaz.msg)add_service_files(DIRECTORYsrvFILESPing.srv)add_action_files(DIRECTORYactionFILESDoPong.action)generate_messages(DEPENDENCIESactionlib_msgsstd_msgsgeometry_msgs)Then change it to this (example)rosidl_generate_interfaces(${PROJECT_NAME}"msg/FooBar.msg""msg/Baz.msg""srv/Ping.srv""action/DoPong.action"DEPENDENCIESactionlib_msgsstd_msgsgeometry_msgs)Remove references to the devel spaceRemove any references to thedevel spacesuch asCATKIN_DEVEL_PREFIX. There is no equivalent to thedevel spacein ROS 2.Unit testsIf your package usesgtestthen:ReplaceCATKIN_ENABLE_TESTINGwithBUILD_TESTING.Replacecatkin_add_gtestwithament_add_gtest.Add afind_package()forament_cmake_gtestinstead ofGTestFor example, if your ROS 1 package adds tests like this:if (CATKIN_ENABLE_TESTING) find_package(GTest REQUIRED) include_directories(${GTEST_INCLUDE_DIRS}) catkin_add_gtest(my_test src/test/some_test.cpp)


key: chroma:document
string_value:
catkin_add_gtest(my_test src/test/some_test.cpp) target_link_libraries(my_test # ... ${GTEST_LIBRARIES}) endif()Then change it to this:if(BUILD_TESTING)find_package(ament_cmake_gtestREQUIRED)ament_add_gtest(my_testsrc/test/test_something.cpp)target_link_libraries(my_test#...)endif()Add<test_depend>ament_cmake_gtest</test_depend>to yourpackage.xml(example).<test_depend>ament_cmake_gtest</test_depend>LintersThe ROS 2 codestyle guidediffers from ROS 1.If you choose to follow the ROS 2 style guide, then turn on automatic linter tests by adding these lines in aif(BUILD_TESTING)block:if(BUILD_TESTING)find_package(ament_lint_autoREQUIRED)ament_lint_auto_find_test_dependencies()# ...endif()Add the following dependencies to yourpackage.xml:<test_depend>ament_lint_auto</test_depend><test_depend>ament_lint_common</test_depend>Update source codeMessages, services, and actionsThe namespace of ROS 2 messages, services, and actions use a subnamespace (msg,srv, oraction, respectively) after the package name. Therefore an


key: chroma:document
string_value:
oraction, respectively) after the package name. Therefore an include looks like:#include<my_interfaces/msg/my_message.hpp>. The C++ type is then named:my_interfaces::msg::MyMessage.Shared pointer types are provided as typedefs within the message structs:my_interfaces::msg::MyMessage::SharedPtras well asmy_interfaces::msg::MyMessage::ConstSharedPtr.For more details please see the article about thegenerated C++ interfaces.The migration requires includes to change by:inserting the subfoldermsgbetween the package name and message datatypechanging the included filename from CamelCase to underscore separationchanging from*.hto*.hpp// ROS 1 style is in comments, ROS 2 follows, uncommented.// # include <geometry_msgs/PointStamped.h>#include<geometry_msgs/msg/point_stamped.hpp>// geometry_msgs::PointStamped point_stamped;geometry_msgs::msg::PointStampedpoint_stamped;The migration requires code to insert themsgnamespace into all instances.Use of service objectsService callbacks in ROS 2 do not have boolean return


key: chroma:document
string_value:
objectsService callbacks in ROS 2 do not have boolean return values. Instead of returning false on failures, throwing exceptions is recommended.// ROS 1 style is in comments, ROS 2 follows, uncommented.// #include "nav_msgs/GetMap.h"#include"nav_msgs/srv/get_map.hpp"// bool service_callback(//   nav_msgs::GetMap::Request & request,//   nav_msgs::GetMap::Response & response)voidservice_callback(conststd::shared_ptr<nav_msgs::srv::GetMap::Request>request,std::shared_ptr<nav_msgs::srv::GetMap::Response>response){// ...// return true;  // or false for failure}Usages of ros::TimeFor usages ofros::Time:Replace all instances ofros::Timewithrclcpp::TimeIf your messages or code makes use of std_msgs::Time:Convert all instances of std_msgs::Time to builtin_interfaces::msg::TimeConvert all#include"std_msgs/time.hto#include"builtin_interfaces/msg/time.hpp"Convert all instances using the std_msgs::Time fieldnsecto the builtin_interfaces::msg::Time fieldnanosecUsages of ros::RateThere is an equivalent


key: chroma:document
string_value:
fieldnanosecUsages of ros::RateThere is an equivalent typerclcpp::Rateobject which is basically a drop in replacement forros::Rate.BoostMuch of the functionality previously provided by Boost has been integrated into the C++ standard library. As such we would like to take advantage of the new core features and avoid the dependency on boost where possible.Shared PointersTo switch shared pointers from boost to standard C++ replace instances of:#include<boost/shared_ptr.hpp>with#include<memory>boost::shared_ptrwithstd::shared_ptrThere may also be variants such asweak_ptrwhich you want to convert as well.Also it is recommended practice to useusinginstead oftypedef.usinghas the ability to work better in templated logic. For detailssee hereThread/MutexesAnother common part of boost used in ROS codebases are mutexes inboost::thread.Replaceboost::mutex::scoped_lockwithstd::unique_lock<std::mutex>Replaceboost::mutexwithstd::mutexReplace#include<boost/thread/mutex.hpp>with#include<mutex>Unordered


key: chroma:document
string_value:
MapReplace:#include<boost/unordered_map.hpp>with#include<unordered_map>boost::unordered_mapwithstd::unordered_mapfunctionReplace:#include<boost/function.hpp>with#include<functional>boost::functionwithstd::function


key: chroma:document
string_value:
Code Examples:

Language: unknown

cmake_minimum_required(VERSION3.14.4)

Language: unknown

# Remove this!<buildtool_depend>catkin</buildtool_depend>

Language: unknown

<buildtool_depend>ament_cmake_ros</buildtool_depend>

Language: unknown

<export><build_type>ament_cmake</build_type></export>

Language: unknown # Add this to the bottom of your CMakeLists.txtament_package()

Language: unknown

find_package(catkinREQUIREDCOMPONENTSfoobarstd_msgs)find_package(bazREQUIRED)

Language: unknown

find_package(ament_cmake_rosREQUIRED)find_package(fooREQUIRED)find_package(barREQUIRED)find_package(std_msgsREQUIRED)find_package(bazREQUIRED)

Language: unknown # Delete calls to include_directories like this one! include_directories(include ${catkin_INCLUDE_DIRS})

Language: unknown

target_include_directories(my_libraryPUBLIC"$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>""$<INSTALL_INTERFACE:include/${PROJECT_NAME}>")

Language: unknown

target_link_libraries(my_library ${catkin_LIBRARIES} ${baz_LIBRARIES})


key: chroma:document
string_value:
Language: unknown

target_link_libraries(my_libraryPUBLICfoo::foobar::bar${std_msgs_TARGETS}baz::baz)

Language: unknown

catkin_package(

INCLUDE_DIRS include

LIBRARIES my_library

CATKIN_DEPENDS foo bar std_msgs

DEPENDS baz

)

install(TARGETS my_library

ARCHIVE DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION}

LIBRARY DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION}

RUNTIME DESTINATION ${CATKIN_GLOBAL_BIN_DESTINATION}

)

Language: unknown

install(TARGETSmy_libraryEXPORTexport_my_packageARCHIVEDESTINATIONlibLIBRARYDESTINATIONlibRUNTIMEDESTINATIONbin)

Language: unknown

ament_export_targets(export_my_package)

Language: unknown

ament_export_dependencies(foobarstd_msgsbaz)

Language: unknown

<buildtool_depend>rosidl_default_generators</buildtool_depend>

Language: unknown

<exec_depend>rosidl_default_runtime</exec_depend>

Language: unknown

<member_of_group>rosidl_interface_packages</member_of_group>

Language: unknown


key: chroma:document
string_value:
Language: unknown

add_message_files(DIRECTORYmsgFILESFooBar.msgBaz.msg)add_service_files(DIRECTORYsrvFILESPing.srv)add_action_files(DIRECTORYactionFILESDoPong.action)generate_messages(DEPENDENCIESactionlib_msgsstd_msgsgeometry_msgs)

Language: unknown

rosidl_generate_interfaces(${PROJECT_NAME}"msg/FooBar.msg""msg/Baz.msg""srv/Ping.srv""action/DoPong.action"DEPENDENCIESactionlib_msgsstd_msgsgeometry_msgs)

Language: unknown

if (CATKIN_ENABLE_TESTING)

find_package(GTest REQUIRED)

include_directories(${GTEST_INCLUDE_DIRS})

catkin_add_gtest(my_test src/test/some_test.cpp)

target_link_libraries(my_test

# ...

${GTEST_LIBRARIES})

endif()

Language: unknown

if(BUILD_TESTING)find_package(ament_cmake_gtestREQUIRED)ament_add_gtest(my_testsrc/test/test_something.cpp)target_link_libraries(my_test#...)endif()

Language: unknown

<test_depend>ament_cmake_gtest</test_depend>

Language: unknown

if(BUILD_TESTING)find_package(ament_lint_autoREQUIRED)ament_lint_auto_find_test_dependencies()# ...endif()


key: chroma:document
string_value:
Language: unknown

<test_depend>ament_lint_auto</test_depend><test_depend>ament_lint_common</test_depend>

Language: unknown // ROS 1 style is in comments, ROS 2 follows, uncommented.// # include <geometry_msgs/PointStamped.h>#include<geometry_msgs/msg/point_stamped.hpp>// geometry_msgs::PointStamped point_stamped;geometry_msgs::msg::PointStampedpoint_stamped;

Language: unknown // ROS 1 style is in comments, ROS 2 follows, uncommented.// #include "nav_msgs/GetMap.h"#include"nav_msgs/srv/get_map.hpp"// bool service_callback(//   nav_msgs::GetMap::Request & request,//   nav_msgs::GetMap::Response & response)voidservice_callback(conststd::shared_ptr<nav_msgs::srv::GetMap::Request>request,std::shared_ptr<nav_msgs::srv::GetMap::Response>response){// ...// return true;  // or false for failure}


key: source
string_value:
/Users/ad12/ros2-rag/exported_docs/ros2/Building_a_real-time_Linux_kernel_[community-contributed].txt


key: chroma:document
string_value:
Title: Building a real

time Linux kernel [community

contributed]

URL: https://docs.ros.org/en/jazzy/Tutorials/Miscellaneous/Building

Realtime

rt_preempt

kernel

for

ROS

2.html

Section: Installation

--------------------------------------------------------------------------------


key: chroma:document
string_value:
Building a real-time Linux kernel [community-contributed]This tutorial begins with a clean Ubuntu 20.04.1 install on Intel x86_64. Actual kernel is 5.4.0-54-generic, but we will install the Latest Stable RT_PREEMPT Version. To build the kernel you need at least 30GB free disk space.Checkhttps://wiki.linuxfoundation.org/realtime/startfor the latest stable version, at the time of writing this is “Latest Stable Version 5.4-rt”. If we click on thelink, we get the exact version. Currently it is patch-5.4.78-rt44.patch.gz.We create a directory in our home dir withmkdir~/kerneland switch into it withcd~/kernelWe can go with a browser tohttps://mirrors.edge.kernel.org/pub/linux/kernel/v5.x/and see if the version is there. You can download it from the site and move it manually from /Downloads to the /kernel folder, or download it using wget by right clicking the link using “copy link location”. Example:wgethttps://mirrors.edge.kernel.org/pub/linux/kernel/v5.x/linux-5.4.78.tar.gzunpack it


key: chroma:document
string_value:
it withtar-xzflinux-5.4.78.tar.gzdownload rt_preempt patch matching the Kernel version we just downloaded over athttp://cdn.kernel.org/pub/linux/kernel/projects/rt/5.4/wgethttp://cdn.kernel.org/pub/linux/kernel/projects/rt/5.4/older/patch-5.4.78-rt44.patch.gzunpack it withgunzippatch-5.4.78-rt44.patch.gzThen switch into the linux directory withcdlinux-5.4.78/and patch the kernel with the realtime patchpatch-p1<../patch-5.4.78-rt44.patchWe simply want to use the config of our Ubuntu installation, so we get the Ubuntu config withcp/boot/config-5.4.0-54-generic.configOpen Software & Updates. in the Ubuntu Software menu tick the ‘Source code’ boxWe need some tools to build kernel, install them withsudoapt-getbuild-deplinux sudoapt-getinstalllibncurses-devflexbisonopenssllibssl-devdkmslibelf-devlibudev-devlibpci-devlibiberty-devautoconffakerootTo enable all Ubuntu configurations, we simply useyes''|makeoldconfigThen we need to enable rt_preempt in the kernel. We callmakemenuconfigand set the following# Enable


key: chroma:document
string_value:
the kernel. We callmakemenuconfigand set the following# Enable CONFIG_PREEMPT_RT->GeneralSetup->PreemptionModel(FullyPreemptibleKernel(Real-Time))(X)FullyPreemptibleKernel(Real-Time)# Enable CONFIG_HIGH_RES_TIMERS->Generalsetup->Timerssubsystem[*]HighResolutionTimerSupport# Enable CONFIG_NO_HZ_FULL->Generalsetup->Timerssubsystem->Timertickhandling(Fulldyntickssystem(tickless))(X)Fulldyntickssystem(tickless)# Set CONFIG_HZ_1000 (note: this is no longer in the General Setup menu, go back twice)->Processortypeandfeatures->Timerfrequency(1000HZ)(X)1000HZ# Set CPU_FREQ_DEFAULT_GOV_PERFORMANCE [=y]->PowermanagementandACPIoptions->CPUFrequencyscaling->CPUFrequencyscaling(CPU_FREQ[=y])->DefaultCPUFreqgovernor(<choice>[=y])(X)performanceSave and exit menuconfig. Now we’re going to build the kernel which will take quite some time. (10-30min on a modern cpu)make-j`nproc`deb-pkgAfter the build is finished check the deb packagesls../*deb


key: chroma:document
string_value:
the build is finished check the deb packagesls../*deb ../linux-headers-5.4.78-rt41_5.4.78-rt44-1_amd64.deb../linux-image-5.4.78-rt44-dbg_5.4.78-rt44-1_amd64.deb ../linux-image-5.4.78-rt41_5.4.78-rt44-1_amd64.deb../linux-libc-dev_5.4.78-rt44-1_amd64.debThen we install all kernel deb packagessudodpkg-i../*.debNow the real time kernel should be installed. Reboot the system and check the new kernel versionsudoreboot uname-a Linuxros2host5.4.78-rt44#1 SMP PREEMPT_RT Fri Nov 6 10:37:59 CET 2020 x86_64 xx


key: chroma:document
string_value:
Code Examples:

Language: unknown

mkdir~/kernel

Language: unknown

cd~/kernel

Language: unknown

wgethttps://mirrors.edge.kernel.org/pub/linux/kernel/v5.x/linux

5.4.78.tar.gz

Language: unknown

tar

xzflinux

5.4.78.tar.gz

Language: unknown

wgethttp://cdn.kernel.org/pub/linux/kernel/projects/rt/5.4/older/patch

5.4.78

rt44.patch.gz

Language: unknown

gunzippatch

5.4.78

rt44.patch.gz

Language: unknown

cdlinux

5.4.78/

Language: unknown

patch

p1<../patch

5.4.78

rt44.patch

Language: unknown

cp/boot/config

5.4.0

54

generic.config

Language: unknown

sudoapt

getbuild

deplinux

sudoapt

getinstalllibncurses

devflexbisonopenssllibssl

devdkmslibelf

devlibudev

devlibpci

devlibiberty

devautoconffakeroot

Language: unknown

yes''|makeoldconfig

Language: unknown

makemenuconfig


key: chroma:document
string_value:
yes''|makeoldconfig

Language: unknown

makemenuconfig

Language: unknown # Enable CONFIG_PREEMPT_RT->GeneralSetup->PreemptionModel(FullyPreemptibleKernel(Real-Time))(X)FullyPreemptibleKernel(Real-Time)# Enable CONFIG_HIGH_RES_TIMERS->Generalsetup->Timerssubsystem[*]HighResolutionTimerSupport# Enable CONFIG_NO_HZ_FULL->Generalsetup->Timerssubsystem->Timertickhandling(Fulldyntickssystem(tickless))(X)Fulldyntickssystem(tickless)# Set CONFIG_HZ_1000 (note: this is no longer in the General Setup menu, go back twice)->Processortypeandfeatures->Timerfrequency(1000HZ)(X)1000HZ# Set CPU_FREQ_DEFAULT_GOV_PERFORMANCE [=y]->PowermanagementandACPIoptions->CPUFrequencyscaling->CPUFrequencyscaling(CPU_FREQ[=y])->DefaultCPUFreqgovernor(<choice>[=y])(X)performance

Language: unknown

make

j`nproc`deb

pkg

Language: unknown

ls../

deb

../linux

headers

5.4.78

rt41_5.4.78

rt44

1_amd64.deb../linux

image

5.4.78

rt44

dbg_5.4.78

rt44

1_amd64.deb

../linux

image

5.4.78

rt41_5.4.78

rt44

1_amd64.deb../linux

libc


key: chroma:document
string_value:
image

5.4.78

rt41_5.4.78

rt44

1_amd64.deb../linux

libc

dev_5.4.78

rt44

1_amd64.deb

Language: unknown

sudodpkg

i../

.deb

Language: unknown sudoreboot uname-a Linuxros2host5.4.78-rt44#1 SMP PREEMPT_RT Fri Nov 6 10:37:59 CET 2020 x86_64 xx


key: chroma:document
string_value:
Title: Quality of Service settings

URL: https://docs.ros.org/en/jazzy/Concepts/Intermediate/About-Quality-of-Service-Settings.html

Section: Installation

--------------------------------------------------------------------------------

Quality of Service settingsTable of ContentsOverviewQoS policiesComparison to ROS 1QoS profilesQoS compatibilitiesComparison to ROS 1QoS eventsMatched eventsOverviewROS 2 offers a rich variety of Quality of Service (QoS) policies that allow you to tune communication between nodes.

With the right set of Quality of Service policies, ROS 2 can be as reliable as TCP or as best-effort as UDP, with many, many possible states in between.


key: chroma:document
string_value:
Unlike ROS 1, which primarily only supported TCP, ROS 2 benefits from the flexibility of the underlying DDS transport in environments with lossy wireless networks where a “best effort” policy would be more suitable, or in real-time computing systems where the right Quality of Service profile is needed to meet deadlines.A set of QoS “policies” combine to form a QoS “profile”.

Given the complexity of choosing the correct QoS policies for a given scenario, ROS 2 provides a set of predefined QoS profiles for common use cases (e.g. sensor data).

At the same time, developers are given the flexibility to control specific policies of the QoS profiles.QoS profiles can be specified for publishers, subscriptions, service servers and clients.


key: chroma:document
string_value:
A QoS profile can be applied independently to each instance of the aforementioned entities, but if different profiles are used, it is possible that they will be incompatible, preventing the delivery of messages.QoS policiesThe base QoS profile currently includes settings for the following policies:HistoryKeep last: only store up to N samples, configurable via the queue depth option.Keep all: store all samples, subject to the configured resource limits of the underlying middleware.DepthQueue size: only honored if the “history” policy was set to “keep last”.ReliabilityBest effort: attempt to deliver samples, but may lose them if the network is not robust.Reliable: guarantee that samples are delivered, may retry multiple times.DurabilityTransient local: the publisher becomes responsible for persisting samples for “late-joining” subscriptions.Volatile: no attempt is made to persist samples.DeadlineDuration: the expected maximum amount of time between subsequent messages being published to a


key: chroma:document
string_value:
amount of time between subsequent messages being published to a topicLifespanDuration: the maximum amount of time between the publishing and the reception of a message without the message being considered stale or expired (expired messages are silently dropped and are effectively never received).LivelinessAutomatic: the system will consider all of the node’s publishers to be alive for another “lease duration” when any one of its publishers has published a message.Manual by topic: the system will consider the publisher to be alive for another “lease duration” if it manually asserts that it is still alive (via a call to the publisher API).Lease DurationDuration: the maximum period of time a publisher has to indicate that it is alive before the system considers it to have lost liveliness (losing liveliness could be an indication of a failure).For each of the policies that is not a duration, there is also the option of “system default”, which uses the default of the underlying middleware.


key: chroma:document
string_value:
For each of the policies that is a duration, there also exists a “default” option that means the duration is unspecified, which the underlying middleware will usually interpret as an infinitely long duration.Comparison to ROS 1The “history” and “depth” policies in ROS 2 combine to provide functionality akin to the queue size in ROS 1.The “reliability” policy in ROS 2 is akin to the use of either UDPROS (only inroscpp) for “best effort”, or TCPROS (ROS 1 default) for “reliable”.

Note however that even the reliable policy in ROS 2 is implemented using UDP, which allows for multicasting if appropriate.The “durability” policy “transient local”, combined with any depth, provides functionality similar to that of “latching” publishers.

The remaining policies in ROS 2 are not akin to anything that is available in ROS 1, meaning that ROS 2 is more featureful than ROS 1 in this respect.


key: chroma:document
string_value:
It is possible that in the future, even more QoS policies will be available in ROS 2.QoS profilesProfiles allow developers to focus on their applications without worrying about every QoS setting possible.

A QoS profile defines a set of policies that are expected to go well together for a particular use case.The currently defined QoS profiles are:Default QoS settings for publishers and subscriptionsIn order to make the transition from ROS 1 to ROS 2 easier, exercising a similar network behavior is desirable.

By default, publishers and subscriptions in ROS 2 have “keep last” for history with a queue size of 10, “reliable” for reliability, “volatile” for durability, and “system default” for liveliness.

Deadline, lifespan, and lease durations are also all set to “default”.ServicesIn the same vein as publishers and subscriptions, services are reliable.

It is especially important for services to use volatile durability, as otherwise service servers that re-start may receive outdated requests.


key: chroma:document
string_value:
While the client is protected from receiving multiple responses, the server is not protected from side-effects of receiving the outdated requests.Sensor dataFor sensor data, in most cases it’s more important to receive readings in a timely fashion, rather than ensuring that all of them arrive.

That is, developers want the latest samples as soon as they are captured, at the expense of maybe losing some.

For that reason the sensor data profile uses best effort reliability and a smaller queue size.ParametersParameters in ROS 2 are based on services, and as such have a similar profile.

The difference is that parameters use a much larger queue depth so that requests do not get lost when, for example, the parameter client is unable to reach the parameter service server.System defaultThis uses the RMW implementation’s default values for all of the policies.

Different RMW implementations may have different defaults.Click herefor the specific policies in use for the above profiles.


key: chroma:document
string_value:
The settings in these profiles are subject to further tweaks, based on the feedback from the community.QoS compatibilitiesNote:This section refers to publishers and subscriptions but the content applies to service servers and clients in the same manner.QoS profiles may be configured for publishers and subscriptions independently.

A connection between a publisher and a subscription is only made if the pair has compatible QoS profiles.QoS profile compatibility is determined based on a “Request vs Offered” model.

Subscriptionsrequesta QoS profile that is the “minimum quality” that it is willing to accept, and publishersoffera QoS profile that is the “maximum quality” that it is able to provide.

Connections are only made if every policy of the requested QoS profile is not more stringent than that of the offered QoS profile.

Multiple subscriptions can be connected to a single publisher simultaneously even if their requested QoS profiles are different.


key: chroma:document
string_value:
The compatibility between a publisher and a subscription is unaffected by the presence of other publishers and subscriptions.The following tables show the compatibility of the different policy settings and the result:Compatibility of reliability QoS policies:PublisherSubscriptionCompatibleBest effortBest effortYesBest effortReliableNoReliableBest effortYesReliableReliableYesCompatibility of durability QoS policies:PublisherSubscriptionCompatibleResultVolatileVolatileYesNew messages onlyVolatileTransient localNoNo communicationTransient localVolatileYesNew messages onlyTransient localTransient localYesNew and old messagesTo achieve a “latched” topic that is visible to late subscribers,


key: chroma:document
string_value:
both the publisher and subscriber must agree to use ‘Transient Local’.Compatibility of deadline QoS policies:Assumexandyare arbitrary valid duration values.PublisherSubscriptionCompatibleDefaultDefaultYesDefaultxNoxDefaultYesxxYesxy(wherey>x)Yesxy(wherey<x)NoCompatibility of liveliness QoS policies:PublisherSubscriptionCompatibleAutomaticAutomaticYesAutomaticManual by topicNoManual by topicAutomaticYesManual by topicManual by topicYesCompatibility of lease duration QoS policies:Assumexandyare arbitrary valid duration values.PublisherSubscriptionCompatibleDefaultDefaultYesDefaultxNoxDefaultYesxxYesxy(wherey>x)Yesxy(wherey<x)NoIn order for a connection to be made, all of the policies that affect compatibility must be compatible.


key: chroma:document
string_value:
For example, even if a requested and offered QoS profile pair has compatible reliability QoS policies, but they have incompatible durability QoS policies, a connection will still not be made.When connections are not made, no messages will be passed between the publisher and subscription.

There are mechanisms to detect this situation, which will be covered in a later section.Comparison to ROS 1Historically in ROS 1, any publisher and subscriber with the same message type on the same topic would be connected.

The possibility of incompatible requested and offered QoS profiles is something new to be aware of when using ROS 2.QoS eventsSome QoS policies have possible events related to them.


key: chroma:document
string_value:
Developers may provide each publisher and subscription with callback functions that are triggered by these QoS events and handle them in a way they see fit, similar to how messages received on a topic are handled.Developers may subscribe to the following QoS events that are associated with a publisher:Offered deadline missedThe publisher has not published a message within the expected duration that was set out by the deadline QoS policy.Liveliness lostThe publisher has failed to indicate its liveliness within the lease duration.Offered incompatible QoSThe publisher has encountered a subscription on the same topic that is requesting a QoS profile that the offered QoS profile cannot satisfy, resulting in no connection between the publisher and that subscription.Developers may subscribe to the following QoS events that are associated with a subscription:Requested deadline missedThe subscription has not received a message within the expected duration that was set out by the deadline QoS policy.Liveliness


key: chroma:document
string_value:
duration that was set out by the deadline QoS policy.Liveliness changedThe subscription has noticed that one or more publishers on the subscribed topic has failed to indicate their liveliness within the lease duration.Requested incompatible QoSThe subscription has encountered a publisher on the same topic that is offering a QoS profile that does not satisfy the requested QoS profile, resulting in no connection between the subscription and that publisher.Matched eventsIn addition to QoS events, matched events can be generated when any publisher and subscription establishes or drops the connection between them.


key: chroma:document
string_value:
Developers may provide each publisher and subscription with callback functions that are triggered by matched events and handle them in a way they see fit, similar to how messages received on a topic are handled.Developers can subscribe to this event with a publisher or a subscription.publisher: this event happens when it finds a subscription which matches the topic and has compatible QoS or a connected subscription is disconnectedsubscription: this event happens when it finds a publisher which matches the topic and has compatible QoS or a connected publisher is disconnectedThere are demos showing how to use the event:rclcpp:demo coderclpy:demo code


key: chroma:document
string_value:
Title: ament_cmake user documentation

URL: https://docs.ros.org/en/jazzy/How

To

Guides/Ament

CMake

Documentation.html

Section: Installation

--------------------------------------------------------------------------------


key: chroma:document
string_value:
ament_cmake user documentationament_cmakeis the build system for CMake based packages in ROS 2 (in particular, it will be used for most C/C++ projects). It is a set of scripts enhancing CMake and adding convenience functionality for package authors. Before usingament_cmake, it is very helpful to know the basics ofCMake. An official tutorial can be foundhere.Table of ContentsBasicsBasic project outlineCompiler and linker optionsFinding dependenciesAdding targetsLinking to dependenciesInstallingLinting and TestingLintingTestingExtending amentAdding a function/macro to amentAdding to extension pointsAdding extension pointsAdding resourcesThe ament index explainedQuerying the ament indexAdding to the ament indexBasicsA basic CMake outline can be produced usingros2pkgcreate<package_name>on the command line. The build information is then gathered in two files: thepackage.xmland theCMakeLists.txt, which must be in the same directory. Thepackage.xmlmust contain all dependencies and a bit of metadata to allow


key: chroma:document
string_value:
contain all dependencies and a bit of metadata to allow colcon to find the correct build order for your packages, to install the required dependencies in CI, and to provide the information for a release withbloom. TheCMakeLists.txtcontains the commands to build and package executables and libraries and will be the main focus of this document.Basic project outlineThe basic outline of theCMakeLists.txtof an ament package contains:cmake_minimum_required(VERSION3.8)project(my_project)ament_package()The argument toprojectwill be the package name and must be identical to the package name in thepackage.xml.The project setup is done byament_package()and this call must occur exactly once per package.ament_package()installs thepackage.xml, registers the package with the ament index, and installs configuration (and possibly target) files for CMake so that it can be found by other packages usingfind_package. Sinceament_package()gathers a lot of information from theCMakeLists.txtit should be the last call in


key: chroma:document
string_value:
information from theCMakeLists.txtit should be the last call in yourCMakeLists.txt.ament_packagecan be given additional arguments:CONFIG_EXTRAS: a list of CMake files (.cmakeor.cmake.intemplates expanded byconfigure_file()) which should be available to clients of the package. For an example of when to use these arguments, see the discussion inAdding resources. For more information on how to use template files, seethe official documentation.CONFIG_EXTRAS_POST: same asCONFIG_EXTRAS, but the order in which the files are added differs. WhileCONFIG_EXTRASfiles are included before the files generated for theament_export_*calls the files fromCONFIG_EXTRAS_POSTare included afterwards.Instead of adding toament_package, you can also add to the variable${PROJECT_NAME}_CONFIG_EXTRASand${PROJECT_NAME}_CONFIG_EXTRAS_POSTwith the same effect. The only difference is again the order in which the files are added with the following total order:files added byCONFIG_EXTRASfiles added by appending


key: chroma:document
string_value:
total order:files added byCONFIG_EXTRASfiles added by appending to${PROJECT_NAME}_CONFIG_EXTRASfiles added by appending to${PROJECT_NAME}_CONFIG_EXTRAS_POSTfiles added byCONFIG_EXTRAS_POSTCompiler and linker optionsROS 2 targets compilers which comply with the C++17 and C99 standard. Newer versions might be targeted in the future and are referencedhere. Therefore it is customary to set the corresponding CMake flags:if(NOTCMAKE_C_STANDARD)set(CMAKE_C_STANDARD99)endif()if(NOTCMAKE_CXX_STANDARD)set(CMAKE_CXX_STANDARD17)endif()To keep the code clean, compilers should throw warnings for questionable code and these warnings should be fixed.It is recommended to at least cover the following warning levels:For Visual Studio: the defaultW1warningsFor GCC and Clang:-Wall-Wextra-Wpedanticare highly recommended and-Wshadowis advisableIt is currently recommended to useadd_compile_optionsto add these options for all targets. This avoids cluttering the code with target-based compile options for all executables, libraries,


key: chroma:document
string_value:
target-based compile options for all executables, libraries, and tests:if(CMAKE_COMPILER_IS_GNUCXXORCMAKE_CXX_COMPILER_IDMATCHES"Clang")add_compile_options(-Wall-Wextra-Wpedantic)endif()Finding dependenciesMostament_cmakeprojects will have dependencies on other packages. In CMake, this is accomplished by callingfind_package. For instance, if your package depends onrclcpp, then theCMakeLists.txtfile should contain:find_package(rclcppREQUIRED)NoteIt should never be necessary tofind_packagea library that is not explicitly needed but is a dependency of another dependency that is explicitly needed. If that is the case, file a bug against the corresponding package.Adding targetsIn CMake nomenclature,targetsare the artifacts that this project will create. Either libraries or executables can be created, and a single project can contain zero or many of each of them.LibrariesExecutablesThese are created with a call toadd_library, which should contain both the name of the target and the source files that should be


key: chroma:document
string_value:
both the name of the target and the source files that should be compiled to create the library.With the separation of header files and implementation in C/C++, it is not usually necessary to add header files as arguments toadd_library.The following best practice is proposed:Put all headers which should be usable by clients of this library (and therefore must be installed) into a subdirectory of theincludefolder named like the package, while all other files (.c/.cppand header files which should not be exported) are inside thesrcfolderOnly.c/.cppfiles are explicitly referenced in the call toadd_libraryFind headers to your librarymy_libraryviatarget_include_directories(my_libraryPUBLIC"$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>""$<INSTALL_INTERFACE:include/${PROJECT_NAME}>")This adds all files in the folder${CMAKE_CURRENT_SOURCE_DIR}/includeto the public interface during build time and all files in the include folder (relative to${CMAKE_INSTALL_DIR}) when being installed.ros2pkgcreatecreates a


key: chroma:document
string_value:
when being installed.ros2pkgcreatecreates a package layout that follows these rules.NoteSince Windows is one of the officially supported platforms, to have maximum impact, any package should also build on Windows. The Windows library format enforces symbol visibility; that is, every symbol which should be used from a client has to be explicitly exported by the library (and symbols need to be implicitly imported).Since GCC and Clang builds do not generally do this, it is advised to use the logic inthe GCC wiki. To use it for a package calledmy_library:Copy the logic in the link into a header file calledvisibility_control.hpp.ReplaceDLLbyMY_LIBRARY(for an example, see visibility control ofrviz_rendering).Use the macros “MY_LIBRARY_PUBLIC” for all symbols you need to export (i.e. classes or functions).In the projectCMakeLists.txtuse:target_compile_definitions(my_libraryPRIVATE"MY_LIBRARY_BUILDING_LIBRARY")For more details, seeWindows Symbol Visibility in the Windows Tips and Tricks document.These should be


key: chroma:document
string_value:
in the Windows Tips and Tricks document.These should be created with a call toadd_executable, which should contain both the name of the target and the source files that should be compiled to create the executable. The executable may also have to be linked with any libraries created in this package by usingtarget_link_libraries.Since executables aren’t generally used by clients as a library, no header files need to be put in theincludedirectory.In the case that a package has both libraries and executables, make sure to combine the advice from both “Libraries” and “Executables” above.Linking to dependenciesThere are two ways to link your targets against a dependency.The first and recommended way is to use the ament macroament_target_dependencies. As an example, suppose we want to linkmy_libraryagainst the linear algebra library Eigen3.find_package(Eigen3REQUIRED)ament_target_dependencies(my_libraryPUBLICEigen3)It includes the necessary headers and libraries and their dependencies to be correctly found by the


key: chroma:document
string_value:
libraries and their dependencies to be correctly found by the project.The second way is to usetarget_link_libraries.Modern CMake prefers to use only targets, exporting and linking against them. CMake targets may be namespaced, similar to C++. Prefer to use the namespaced targets if they are available. For instance,Eigen3defines the targetEigen3::Eigen.In the example of Eigen3, the call should then look liketarget_link_libraries(my_libraryPUBLICEigen3::Eigen)This will also include necessary headers, libraries and their dependencies. Note that this dependency must have been previously discovered via a call tofind_package.InstallingLibrariesExecutablesWhen building a reusable library, some information needs to be exported for downstream packages to easily use it.First, install the headers files which should be available to clients. The include directory is custom to support overlays incolcon;


key: chroma:document
string_value:
The include directory is custom to support overlays incolcon; seehttps://colcon.readthedocs.io/en/released/user/overriding-packages.html#install-headers-to-a-unique-include-directoryfor more information.install(DIRECTORYinclude/DESTINATIONinclude/${PROJECT_NAME})Next, install the targets and create the export target (export_${PROJECT_NAME}) that other code will use to find this package. Note that you can use a singleinstallcall to install all of the libraries in the project.install(TARGETSmy_libraryEXPORTexport_${PROJECT_NAME}LIBRARYDESTINATIONlibARCHIVEDESTINATIONlibRUNTIMEDESTINATIONbin)ament_export_targets(export_${PROJECT_NAME}HAS_LIBRARY_TARGET)ament_export_dependencies(some_dependency)Here is what’s happening in the snippet above:Theament_export_targetsmacro exports the targets for CMake. This is necessary to allow your library’s clients to use thetarget_link_libraries(clientPRIVATEmy_library::my_library)syntax. If the export set includes a library, add the


key: chroma:document
string_value:
If the export set includes a library, add the optionHAS_LIBRARY_TARGETtoament_export_targets, which adds potential libraries to environment variables.Theament_export_dependenciesexports dependencies to downstream packages. This is necessary so that the user of the library does not have to callfind_packagefor those dependencies, too.WarningCallingament_export_targets,ament_export_dependencies, or other ament commands from a CMake subdirectory will not work as expected. This is because the CMake subdirectory has no way of setting necessary variables in the parent scope whereament_packageis called.NoteWindows DLLs are treated as runtime artifacts and installed into theRUNTIMEDESTINATIONfolder. It is therefore advised to keep theRUNTIMEinstall even when developing libraries on Unix based systems.TheEXPORTnotation of the install call requires additional attention: It installs the CMake files for themy_librarytarget. It must be named exactly the same as the argument inament_export_targets. To ensure that it can be


key: chroma:document
string_value:
the argument inament_export_targets. To ensure that it can be used viaament_target_dependencies, it should not be named exactly the same as the library name, but instead should have a prefix likeexport_(as shown above).All install paths are relative toCMAKE_INSTALL_PREFIX, which is already set correctly by colcon/ament.There are two additional functions which are available, but are superfluous for target based installs:ament_export_include_directories("include/${PROJECT_NAME}")ament_export_libraries(my_library)The first macro marks the directory of the exported include directories. The second macro marks the location of the installed library (this is done by theHAS_LIBRARY_TARGETargument in the call toament_export_targets). These should only be used if the downstream projects can’t or don’t want to use CMake target based dependencies.Some of the macros can take different types of arguments for non-target exports, but since the recommended way for modern Make is to use targets, we will not cover them here.


key: chroma:document
string_value:
for modern Make is to use targets, we will not cover them here. Documentation of these options can be found in the source code itself.When installing an executable, the following stanzamust be followed exactlyfor the rest of the ROS tooling to find it:install(TARGETSmy_exeDESTINATIONlib/${PROJECT_NAME})In the case that a package has both libraries and executables, make sure to combine the advice from both “Libraries” and “Executables” above.Linting and TestingIn order to separate testing from building the library with colcon, wrap all calls to linters and tests in a conditional:if(BUILD_TESTING)find_package(ament_cmake_gtestREQUIRED)ament_add_gtest(<tests>)endif()LintingIt’s advised to use the combined call fromament_lint_auto:find_package(ament_lint_autoREQUIRED)ament_lint_auto_find_test_dependencies()This will run linters as defined in thepackage.xml. It is recommended to use the set of linters defined by the packageament_lint_common. The individual linters included there, as well as their functions, can


key: chroma:document
string_value:
linters included there, as well as their functions, can be seen in theament_lint_common docs.Linters provided by ament can also be added separately, instead of runningament_lint_auto. One example of how to do so can be found in theament_cmake_lint_cmake documentation.TestingAment contains CMake macros to simplify setting up GTests. Call:find_package(ament_cmake_gtest)ament_add_gtest(some_test<test_sources>)to add a GTest. This is then a regular target which can be linked against other libraries (such as the project library). The macros have additional parameters:APPEND_ENV: append environment variables. For instance you can add to the ament prefix path by calling:find_package(ament_cmake_gtestREQUIRED)ament_add_gtest(some_test<test_sources>APPEND_ENVPATH=some/addtional/path/for/testing/resources)APPEND_LIBRARY_DIRS: append libraries so that they can be found by the linker at runtime. This can be achieved by setting environment variables likePATHon Windows andLD_LIBRARY_PATHon Linux, but this makes the call


key: chroma:document
string_value:
Windows andLD_LIBRARY_PATHon Linux, but this makes the call platform specific.ENV: set environment variables (same syntax asAPPEND_ENV).TIMEOUT: set a test timeout in second. The default for GTests is 60 seconds.  For example:ament_add_gtest(some_test<test_sources>TIMEOUT120)SKIP_TEST: skip this test (will be shown as “passed” in the console output).SKIP_LINKING_MAIN_LIBRARIES: Don’t link against GTest.WORKING_DIRECTORY: set the working directory for the test.The default working directory otherwise is theCMAKE_CURRENT_BINARY_DIR, which is described in theCMake documentation.Similarly, there is a CMake macro to set up GTest including GMock:find_package(ament_cmake_gmockREQUIRED)ament_add_gmock(some_test<test_sources>)It has the same additional parameters asament_add_gtest.Extending amentIt is possible to register additional macros/functions withament_cmakeand extend it in several ways.Adding a function/macro to amentExtending ament will often times mean that you want to have some functions available to


key: chroma:document
string_value:
times mean that you want to have some functions available to other packages. The best way to provide the macro to client packages is to register it with ament.This can be done by appending the${PROJECT_NAME}_CONFIG_EXTRASvariable, which is used byament_package()vialist(APPEND${PROJECT_NAME}_CONFIG_EXTRASpath/to/file.cmake"other/pathto/file.cmake")Alternatively, you can directly add the files to theament_package()call:ament_package(CONFIG_EXTRASpath/to/file.cmakeother/pathto/file.cmake)Adding to extension pointsIn addition to simple files with functions that can be used in other packages, you can also add extensions to ament. Those extensions are scripts which are executed with the function which defines the extension point. The most common use-case for ament extensions is probably registering rosidl message generators: When writing a generator, you normally want to generate all messages and services with your generator also without modifying the code for the message/service definition packages. This is


key: chroma:document
string_value:
the code for the message/service definition packages. This is possible by registering the generator as an extension torosidl_generate_interfaces.As an example, seeament_register_extension("rosidl_generate_interfaces""rosidl_generator_cpp""rosidl_generator_cpp_generate_interfaces.cmake")which registers the macrorosidl_generator_cpp_generate_interfaces.cmakefor the packagerosidl_generator_cppto the extension pointrosidl_generate_interfaces. When the extension point gets executed, this will trigger the execution of the scriptrosidl_generator_cpp_generate_interfaces.cmakehere. In particular, this will call the generator whenever the functionrosidl_generate_interfacesgets executed.The most important extension point for generators, aside fromrosidl_generate_interfaces, isament_package, which will simply execute scripts with theament_package()call. This extension point is useful when registering resources (see below).ament_register_extensionis a function which takes exactly three arguments:extension_point: The name


key: chroma:document
string_value:
which takes exactly three arguments:extension_point: The name of the extension point (most of the time this will be one ofament_packageorrosidl_generate_interfaces)package_name: The name of the package containing the CMake file (i.e. the project name of the project where the file is written to)cmake_filename: The CMake file executed when the extension point is runNoteIt is possible to define custom extension points in a similar manner toament_packageandrosidl_generate_interfaces, but this should hardly be necessary.Adding extension pointsVery rarely, it might be interesting to define a new extension point to ament.Extension points can be registered within a macro so that all extensions will be executed when the corresponding macro is called. To do so:Define and document a name for your extension (e.g.my_extension_point), which is the name passed to theament_register_extensionmacro when using the extension point.In the macro/function which should execute the extensions


key: chroma:document
string_value:
point.In the macro/function which should execute the extensions call:ament_execute_extensions(my_extension_point)Ament extensions work by defining a variable containing the name of the extension point and filling it with the macros to be executed. Upon callingament_execute_extensions, the scripts defined in the variable are then executed one after another.Adding resourcesEspecially when developing plugins or packages which allow plugins it is often essential to add resources to one ROS package from another (e.g. a plugin). Examples can be plugins for tools using the pluginlib.This can be achieved using the ament index (also called “resource index”).The ament index explainedFor details on the design and intentions, seehereIn principle, the ament index is contained in a folder within the install/share folder of your package. It contains shallow subfolders named after different types of resources. Within the subfolder, each package providing said resource is referenced by name with a “marker file”. The file


key: chroma:document
string_value:
resource is referenced by name with a “marker file”. The file may contain whatever content necessary to obtain the resources, e.g. relative paths to the installation directories of the resource, it may also be simply empty.To give an example, consider providing display plugins for RViz: When providing RViz plugins in a project namedmy_rviz_displayswhich will be read by the pluginlib, you will provide aplugin_description.xmlfile, which will be installed and used by the pluginlib to load the plugins. To achieve this, the plugin_description.xml is registered as a resource in the resource_index viapluginlib_export_plugin_description_file(rviz_commonplugins_description.xml)When runningcolconbuild, this installs a filemy_rviz_displaysinto a subfolderrviz_common__pluginlib__plugininto the resource_index. Pluginlib factories within rviz_common will know to gather information from all folders namedrviz_common__pluginlib__pluginfor packages that export plugins. The marker file for pluginlib factories contains an


key: chroma:document
string_value:
plugins. The marker file for pluginlib factories contains an install-folder relative path to theplugins_description.xmlfile (and the name of the library as marker file name). With this information, the pluginlib can load the library and know which plugins to load from theplugin_description.xmlfile.As a second example, consider the possibility to let your own RViz plugins use your own custom meshes. Meshes get loaded at startup time so that the plugin owner does not have to deal with it, but this implies RViz has to know about the meshes. To achieve this, RViz provides a function:register_rviz_ogre_media_exports(DIRECTORIES<my_dirs>)This registers the directories as an ogre_media resource in the ament index. In short, it installs a file named after the project which calls the function into a subfolder calledrviz_ogre_media_exports. The file contains the install folder relative paths to the directories listed in the macros. On startup time, RViz can now search for all folders calledrviz_ogre_media_exportsand


key: chroma:document
string_value:
can now search for all folders calledrviz_ogre_media_exportsand load resources in all folders provided. These searches are done usingament_index_cpp(orament_index_pyfor Python packages).In the following sections we will explore how to add your own resources to the ament index and provide best practices for doing so.Querying the ament indexIf necessary, it is possible to query the ament index for resources via CMake. To do so, there are three functions:ament_index_has_resource: Obtain a prefix path to the resource if it exists with the following parameters:var: the output parameter: fill this variable with FALSE if the resource does not exist or the prefix path to the resource otherwiseresource_type: The type of the resource (e.g.rviz_common__pluginlib__plugin)resource_name: The name of the resource which usually amounts to the name of the package having added the resource of type resource_type (e.g.rviz_default_plugins)ament_index_get_resource: Obtain the content of a specific resource, i.e. the contents of


key: chroma:document
string_value:
Obtain the content of a specific resource, i.e. the contents of the marker file in the ament index.var: the output parameter: filled with the content of the resource marker file if it exists.resource_type: The type of the resource (e.g.rviz_common__pluginlib__plugin)resource_name: The name of the resource which usually amounts to the name of the package having added the resource of type resource_type (e.g.rviz_default_plugins)PREFIX_PATH: The prefix path to search for (usually, the defaultament_index_get_prefix_path()will be enough).Note thatament_index_get_resourcewill throw an error if the resource does not exist, so it might be necessary to check usingament_index_has_resource.ament_index_get_resources: Get all packages which registered resources of a specific type from the indexvar: Output parameter: filled with a list of names of all packages which registered a resource of resource_typeresource_type: The type of the resource (e.g.rviz_common__pluginlib__plugin)PREFIX_PATH: The prefix path to search for


key: chroma:document
string_value:
The prefix path to search for (usually, the defaultament_index_get_prefix_path()will be enough).Adding to the ament indexDefining a resource requires two bits of information:a name for the resource which must be unique,a layout of the marker file, which can be anything and could also be empty (this is true for instance for the “package” resource marking a ROS 2 package)For the RViz mesh resource, the corresponding choices were:rviz_ogre_media_exportsas name of the resource,install path relative paths to all folders containing resources. This will already enable you to write the logic for using the corresponding resource in your package.To allow users to easily register resources for your package, you should furthermore provide macros or functions such as the pluginlib function orrviz_ogre_media_exportsfunction.To register a resource, use the ament functionament_index_register_resource. This will create and install the marker files in the resource_index. As an example, the corresponding call


key: chroma:document
string_value:
in the resource_index. As an example, the corresponding call forrviz_ogre_media_exportsis the following:ament_index_register_resource(rviz_ogre_media_exportsCONTENT${OGRE_MEDIA_RESOURCE_FILE})This installs a file named like${PROJECT_NAME}into a folderrviz_ogre_media_exportsinto the resource_index with content given by variable${OGRE_MEDIA_RESOURCE_FILE}. The macro has a number of parameters that can be useful:the first (unnamed) parameter is the name of the resource, which amounts to the name of the folder in the resource_indexCONTENT: The content of the marker file as string. This could be a list of relative paths, etc.CONTENTcannot be used together withCONTENT_FILE.CONTENT_FILE: The path to a file which will be use to create the marker file. The file can be a plain file or a template file expanded withconfigure_file().CONTENT_FILEcannot be used together withCONTENT.PACKAGE_NAME: The name of the package/library exporting the resource, which amounts to the name of the marker file. Defaults


key: chroma:document
string_value:
which amounts to the name of the marker file. Defaults to${PROJECT_NAME}.AMENT_INDEX_BINARY_DIR: The base path of the generated ament index. Unless really necessary, always use the default${CMAKE_BINARY_DIR}/ament_cmake_index.SKIP_INSTALL: Skip installing the marker file.Since only one marker file exists per package, it is usually a problem if the CMake function/macro gets called twice by the same project. However, for large projects it might be best to split up calls registering resources.Therefore, it is best practice to let a macro registering a resource such asregister_rviz_ogre_media_exports.cmakeonly fill some variables. The real call toament_index_register_resourcecan then be added within an ament extension toament_package. Since there must only ever be one call toament_packageper project, there will always only be one place where the resource gets registered. In the case ofrviz_ogre_media_exportsthis amounts to the following strategy:The macroregister_rviz_ogre_media_exportstakes a list of folders


key: chroma:document
string_value:
macroregister_rviz_ogre_media_exportstakes a list of folders and appends them to a variable calledOGRE_MEDIA_RESOURCE_FILE.Another macro calledregister_rviz_ogre_media_exports_hookcallsament_index_register_resourceif${OGRE_MEDIA_RESOURCE_FILE}is non-empty.Theregister_rviz_ogre_media_exports_hook.cmakefile is registered as an ament extension in a third fileregister_rviz_ogre_media_exports_hook-extras.cmakevia callingament_register_extension("ament_package""rviz_rendering""register_rviz_ogre_media_exports_hook.cmake")The filesregister_rviz_ogre_media_exports.cmakeandregister_rviz_ogre_media_exports_hook-extra.cmakeare registered asCONFIG_EXTRAwithament_package().


key: chroma:document
string_value:
Code Examples:

Language: unknown

cmake_minimum_required(VERSION3.8)project(my_project)ament_package()

Language: unknown

if(NOTCMAKE_C_STANDARD)set(CMAKE_C_STANDARD99)endif()if(NOTCMAKE_CXX_STANDARD)set(CMAKE_CXX_STANDARD17)endif()

Language: unknown

if(CMAKE_COMPILER_IS_GNUCXXORCMAKE_CXX_COMPILER_IDMATCHES"Clang")add_compile_options(

Wall

Wextra

Wpedantic)endif()

Language: unknown

find_package(rclcppREQUIRED)

Language: unknown

target_include_directories(my_libraryPUBLIC"$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>""$<INSTALL_INTERFACE:include/${PROJECT_NAME}>")

Language: unknown

target_compile_definitions(my_libraryPRIVATE"MY_LIBRARY_BUILDING_LIBRARY")

Language: unknown

find_package(Eigen3REQUIRED)ament_target_dependencies(my_libraryPUBLICEigen3)

Language: unknown

target_link_libraries(my_libraryPUBLICEigen3::Eigen)

Language: unknown

install(DIRECTORYinclude/DESTINATIONinclude/${PROJECT_NAME})

Language: unknown


key: chroma:document
string_value:
Language: unknown

install(TARGETSmy_libraryEXPORTexport_${PROJECT_NAME}LIBRARYDESTINATIONlibARCHIVEDESTINATIONlibRUNTIMEDESTINATIONbin)ament_export_targets(export_${PROJECT_NAME}HAS_LIBRARY_TARGET)ament_export_dependencies(some_dependency)

Language: unknown

ament_export_include_directories("include/${PROJECT_NAME}")ament_export_libraries(my_library)

Language: unknown

install(TARGETSmy_exeDESTINATIONlib/${PROJECT_NAME})

Language: unknown

if(BUILD_TESTING)find_package(ament_cmake_gtestREQUIRED)ament_add_gtest(<tests>)endif()

Language: unknown

find_package(ament_lint_autoREQUIRED)ament_lint_auto_find_test_dependencies()

Language: unknown

find_package(ament_cmake_gtest)ament_add_gtest(some_test<test_sources>)

Language: unknown

find_package(ament_cmake_gtestREQUIRED)ament_add_gtest(some_test<test_sources>APPEND_ENVPATH=some/addtional/path/for/testing/resources)

Language: unknown

ament_add_gtest(some_test<test_sources>TIMEOUT120)

Language: unknown


key: chroma:document
string_value:
Language: unknown

find_package(ament_cmake_gmockREQUIRED)ament_add_gmock(some_test<test_sources>)

Language: unknown

list(APPEND${PROJECT_NAME}_CONFIG_EXTRASpath/to/file.cmake"other/pathto/file.cmake")

Language: unknown

ament_package(CONFIG_EXTRASpath/to/file.cmakeother/pathto/file.cmake)

Language: unknown

ament_register_extension("rosidl_generate_interfaces""rosidl_generator_cpp""rosidl_generator_cpp_generate_interfaces.cmake")

Language: unknown

ament_execute_extensions(my_extension_point)

Language: unknown

pluginlib_export_plugin_description_file(rviz_commonplugins_description.xml)

Language: unknown

register_rviz_ogre_media_exports(DIRECTORIES<my_dirs>)

Language: unknown

ament_index_register_resource(rviz_ogre_media_exportsCONTENT${OGRE_MEDIA_RESOURCE_FILE})

Language: unknown

ament_register_extension("ament_package""rviz_rendering""register_rviz_ogre_media_exports_hook.cmake")


key: chroma:document
string_value:
Title: Building a Custom RViz Display URL: https://docs.ros.org/en/jazzy/Tutorials/Intermediate/RViz/RViz-Custom-Display/RViz-Custom-Display.html Section: Installation --------------------------------------------------------------------------------


key: chroma:document
string_value:
Building a Custom RViz DisplayBackgroundThere are many types of data that have existing visualizations in RViz. However, if there is a message type that does not yet have a plugin to display it, there are two choices to see it in RViz.Convert the message to another type, such asvisualization_msgs/Marker.Write a Custom RViz Display.With the first option, there is more network traffic and limitations to how the data can be represented. It is also quick and flexible. The latter option is explained in this tutorial. It takes a bit of work, but can lead to much richer visualizations.All of the code for this tutorial can be found inthis repository. In order to see the incremental progress of the plugin written in this tutorial, the repository has different branches (step2,step3…) that can each be compiled and run as you go.Point2D MessageWe’ll be playing with a toy message defined in therviz_plugin_tutorial_msgspackage:Point2D.msg:std_msgs/Headerheaderfloat64xfloat64yBoilerplate for Basic PluginStrap in,


key: chroma:document
string_value:
for Basic PluginStrap in, there’s a lot of code. You can view the full version of this code with the branch namestep1.Header FileHere are the contents ofpoint_display.hpp#ifndef RVIZ_PLUGIN_TUTORIAL__POINT_DISPLAY_HPP_#define RVIZ_PLUGIN_TUTORIAL__POINT_DISPLAY_HPP_#include<rviz_common/message_filter_display.hpp>#include<rviz_plugin_tutorial_msgs/msg/point2_d.hpp>namespacerviz_plugin_tutorial{classPointDisplay:publicrviz_common::MessageFilterDisplay<rviz_plugin_tutorial_msgs::msg::Point2D>{Q_OBJECTprotected:voidprocessMessage(constrviz_plugin_tutorial_msgs::msg::Point2D::ConstSharedPtrmsg)override;};}// namespace rviz_plugin_tutorial#endif// RVIZ_PLUGIN_TUTORIAL__POINT_DISPLAY_HPP_We’re implementing theMessageFilterDisplayclass which can be used with any message with astd_msgs/Header.The class is templated with ourPoint2Dmessage type.For reasons outside the scope of this tutorial, you need theQ_OBJECTmacro in there to get the QT parts of the GUI to work.processMessageis the only method that needs to be


key: chroma:document
string_value:
GUI to work.processMessageis the only method that needs to be implemented, which we’ll do in the cpp file.Source Filepoint_display.cpp#include<rviz_plugin_tutorial/point_display.hpp>#include<rviz_common/logging.hpp>namespacerviz_plugin_tutorial{voidPointDisplay::processMessage(constrviz_plugin_tutorial_msgs::msg::Point2D::ConstSharedPtrmsg){RVIZ_COMMON_LOG_INFO_STREAM("We got a message with frame "<<msg->header.frame_id);}}// namespace rviz_plugin_tutorial#include<pluginlib/class_list_macros.hpp>PLUGINLIB_EXPORT_CLASS(rviz_plugin_tutorial::PointDisplay,rviz_common::Display)The logging is not strictly necessary, but helps with debugging.In order for RViz to find our plugin, we need thisPLUGINLIBinvocation in our code (as well as other things below).package.xmlWe need the following three dependencies in our


key: chroma:document
string_value:
need the following three dependencies in our package.xml:<depend>pluginlib</depend><depend>rviz_common</depend><depend>rviz_plugin_tutorial_msgs</depend>rviz_common_plugins.xml<librarypath="point_display"><classtype="rviz_plugin_tutorial::PointDisplay"base_class_type="rviz_common::Display"><description></description></class></library>This is standardpluginlibcode.The librarypathis the name of the library we’ll assign in the CMake.The class should match thePLUGINLIBinvocation from above.We’ll come back to the description later, I promise.CMakeLists.txtAdd the following lines to the top of the standard


key: chroma:document
string_value:
the following lines to the top of the standard boilerplate.find_package(ament_cmake_rosREQUIRED)find_package(pluginlibREQUIRED)find_package(rviz_commonREQUIRED)find_package(rviz_plugin_tutorial_msgsREQUIRED)set(CMAKE_AUTOMOCON)qt5_wrap_cpp(MOC_FILESinclude/rviz_plugin_tutorial/point_display.hpp)add_library(point_displaysrc/point_display.cpp${MOC_FILES})target_include_directories(point_displayPUBLIC$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>$<INSTALL_INTERFACE:include>)ament_target_dependencies(point_displaypluginlibrviz_commonrviz_plugin_tutorial_msgs)install(TARGETSpoint_displayEXPORTexport_rviz_plugin_tutorialARCHIVEDESTINATIONlibLIBRARYDESTINATIONlibRUNTIMEDESTINATIONbin)install(DIRECTORYinclude/DESTINATIONinclude)install(FILESrviz_common_plugins.xmlDESTINATIONshare/${PROJECT_NAME})ament_export_include_directories(include)ament_export_targets(export_rviz_plugin_tutorial)pluginlib_export_plugin_description_file(rviz_commonrviz_common_plugins.xml)To generate the proper Qt files, we need


key: chroma:document
string_value:
generate the proper Qt files, we need toTurnCMAKE_AUTOMOCon.Wrap the headers by callingqt5_wrap_cppwith each header that hasQ_OBJECTin it.Include theMOC_FILESin the library alongside our other cpp files.Note that if you do NOT wrap your header files, you may get an error message when attempting to load the plugin at runtime, along the lines of:[rviz2]: PluginlibFactory: The plugin for class 'rviz_plugin_tutorial::PointDisplay' failed to load. Error: Failed to load library /home/ros/ros2_ws/install/rviz_plugin_tutorial/lib/libpoint_display.so. Make sure that you are calling the PLUGINLIB_EXPORT_CLASS macro in the library code, and that names are consistent between this macro and your XML. Error string: Could not load library LoadLibrary error: /home/ros/ros2_ws/install/rviz_plugin_tutorial/lib/libpoint_display.so: undefined symbol: _ZTVN20rviz_plugin_tutorial12PointDisplayE, at /tmp/binarydeb/ros-foxy-rcutils-1.1.4/src/shared_library.c:84A lot of the other code ensures that the plugin portion works. Namely,


key: chroma:document
string_value:
the other code ensures that the plugin portion works. Namely, callingpluginlib_export_plugin_description_fileis essential to getting RViz to find your new plugin.Testing it outCompile your code and runrviz2. You should be able to add your new plugin by clickingAddin the bottom left, and then selecting your package/plugin.Initially, the display will be in an error state because you have yet to assign a topic.If we put the topic/pointin, it should load fine but not display anything.You can publish messages with the following command:ros2topicpub/pointrviz_plugin_tutorial_msgs/msg/Point2D"{header: {frame_id: map}, x: 1, y: 2}"-r0.5That should result in the “We got a message” logging to appear in thestdoutof RViz.Actual VisualizationYou can view the full version of this step with the branch namestep2.First, you need to add a dependency inCMakeLists.txtandpackage.xmlon the packagerviz_rendering.We need to add three lines to the header file:#include<rviz_rendering/objects/shape.hpp>- There’slots of options in


key: chroma:document
string_value:
There’slots of options in the rviz_rendering packagefor objects to build your visualization on. Here we’re using a simple shape.In the class, we’ll add a newprotectedvirtual method:voidonInitialize()override;We also add a pointer to our shape object:std::unique_ptr<rviz_rendering::Shape>point_shape_;Then in the cpp file, we define theonInitializemethod:voidPointDisplay::onInitialize(){MFDClass::onInitialize();point_shape_=std::make_unique<rviz_rendering::Shape>(rviz_rendering::Shape::Type::Cube,scene_manager_,scene_node_);}MFDClassisaliasedto the templated parent class for convenience.The shape object must be constructed here in theonInitializemethod rather than the constructor because otherwisescene_manager_andscene_node_would not be ready.We also update ourprocessMessagemethod:voidPointDisplay::processMessage(constrviz_plugin_tutorial_msgs::msg::Point2D::ConstSharedPtrmsg){RVIZ_COMMON_LOG_INFO_STREAM("We got a message with frame


key: chroma:document
string_value:
got a message with frame "<<msg->header.frame_id);Ogre::Vector3position;Ogre::Quaternionorientation;if(!context_->getFrameManager()->getTransform(msg->header,position,orientation)){RVIZ_COMMON_LOG_DEBUG_STREAM("Error transforming from frame '"<<msg->header.frame_id<<"' to frame '"<<qPrintable(fixed_frame_)<<"'");}scene_node_->setPosition(position);scene_node_->setOrientation(orientation);Ogre::Vector3point_pos;point_pos.x=msg->x;point_pos.y=msg->y;point_shape_->setPosition(point_pos);}We need to get the proper frame for our message and transform thescene_node_accordingly. This ensures that the visualization does not always appear relative to the fixed frame.The actual visualization that we’ve been building up to is in the last four lines: we set the position of the visualization to match the message’s position.The result should look like this:If the box does not appear in that location, it might be because:You are not publishing the topic at this timeThe message hasn’t been published in the last 2


key: chroma:document
string_value:
at this timeThe message hasn’t been published in the last 2 seconds.You did not properly set the topic in RViz.It’s Nice to Have Options.If you want to allow users to customize different properties of the visualization, you need to addrviz_common::Property objects.You can view the full version of this step with the branch namestep3.Header UpdatesInclude the header file for color properties:#include<rviz_common/properties/color_property.hpp>. Color is but one of many properties you can set.Add in the prototype forupdateStyle, which is called whenever the GUI is changed via Qt’s SIGNAL/SLOT framework:privateQ_SLOTS:voidupdateStyle();Add in a new property to store the property itself:std::unique_ptr<rviz_common::properties::ColorProperty>color_property_;Cpp Updates#include<rviz_common/properties/parse_color.hpp>- Contains helper function to convert property to OGRE color.To ouronInitializewe addcolor_property_=std::make_unique<rviz_common::properties::ColorProperty>("Point Color",QColor(36,64,142),"Color to


key: chroma:document
string_value:
Color",QColor(36,64,142),"Color to draw the point.",this,SLOT(updateStyle()));updateStyle();This constructs the object with its name, default value, description and the callback.We callupdateStyledirectly so that the color is set at the beginning even before the property is changed.Then we define the callback.voidPointDisplay::updateStyle(){Ogre::ColourValuecolor=rviz_common::properties::qtToOgre(color_property_->getColor());point_shape_->setColor(color);}The result should look like this:Ooh, pink!Status ReportYou can view the full version of this step with the branch namestep4.You can also set the status of the display. As an arbitrary example, let’s make our display show a warning when the x coordinate is negative, because why not? InprocessMessage:if(msg->x<0){setStatus(StatusProperty::Warn,"Message","I will complain about points with negative x values.");}else{setStatus(StatusProperty::Ok,"Message","OK");}We’re assuming a previoususingrviz_common::properties::StatusProperty;declaration.Think of the


key: chroma:document
string_value:
of the status as Key/Value pairs, with the key being some string (here we’re using"Message") and the values are the status level (error/warn/ok) and the description (some other string).CleanupNow its time to clean it up a bit. This makes things look nicer and be a little easier to use, but aren’t strictly required. You can view the full version of this step with the branch namestep5.First, we update the plugin declaration.<librarypath="point_display"><classname="Point2D"type="rviz_plugin_tutorial::PointDisplay"base_class_type="rviz_common::Display"><description>Tutorialtodisplayapoint</description><message_type>rviz_plugin_tutorial_msgs/msg/Point2D</message_type></class></library>We add thenamefield to theclasstag. This changes the name that is displayed in RViz. In code, it makes sense to call it aPointDisplaybut in RViz, we want to simplify.We put actual text into the description. Don’t be lazy.By declaring the specific message type here, when you attempt to add a Display by Topic, it will suggest this


key: chroma:document
string_value:
you attempt to add a Display by Topic, it will suggest this plugin for the topics of that type.We also add an icon for the plugin aticons/classes/Point2D.png. The folder is hardcoded, and the filename should match the name from the plugin declaration (or the name of the class if not specified).[icon source]We need to install the image file in the CMake.install(FILESicons/classes/Point2D.pngDESTINATIONshare/${PROJECT_NAME}/icons/classes)Now when you add the display, it should show up with an icon and description.Here is the display when attempting to add by topic:And finally, here’s the icon in the standard interface:Note, if you change the plugins name, previous RViz configurations will no longer work.


key: chroma:document
string_value:
Code Examples:

Language: unknown

std_msgs/Headerheaderfloat64xfloat64y

Language: unknown #ifndef RVIZ_PLUGIN_TUTORIAL__POINT_DISPLAY_HPP_#define RVIZ_PLUGIN_TUTORIAL__POINT_DISPLAY_HPP_#include<rviz_common/message_filter_display.hpp>#include<rviz_plugin_tutorial_msgs/msg/point2_d.hpp>namespacerviz_plugin_tutorial{classPointDisplay:publicrviz_common::MessageFilterDisplay<rviz_plugin_tutorial_msgs::msg::Point2D>{Q_OBJECTprotected:voidprocessMessage(constrviz_plugin_tutorial_msgs::msg::Point2D::ConstSharedPtrmsg)override;};}// namespace rviz_plugin_tutorial#endif// RVIZ_PLUGIN_TUTORIAL__POINT_DISPLAY_HPP_


key: chroma:document
string_value:
Language: unknown #include<rviz_plugin_tutorial/point_display.hpp>#include<rviz_common/logging.hpp>namespacerviz_plugin_tutorial{voidPointDisplay::processMessage(constrviz_plugin_tutorial_msgs::msg::Point2D::ConstSharedPtrmsg){RVIZ_COMMON_LOG_INFO_STREAM("We got a message with frame "<<msg->header.frame_id);}}// namespace rviz_plugin_tutorial#include<pluginlib/class_list_macros.hpp>PLUGINLIB_EXPORT_CLASS(rviz_plugin_tutorial::PointDisplay,rviz_common::Display)

Language: unknown

<depend>pluginlib</depend><depend>rviz_common</depend><depend>rviz_plugin_tutorial_msgs</depend>

Language: unknown

<librarypath="point_display"><classtype="rviz_plugin_tutorial::PointDisplay"base_class_type="rviz_common::Display"><description></description></class></library>

Language: unknown


key: chroma:document
string_value:
Language: unknown

find_package(ament_cmake_rosREQUIRED)find_package(pluginlibREQUIRED)find_package(rviz_commonREQUIRED)find_package(rviz_plugin_tutorial_msgsREQUIRED)set(CMAKE_AUTOMOCON)qt5_wrap_cpp(MOC_FILESinclude/rviz_plugin_tutorial/point_display.hpp)add_library(point_displaysrc/point_display.cpp${MOC_FILES})target_include_directories(point_displayPUBLIC$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>$<INSTALL_INTERFACE:include>)ament_target_dependencies(point_displaypluginlibrviz_commonrviz_plugin_tutorial_msgs)install(TARGETSpoint_displayEXPORTexport_rviz_plugin_tutorialARCHIVEDESTINATIONlibLIBRARYDESTINATIONlibRUNTIMEDESTINATIONbin)install(DIRECTORYinclude/DESTINATIONinclude)install(FILESrviz_common_plugins.xmlDESTINATIONshare/${PROJECT_NAME})ament_export_include_directories(include)ament_export_targets(export_rviz_plugin_tutorial)pluginlib_export_plugin_description_file(rviz_commonrviz_common_plugins.xml)


key: chroma:document
string_value:
Language: unknown [rviz2]: PluginlibFactory: The plugin for class 'rviz_plugin_tutorial::PointDisplay' failed to load. Error: Failed to load library /home/ros/ros2_ws/install/rviz_plugin_tutorial/lib/libpoint_display.so. Make sure that you are calling the PLUGINLIB_EXPORT_CLASS macro in the library code, and that names are consistent between this macro and your XML. Error string: Could not load library LoadLibrary error: /home/ros/ros2_ws/install/rviz_plugin_tutorial/lib/libpoint_display.so: undefined symbol: _ZTVN20rviz_plugin_tutorial12PointDisplayE, at /tmp/binarydeb/ros-foxy-rcutils-1.1.4/src/shared_library.c:84

Language: unknown ros2topicpub/pointrviz_plugin_tutorial_msgs/msg/Point2D"{header: {frame_id: map}, x: 1, y: 2}"-r0.5

Language: unknown

voidPointDisplay::onInitialize(){MFDClass::onInitialize();point_shape_=std::make_unique<rviz_rendering::Shape>(rviz_rendering::Shape::Type::Cube,scene_manager_,scene_node_);}


key: chroma:document
string_value:
Language: unknown voidPointDisplay::processMessage(constrviz_plugin_tutorial_msgs::msg::Point2D::ConstSharedPtrmsg){RVIZ_COMMON_LOG_INFO_STREAM("We got a message with frame "<<msg->header.frame_id);Ogre::Vector3position;Ogre::Quaternionorientation;if(!context_->getFrameManager()->getTransform(msg->header,position,orientation)){RVIZ_COMMON_LOG_DEBUG_STREAM("Error transforming from frame '"<<msg->header.frame_id<<"' to frame '"<<qPrintable(fixed_frame_)<<"'");}scene_node_->setPosition(position);scene_node_->setOrientation(orientation);Ogre::Vector3point_pos;point_pos.x=msg->x;point_pos.y=msg->y;point_shape_->setPosition(point_pos);}

Language: unknown

privateQ_SLOTS:voidupdateStyle();

Language: unknown color_property_=std::make_unique<rviz_common::properties::ColorProperty>("Point Color",QColor(36,64,142),"Color to draw the point.",this,SLOT(updateStyle()));updateStyle();

Language: unknown

voidPointDisplay::updateStyle(){Ogre::ColourValuecolor=rviz_common::properties::qtToOgre(color_property_


key: chroma:document
string_value:
>getColor());point_shape_

>setColor(color);}

Language: unknown if(msg->x<0){setStatus(StatusProperty::Warn,"Message","I will complain about points with negative x values.");}else{setStatus(StatusProperty::Ok,"Message","OK");}

Language: unknown

<librarypath="point_display"><classname="Point2D"type="rviz_plugin_tutorial::PointDisplay"base_class_type="rviz_common::Display"><description>Tutorialtodisplayapoint</description><message_type>rviz_plugin_tutorial_msgs/msg/Point2D</message_type></class></library>

Language: unknown

install(FILESicons/classes/Point2D.pngDESTINATIONshare/${PROJECT_NAME}/icons/classes)


key: chroma:document
string_value:
Title: How To Guides

URL: https://docs.ros.org/en/jazzy/How

To

Guides.html

Section: How

To

Guides

--------------------------------------------------------------------------------


key: chroma:document
string_value:
Title: Eclipse Cyclone DDS

URL: https://docs.ros.org/en/jazzy/Installation/DDS

Implementations/Working

with

Eclipse

CycloneDDS.html

Section: Installation

--------------------------------------------------------------------------------


key: chroma:document
string_value:
Eclipse Cyclone DDSEclipse Cyclone DDS is a very performant and robust open-source DDS implementation. Cyclone DDS is developed completely in the open as an Eclipse IoT project. See also:https://projects.eclipse.org/projects/iot.cycloneddsPrerequisitesHaverosdep installed.Install packagesThe easiest way is to install from ROS 2 apt repository.sudoaptinstallros-jazzy-rmw-cyclonedds-cppBuild from source codeBuilding from source code is also another way to install.First, clone Cyclone DDS and rmw_cyclonedds in the ROS 2 workspace source directory.cdros2_ws/src gitclonehttps://github.com/ros2/rmw_cycloneddsros2/rmw_cyclonedds-bjazzy gitclonehttps://github.com/eclipse-cyclonedds/cycloneddseclipse-cyclonedds/cycloneddsThen, install necessary packages for Cyclone DDS.cd.. rosdepinstall--fromsrc-iFinally, run colcon build.colconbuild--symlink-installSwitch to rmw_cycloneddsSwitch from other rmw to rmw_cyclonedds by specifying the environment variable.exportRMW_IMPLEMENTATION=rmw_cyclonedds_cppSee also:Working


key: chroma:document
string_value:
also:Working with multiple RMW implementationsRun the talker and listenerNow runtalkerandlistenerto test Cyclone DDS.ros2rundemo_nodes_cpptalkerros2rundemo_nodes_cpplistener


key: chroma:document
string_value:
Code Examples:

Language: unknown

sudoaptinstallros

jazzy

rmw

cyclonedds

cpp

Language: unknown

cdros2_ws/src

gitclonehttps://github.com/ros2/rmw_cycloneddsros2/rmw_cyclonedds

bjazzy

gitclonehttps://github.com/eclipse

cyclonedds/cycloneddseclipse

cyclonedds/cyclonedds

Language: unknown

cd..

rosdepinstall-

fromsrc

i

Language: unknown

colconbuild-

symlink

install

Language: unknown

exportRMW_IMPLEMENTATION=rmw_cyclonedds_cpp

Language: unknown

ros2rundemo_nodes_cpptalker

Language: unknown

ros2rundemo_nodes_cpplistener


key: chroma:document
string_value:
Title: Bouncy Bolson (bouncy)

URL: https://docs.ros.org/en/jazzy/Releases/Release-Bouncy-Bolson.html

Section: Installation

--------------------------------------------------------------------------------


key: chroma:document
string_value:
Bouncy Bolson (bouncy)Table of ContentsSupported PlatformsFeaturesNew features in this ROS 2 releaseChanges since the Ardent releaseKnown IssuesBouncy Bolsonis the second release of ROS 2.Supported PlatformsThis version of ROS 2 is supported on four platforms (seeREP 2000for full details):Ubuntu 18.04 (Bionic)Debian packages for amd64 as well as arm64Ubuntu 16.04 (Xenial)no Debian packages but building from source is supportedMac macOS 10.12 (Sierra)Windows 10 with Visual Studio 2017Binary packages as well as instructions for how to compile from source are provided (seeinstall instructionsas well asdocumentation).FeaturesNew features in this ROS 2 releaseNew launch systemfeaturing a much more capable and flexible Python API.Parameters can be passed ascommand line argumentsto C++ executables.Static remapping viacommand line arguments.Various improvements to the Python client library.Support for publishing and subscribing to serialized data.


key: chroma:document
string_value:
This is the foundation for the upcoming work towards a native rosbag implementation.Morecommand line tools, e.g. for working with parameters and lifecycle states.Binary packages / fat archives support three RMW implementations by default (without the need to build from source):eProsima’s Fast RTPS (default)RTI’s ConnextADLINK’s OpenSpliceFor an overview of all features available, including those from earlier releases, please see theFeaturespage.Changes since the Ardent releaseChanges since theArdent Apalonerelease:The Python packagelaunchhas been redesigned.

The previous Python API has been moved into a submodulelaunch.legacy.

You can update existing launch files to continue to use the legacy API if a transition to the new Python API is not desired.The ROS topic names containing namespaces are mapped to DDS topics including their namespaces.

DDS partitions are not being used anymore for this.The recommended build tool is nowcolconinstead ofament_tools.


key: chroma:document
string_value:
This switch has noimplicationsfor the code in each ROS 2 package.

The install instructions have been updated and theread-the-docs pagedescribes how to map an existingament_toolscall tocolcon.The argument order ofthis rclcpp::Node::create_subscription() signaturehas been modified.Known IssuesNew-style launch filesmay hang on shutdownfor some combinations of platform and RMW implementation.Static remapping of namespacesnot working correctlywhen addressed to a particular node.Opensplice error messages may be printedwhen usingros2paramandros2lifecyclecommand-line tools.


key: chroma:document
string_value:
Title: Topics

URL: https://docs.ros.org/en/jazzy/Concepts/Basic/About

Topics.html

Section: Installation

--------------------------------------------------------------------------------


key: chroma:document
string_value:
TopicsTable of ContentsPublish/SubscribeAnonymousStrongly-typedTopics are one of the three primary styles of interfaces provided by ROS 2. Topics should be used for continuous data streams, like sensor data, robot state, etc.As stated earlier, ROS 2 is a strongly-typed, anonymous publish/subscribe system. Let’s break down that sentence and explain it a bit more.Publish/SubscribeA publish/subscribe system is one in which there are producers of data (publishers) and consumers of data (subscribers). The publishers and subscribers know how to contact each other through the concept of a “topic”, which is a common name so that the entites can find each other. For instance, when you create a publisher, you must also give it a string that is the name of the topic; the same goes for the subscriber. Any publishers and subscribers that are on the same topic name can directly communicate with each other. There may be zero or more publishers and zero or more subscribers on any particular topic. When data is published


key: chroma:document
string_value:
subscribers on any particular topic. When data is published to the topic by any of the publishers, all subscribers in the system will receive the data. This system is also known as a “bus”, since it somewhat resembles a device bus from electrical engineering. This concept of a bus is part of what makes ROS 2 a powerful and flexible system. Publishers and subscribers can come and go as needed, meaning that debugging and introspection are natural extensions to the system. For instance, if you want to record data, you can use theros2bagrecordcommand. Under the hood,ros2bagrecordcreates a new subscriber to whatever topic you tell it, without interrupting the flow of data to the other parts of the system.AnonymousAnother fact mentioned in the introduction is that ROS 2 is “anonymous”. This means that when a subscriber gets a piece of data, it doesn’t generally know or care which publisher originally sent it (though it can find out if it wants). The benefit to this architecture is that publishers and subscribers


key: chroma:document
string_value:
benefit to this architecture is that publishers and subscribers can be swapped out at will without affecting the rest of the system.Strongly-typedFinally, the introduction also mentioned that the publish/subscribe system is “strongly-typed”. That has two meanings in this context:The types of each field in a ROS message are typed, and that type is enforced at various levels. For instance, if the ROS message contains:uint32field1stringfield2Then the code will ensure thatfield1is always an unsigned integer and thatfield2is always a string.The semantics of each field are well-defined.  There is no automated mechanism to ensure this, but all of the core ROS types have strong semantics associated with them.  For instance, the IMU message contains a 3-dimensional vector for the measured angular velocity, and each of the dimensions is specified to be in radians/second.  Other interpretations should not be placed into the message.


key: chroma:document
string_value:
Title: Dashing Diademata (dashing)

URL: https://docs.ros.org/en/jazzy/Releases/Release

Dashing

Diademata.html

Section: Installation

--------------------------------------------------------------------------------


key: chroma:document
string_value:
Dashing Diademata (dashing)Table of ContentsSupported PlatformsInstallationNew features in this ROS 2 releaseChanges since the Crystal releaseDeclaring Parametersament_cmakerclcpprclcpp_componentsrclpyrosidlrosidl_generator_cpprosidl_generator_pylaunchrmwactionsrvizKnown IssuesTimeline before the releaseDashing Diadematais the fourth release of ROS 2.Supported PlatformsDashing Diademata is primarily supported on the following platforms:Tier 1 platforms:Ubuntu 18.04 (Bionic):amd64andarm64Mac macOS 10.12 (Sierra)Windows 10 (Visual Studio 2019)Tier 2 platforms:Ubuntu 18.04 (Bionic):arm32Tier 3 platforms:Debian Stretch (9):amd64,arm64andarm32OpenEmbedded Thud (2.6) / webOS OSE:arm32andx86For more information about RMW implementations, compiler / interpreter versions, and system dependency versions seeREP 2000.InstallationInstall Dashing DiademataNew features in this ROS 2 releaseA few features and improvements we would like to highlight:Componentsare now the recommended way to write your node. They can be


key: chroma:document
string_value:
now the recommended way to write your node. They can be used standalone as well as being composed within a process and both ways are fully support fromlaunchfiles.Theintra-process communication(C++ only) has been improved - both in terms of latency as well as minimizing copies.The Python client library has been updated to match most of the C++ equivalent and some important bug fixes and improvements have landed related to memory usage and performance.Parameters are now a complete alternative todynamic_reconfigurefrom ROS 1 including constraints like ranges or being read-only.By relying on (a subset of)IDL 4.2for the message generation pipeline it is now possible to use.idlfiles (beside.msg/.srv/.actionfiles). This change comes with support for optional UTF-8 encoding for ordinary strings as well as UTF-16 encoded multi-byte strings (seewide strings design article).Command line tools related toactionsandcomponents.Support for Deadline, Lifespan & Liveliness quality of service settings.MoveIt 2alpha


key: chroma:document
string_value:
Lifespan & Liveliness quality of service settings.MoveIt 2alpha release.Please see theDashing meta ticketon GitHub, which contains more information as well as references to specific tickets with additional details.Changes since the Crystal releaseDeclaring ParametersThere have been some changes to the behavior of parameters starting in Dashing, which have also lead to some new API’s and the deprecation of other API’s. See therclcppandrclpysections below for more information about API changes.Getting and Setting Undeclared ParametersAs of Dashing, parameters now need to be declared before being accessed or set.Before Dashing, you could callget_parameter(name)and get either a value, if it had been previously set, or a parameter of typePARAMETER_NOT_SET. You could also callset_parameter(name,value)at any point, even if the parameter was previously unset.Since Dashing, you need to first declare a parameter before getting or setting it. If you try to get or set an undeclared parameter you will either get an


key: chroma:document
string_value:
to get or set an undeclared parameter you will either get an exception thrown, e.g. ParameterNotDeclaredException, or in certain cases you will get an unsuccessful result communicated in a variety of ways (see specific functions for more details).However, you can get the old behavior (mostly, see the note in the next paragraph) by using theallow_undeclared_parametersoption when creating your node. You might want to do this in order to avoid code changes for now, or in order to fulfill some uncommon use cases. For example, a “global parameter server” or “parameter blackboard” may want to allow external nodes to set new parameters on itself without first declaring them, so it may use theallow_undeclared_parametersoption to accomplish that. In most cases, however, this option is not recommended because it makes the rest of the parameter API less safe to bugs like parameter name typos and “use before set” logical errors.Note that usingallow_undeclared_parameterswill get you most of the old behavior specifically


key: chroma:document
string_value:
get you most of the old behavior specifically for “get” and “set” methods, but it will not revert all the behavior changes related to parameters back to how it was for ROS Crystal. For that you need to also set theautomatically_declare_parameters_from_overridesoption totrue, which is described below inParameter Configuration using a YAML File.Declaring a Parameter with a ParameterDescriptorAnother benefit to declaring your parameters before using them, is that it allows you to declare a parameter descriptor at the same time.Now when declaring a parameter you may include a customParameterDescriptoras well as a name and default value. TheParameterDescriptoris defined as a message inrcl_interfaces/msg/ParameterDescriptorand contains meta data likedescriptionand constraints likeread_onlyorinteger_range. These constraints can be used to reject invalid values when setting parameters and/or as hints to external tools about what values are valid for a given parameter. Theread_onlyconstraint will prevent the


key: chroma:document
string_value:
for a given parameter. Theread_onlyconstraint will prevent the parameter’s value from changing after being declared, as well as prevent if from being undeclared.For reference, here’s a link to theParameterDescriptormessage as of the time of writing this:https://github.com/ros2/rcl_interfaces/blob/0aba5a142878c2077d7a03977087e7d74d40ee68/rcl_interfaces/msg/ParameterDescriptor.msg#L1Parameter Configuration using a YAML FileAs of Dashing, parameters in a YAML configuration file, e.g. passed to the node via the command line argument__params:=, are only used to override a parameter’s default value when declaring the parameter.Before Dashing, any parameters you passed via a YAML file would be implicitly set on the node.Since Dashing, this is no longer the case, as parameters need to be declared in order to appear on the node to external observers, likeros2paramlist.The old behavior may be achieved using theautomatically_declare_parameters_from_overridesoption when creating a node. This option, if set totrue, will


key: chroma:document
string_value:
when creating a node. This option, if set totrue, will automatically declare all parameters in the input YAML file when the node is constructed. This may be used to avoid major changes to your existing code or to serve specific use cases. For example, a “global parameter server” may want to be seeded with arbitrary parameters on launch, which it could not have declared ahead of time. Most of the time, however, this option is not recommended, as it may lead to setting a parameter in a YAML file with the assumption that the node will use it, even if the node does not actually use it.In the future we hope to have a checker that will warn you if you pass a parameter to a node that it was not expecting.The parameters in the YAML file will continue to influence the value of parameters when they are first declared.ament_cmakeThe CMake functionament_index_has_resourcewas returning eitherTRUEorFALSE. As ofthis releaseit returns either the prefix path in case the resource was found orFALSE.If you are using the return


key: chroma:document
string_value:
case the resource was found orFALSE.If you are using the return value in a CMake condition like this:ament_index_has_resource(var...)if(${var})you need to update the condition to ensure it considers a string value asTRUE:if(var)rclcppBehavior Change forNode::get_node_names()The functionNodeGraph::get_node_names(), and therefore alsoNode::get_node_names(), now returns astd::vector<std::string>containing fully qualified node names with their namespaces included, instead of just the node names.Changed the Way that Options are Passed to NodesExtended arguments (beyond name and namespace) to therclcpp::Node()constructor have been replaced with arclcpp::NodeOptionsstructure. Seeros2/rclcpp#622for details about the structure and default values of the options.If you are using any of the extended arguments torclcpp::Node()like


key: chroma:document
string_value:
are using any of the extended arguments torclcpp::Node()like this:autocontext=rclcpp::contexts::default_context::get_global_default_context();std::vector<std::string>args;std::vector<rclcpp::Parameter>params={rclcpp::Parameter("use_sim_time",true)};autonode=std::make_shared<rclcpp::Node>("foo_node","bar_namespace",context,args,params);You need to update to use theNodeOptionsstructurestd::vector<std::string>args;std::vector<rclcpp::Parameter>params={rclcpp::Parameter("use_sim_time",true)};rclcpp::NodeOptionsnode_options;node_options.arguments(args);node_options.parameter_overrides(params);autonode=std::make_shared<rclcpp::Node>("foo_node","bar_namespace",node_options);Changes to Creating Publishers and SubscriptionsThere have been a few changes to creating publishers and subscriptions which are new in Dashing:QoS settings are now passed using the newrclcpp::QoSclass, and the API encourages the user to specify at least the history depth.Options are now passed as an object,


key: chroma:document
string_value:
at least the history depth.Options are now passed as an object, i.e.rclcpp::PublisherOptionsandrclcpp::SubscriptionOptions.All changes are backwards compatible (no code changes are required), but several existing call styles have been deprecated. Users are encouraged to update to the new signatures.In the past, when creating a publisher or subscription, you could either not specify any QoS settings (e.g. just provide topic name for a publisher) or you could specify a “qos profile” data structure (of typermw_qos_profile_t) with all the settings already set. Now you must use the newrclcpp::QoSobject to specify your QoS and at least the history settings for your QoS. This encourages the user to specify a history depth when usingKEEP_LAST, rather than defaulting it to a value that may or may not be appropriate.In ROS 1, this was known as thequeue_sizeand it was required in both C++ and Python. We’re changing the ROS 2 API to bring this requirement back.Also, any options which could previously be passed during


key: chroma:document
string_value:
back.Also, any options which could previously be passed during creation of a publisher or subscription have now been encapsulated in anrclcpp::PublisherOptionsandrclcpp::SubscriptionOptionsclass respectively. This allows for shorter signatures, more convenient use, and for adding new future options without breaking API.Some signatures for creating publishers and subscribers are now deprecated, and new signatures have been added to allow you to use the newrclcpp::QoSand publisher/subscription option classes.These are the new and recommended


key: chroma:document
string_value:
option classes.These are the new and recommended API’s:template<typenameMessageT,typenameAllocatorT=std::allocator<void>,typenamePublisherT=::rclcpp::Publisher<MessageT,AllocatorT>>std::shared_ptr<PublisherT>create_publisher(conststd::string&topic_name,constrclcpp::QoS&qos,constPublisherOptionsWithAllocator<AllocatorT>&options=PublisherOptionsWithAllocator<AllocatorT>());template<typenameMessageT,typenameCallbackT,typenameAllocatorT=std::allocator<void>,typenameSubscriptionT=rclcpp::Subscription<typenamerclcpp::subscription_traits::has_message_type<CallbackT>::type,AllocatorT>>std::shared_ptr<SubscriptionT>create_subscription(conststd::string&topic_name,constrclcpp::QoS&qos,CallbackT&&callback,constSubscriptionOptionsWithAllocator<AllocatorT>&options=SubscriptionOptionsWithAllocator<AllocatorT>(),typenamerclcpp::message_memory_strategy::MessageMemoryStrategy<typenamerclcpp::subscription_traits::has_message_type<CallbackT>::type,AllocatorT>::SharedPtrmsg_mem_strat=nullptr);And these are the deprecated


key: chroma:document
string_value:
these are the deprecated ones:template<typenameMessageT,typenameAllocatorT=std::allocator<void>,typenamePublisherT=::rclcpp::Publisher<MessageT,AllocatorT>>[[deprecated("use create_publisher(const std::string &, const rclcpp::QoS &, ...) instead")]]std::shared_ptr<PublisherT>create_publisher(conststd::string&topic_name,size_tqos_history_depth,std::shared_ptr<AllocatorT>allocator);template<typenameMessageT,typenameAllocatorT=std::allocator<void>,typenamePublisherT=::rclcpp::Publisher<MessageT,AllocatorT>>[[deprecated("use create_publisher(const std::string &, const rclcpp::QoS &, ...) instead")]]std::shared_ptr<PublisherT>create_publisher(conststd::string&topic_name,constrmw_qos_profile_t&qos_profile=rmw_qos_profile_default,std::shared_ptr<AllocatorT>allocator=nullptr);template<typenameMessageT,typenameCallbackT,typenameAlloc=std::allocator<void>,typenameSubscriptionT=rclcpp::Subscription<typenamerclcpp::subscription_traits::has_message_type<CallbackT>::type,Alloc>>[[deprecated("use create_subscription(const


key: chroma:document
string_value:
create_subscription(const std::string &, const rclcpp::QoS &, CallbackT, ...) instead")]]std::shared_ptr<SubscriptionT>create_subscription(conststd::string&topic_name,CallbackT&&callback,constrmw_qos_profile_t&qos_profile=rmw_qos_profile_default,rclcpp::callback_group::CallbackGroup::SharedPtrgroup=nullptr,boolignore_local_publications=false,typenamerclcpp::message_memory_strategy::MessageMemoryStrategy<typenamerclcpp::subscription_traits::has_message_type<CallbackT>::type,Alloc>::SharedPtrmsg_mem_strat=nullptr,std::shared_ptr<Alloc>allocator=nullptr);template<typenameMessageT,typenameCallbackT,typenameAlloc=std::allocator<void>,typenameSubscriptionT=rclcpp::Subscription<typenamerclcpp::subscription_traits::has_message_type<CallbackT>::type,Alloc>>[[deprecated("use create_subscription(const std::string &, const rclcpp::QoS &, CallbackT, ...)


key: chroma:document
string_value:
std::string &, const rclcpp::QoS &, CallbackT, ...) instead")]]std::shared_ptr<SubscriptionT>create_subscription(conststd::string&topic_name,CallbackT&&callback,size_tqos_history_depth,rclcpp::callback_group::CallbackGroup::SharedPtrgroup=nullptr,boolignore_local_publications=false,typenamerclcpp::message_memory_strategy::MessageMemoryStrategy<typenamerclcpp::subscription_traits::has_message_type<CallbackT>::type,Alloc>::SharedPtrmsg_mem_strat=nullptr,std::shared_ptr<Alloc>allocator=nullptr);The change to how QoS is passed is most likely to impact users.A typical change for a publisher looks like this:- pub_ = create_publisher<std_msgs::msg::String>("chatter");+ pub_ = create_publisher<std_msgs::msg::String>("chatter", 10);And for a subscription:- sub_ = create_subscription<std_msgs::msg::String>("chatter", callback);+ sub_ = create_subscription<std_msgs::msg::String>("chatter", 10, callback);If you have no idea what depth to use and don’t care right now (maybe just prototyping), then we recommend using10,


key: chroma:document
string_value:
right now (maybe just prototyping), then we recommend using10, as that was the default before and should preserve existing behavior.More in depth documentation about how to select an appropriate depth is forthcoming.This is an example of a slightly more involved change to avoid the newly deprecated API’s:- // Creates a latched topic- rmw_qos_profile_t qos = rmw_qos_profile_default;- qos.depth = 1;- qos.durability = RMW_QOS_POLICY_DURABILITY_TRANSIENT_LOCAL;-model_xml_.data = model_xml;node_handle->declare_parameter("robot_description", model_xml);description_pub_ = node_handle->create_publisher<std_msgs::msg::String>(-   "robot_description", qos);+   "robot_description",+   // Transient local is similar to latching in ROS 1.+   rclcpp::QoS(1).transient_local());See the pull request (and connected pull requests) that introduced the QoS change for more examples and details:https://github.com/ros2/rclcpp/pull/713https://github.com/ros2/demos/pull/332https://github.com/ros2/robot_state_publisher/pull/19and


key: chroma:document
string_value:
others…Changes Due to Declare Parameter ChangeFor details about the actual behavior change, seeDeclaring Parametersabove.There are several new API calls in therclcpp::Node’s interface:Methods that declare parameters given a name, optional default value, optional descriptor, and return the value actually


key: chroma:document
string_value:
value, optional descriptor, and return the value actually set:constrclcpp::ParameterValue&rclcpp::Node::declare_parameter(conststd::string&name,constrclcpp::ParameterValue&default_value=rclcpp::ParameterValue(),constrcl_interfaces::msg::ParameterDescriptor&parameter_descriptor=rcl_interfaces::msg::ParameterDescriptor());template<typenameParameterT>autorclcpp::Node::declare_parameter(conststd::string&name,constParameterT&default_value,constrcl_interfaces::msg::ParameterDescriptor&parameter_descriptor=rcl_interfaces::msg::ParameterDescriptor());template<typenameParameterT>std::vector<ParameterT>rclcpp::Node::declare_parameters(conststd::string&namespace_,conststd::map<std::string,ParameterT>&parameters);template<typenameParameterT>std::vector<ParameterT>rclcpp::Node::declare_parameters(conststd::string&namespace_,conststd::map<std::string,std::pair<ParameterT,rcl_interfaces::msg::ParameterDescriptor>>&parameters);A method to undeclare parameters and to check if a parameter has been


key: chroma:document
string_value:
to undeclare parameters and to check if a parameter has been declared:voidrclcpp::Node::undeclare_parameter(conststd::string&name);boolrclcpp::Node::has_parameter(conststd::string&name)const;Some convenience methods that did not previously exist:rcl_interfaces::msg::SetParametersResultrclcpp::Node::set_parameter(constrclcpp::Parameter&parameter);std::vector<rclcpp::Parameter>rclcpp::Node::get_parameters(conststd::vector<std::string>&names)const;rcl_interfaces::msg::ParameterDescriptorrclcpp::Node::describe_parameter(conststd::string&name)const;A new method to set the callback which is called anytime a parameter will be changed, giving you the opportunity to reject it:usingOnParametersSetCallbackType=rclcpp::node_interfaces::NodeParametersInterface::OnParametersSetCallbackType;OnParametersSetCallbackTyperclcpp::Node::set_on_parameters_set_callback(OnParametersSetCallbackTypecallback);There were also several deprecated methods:template<typenameParameterT>[[deprecated("use declare_parameter()


key: chroma:document
string_value:
declare_parameter() instead")]]voidrclcpp::Node::set_parameter_if_not_set(conststd::string&name,constParameterT&value);template<typenameParameterT>[[deprecated("use declare_parameters() instead")]]voidrclcpp::Node::set_parameters_if_not_set(conststd::string&name,conststd::map<std::string,ParameterT>&values);template<typenameParameterT>[[deprecated("use declare_parameter() and it's return value instead")]]voidrclcpp::Node::get_parameter_or_set(conststd::string&name,ParameterT&value,constParameterT&alternative_value);template<typenameCallbackT>[[deprecated("use set_on_parameters_set_callback() instead")]]voidrclcpp::Node::register_param_change_callback(CallbackT&&callback);Memory StrategyThe interfacerclcpp::memory_strategy::MemoryStrategywas using the typedefWeakNodeVectorin various method signatures. As of Dashing the typedef has been been changed toWeakNodeListand with it the type of the parameter in various methods. Any custom memory strategy needs to be updated to match the modified interface.The


key: chroma:document
string_value:
needs to be updated to match the modified interface.The relevant API change can be found inros2/rclcpp#741.rclcpp_componentsThe correct way to implement composition in Dashing is by utilizing therclcpp_componentspackage.The following changes must be made to nodes in order to correctly implement runtime composition:The Node must have a constructor that takesrclcpp::NodeOptions:classListener:publicrclcpp::Node{Listener(constrclcpp::NodeOptions&options):Node("listener",options){}};C++ registration macros (if present) need to be updated to use therclcpp_componentsequivalent. If not present, registration macros must be added in one translation unit.// Insert at bottom of translation unit, e.g. listener.cpp#include"rclcpp_components/register_node_macro.hpp"// Use fully-qualifed name in registrationRCLCPP_COMPONENTS_REGISTER_NODE(composition::Listener);CMake registration macros (if present) need to be updated. If not present, registration macros must be added to the project’s


key: chroma:document
string_value:
not present, registration macros must be added to the project’s CMake.add_library(listenersrc/listener.cpp)rclcpp_components_register_nodes(listener"composition::Listener")For more information on composition, seethe tutorialrclpyChanges to Creating Publishers, Subscriptions, and QoS ProfilesPrior to Dashing, you could optionally provide aQoSProfileobject when creating a publisher or subscription. In an effort to encourage users to specify a history depth for message queues, we nowrequirethat a depth value orQoSProfileobject is given when creating publishers or subscriptions.To create a publisher, previously you would have written:node.create_publisher(Empty,'chatter')# Or using a keyword argument for QoSProfilenode.create_publisher(Empty,'chatter',qos_profile=qos_profile_sensor_data)In Dashing, prefer the following API that provides a depth value orQoSProfileobject as a third positional argument:# Assume a history setting of KEEP_LAST with depth 10node.create_publisher(Empty,'chatter',10)# Or pass a


key: chroma:document
string_value:
depth 10node.create_publisher(Empty,'chatter',10)# Or pass a QoSProfile object directlynode.create_publisher(Empty,'chatter',qos_profile_sensor_data)Likewise for subscriptions, previously you would have written:node.create_subscription(BasicTypes,'chatter',lambdamsg:print(msg))# Or using a keyword argument for QoSProfilenode.create_subscription(BasicTypes,'chatter',lambdamsg:print(msg),qos_profile=qos_profile_sensor_data)In Dashing:# Assume a history setting of KEEP_LAST with depth 10node.create_subscription(BasicTypes,'chatter',lambdamsg:print(msg),10)# Or pass a QoSProfile object directlynode.create_subscription(BasicTypes,'chatter',lambdamsg:print(msg),qos_profile_sensor_data)To ease the transition, users who do not use the new API will see deprecation warnings.Furthermore, we also require that when constructingQoSProfileobjects that a history policy and/or depth is set. If a history policy ofKEEP_LASTis provided, then a depth argument is also required. For example, these calls are


key: chroma:document
string_value:
a depth argument is also required. For example, these calls are valid:QoSProfile(history=QoSHistoryPolicy.RMW_QOS_POLICY_HISTORY_KEEP_ALL)QoSProfile(history=QoSHistoryPolicy.RMW_QOS_POLICY_HISTORY_KEEP_LAST,depth=10)QoSProfile(depth=10)# equivalent to the previous lineAnd these calls will cause a deprecation warning:QoSProfile()QoSProfile(reliability=QoSReliabilityPolicy.RMW_QOS_POLICY_RELIABILITY_BEST_EFFORT)# KEEP_LAST but no depthQoSProfile(history=QoSHistoryPolicy.RMW_QOS_POLICY_HISTORY_KEEP_LAST)See the issue and pull request related to introducing this change for more details:https://github.com/ros2/rclpy/issues/342https://github.com/ros2/rclpy/pull/344Changes Due to Declare Parameter ChangeFor details about the actual behavior change, seeDeclaring Parametersabove. The changes are analogous to the ones inrclcpp.These are the new API methods available inrclpy.node.Nodeinterface:To declare parameters given a name, an optional default value (supported byrcl_interfaces.msg.ParameterValue) and an optional


key: chroma:document
string_value:
(supported byrcl_interfaces.msg.ParameterValue) and an optional descriptor, returning the value actually set:defdeclare_parameter(name:str,value:Any=None,descriptor:ParameterDescriptor=ParameterDescriptor())->Parameterdefdeclare_parameters(namespace:str,parameters:List[Union[Tuple[str],Tuple[str,Any],Tuple[str,Any,ParameterDescriptor],]])->List[Parameter]To undeclare previously declared parameters and to check if a parameter has been declared beforehand:defundeclare_parameter(name:str)->Nonedefhas_parameter(name:str)->boolTo get and set parameter descriptors:defdescribe_parameter(name:str)->ParameterDescriptordefdescribe_parameters(names:List[str])->List[ParameterDescriptor]defset_descriptor(name:str,descriptor:ParameterDescriptor,alternative_value:Optional[ParameterValue]=None)->ParameterValueA convenience method to get parameters that may not have been declared:defget_parameter_or(name:str,alternative_value:Optional[Parameter]=None)->ParameterOther changesrclpy.parameter.Parametercan now guess its type


key: chroma:document
string_value:
changesrclpy.parameter.Parametercan now guess its type without explicitly setting it (as long as it’s one of the supported ones byrcl_interfaces.msg.ParameterValue). For example, this code:p=Parameter('myparam',Parameter.Type.DOUBLE,2.41)Is equivalent to this code:p=Parameter('myparam',value=2.41)This change does not break existing API.rosidlUntil Crystal each message generator package registered itself using theament_cmakeextension pointrosidl_generate_interfacesand was passed a set of.msg/.srv/.actionfiles. As of Dashing the message generation pipeline is based on.idlfiles instead.Any message generator package needs to change and register itself using the new extension pointrosidl_generate_idl_interfaceswhich passes only.idlfiles instead. The message generators for the commonly supported languages C, C++, and Python as well as the typesupport packages for introspection, Fast RTPS, Connext and OpenSplice have already been updated (seeros2/rosidl#334). The CMake code callingrosidl_generate_interfaces()can


key: chroma:document
string_value:
The CMake code callingrosidl_generate_interfaces()can either pass.idlfiles directly or pass.msg/.srv/.actionwhich will then internally be converted into.idlfiles before being passed to each message generator.The format of.msg/.srv/.actionfiles is not being evolved in the future. The mapping between.msg/.srv/.actionfiles and.idlfiles is described inthis design article. Asecond design articledescribes the supported features in.idlfiles. In order to leverage any of the new features existing interfaces need to be converted (e.g. using the command line toolsmsg2idl/srv2idl/action2idl).To distinguish same type names, but with different namespaces, the introspection structs now contain a namespace field that replaces the package name (seeros2/rosidl#335).Mapping of char in .msg filesInROS 1charhas been deprecated for a long time and is being mapped touint8. In ROS 2 until Crystalcharwas mapped to a single character (charin C / C++,strwith length 1 in Python) in an effort to provide a more natural mapping. As of


key: chroma:document
string_value:
Python) in an effort to provide a more natural mapping. As of Dashing the ROS 1 semantic has been restored andcharmaps touint8again.rosidl_generator_cppThe C++ data structures generated for messages, services and actions provide setter methods for each field. Until Crystal each setter returned a pointer to the data structure itself to enable the named parameter idiom. As of Dashing these settersreturn a referenceinstead since that seems to be the more common signature as well as it clarifies that the returned value can’t be anullptr.rosidl_generator_pyUntil Crystal an array (fixed size) or sequence (dynamic size, optionally with an upper boundary) field in a message was stored as alistin Python. As of Dashing the Python type for arrays / sequences of numeric values has been changed:an array of numeric values is stored as anumpy.ndarray(thedtypeis chosen to match the type of the numeric value)a sequence of numeric values is stored as anarray.array(thetypenameis chosen to match the type of the numeric


key: chroma:document
string_value:
chosen to match the type of the numeric value)As before an array / sequence of non-numeric types is still represented as alistin Python.This change brings a number of benefits:The new data structures ensure that each item in the array / sequence complies with the value range restrictions of the numeric type.The numeric values can be stored more efficiently in memory which avoid the overhead of Python objects for each item.The memory layout of both data structures allows to read and write all items of the array / sequence in a single operation which makes the conversion from and to Python significantly faster / more efficient.launchThelaunch_testingpackage caught up with thelaunchpackage redesign done in Bouncy Bolson. The legacy Python API, already moved into thelaunch.legacysubmodule, has thus been deprecated and removed.Seelaunchexamplesanddocumentationfor reference on how to use its new API.Seedemos testsfor reference on how to use the newlaunch_testingAPI.rmwChanges since theCrystal Clemmysrelease:New


key: chroma:document
string_value:
since theCrystal Clemmysrelease:New API inrmw, a fini function forrmw_context_t:rmw_context_finiModification ofrmw, now passesrmw_context_ttormw_create_wait_set:rmw_create_wait_setNew APIs inrmwfor preallocating space for published and subscribed messages:rmw_init_publisher_allocationrmw_fini_publisher_allocationrmw_init_subscription_allocationrmw_fini_subscription_allocationrmw_serialized_message_sizeModification ofrmw, now passesrmw_publisher_allocation_torrmw_subscription_allocation_ttormw_publishandrmw_take, respectively. Note that this argument can beNULLornullptr, which keeps existing Crystal behavior.rmw_publishrmw_takeType names returned byrmw_get_*_names_and_types*functions should have a fully-qualified namespace. For example, instead ofrcl_interfaces/Parameterandrcl_interfaces/GetParameters, the returned type names should bercl_interface/msg/Parameterandrcl_interfaces/srv/GetParameters.actionsChanges torclcpp_action::Clientsignatures:The signature ofrclcpp_action::Client::async_send_goalhas


key: chroma:document
string_value:
signature ofrclcpp_action::Client::async_send_goalhas changed. Now users can optionally provide callback functions for thegoal responseand theresultusing the newSendGoalOptionsstruct. The goal response callback is called when an action server accepts or rejects the goal and the result callback is called when the result for the goal is received. Optional callbacks were also added torclcpp_action::Client::async_cancel_goalandrclcpp_action::Client::async_get_result.Changes to goal transition names:The names of goal state transitions have been refactored to reflect the design documention. This affectsrcl_action,rclcpp_action, andrclpy. Here is a list of the event name changes (Old name -> New name):GOAL_EVENT_CANCEL -> GOAL_EVENT_CANCEL_GOALGOAL_EVENT_SET_SUCCEEDED -> GOAL_EVENT_SUCCEEDGOAL_EVENT_SET_ABORTED -> GOAL_EVENT_ABORTGOAL_EVENT_SET_CANCELED -> GOAL_EVENT_CANCELEDChanges toCancelGoal.srv:Areturn_codefield was added to the response message of theCancelGoalservice. This is to better communicate a reason


key: chroma:document
string_value:
of theCancelGoalservice. This is to better communicate a reason for a failed service call. See thepull requestand connected issue for details.rvizPlugins should use fully qualified type names otherwise a warning will be logged. Forexample, use the typesensor_msgs/msg/Imageinstead ofsensor_msgs/Image. SeePR introducing this changefor more details.Known Issues[ros2/rclcpp#715]There is an inconsistency in the way that parameter YAML files are loaded between standalone ROS 2 nodes and composed ROS 2 nodes. Currently available workarounds are noted in anissue comment[ros2/rclpy#360]rclpy nodes ignorectrl-cwhen using OpenSplice on Windows.[ros2/rosidl_typesupport_opensplice#30]There is a bug preventing nesting a message inside of a service or action definition with the same name when using OpenSplice.[ros2/rclcpp#781]Callingget_parameter/list_parameterfrom withinon_set_parameter_callbackcauses a deadlock on Dashing.  This is fixed for Eloquent, but is an ABI break so has not been backported to


key: chroma:document
string_value:
for Eloquent, but is an ABI break so has not been backported to Dashing.[ros2/rclcpp#912]Inter-process communication forces a message copy when intra-process communication takes place between anstd::unique_ptrpublisher and a singlestd::unique_ptrsubscription (publishedstd::unique_ptris internally being promoted to anstd::shared_ptr).[ros2/rosbag2#125]Topics with unreliable QOS are not recorded.[ros2/rclcpp#715]Composable nodes cannot receive parameters via remapping. Supplying parameters to composable nodes can be accomplished using the methods described in[this comment].[ros2/rclcpp#893]rclcpp::Contextis not destroyed because of a reference cycle withrclcpp::GraphListener. This causes a memory leak. A fix has not been backported because of the risk of breaking ABI.Timeline before the releaseA few milestones leading up to the release:Mon. Apr 8th (alpha)First releases of core packages available. Testing can happen from now on (some features might not have landed yet).Thu. May 2ndAPI freeze for core


key: chroma:document
string_value:
might not have landed yet).Thu. May 2ndAPI freeze for core packagesMon. May 6th (beta)Updated releases of core packages available. Additional testing of the latest features.Thu. May 16thFeature freeze. Only bug fix releases should be made after this point. New packages can be released independently.Mon. May 20th (release candidate)Updated releases of core packages available.Wed. May 29thFreeze rosdistro. No PRs for Dashing on therosdistrorepo will be merged (reopens after the release announcement).


key: chroma:document
string_value:
Code Examples:

Language: unknown

ament_index_has_resource(var...)if(${var})

Language: unknown

if(var)

Language: unknown

autocontext=rclcpp::contexts::default_context::get_global_default_context();std::vector<std::string>args;std::vector<rclcpp::Parameter>params={rclcpp::Parameter("use_sim_time",true)};autonode=std::make_shared<rclcpp::Node>("foo_node","bar_namespace",context,args,params);

Language: unknown

std::vector<std::string>args;std::vector<rclcpp::Parameter>params={rclcpp::Parameter("use_sim_time",true)};rclcpp::NodeOptionsnode_options;node_options.arguments(args);node_options.parameter_overrides(params);autonode=std::make_shared<rclcpp::Node>("foo_node","bar_namespace",node_options);

Language: unknown


key: chroma:document
string_value:
Language: unknown

template<typenameMessageT,typenameAllocatorT=std::allocator<void>,typenamePublisherT=::rclcpp::Publisher<MessageT,AllocatorT>>std::shared_ptr<PublisherT>create_publisher(conststd::string&topic_name,constrclcpp::QoS&qos,constPublisherOptionsWithAllocator<AllocatorT>&options=PublisherOptionsWithAllocator<AllocatorT>());template<typenameMessageT,typenameCallbackT,typenameAllocatorT=std::allocator<void>,typenameSubscriptionT=rclcpp::Subscription<typenamerclcpp::subscription_traits::has_message_type<CallbackT>::type,AllocatorT>>std::shared_ptr<SubscriptionT>create_subscription(conststd::string&topic_name,constrclcpp::QoS&qos,CallbackT&&callback,constSubscriptionOptionsWithAllocator<AllocatorT>&options=SubscriptionOptionsWithAllocator<AllocatorT>(),typenamerclcpp::message_memory_strategy::MessageMemoryStrategy<typenamerclcpp::subscription_traits::has_message_type<CallbackT>::type,AllocatorT>::SharedPtrmsg_mem_strat=nullptr);


key: chroma:document
string_value:
Language: unknown template<typenameMessageT,typenameAllocatorT=std::allocator<void>,typenamePublisherT=::rclcpp::Publisher<MessageT,AllocatorT>>[[deprecated("use create_publisher(const std::string &, const rclcpp::QoS &, ...) instead")]]std::shared_ptr<PublisherT>create_publisher(conststd::string&topic_name,size_tqos_history_depth,std::shared_ptr<AllocatorT>allocator);template<typenameMessageT,typenameAllocatorT=std::allocator<void>,typenamePublisherT=::rclcpp::Publisher<MessageT,AllocatorT>>[[deprecated("use create_publisher(const std::string &, const rclcpp::QoS &, ...) instead")]]std::shared_ptr<PublisherT>create_publisher(conststd::string&topic_name,constrmw_qos_profile_t&qos_profile=rmw_qos_profile_default,std::shared_ptr<AllocatorT>allocator=nullptr);template<typenameMessageT,typenameCallbackT,typenameAlloc=std::allocator<void>,typenameSubscriptionT=rclcpp::Subscription<typenamerclcpp::subscription_traits::has_message_type<CallbackT>::type,Alloc>>[[deprecated("use create_subscription(const std::string


key: chroma:document
string_value:
std::string &, const rclcpp::QoS &, CallbackT, ...) instead")]]std::shared_ptr<SubscriptionT>create_subscription(conststd::string&topic_name,CallbackT&&callback,size_tqos_history_depth,rclcpp::callback_group::CallbackGroup::SharedPtrgroup=nullptr,boolignore_local_publications=false,typenamerclcpp::message_memory_strategy::MessageMemoryStrategy<typenamerclcpp::subscription_traits::has_message_type<CallbackT>::type,Alloc>::SharedPtrmsg_mem_strat=nullptr,std::shared_ptr<Alloc>allocator=nullptr);


key: chroma:document
string_value:
Language: unknown - pub_ = create_publisher<std_msgs::msg::String>("chatter");+ pub_ = create_publisher<std_msgs::msg::String>("chatter", 10);

Language: unknown - sub_ = create_subscription<std_msgs::msg::String>("chatter", callback);+ sub_ = create_subscription<std_msgs::msg::String>("chatter", 10, callback);

Language: unknown - // Creates a latched topic- rmw_qos_profile_t qos = rmw_qos_profile_default;- qos.depth = 1;- qos.durability = RMW_QOS_POLICY_DURABILITY_TRANSIENT_LOCAL;-model_xml_.data = model_xml;node_handle->declare_parameter("robot_description", model_xml);description_pub_ = node_handle->create_publisher<std_msgs::msg::String>(-   "robot_description", qos);+   "robot_description",+   // Transient local is similar to latching in ROS 1.+   rclcpp::QoS(1).transient_local());

Language: unknown


key: chroma:document
string_value:
Language: unknown

constrclcpp::ParameterValue&rclcpp::Node::declare_parameter(conststd::string&name,constrclcpp::ParameterValue&default_value=rclcpp::ParameterValue(),constrcl_interfaces::msg::ParameterDescriptor&parameter_descriptor=rcl_interfaces::msg::ParameterDescriptor());template<typenameParameterT>autorclcpp::Node::declare_parameter(conststd::string&name,constParameterT&default_value,constrcl_interfaces::msg::ParameterDescriptor&parameter_descriptor=rcl_interfaces::msg::ParameterDescriptor());template<typenameParameterT>std::vector<ParameterT>rclcpp::Node::declare_parameters(conststd::string&namespace_,conststd::map<std::string,ParameterT>&parameters);template<typenameParameterT>std::vector<ParameterT>rclcpp::Node::declare_parameters(conststd::string&namespace_,conststd::map<std::string,std::pair<ParameterT,rcl_interfaces::msg::ParameterDescriptor>>&parameters);

Language: unknown


key: chroma:document
string_value:
Language: unknown

voidrclcpp::Node::undeclare_parameter(conststd::string&name);boolrclcpp::Node::has_parameter(conststd::string&name)const;

Language: unknown

rcl_interfaces::msg::SetParametersResultrclcpp::Node::set_parameter(constrclcpp::Parameter&parameter);std::vector<rclcpp::Parameter>rclcpp::Node::get_parameters(conststd::vector<std::string>&names)const;rcl_interfaces::msg::ParameterDescriptorrclcpp::Node::describe_parameter(conststd::string&name)const;

Language: unknown

usingOnParametersSetCallbackType=rclcpp::node_interfaces::NodeParametersInterface::OnParametersSetCallbackType;OnParametersSetCallbackTyperclcpp::Node::set_on_parameters_set_callback(OnParametersSetCallbackTypecallback);


key: chroma:document
string_value:
Language: unknown template<typenameParameterT>[[deprecated("use declare_parameter() instead")]]voidrclcpp::Node::set_parameter_if_not_set(conststd::string&name,constParameterT&value);template<typenameParameterT>[[deprecated("use declare_parameters() instead")]]voidrclcpp::Node::set_parameters_if_not_set(conststd::string&name,conststd::map<std::string,ParameterT>&values);template<typenameParameterT>[[deprecated("use declare_parameter() and it's return value instead")]]voidrclcpp::Node::get_parameter_or_set(conststd::string&name,ParameterT&value,constParameterT&alternative_value);template<typenameCallbackT>[[deprecated("use set_on_parameters_set_callback() instead")]]voidrclcpp::Node::register_param_change_callback(CallbackT&&callback);

Language: unknown

classListener:publicrclcpp::Node{Listener(constrclcpp::NodeOptions&options):Node("listener",options){}};


key: chroma:document
string_value:
Language: unknown // Insert at bottom of translation unit, e.g. listener.cpp#include"rclcpp_components/register_node_macro.hpp"// Use fully-qualifed name in registrationRCLCPP_COMPONENTS_REGISTER_NODE(composition::Listener);

Language: unknown

add_library(listenersrc/listener.cpp)rclcpp_components_register_nodes(listener"composition::Listener")

Language: unknown node.create_publisher(Empty,'chatter')# Or using a keyword argument for QoSProfilenode.create_publisher(Empty,'chatter',qos_profile=qos_profile_sensor_data)

Language: unknown # Assume a history setting of KEEP_LAST with depth 10node.create_publisher(Empty,'chatter',10)# Or pass a QoSProfile object directlynode.create_publisher(Empty,'chatter',qos_profile_sensor_data)

Language: unknown node.create_subscription(BasicTypes,'chatter',lambdamsg:print(msg))# Or using a keyword argument for QoSProfilenode.create_subscription(BasicTypes,'chatter',lambdamsg:print(msg),qos_profile=qos_profile_sensor_data)


key: chroma:document
string_value:
Language: unknown # Assume a history setting of KEEP_LAST with depth 10node.create_subscription(BasicTypes,'chatter',lambdamsg:print(msg),10)# Or pass a QoSProfile object directlynode.create_subscription(BasicTypes,'chatter',lambdamsg:print(msg),qos_profile_sensor_data)

Language: unknown QoSProfile(history=QoSHistoryPolicy.RMW_QOS_POLICY_HISTORY_KEEP_ALL)QoSProfile(history=QoSHistoryPolicy.RMW_QOS_POLICY_HISTORY_KEEP_LAST,depth=10)QoSProfile(depth=10)# equivalent to the previous line

Language: unknown QoSProfile()QoSProfile(reliability=QoSReliabilityPolicy.RMW_QOS_POLICY_RELIABILITY_BEST_EFFORT)# KEEP_LAST but no depthQoSProfile(history=QoSHistoryPolicy.RMW_QOS_POLICY_HISTORY_KEEP_LAST)

Language: unknown

defdeclare_parameter(name:str,value:Any=None,descriptor:ParameterDescriptor=ParameterDescriptor())

>Parameterdefdeclare_parameters(namespace:str,parameters:List[Union[Tuple[str],Tuple[str,Any],Tuple[str,Any,ParameterDescriptor],]])

>List[Parameter]

Language: unknown

defundeclare_parameter(name:str)


key: chroma:document
string_value:
Language: unknown

defundeclare_parameter(name:str)

>Nonedefhas_parameter(name:str)

>bool

Language: unknown

defdescribe_parameter(name:str)

>ParameterDescriptordefdescribe_parameters(names:List[str])

>List[ParameterDescriptor]defset_descriptor(name:str,descriptor:ParameterDescriptor,alternative_value:Optional[ParameterValue]=None)

>ParameterValue

Language: unknown

defget_parameter_or(name:str,alternative_value:Optional[Parameter]=None)

>Parameter

Language: unknown

p=Parameter('myparam',Parameter.Type.DOUBLE,2.41)

Language: unknown

p=Parameter('myparam',value=2.41)


key: chroma:document
string_value:
Title: Implementing custom interfaces

URL: https://docs.ros.org/en/jazzy/Tutorials/Beginner

Client

Libraries/Single

Package

Define

And

Use

Interface.html

Section: Installation

--------------------------------------------------------------------------------


key: chroma:document
string_value:
Implementing custom interfacesGoal:Learn more ways to implement custom interfaces in ROS 2.Tutorial level:BeginnerTime:15 minutesContentsBackgroundPrerequisitesTasks1 Create a package2 Create a msg file3 Use an interface from the same package4 Try it out5 (Extra) Use an existing interface definitionSummaryNext stepsRelated contentBackgroundIn aprevious tutorial, you learned how to create custom msg and srv interfaces.While best practice is to declare interfaces in dedicated interface packages, sometimes it can be convenient to declare, create and use an interface all in one package.Recall that interfaces can currently only be defined in CMake packages. It is possible, however, to have Python libraries and nodes in CMake packages (usingament_cmake_python), so you could define interfaces and Python nodes together in one package. We’ll use a CMake package and C++ nodes here for the sake of simplicity.This tutorial will focus on the msg interface type, but the steps here are applicable to all interface


key: chroma:document
string_value:
type, but the steps here are applicable to all interface types.PrerequisitesWe assume you’ve reviewed the basics in theCreating custom msg and srv filestutorial before working through this one.You should haveROS 2 installed, aworkspace, and an understanding ofcreating packages.As always, don’t forget tosource ROS 2in every new terminal you open.Tasks1 Create a packageIn your workspacesrcdirectory, create a packagemore_interfacesand make a directory within it for msg files:ros2 pkg create --build-type ament_cmake --license Apache-2.0 more_interfacesmkdir more_interfaces/msg2 Create a msg fileInsidemore_interfaces/msg, create a new fileAddressBook.msg, and paste the following code to create a message meant to carry information about an individual:uint8PHONE_TYPE_HOME=0uint8PHONE_TYPE_WORK=1uint8PHONE_TYPE_MOBILE=2stringfirst_namestringlast_namestringphone_numberuint8phone_typeThis message is composed of these fields:first_name: of type stringlast_name: of type stringphone_number: of type stringphone_type:


key: chroma:document
string_value:
of type stringphone_number: of type stringphone_type: of type uint8, with several named constant values definedNote that it’s possible to set default values for fields within a message definition. SeeInterfacesfor more ways you can customize interfaces.Next, we need to make sure that the msg file is turned into source code for C++, Python, and other languages.2.1 Build a msg fileOpenpackage.xmland add the following lines:<buildtool_depend>rosidl_default_generators</buildtool_depend><exec_depend>rosidl_default_runtime</exec_depend><member_of_group>rosidl_interface_packages</member_of_group>Note that at build time, we needrosidl_default_generators, while at runtime, we only needrosidl_default_runtime.OpenCMakeLists.txtand add the following lines:Find the package that generates message code from msg/srv files:find_package(rosidl_default_generatorsREQUIRED)Declare the list of messages you want to generate:set(msg_files"msg/AddressBook.msg")By adding the .msg files manually, we make sure that CMake knows when it


key: chroma:document
string_value:
the .msg files manually, we make sure that CMake knows when it has to reconfigure the project after you add other .msg files.Generate the messages:rosidl_generate_interfaces(${PROJECT_NAME}${msg_files})Also make sure you export the message runtime dependency:ament_export_dependencies(rosidl_default_runtime)Now you’re ready to generate source files from your msg definition. We’ll skip the compile step for now as we’ll do it all together below in step 4.3 Use an interface from the same packageNow we can start writing code that uses this message.Inmore_interfaces/srccreate a file calledpublish_address_book.cppand paste the following


key: chroma:document
string_value:
a file calledpublish_address_book.cppand paste the following code:#include<chrono>#include<memory>#include"rclcpp/rclcpp.hpp"#include"more_interfaces/msg/address_book.hpp"usingnamespacestd::chrono_literals;classAddressBookPublisher:publicrclcpp::Node{public:AddressBookPublisher():Node("address_book_publisher"){address_book_publisher_=this->create_publisher<more_interfaces::msg::AddressBook>("address_book",10);autopublish_msg=[this]()->void{automessage=more_interfaces::msg::AddressBook();message.first_name="John";message.last_name="Doe";message.phone_number="1234567890";message.phone_type=message.PHONE_TYPE_MOBILE;std::cout<<"Publishing Contact\nFirst:"<<message.first_name<<"


key: chroma:document
string_value:
Contact\nFirst:"<<message.first_name<<"  Last:"<<message.last_name<<std::endl;this->address_book_publisher_->publish(message);};timer_=this->create_wall_timer(1s,publish_msg);}private:rclcpp::Publisher<more_interfaces::msg::AddressBook>::SharedPtraddress_book_publisher_;rclcpp::TimerBase::SharedPtrtimer_;};intmain(intargc,char*argv[]){rclcpp::init(argc,argv);rclcpp::spin(std::make_shared<AddressBookPublisher>());rclcpp::shutdown();return0;}3.1 The code explainedInclude the header of our newly createdAddressBook.msg.#include"more_interfaces/msg/address_book.hpp"Create a node and anAddressBookpublisher.usingnamespacestd::chrono_literals;classAddressBookPublisher:publicrclcpp::Node{public:AddressBookPublisher():Node("address_book_publisher"){address_book_publisher_=this->create_publisher<more_interfaces::msg::AddressBook>("address_book");Create a callback to publish the messages periodically.autopublish_msg=[this]()->void{Create anAddressBookmessage instance that we will later


key: chroma:document
string_value:
anAddressBookmessage instance that we will later publish.automessage=more_interfaces::msg::AddressBook();PopulateAddressBookfields.message.first_name="John";message.last_name="Doe";message.phone_number="1234567890";message.phone_type=message.PHONE_TYPE_MOBILE;Finally send the message periodically.std::cout<<"Publishing Contact\nFirst:"<<message.first_name<<"  Last:"<<message.last_name<<std::endl;this->address_book_publisher_->publish(message);Create a 1 second timer to call ourpublish_msgfunction every second.timer_=this->create_wall_timer(1s,publish_msg);3.2 Build the publisherWe need to create a new target for this node in theCMakeLists.txt:find_package(rclcppREQUIRED)add_executable(publish_address_booksrc/publish_address_book.cpp)ament_target_dependencies(publish_address_bookrclcpp)install(TARGETSpublish_address_bookDESTINATIONlib/${PROJECT_NAME})3.3 Link against the interfaceIn order to use the messages generated in the same package we need to use the following CMake


key: chroma:document
string_value:
in the same package we need to use the following CMake code:rosidl_get_typesupport_target(cpp_typesupport_target${PROJECT_NAME}rosidl_typesupport_cpp)target_link_libraries(publish_address_book"${cpp_typesupport_target}")This finds the relevant generated C++ code fromAddressBook.msgand allows your target to link against it.You may have noticed that this step was not necessary when the interfaces being used were from a different package that was built independently. This CMake code is only required when you want to use interfaces in the same package as the one in which they are defined.4 Try it outReturn to the root of the workspace to build the package:LinuxmacOSWindowscd ~/ros2_wscolcon build --packages-up-to more_interfacescd ~/ros2_wscolcon build --packages-up-to more_interfacescd /ros2_wscolcon build --merge-install --packages-up-to more_interfacesThen source the workspace and run the publisher:LinuxmacOSWindowssource install/local_setup.bashros2 run more_interfaces publish_address_book.


key: chroma:document
string_value:
run more_interfaces publish_address_book. install/local_setup.bashros2 run more_interfaces publish_address_bookcall install/local_setup.batros2 run more_interfaces publish_address_bookOr using Powershell:install/local_setup.ps1ros2 run more_interfaces publish_address_bookYou should see the publisher relaying the msg you defined, including the values you set inpublish_address_book.cpp.To confirm the message is being published on theaddress_booktopic, open another terminal, source the workspace, and calltopicecho:LinuxmacOSWindowssource install/setup.bashros2 topic echo /address_book. install/setup.bashros2 topic echo /address_bookcall install/setup.batros2 topic echo /address_bookOr using Powershell:install/setup.ps1ros2 topic echo /address_bookWe won’t create a subscriber in this tutorial, but you can try to write one yourself for practice (useWriting a simple publisher and subscriber (C++)to help).5 (Extra) Use an existing interface definitionNoteYou can use an existing interface definition in a new


key: chroma:document
string_value:
can use an existing interface definition in a new interface definition. For example, let’s say there is a message namedContact.msgthat belongs to an existing ROS 2 package namedrosidl_tutorials_msgs. Assume that its definition is identical to our custom-madeAddressBook.msginterface from earlier.In that case you could have definedAddressBook.msg(an interface in the packagewithyour nodes) as typeContact(an interface in aseparatepackage). You could even defineAddressBook.msgas anarrayof typeContact, like so:rosidl_tutorials_msgs/Contact[]address_bookTo generate this message you would need to declare a dependency onContact.msg'spackage,rosidl_tutorials_msgs, inpackage.xml:<build_depend>rosidl_tutorials_msgs</build_depend><exec_depend>rosidl_tutorials_msgs</exec_depend>And inCMakeLists.txt:find_package(rosidl_tutorials_msgsREQUIRED)rosidl_generate_interfaces(${PROJECT_NAME}${msg_files}DEPENDENCIESrosidl_tutorials_msgs)You would also need to include the header ofContact.msgin your publisher node in order to be


key: chroma:document
string_value:
the header ofContact.msgin your publisher node in order to be able to addcontactsto youraddress_book.#include"rosidl_tutorials_msgs/msg/contact.hpp"You could change the callback to something like this:autopublish_msg=[this]()->void{automsg=std::make_shared<more_interfaces::msg::AddressBook>();{rosidl_tutorials_msgs::msg::Contactcontact;contact.first_name="John";contact.last_name="Doe";contact.phone_number="1234567890";contact.phone_type=message.PHONE_TYPE_MOBILE;msg->address_book.push_back(contact);}{rosidl_tutorials_msgs::msg::Contactcontact;contact.first_name="Jane";contact.last_name="Doe";contact.phone_number="4254242424";contact.phone_type=message.PHONE_TYPE_HOME;msg->address_book.push_back(contact);}std::cout<<"Publishing address book:"<<std::endl;for(autocontact:msg->address_book){std::cout<<"First:"<<contact.first_name<<"  Last:"<<contact.last_name<<std::endl;}address_book_publisher_->publish(*msg);};Building and running these changes would show the msg defined as expected, as well as the array of


key: chroma:document
string_value:
would show the msg defined as expected, as well as the array of msgs defined above.SummaryIn this tutorial, you tried out different field types for defining interfaces, then built an interface in the same package where it’s being used.You also learned how to use another interface as a field type, as well as thepackage.xml,CMakeLists.txt, and#includestatements necessary for utilizing that feature.Next stepsNext you will create a simple ROS 2 package with a custom parameter that you will learn to set from a launch file. Again, you can choose to write it in eitherC++orPython.Related contentThere areseveral design articleson ROS 2 interfaces and the IDL (interface definition language).


key: chroma:document
string_value:
Code Examples:

Language: unknown

ros2 pkg create -

build

type ament_cmake -

license Apache

2.0 more_interfacesmkdir more_interfaces/msg

Language: unknown

uint8PHONE_TYPE_HOME=0uint8PHONE_TYPE_WORK=1uint8PHONE_TYPE_MOBILE=2stringfirst_namestringlast_namestringphone_numberuint8phone_type

Language: unknown

<buildtool_depend>rosidl_default_generators</buildtool_depend><exec_depend>rosidl_default_runtime</exec_depend><member_of_group>rosidl_interface_packages</member_of_group>

Language: unknown

find_package(rosidl_default_generatorsREQUIRED)

Language: unknown

set(msg_files"msg/AddressBook.msg")

Language: unknown

rosidl_generate_interfaces(${PROJECT_NAME}${msg_files})

Language: unknown

ament_export_dependencies(rosidl_default_runtime)

Language: unknown


key: chroma:document
string_value:
Language: unknown

#include<chrono>#include<memory>#include"rclcpp/rclcpp.hpp"#include"more_interfaces/msg/address_book.hpp"usingnamespacestd::chrono_literals;classAddressBookPublisher:publicrclcpp::Node{public:AddressBookPublisher():Node("address_book_publisher"){address_book_publisher_=this

>create_publisher<more_interfaces::msg::AddressBook>("address_book",10);autopublish_msg=[this]()

>void{automessage=more_interfaces::msg::AddressBook();message.first_name="John";message.last_name="Doe";message.phone_number="1234567890";message.phone_type=message.PHONE_TYPE_MOBILE;std::cout<<"Publishing Contact\nFirst:"<<message.first_name<<"  Last:"<<message.last_name<<std::endl;this

>address_book_publisher_

>publish(message);};timer_=this

>create_wall_timer(1s,publish_msg);}private:rclcpp::Publisher<more_interfaces::msg::AddressBook>::SharedPtraddress_book_publisher_;rclcpp::TimerBase::SharedPtrtimer_;};intmain(intargc,char


key: chroma:document
string_value:
argv[]){rclcpp::init(argc,argv);rclcpp::spin(std::make_shared<AddressBookPublisher>());rclcpp::shutdown();return0;}

Language: unknown

#include"more_interfaces/msg/address_book.hpp"

Language: unknown

usingnamespacestd::chrono_literals;classAddressBookPublisher:publicrclcpp::Node{public:AddressBookPublisher():Node("address_book_publisher"){address_book_publisher_=this

>create_publisher<more_interfaces::msg::AddressBook>("address_book");

Language: unknown

autopublish_msg=[this]()

>void{

Language: unknown

automessage=more_interfaces::msg::AddressBook();

Language: unknown

message.first_name="John";message.last_name="Doe";message.phone_number="1234567890";message.phone_type=message.PHONE_TYPE_MOBILE;

Language: unknown

std::cout<<"Publishing Contact\nFirst:"<<message.first_name<<"  Last:"<<message.last_name<<std::endl;this

>address_book_publisher_

>publish(message);

Language: unknown

timer_=this

>create_wall_timer(1s,publish_msg);

Language: unknown


key: chroma:document
string_value:
>create_wall_timer(1s,publish_msg);

Language: unknown

find_package(rclcppREQUIRED)add_executable(publish_address_booksrc/publish_address_book.cpp)ament_target_dependencies(publish_address_bookrclcpp)install(TARGETSpublish_address_bookDESTINATIONlib/${PROJECT_NAME})

Language: unknown

rosidl_get_typesupport_target(cpp_typesupport_target${PROJECT_NAME}rosidl_typesupport_cpp)target_link_libraries(publish_address_book"${cpp_typesupport_target}")

Language: unknown

cd ~/ros2_wscolcon build -

packages

up

to more_interfaces

Language: unknown

cd ~/ros2_wscolcon build -

packages

up

to more_interfaces

Language: unknown

cd /ros2_wscolcon build -

merge

install -

packages

up

to more_interfaces

Language: unknown source install/local_setup.bashros2 run more_interfaces publish_address_book

Language: unknown . install/local_setup.bashros2 run more_interfaces publish_address_book

Language: unknown call install/local_setup.batros2 run more_interfaces publish_address_book

Language: unknown


key: chroma:document
string_value:
Language: unknown

install/local_setup.ps1ros2 run more_interfaces publish_address_book

Language: unknown source install/setup.bashros2 topic echo /address_book

Language: unknown . install/setup.bashros2 topic echo /address_book

Language: unknown call install/setup.batros2 topic echo /address_book

Language: unknown

install/setup.ps1ros2 topic echo /address_book

Language: unknown

rosidl_tutorials_msgs/Contact[]address_book

Language: unknown

<build_depend>rosidl_tutorials_msgs</build_depend><exec_depend>rosidl_tutorials_msgs</exec_depend>

Language: unknown

find_package(rosidl_tutorials_msgsREQUIRED)rosidl_generate_interfaces(${PROJECT_NAME}${msg_files}DEPENDENCIESrosidl_tutorials_msgs)

Language: unknown

#include"rosidl_tutorials_msgs/msg/contact.hpp"

Language: unknown

autopublish_msg=[this]()


key: chroma:document
string_value:
Language: unknown

autopublish_msg=[this]()

>void{automsg=std::make_shared<more_interfaces::msg::AddressBook>();{rosidl_tutorials_msgs::msg::Contactcontact;contact.first_name="John";contact.last_name="Doe";contact.phone_number="1234567890";contact.phone_type=message.PHONE_TYPE_MOBILE;msg

>address_book.push_back(contact);}{rosidl_tutorials_msgs::msg::Contactcontact;contact.first_name="Jane";contact.last_name="Doe";contact.phone_number="4254242424";contact.phone_type=message.PHONE_TYPE_HOME;msg

>address_book.push_back(contact);}std::cout<<"Publishing address book:"<<std::endl;for(autocontact:msg

>address_book){std::cout<<"First:"<<contact.first_name<<"  Last:"<<contact.last_name<<std::endl;}address_book_publisher_

>publish(

msg);};


key: chroma:document
string_value:
Title: Writing an action server and client (C++) URL: https://docs.ros.org/en/jazzy/Tutorials/Intermediate/Writing-an-Action-Server-Client/Cpp.html Section: Installation --------------------------------------------------------------------------------


key: chroma:document
string_value:
Writing an action server and client (C++)Goal:Implement an action server and client in C++.Tutorial level:IntermediateTime:15 minutesContentsBackgroundPrerequisitesTasks1 Creating the custom_action_cpp package2 Writing an action server3 Writing an action clientSummaryRelated contentBackgroundActions are a form of asynchronous communication in ROS.Action clientssend goal requests toaction servers.Action serverssend goal feedback and results toaction clients.PrerequisitesYou will need thecustom_action_interfacespackage and theFibonacci.actioninterface defined in the previous tutorial,Creating an action.Tasks1 Creating the custom_action_cpp packageAs we saw in theCreating a packagetutorial, we need to create a new package to hold our C++ and supporting code.1.1 Creating the custom_action_cpp packageGo into the action workspace you created in theprevious tutorial(remember to source the workspace), and create a new package for the C++ action server:LinuxmacOSWindowscd~/ros2_ws/src


key: chroma:document
string_value:
for the C++ action server:LinuxmacOSWindowscd~/ros2_ws/src ros2pkgcreate--dependenciescustom_action_interfacesrclcpprclcpp_actionrclcpp_components--licenseApache-2.0--custom_action_cppcd~/ros2_ws/src ros2pkgcreate--dependenciescustom_action_interfacesrclcpprclcpp_actionrclcpp_components--licenseApache-2.0--custom_action_cppcd\ros2_ws\src ros2pkgcreate--dependenciescustom_action_interfacesrclcpprclcpp_actionrclcpp_components--licenseApache-2.0--custom_action_cpp1.2 Adding in visibility controlIn order to make the package compile and work on Windows, we need to add in some “visibility control”. For more details, seeWindows Symbol Visibility in the Windows Tips and Tricks document.Open upcustom_action_cpp/include/custom_action_cpp/visibility_control.h, and put the following code in:#ifndef CUSTOM_ACTION_CPP__VISIBILITY_CONTROL_H_#define CUSTOM_ACTION_CPP__VISIBILITY_CONTROL_H_#ifdef __cplusplusextern"C"{#endif// This logic was borrowed (then namespaced) from the examples on the gcc wiki://


key: chroma:document
string_value:
(then namespaced) from the examples on the gcc wiki://     https://gcc.gnu.org/wiki/Visibility#if defined _WIN32 || defined __CYGWIN__#ifdef __GNUC__#define CUSTOM_ACTION_CPP_EXPORT __attribute__ ((dllexport))#define CUSTOM_ACTION_CPP_IMPORT __attribute__ ((dllimport))#else#define CUSTOM_ACTION_CPP_EXPORT __declspec(dllexport)#define CUSTOM_ACTION_CPP_IMPORT __declspec(dllimport)#endif#ifdef CUSTOM_ACTION_CPP_BUILDING_DLL#define CUSTOM_ACTION_CPP_PUBLIC CUSTOM_ACTION_CPP_EXPORT#else#define CUSTOM_ACTION_CPP_PUBLIC CUSTOM_ACTION_CPP_IMPORT#endif#define CUSTOM_ACTION_CPP_PUBLIC_TYPE CUSTOM_ACTION_CPP_PUBLIC#define CUSTOM_ACTION_CPP_LOCAL#else#define CUSTOM_ACTION_CPP_EXPORT __attribute__ ((visibility("default")))#define CUSTOM_ACTION_CPP_IMPORT#if __GNUC__ >= 4#define CUSTOM_ACTION_CPP_PUBLIC __attribute__ ((visibility("default")))#define CUSTOM_ACTION_CPP_LOCAL  __attribute__ ((visibility("hidden")))#else#define CUSTOM_ACTION_CPP_PUBLIC#define CUSTOM_ACTION_CPP_LOCAL#endif#define


key: chroma:document
string_value:
CUSTOM_ACTION_CPP_LOCAL#endif#define CUSTOM_ACTION_CPP_PUBLIC_TYPE#endif#ifdef __cplusplus}#endif#endif// CUSTOM_ACTION_CPP__VISIBILITY_CONTROL_H_2 Writing an action serverLet’s focus on writing an action server that computes the Fibonacci sequence using the action we created in theCreating an actiontutorial.2.1 Writing the action server codeOpen upcustom_action_cpp/src/fibonacci_action_server.cpp, and put the following code


key: chroma:document
string_value:
and put the following code in:#include<functional>#include<memory>#include<thread>#include"custom_action_interfaces/action/fibonacci.hpp"#include"rclcpp/rclcpp.hpp"#include"rclcpp_action/rclcpp_action.hpp"#include"rclcpp_components/register_node_macro.hpp"#include"custom_action_cpp/visibility_control.h"namespacecustom_action_cpp{classFibonacciActionServer:publicrclcpp::Node{public:usingFibonacci=custom_action_interfaces::action::Fibonacci;usingGoalHandleFibonacci=rclcpp_action::ServerGoalHandle<Fibonacci>;CUSTOM_ACTION_CPP_PUBLICexplicitFibonacciActionServer(constrclcpp::NodeOptions&options=rclcpp::NodeOptions()):Node("fibonacci_action_server",options){usingnamespacestd::placeholders;autohandle_goal=[this](constrclcpp_action::GoalUUID&uuid,std::shared_ptr<constFibonacci::Goal>goal){RCLCPP_INFO(this->get_logger(),"Received goal request with order


key: chroma:document
string_value:
goal request with order %d",goal->order);(void)uuid;returnrclcpp_action::GoalResponse::ACCEPT_AND_EXECUTE;};autohandle_cancel=[this](conststd::shared_ptr<GoalHandleFibonacci>goal_handle){RCLCPP_INFO(this->get_logger(),"Received request to cancel goal");(void)goal_handle;returnrclcpp_action::CancelResponse::ACCEPT;};autohandle_accepted=[this](conststd::shared_ptr<GoalHandleFibonacci>goal_handle){// this needs to return quickly to avoid blocking the executor,// so we declare a lambda function to be called inside a new threadautoexecute_in_thread=[this,goal_handle](){returnthis->execute(goal_handle);};std::thread{execute_in_thread}.detach();};this->action_server_=rclcpp_action::create_server<Fibonacci>(this,"fibonacci",handle_goal,handle_cancel,handle_accepted);}private:rclcpp_action::Server<Fibonacci>::SharedPtraction_server_;voidexecute(conststd::shared_ptr<GoalHandleFibonacci>goal_handle){RCLCPP_INFO(this->get_logger(),"Executing


key: chroma:document
string_value:
goal");rclcpp::Rateloop_rate(1);constautogoal=goal_handle->get_goal();autofeedback=std::make_shared<Fibonacci::Feedback>();auto&sequence=feedback->partial_sequence;sequence.push_back(0);sequence.push_back(1);autoresult=std::make_shared<Fibonacci::Result>();for(inti=1;(i<goal->order)&&rclcpp::ok();++i){// Check if there is a cancel requestif(goal_handle->is_canceling()){result->sequence=sequence;goal_handle->canceled(result);RCLCPP_INFO(this->get_logger(),"Goal canceled");return;}// Update sequencesequence.push_back(sequence[i]+sequence[i-1]);// Publish feedbackgoal_handle->publish_feedback(feedback);RCLCPP_INFO(this->get_logger(),"Publish feedback");loop_rate.sleep();}// Check if goal is doneif(rclcpp::ok()){result->sequence=sequence;goal_handle->succeed(result);RCLCPP_INFO(this->get_logger(),"Goal succeeded");}};};// class FibonacciActionServer}// namespace custom_action_cppRCLCPP_COMPONENTS_REGISTER_NODE(custom_action_cpp::FibonacciActionServer)The first few lines include all of the headers we need to


key: chroma:document
string_value:
first few lines include all of the headers we need to compile.Next we create a class that is a derived class ofrclcpp::Node:classFibonacciActionServer:publicrclcpp::NodeThe constructor for theFibonacciActionServerclass initializes the node name asfibonacci_action_server:explicitFibonacciActionServer(constrclcpp::NodeOptions&options=rclcpp::NodeOptions()):Node("fibonacci_action_server",options)The constructor also instantiates a new action server:loop_rate.sleep();}// Check if goal is doneif(rclcpp::ok()){An action server requires 6 things:The templated action type name:Fibonacci.A ROS 2 node to add the action to:this.The action name:'fibonacci'.A callback function for handling goals:handle_goalA callback function for handling cancellation:handle_cancel.A callback function for handling goal accept:handle_accept.The implementation of the various callbacks is done with [lambda expressions](https://en.cppreference.com/w/cpp/language/lambda) within the constructor. Note that all of the callbacks need to return


key: chroma:document
string_value:
the constructor. Note that all of the callbacks need to return quickly, otherwise we risk starving the executor.We start with the callback for handling new goals:autohandle_goal=[this](constrclcpp_action::GoalUUID&uuid,std::shared_ptr<constFibonacci::Goal>goal){RCLCPP_INFO(this->get_logger(),"Received goal request with order %d",goal->order);(void)uuid;returnrclcpp_action::GoalResponse::ACCEPT_AND_EXECUTE;};This implementation just accepts all goals.Next up is the callback for dealing with cancellation:autohandle_cancel=[this](conststd::shared_ptr<GoalHandleFibonacci>goal_handle){RCLCPP_INFO(this->get_logger(),"Received request to cancel goal");(void)goal_handle;returnrclcpp_action::CancelResponse::ACCEPT;};This implementation just tells the client that it accepted the cancellation.The last of the callbacks accepts a new goal and starts processing it:autohandle_accepted=[this](conststd::shared_ptr<GoalHandleFibonacci>goal_handle){// this needs to return quickly to avoid blocking the executor,// so we declare


key: chroma:document
string_value:
return quickly to avoid blocking the executor,// so we declare a lambda function to be called inside a new threadautoexecute_in_thread=[this,goal_handle](){returnthis->execute(goal_handle);};std::thread{execute_in_thread}.detach();};Since the execution is a long-running operation, we spawn off a thread to do the actual work and return fromhandle_acceptedquickly.All further processing and updates are done in theexecutemethod in the new thread:voidexecute(conststd::shared_ptr<GoalHandleFibonacci>goal_handle){RCLCPP_INFO(this->get_logger(),"Executing goal");rclcpp::Rateloop_rate(1);constautogoal=goal_handle->get_goal();autofeedback=std::make_shared<Fibonacci::Feedback>();auto&sequence=feedback->partial_sequence;sequence.push_back(0);sequence.push_back(1);autoresult=std::make_shared<Fibonacci::Result>();for(inti=1;(i<goal->order)&&rclcpp::ok();++i){// Check if there is a cancel requestif(goal_handle->is_canceling()){result->sequence=sequence;goal_handle->canceled(result);RCLCPP_INFO(this->get_logger(),"Goal


key: chroma:document
string_value:
canceled");return;}// Update sequencesequence.push_back(sequence[i]+sequence[i-1]);// Publish feedbackgoal_handle->publish_feedback(feedback);RCLCPP_INFO(this->get_logger(),"Publish feedback");loop_rate.sleep();}// Check if goal is doneif(rclcpp::ok()){result->sequence=sequence;goal_handle->succeed(result);RCLCPP_INFO(this->get_logger(),"Goal succeeded");}};This work thread processes one sequence number of the Fibonacci sequence every second, publishing a feedback update for each step. When it has finished processing, it marks thegoal_handleas succeeded, and quits.We now have a fully functioning action server.  Let’s get it built and running.2.2 Compiling the action serverIn the previous section we put the action server code into place. To get it to compile and run, we need to do a couple of additional things.First we need to setup the CMakeLists.txt so that the action server is compiled. Open upcustom_action_cpp/CMakeLists.txt, and add the following right after


key: chroma:document
string_value:
and add the following right after thefind_packagecalls:add_library(action_serverSHAREDsrc/fibonacci_action_server.cpp)target_include_directories(action_serverPRIVATE$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>$<INSTALL_INTERFACE:include>)target_compile_definitions(action_serverPRIVATE"CUSTOM_ACTION_CPP_BUILDING_DLL")ament_target_dependencies(action_server"custom_action_interfaces""rclcpp""rclcpp_action""rclcpp_components")rclcpp_components_register_node(action_serverPLUGIN"custom_action_cpp::FibonacciActionServer"EXECUTABLEfibonacci_action_server)install(TARGETSaction_serverARCHIVEDESTINATIONlibLIBRARYDESTINATIONlibRUNTIMEDESTINATIONbin)And now we can compile the package.  Go to the top-level of theros2_ws, and run:colconbuildThis should compile the entire workspace, including thefibonacci_action_serverin thecustom_action_cpppackage.2.3 Running the action serverNow that we have the action server built, we can run it. Source the workspace we just built (ros2_ws), and try to run the action


key: chroma:document
string_value:
workspace we just built (ros2_ws), and try to run the action server:ros2runcustom_action_cppfibonacci_action_server3 Writing an action client3.1 Writing the action client codeOpen upcustom_action_cpp/src/fibonacci_action_client.cpp, and put the following code


key: chroma:document
string_value:
and put the following code in:#include<functional>#include<future>#include<memory>#include<string>#include<sstream>#include"custom_action_interfaces/action/fibonacci.hpp"#include"rclcpp/rclcpp.hpp"#include"rclcpp_action/rclcpp_action.hpp"#include"rclcpp_components/register_node_macro.hpp"namespacecustom_action_cpp{classFibonacciActionClient:publicrclcpp::Node{public:usingFibonacci=custom_action_interfaces::action::Fibonacci;usingGoalHandleFibonacci=rclcpp_action::ClientGoalHandle<Fibonacci>;explicitFibonacciActionClient(constrclcpp::NodeOptions&options):Node("fibonacci_action_client",options){this->client_ptr_=rclcpp_action::create_client<Fibonacci>(this,"fibonacci");autotimer_callback_lambda=[this](){returnthis->send_goal();};this->timer_=this->create_wall_timer(std::chrono::milliseconds(500),timer_callback_lambda);}voidsend_goal(){usingnamespacestd::placeholders;this->timer_->cancel();if(!this->client_ptr_->wait_for_action_server()){RCLCPP_ERROR(this->get_logger(),"Action server not available after


key: chroma:document
string_value:
server not available after waiting");rclcpp::shutdown();}autogoal_msg=Fibonacci::Goal();goal_msg.order=10;RCLCPP_INFO(this->get_logger(),"Sending goal");autosend_goal_options=rclcpp_action::Client<Fibonacci>::SendGoalOptions();send_goal_options.goal_response_callback=[this](constGoalHandleFibonacci::SharedPtr&goal_handle){if(!goal_handle){RCLCPP_ERROR(this->get_logger(),"Goal was rejected by server");}else{RCLCPP_INFO(this->get_logger(),"Goal accepted by server, waiting for result");}};send_goal_options.feedback_callback=[this](GoalHandleFibonacci::SharedPtr,conststd::shared_ptr<constFibonacci::Feedback>feedback){std::stringstreamss;ss<<"Next number in sequence received: ";for(autonumber:feedback->partial_sequence){ss<<number<<"


key: chroma:document
string_value:
";for(autonumber:feedback->partial_sequence){ss<<number<<" ";}RCLCPP_INFO(this->get_logger(),ss.str().c_str());};send_goal_options.result_callback=[this](constGoalHandleFibonacci::WrappedResult&result){switch(result.code){caserclcpp_action::ResultCode::SUCCEEDED:break;caserclcpp_action::ResultCode::ABORTED:RCLCPP_ERROR(this->get_logger(),"Goal was aborted");return;caserclcpp_action::ResultCode::CANCELED:RCLCPP_ERROR(this->get_logger(),"Goal was canceled");return;default:RCLCPP_ERROR(this->get_logger(),"Unknown result code");return;}std::stringstreamss;ss<<"Result received: ";for(autonumber:result.result->sequence){ss<<number<<" ";}RCLCPP_INFO(this->get_logger(),ss.str().c_str());rclcpp::shutdown();};this->client_ptr_->async_send_goal(goal_msg,send_goal_options);}private:rclcpp_action::Client<Fibonacci>::SharedPtrclient_ptr_;rclcpp::TimerBase::SharedPtrtimer_;};// class FibonacciActionClient}// namespace custom_action_cppRCLCPP_COMPONENTS_REGISTER_NODE(custom_action_cpp::FibonacciActionClient)The first few


key: chroma:document
string_value:
first few lines include all of the headers we need to compile.Next we create a class that is a derived class ofrclcpp::Node:classFibonacciActionClient:publicrclcpp::NodeThe constructor for theFibonacciActionClientclass initializes the node name asfibonacci_action_client:explicitFibonacciActionClient(constrclcpp::NodeOptions&options):Node("fibonacci_action_client",options)The constructor also instantiates a new action client:this->client_ptr_=rclcpp_action::create_client<Fibonacci>(this,"fibonacci");An action client requires 3 things:The templated action type name:Fibonacci.A ROS 2 node to add the action client to:this.The action name:'fibonacci'.We also instantiate a ROS timer that will kick off the one and only call tosend_goal:autotimer_callback_lambda=[this](){returnthis->send_goal();};this->timer_=this->create_wall_timer(std::chrono::milliseconds(500),timer_callback_lambda);When the timer expires, it will


key: chroma:document
string_value:
the timer expires, it will callsend_goal:voidsend_goal(){usingnamespacestd::placeholders;this->timer_->cancel();if(!this->client_ptr_->wait_for_action_server()){RCLCPP_ERROR(this->get_logger(),"Action server not available after waiting");rclcpp::shutdown();}autogoal_msg=Fibonacci::Goal();goal_msg.order=10;RCLCPP_INFO(this->get_logger(),"Sending goal");autosend_goal_options=rclcpp_action::Client<Fibonacci>::SendGoalOptions();send_goal_options.goal_response_callback=[this](constGoalHandleFibonacci::SharedPtr&goal_handle){if(!goal_handle){RCLCPP_ERROR(this->get_logger(),"Goal was rejected by server");}else{RCLCPP_INFO(this->get_logger(),"Goal accepted by server, waiting for result");}};send_goal_options.feedback_callback=[this](GoalHandleFibonacci::SharedPtr,conststd::shared_ptr<constFibonacci::Feedback>feedback){std::stringstreamss;ss<<"Next number in sequence received: ";for(autonumber:feedback->partial_sequence){ss<<number<<"


key: chroma:document
string_value:
";for(autonumber:feedback->partial_sequence){ss<<number<<" ";}RCLCPP_INFO(this->get_logger(),ss.str().c_str());};send_goal_options.result_callback=[this](constGoalHandleFibonacci::WrappedResult&result){switch(result.code){caserclcpp_action::ResultCode::SUCCEEDED:break;caserclcpp_action::ResultCode::ABORTED:RCLCPP_ERROR(this->get_logger(),"Goal was aborted");return;caserclcpp_action::ResultCode::CANCELED:RCLCPP_ERROR(this->get_logger(),"Goal was canceled");return;default:RCLCPP_ERROR(this->get_logger(),"Unknown result code");return;}std::stringstreamss;ss<<"Result received: ";for(autonumber:result.result->sequence){ss<<number<<" ";}RCLCPP_INFO(this->get_logger(),ss.str().c_str());rclcpp::shutdown();};this->client_ptr_->async_send_goal(goal_msg,send_goal_options);}This function does the following:Cancels the timer (so it is only called once).Waits for the action server to come up.Instantiates a newFibonacci::Goal.Sets the response, feedback, and result callbacks.Sends the goal to the server.When the server


key: chroma:document
string_value:
result callbacks.Sends the goal to the server.When the server receives and accepts the goal, it will send a response to the client. That response is handled bygoal_response_callback:send_goal_options.goal_response_callback=[this](constGoalHandleFibonacci::SharedPtr&goal_handle){if(!goal_handle){RCLCPP_ERROR(this->get_logger(),"Goal was rejected by server");}else{RCLCPP_INFO(this->get_logger(),"Goal accepted by server, waiting for result");}};Assuming the goal was accepted by the server, it will start processing. Any feedback to the client will be handled by thefeedback_callback:send_goal_options.feedback_callback=[this](GoalHandleFibonacci::SharedPtr,conststd::shared_ptr<constFibonacci::Feedback>feedback){std::stringstreamss;ss<<"Next number in sequence received: ";for(autonumber:feedback->partial_sequence){ss<<number<<" ";}RCLCPP_INFO(this->get_logger(),ss.str().c_str());};When the server is finished processing, it will return a result to the client. The result is handled by


key: chroma:document
string_value:
it will return a result to the client. The result is handled by theresult_callback:send_goal_options.result_callback=[this](constGoalHandleFibonacci::WrappedResult&result){switch(result.code){caserclcpp_action::ResultCode::SUCCEEDED:break;caserclcpp_action::ResultCode::ABORTED:RCLCPP_ERROR(this->get_logger(),"Goal was aborted");return;caserclcpp_action::ResultCode::CANCELED:RCLCPP_ERROR(this->get_logger(),"Goal was canceled");return;default:RCLCPP_ERROR(this->get_logger(),"Unknown result code");return;}std::stringstreamss;ss<<"Result received: ";for(autonumber:result.result->sequence){ss<<number<<" ";}RCLCPP_INFO(this->get_logger(),ss.str().c_str());rclcpp::shutdown();};We now have a fully functioning action client.  Let’s get it built and running.3.2 Compiling the action clientIn the previous section we put the action client code into place. To get it to compile and run, we need to do a couple of additional things.First we need to setup the CMakeLists.txt so that the action client is compiled. Open


key: chroma:document
string_value:
the CMakeLists.txt so that the action client is compiled. Open upcustom_action_cpp/CMakeLists.txt, and add the following right after thefind_packagecalls:add_library(action_clientSHAREDsrc/fibonacci_action_client.cpp)target_include_directories(action_clientPRIVATE$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>$<INSTALL_INTERFACE:include>)target_compile_definitions(action_clientPRIVATE"CUSTOM_ACTION_CPP_BUILDING_DLL")ament_target_dependencies(action_client"custom_action_interfaces""rclcpp""rclcpp_action""rclcpp_components")rclcpp_components_register_node(action_clientPLUGIN"custom_action_cpp::FibonacciActionClient"EXECUTABLEfibonacci_action_client)install(TARGETSaction_clientARCHIVEDESTINATIONlibLIBRARYDESTINATIONlibRUNTIMEDESTINATIONbin)And now we can compile the package.  Go to the top-level of theros2_ws, and run:colconbuildThis should compile the entire workspace, including thefibonacci_action_clientin thecustom_action_cpppackage.3.3 Running the action clientNow that we have the action client


key: chroma:document
string_value:
Running the action clientNow that we have the action client built, we can run it. First make sure that an action server is running in a separate terminal. Now source the workspace we just built (ros2_ws), and try to run the action client:ros2runcustom_action_cppfibonacci_action_clientYou should see logged messages for the goal being accepted, feedback being printed, and the final result.SummaryIn this tutorial, you put together a C++ action server and action client line by line, and configured them to exchange goals, feedback, and results.Related contentThere are several ways you could write an action server and client in C++; check out theminimal_action_serverandminimal_action_clientpackages in theros2/examplesrepo.For more detailed information about ROS actions, please refer to thedesign article.


key: chroma:document
string_value:
Code Examples:

Language: unknown

cd~/ros2_ws/src

ros2pkgcreate-

dependenciescustom_action_interfacesrclcpprclcpp_actionrclcpp_components-

licenseApache

2.0-

custom_action_cpp

Language: unknown

cd~/ros2_ws/src

ros2pkgcreate-

dependenciescustom_action_interfacesrclcpprclcpp_actionrclcpp_components-

licenseApache

2.0-

custom_action_cpp

Language: unknown

cd\ros2_ws\src

ros2pkgcreate-

dependenciescustom_action_interfacesrclcpprclcpp_actionrclcpp_components-

licenseApache

2.0-

custom_action_cpp


key: chroma:document
string_value:
Language: unknown #ifndef CUSTOM_ACTION_CPP__VISIBILITY_CONTROL_H_#define CUSTOM_ACTION_CPP__VISIBILITY_CONTROL_H_#ifdef __cplusplusextern"C"{#endif// This logic was borrowed (then namespaced) from the examples on the gcc wiki://     https://gcc.gnu.org/wiki/Visibility#if defined _WIN32 || defined __CYGWIN__#ifdef __GNUC__#define CUSTOM_ACTION_CPP_EXPORT __attribute__ ((dllexport))#define CUSTOM_ACTION_CPP_IMPORT __attribute__ ((dllimport))#else#define CUSTOM_ACTION_CPP_EXPORT __declspec(dllexport)#define CUSTOM_ACTION_CPP_IMPORT __declspec(dllimport)#endif#ifdef CUSTOM_ACTION_CPP_BUILDING_DLL#define CUSTOM_ACTION_CPP_PUBLIC CUSTOM_ACTION_CPP_EXPORT#else#define CUSTOM_ACTION_CPP_PUBLIC CUSTOM_ACTION_CPP_IMPORT#endif#define CUSTOM_ACTION_CPP_PUBLIC_TYPE CUSTOM_ACTION_CPP_PUBLIC#define CUSTOM_ACTION_CPP_LOCAL#else#define CUSTOM_ACTION_CPP_EXPORT __attribute__ ((visibility("default")))#define CUSTOM_ACTION_CPP_IMPORT#if __GNUC__ >= 4#define CUSTOM_ACTION_CPP_PUBLIC __attribute__ ((visibility("default")))#define


key: chroma:document
string_value:
__attribute__ ((visibility("default")))#define CUSTOM_ACTION_CPP_LOCAL  __attribute__ ((visibility("hidden")))#else#define CUSTOM_ACTION_CPP_PUBLIC#define CUSTOM_ACTION_CPP_LOCAL#endif#define CUSTOM_ACTION_CPP_PUBLIC_TYPE#endif#ifdef __cplusplus}#endif#endif// CUSTOM_ACTION_CPP__VISIBILITY_CONTROL_H_


key: chroma:document
string_value:
Language: unknown #include<functional>#include<memory>#include<thread>#include"custom_action_interfaces/action/fibonacci.hpp"#include"rclcpp/rclcpp.hpp"#include"rclcpp_action/rclcpp_action.hpp"#include"rclcpp_components/register_node_macro.hpp"#include"custom_action_cpp/visibility_control.h"namespacecustom_action_cpp{classFibonacciActionServer:publicrclcpp::Node{public:usingFibonacci=custom_action_interfaces::action::Fibonacci;usingGoalHandleFibonacci=rclcpp_action::ServerGoalHandle<Fibonacci>;CUSTOM_ACTION_CPP_PUBLICexplicitFibonacciActionServer(constrclcpp::NodeOptions&options=rclcpp::NodeOptions()):Node("fibonacci_action_server",options){usingnamespacestd::placeholders;autohandle_goal=[this](constrclcpp_action::GoalUUID&uuid,std::shared_ptr<constFibonacci::Goal>goal){RCLCPP_INFO(this->get_logger(),"Received goal request with order


key: chroma:document
string_value:
goal");rclcpp::Rateloop_rate(1);constautogoal=goal_handle->get_goal();autofeedback=std::make_shared<Fibonacci::Feedback>();auto&sequence=feedback->partial_sequence;sequence.push_back(0);sequence.push_back(1);autoresult=std::make_shared<Fibonacci::Result>();for(inti=1;(i<goal->order)&&rclcpp::ok();++i){// Check if there is a cancel requestif(goal_handle->is_canceling()){result->sequence=sequence;goal_handle->canceled(result);RCLCPP_INFO(this->get_logger(),"Goal canceled");return;}// Update sequencesequence.push_back(sequence[i]+sequence[i-1]);// Publish feedbackgoal_handle->publish_feedback(feedback);RCLCPP_INFO(this->get_logger(),"Publish feedback");loop_rate.sleep();}// Check if goal is doneif(rclcpp::ok()){result->sequence=sequence;goal_handle->succeed(result);RCLCPP_INFO(this->get_logger(),"Goal succeeded");}};};// class FibonacciActionServer}// namespace custom_action_cppRCLCPP_COMPONENTS_REGISTER_NODE(custom_action_cpp::FibonacciActionServer)


key: chroma:document
string_value:
Language: unknown

classFibonacciActionServer:publicrclcpp::Node

Language: unknown

explicitFibonacciActionServer(constrclcpp::NodeOptions&options=rclcpp::NodeOptions()):Node("fibonacci_action_server",options)

Language: unknown loop_rate.sleep();}// Check if goal is doneif(rclcpp::ok()){

Language: unknown autohandle_goal=[this](constrclcpp_action::GoalUUID&uuid,std::shared_ptr<constFibonacci::Goal>goal){RCLCPP_INFO(this->get_logger(),"Received goal request with order %d",goal->order);(void)uuid;returnrclcpp_action::GoalResponse::ACCEPT_AND_EXECUTE;};

Language: unknown autohandle_cancel=[this](conststd::shared_ptr<GoalHandleFibonacci>goal_handle){RCLCPP_INFO(this->get_logger(),"Received request to cancel goal");(void)goal_handle;returnrclcpp_action::CancelResponse::ACCEPT;};


key: chroma:document
string_value:
Language: unknown autohandle_accepted=[this](conststd::shared_ptr<GoalHandleFibonacci>goal_handle){// this needs to return quickly to avoid blocking the executor,// so we declare a lambda function to be called inside a new threadautoexecute_in_thread=[this,goal_handle](){returnthis->execute(goal_handle);};std::thread{execute_in_thread}.detach();};


key: chroma:document
string_value:
Language: unknown voidexecute(conststd::shared_ptr<GoalHandleFibonacci>goal_handle){RCLCPP_INFO(this->get_logger(),"Executing goal");rclcpp::Rateloop_rate(1);constautogoal=goal_handle->get_goal();autofeedback=std::make_shared<Fibonacci::Feedback>();auto&sequence=feedback->partial_sequence;sequence.push_back(0);sequence.push_back(1);autoresult=std::make_shared<Fibonacci::Result>();for(inti=1;(i<goal->order)&&rclcpp::ok();++i){// Check if there is a cancel requestif(goal_handle->is_canceling()){result->sequence=sequence;goal_handle->canceled(result);RCLCPP_INFO(this->get_logger(),"Goal canceled");return;}// Update sequencesequence.push_back(sequence[i]+sequence[i-1]);// Publish feedbackgoal_handle->publish_feedback(feedback);RCLCPP_INFO(this->get_logger(),"Publish feedback");loop_rate.sleep();}// Check if goal is doneif(rclcpp::ok()){result->sequence=sequence;goal_handle->succeed(result);RCLCPP_INFO(this->get_logger(),"Goal succeeded");}};

Language: unknown


key: chroma:document
string_value:
Language: unknown

add_library(action_serverSHAREDsrc/fibonacci_action_server.cpp)target_include_directories(action_serverPRIVATE$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>$<INSTALL_INTERFACE:include>)target_compile_definitions(action_serverPRIVATE"CUSTOM_ACTION_CPP_BUILDING_DLL")ament_target_dependencies(action_server"custom_action_interfaces""rclcpp""rclcpp_action""rclcpp_components")rclcpp_components_register_node(action_serverPLUGIN"custom_action_cpp::FibonacciActionServer"EXECUTABLEfibonacci_action_server)install(TARGETSaction_serverARCHIVEDESTINATIONlibLIBRARYDESTINATIONlibRUNTIMEDESTINATIONbin)

Language: unknown

colconbuild

Language: unknown

ros2runcustom_action_cppfibonacci_action_server


key: chroma:document
string_value:
Language: unknown #include<functional>#include<future>#include<memory>#include<string>#include<sstream>#include"custom_action_interfaces/action/fibonacci.hpp"#include"rclcpp/rclcpp.hpp"#include"rclcpp_action/rclcpp_action.hpp"#include"rclcpp_components/register_node_macro.hpp"namespacecustom_action_cpp{classFibonacciActionClient:publicrclcpp::Node{public:usingFibonacci=custom_action_interfaces::action::Fibonacci;usingGoalHandleFibonacci=rclcpp_action::ClientGoalHandle<Fibonacci>;explicitFibonacciActionClient(constrclcpp::NodeOptions&options):Node("fibonacci_action_client",options){this->client_ptr_=rclcpp_action::create_client<Fibonacci>(this,"fibonacci");autotimer_callback_lambda=[this](){returnthis->send_goal();};this->timer_=this->create_wall_timer(std::chrono::milliseconds(500),timer_callback_lambda);}voidsend_goal(){usingnamespacestd::placeholders;this->timer_->cancel();if(!this->client_ptr_->wait_for_action_server()){RCLCPP_ERROR(this->get_logger(),"Action server not available after


key: chroma:document
string_value:
";for(autonumber:feedback->partial_sequence){ss<<number<<" ";}RCLCPP_INFO(this->get_logger(),ss.str().c_str());};send_goal_options.result_callback=[this](constGoalHandleFibonacci::WrappedResult&result){switch(result.code){caserclcpp_action::ResultCode::SUCCEEDED:break;caserclcpp_action::ResultCode::ABORTED:RCLCPP_ERROR(this->get_logger(),"Goal was aborted");return;caserclcpp_action::ResultCode::CANCELED:RCLCPP_ERROR(this->get_logger(),"Goal was canceled");return;default:RCLCPP_ERROR(this->get_logger(),"Unknown result code");return;}std::stringstreamss;ss<<"Result received: ";for(autonumber:result.result->sequence){ss<<number<<" ";}RCLCPP_INFO(this->get_logger(),ss.str().c_str());rclcpp::shutdown();};this->client_ptr_->async_send_goal(goal_msg,send_goal_options);}private:rclcpp_action::Client<Fibonacci>::SharedPtrclient_ptr_;rclcpp::TimerBase::SharedPtrtimer_;};// class FibonacciActionClient}// namespace custom_action_cppRCLCPP_COMPONENTS_REGISTER_NODE(custom_action_cpp::FibonacciActionClient)


key: chroma:document
string_value:
Language: unknown

classFibonacciActionClient:publicrclcpp::Node

Language: unknown

explicitFibonacciActionClient(constrclcpp::NodeOptions&options):Node("fibonacci_action_client",options)

Language: unknown

this

>client_ptr_=rclcpp_action::create_client<Fibonacci>(this,"fibonacci");

Language: unknown

autotimer_callback_lambda=[this](){returnthis

>send_goal();};this

>timer_=this

>create_wall_timer(std::chrono::milliseconds(500),timer_callback_lambda);


key: chroma:document
string_value:
Language: unknown voidsend_goal(){usingnamespacestd::placeholders;this->timer_->cancel();if(!this->client_ptr_->wait_for_action_server()){RCLCPP_ERROR(this->get_logger(),"Action server not available after waiting");rclcpp::shutdown();}autogoal_msg=Fibonacci::Goal();goal_msg.order=10;RCLCPP_INFO(this->get_logger(),"Sending goal");autosend_goal_options=rclcpp_action::Client<Fibonacci>::SendGoalOptions();send_goal_options.goal_response_callback=[this](constGoalHandleFibonacci::SharedPtr&goal_handle){if(!goal_handle){RCLCPP_ERROR(this->get_logger(),"Goal was rejected by server");}else{RCLCPP_INFO(this->get_logger(),"Goal accepted by server, waiting for result");}};send_goal_options.feedback_callback=[this](GoalHandleFibonacci::SharedPtr,conststd::shared_ptr<constFibonacci::Feedback>feedback){std::stringstreamss;ss<<"Next number in sequence received: ";for(autonumber:feedback->partial_sequence){ss<<number<<"


key: chroma:document
string_value:
";for(autonumber:feedback->partial_sequence){ss<<number<<" ";}RCLCPP_INFO(this->get_logger(),ss.str().c_str());};send_goal_options.result_callback=[this](constGoalHandleFibonacci::WrappedResult&result){switch(result.code){caserclcpp_action::ResultCode::SUCCEEDED:break;caserclcpp_action::ResultCode::ABORTED:RCLCPP_ERROR(this->get_logger(),"Goal was aborted");return;caserclcpp_action::ResultCode::CANCELED:RCLCPP_ERROR(this->get_logger(),"Goal was canceled");return;default:RCLCPP_ERROR(this->get_logger(),"Unknown result code");return;}std::stringstreamss;ss<<"Result received: ";for(autonumber:result.result->sequence){ss<<number<<" ";}RCLCPP_INFO(this->get_logger(),ss.str().c_str());rclcpp::shutdown();};this->client_ptr_->async_send_goal(goal_msg,send_goal_options);}


key: chroma:document
string_value:
Language: unknown send_goal_options.goal_response_callback=[this](constGoalHandleFibonacci::SharedPtr&goal_handle){if(!goal_handle){RCLCPP_ERROR(this->get_logger(),"Goal was rejected by server");}else{RCLCPP_INFO(this->get_logger(),"Goal accepted by server, waiting for result");}};

Language: unknown send_goal_options.feedback_callback=[this](GoalHandleFibonacci::SharedPtr,conststd::shared_ptr<constFibonacci::Feedback>feedback){std::stringstreamss;ss<<"Next number in sequence received: ";for(autonumber:feedback->partial_sequence){ss<<number<<" ";}RCLCPP_INFO(this->get_logger(),ss.str().c_str());};


key: chroma:document
string_value:
Language: unknown send_goal_options.result_callback=[this](constGoalHandleFibonacci::WrappedResult&result){switch(result.code){caserclcpp_action::ResultCode::SUCCEEDED:break;caserclcpp_action::ResultCode::ABORTED:RCLCPP_ERROR(this->get_logger(),"Goal was aborted");return;caserclcpp_action::ResultCode::CANCELED:RCLCPP_ERROR(this->get_logger(),"Goal was canceled");return;default:RCLCPP_ERROR(this->get_logger(),"Unknown result code");return;}std::stringstreamss;ss<<"Result received: ";for(autonumber:result.result->sequence){ss<<number<<" ";}RCLCPP_INFO(this->get_logger(),ss.str().c_str());rclcpp::shutdown();};

Language: unknown


key: chroma:document
string_value:
Language: unknown

add_library(action_clientSHAREDsrc/fibonacci_action_client.cpp)target_include_directories(action_clientPRIVATE$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>$<INSTALL_INTERFACE:include>)target_compile_definitions(action_clientPRIVATE"CUSTOM_ACTION_CPP_BUILDING_DLL")ament_target_dependencies(action_client"custom_action_interfaces""rclcpp""rclcpp_action""rclcpp_components")rclcpp_components_register_node(action_clientPLUGIN"custom_action_cpp::FibonacciActionClient"EXECUTABLEfibonacci_action_client)install(TARGETSaction_clientARCHIVEDESTINATIONlibLIBRARYDESTINATIONlibRUNTIMEDESTINATIONbin)

Language: unknown

colconbuild

Language: unknown

ros2runcustom_action_cppfibonacci_action_client


key: chroma:document
string_value:
Title: Related Projects

URL: https://docs.ros.org/en/jazzy/Related

Projects.html

Section: Installation

--------------------------------------------------------------------------------


key: chroma:document
string_value:
Related ProjectsGazeboGazebo(gazebosim.org)and its predecessor Gazebo Classic are the first open source choice for 3D physics simulation of ROS-based robots.Large Community ProjectsLarge community projects involve multiple developers from all over the globe and are typically backed by a dedicated working group (cf.Project Governance).ros2_control(control.ros.org): Flexible framework for real-time control of robots implemented with ROS 2.Navigation2(nav2.org): Comprehensive and flexible navigation stack for mobile robots using ROS 2.MoveIt(moveit.ai): A rich platform for building manipulation applications featuring advanced kinematics, motion planning, control, collision checking, and much more.micro-ROS(micro.ros.org): A platform for putting ROS 2 onto microcontrollers, starting at less than 100 kB of RAM.Further Community ProjectsThe global ROS community develops and maintains hundreds of further packages on top of the core ROS 2 stack. Some of them come with their own websites for documentation. Your


key: chroma:document
string_value:
of them come with their own websites for documentation. Your best entry point to discover these works is theROS Index(index.ros.org).Hint for developers:If you maintain aREADME.mdfile in the root of your package folder (which is not necessarily the root of your repository), this file is rendered into the overview page of your package atindex.ros.org. The file may be used for documenting your package and supersedes the package documentation pages in the ROS Wiki from ROS 1. See thefmi_adapter packageas an example.Company-driven ProjectsIntel ROS 2 ProjectsNVIDIA ROS 2 Projects


key: chroma:document
string_value:
Title: Quality guide: ensuring code quality URL: https://docs.ros.org/en/jazzy/The-ROS2-Project/Contributing/Quality-Guide.html Section: Installation --------------------------------------------------------------------------------


key: chroma:document
string_value:
Quality guide: ensuring code qualityTable of ContentsStatic code analysis as part of the ament package buildStatic Thread Safety Analysis via Code AnnotationDynamic analysis (data races & deadlocks)This page gives guidance about how to improve the software quality of ROS 2 packages, focusing on more specific areas than the Quality Practices section of theDeveloper Guide.The sections below intend to address ROS 2 core, application and ecosystem packages and the core client libraries, C++ and Python. The solutions presented are motivated by design and implementation considerations to improve quality attributes like “Reliability”, “Security”, “Maintainability”, “Determinism”, etc. which relate to non-functional requirements.Static code analysis as part of the ament package buildContext:You have developed your C++ production code.You have created a ROS 2 package with build support withament.Problem:Library level static code analysis is not run as part of the package build procedure.Library level static code


