ROS2 Cheatsheet
Install ROS2
- Über
apt install
installieren (wie hier beschrieben) - Dann, wie in binary installation unter
- “Installing and initializing rosdep” und
- bei älteren EOL distros geht
rosdep install --from-paths /opt/ros/eloquent/share
nur, wennrosdep update --include-eol-distros
ausgeführt wurde - “Installing the missing dependencies”
beschrieben, die restlichen dependencies installieren (ohne 2. funktioniert ROS2 nicht!).
- colcon installieren:
sudo apt install python3-colcon-common-extensions
Uninstall ROS2
sudo apt remove ~nros-galactic-* && sudo apt autoremove
ROS2 Packages
Create a Package
$ mkdir -p ~/dev_ws/src
$ cd ~/dev_ws/src
$ source /opt/ros/eloquent/setup.bash
$ ros2 pkg create --build-type ament_cmake --node-name my_node my_package
package.xml
- make sure to fill in the
<description>
,<maintainer>
and<license>
tags in package.xml - Add a new line after the
ament_cmake
buildtool dependency and paste the following dependencies corresponding to your node’s include statements:
<depend>rclcpp</depend>
<depend>std_msgs</depend>
CMakeLists.txt
# Now open the CMakeLists.txt file. Below the existing dependency find_package(ament_cmake REQUIRED), add the lines:
find_package(rclcpp REQUIRED)
find_package(std_msgs REQUIRED)
# After that, add the executable and name it talker so you can run your node using ros2 run:
add_executable(talker src/publisher_member_function.cpp)
ament_target_dependencies(talker rclcpp std_msgs)
# Finally, add the install(TARGETS…) section so ros2 run can find your executable:
install(TARGETS
talker
DESTINATION lib/${PROJECT_NAME})
Adding a node to CMakeLists.txt
E.g. in order to add the node listener
write:
add_executable(listener src/subscriber_member_function.cpp)
ament_target_dependencies(listener rclcpp std_msgs)
install(TARGETS
talker
listener
DESTINATION lib/${PROJECT_NAME})
Build a package
$ rosdep install -i --from-path src --rosdistro eloquent -y
# check output of resdep install: "#All required rosdeps installed successfully"
# in root of ws, here: "dev_ws":
$ cd ~/dev_ws
$ colcon build --packages-select my_package
Run
Important: open a new terminal, separate from the one where you built the workspace (for both, underlay and overlay) !
# source underlay:
$ source /opt/ros/eloquent/setup.bash
$ cd ~/dev_ws
# source overlay:
$ . install/local_setup.bash
Note: sourcing your main ROS 2 installation’s
setup
and then thedev_ws
overlay’slocal_setup
, is the same as just sourcingdev_ws
’ssetup
, because that includes the environment of the underlay it was created in.
$ ros2 run turtlesim turtlesim_node
rosdep
- Packages declare their dependencies in the package.xml file. This command walks through those declarations and installs the ones that are missing.
- Best practice: check for dependencies every time you clone:
- From the root of your workspace (
dev_ws
), run the following command:rosdep install -i --from-path src --rosdistro eloquent -y
(--ignore-src
means to ignore installing dependencies, even if a rosdep key exists, if the package itself is also in the workspace.)
- From the root of your workspace (
- Best practice: check for dependencies every time you clone:
rosdep update
rosdep install
rosdep install --from-paths /opt/ros/eloquent/share --ignore-src --rosdistro eloquent -y --skip-keys "console_bridge fastcdr fastrtps libopensplice67 libopensplice69 osrf_testing_tools_cpp poco_vendor rmw_connext_cpp rosidl_typesupport_connext_c rosidl_typesupport_connext_cpp rti-connext-dds-5.3.1 tinyxml_vendor tinyxml2_vendor urdfdom urdfdom_headers"
colcon
Installation
sudo apt install python3-colcon-common-extensions
list
$ mkdir -p /tmp/workspace/src # Make a workspace directory with a src subdirectory
$ cd /tmp/workspace # Change directory to the workspace root
$ <...> # Populate the `src` directory with packages
$ colcon list # List all packages in the workspace
$ colcon graph # List all packages in the workspace in topological order
# and visualize their dependencies
build
$ colcon build # Build all packages in the workspace
$ colcon build --packages-select <name-of-pkg>
$ colcon build --packages-up-to <name-of-pkg>
arguments
--packages-up-to
builds the package you want, plus all its dependencies, but not the whole workspace (saves time)--symlink-install
doc- praktisch für development, reduziert das ständige Recompiling
- This enables the developer to change the resources in the source space and skipping the installation step in many situations.
- C++: For CMake packages this is achieved by optionally overriding the CMake
install()
function. - Python: For Python packages the development mode is used to install the package.
- C++: For CMake packages this is achieved by optionally overriding the CMake
- “saves you from having to rebuild every time you tweak python scripts”
--event-handlers console_direct+
shows console output while building (can otherwise be found in the log directory)--cmake-args -DCMAKE_BUILD_TYPE=Release
- Each CMake argument needs to be quoted separately, source:
- e.g.
colcon build --symlink-install --cmake-args ' -DSECURITY=1' ' -DBUILD_TESTING=1' --event-handler console_cohesion+ --build-base $ROS2_WS/build_debug_isolated --install-base $ROS2_WS/install_debug_isolated --cmake-args ' -DCMAKE_BUILD_TYPE=Debug'
- e.g.
- Each CMake argument needs to be quoted separately, source:
--parallel-workers NUMBER
doc- The maximum number of jobs to process in parallel. The default value is the number of logical CPU cores as reported by
os.cpu_count()
.
- The maximum number of jobs to process in parallel. The default value is the number of logical CPU cores as reported by
test
$ colcon test # Test all packages in the workspace
$ colcon test-result --all # Enumerate all test results
$ . install/local_setup.bash # Setup the environment to use the built packages
$ <...> # Use the built packages
ros2 pkg
create
arguments
--build-type
:ament_cmake
--dependencies
will automatically add the necessary dependency lines topackage.xml
andCMakeLists.txt
Publisher-Subscriber
Queue Size
from: source
A real life example can be a scenario of a waiter and a kitchen to wash dishes. Suppose the costumers ends its meals and the waiter takes their dirty dishes to wash in the kitchen. He puts in a table. Whenever the dishwasher can, he goes to table and gets dishes and take to wash. In normal operation the table is never filled. But if someone else give another task to the dishwasher guy, the table will start to get full. Until some time the waiter can’t place dishes anymore and leave tables dirty (problem in the system). But if table is artificially large there (let’s say 1000 square units) the waiter will likely fulfill its job even if dishwasher is busy, considering that after some time he will be able to return to clean dishes.
ros2 param
Pass Parameter via command line
ros2 run package_name executable_name --ros-args -p param_name:=param_value
- e.g.
ros2 run demo_nodes_cpp parameter_blackboard --ros-args -p some_int:=42 -p "a_string:=Hello world" -p "some_lists.some_integers:=[1, 2, 3, 4]" -p "some_lists.some_doubles:=[3.14, 2.718]"
- e.g.
Passing ROS2 Arguments via cmd line
set log-level debug / show debug information
- ros doc
ros2 run logging_demo logging_demo_main --ros-args --log-level debug
API
Subscriber
Time
- see Using time
QoS
Packages
image_transport
Examples:
Publisher:
// from: https://answers.ros.org/question/403966/how-to-initialize-image_transport-using-rclcpp/
class CamPublisher_ : public rclcpp::Node
{
protected:
rclcpp::Node::SharedPtr node_handle_;
image_transport::ImageTransport image_transport_;
image_transport::Publisher image_publisher_;
...
public:
CamPublisher_() :
Node("camera"),
// create the shared_ptr node handle for this node.
node_handle_(std::shared_ptr<CamPublisher_>(this, [](auto *) {})),
image_transport_(node_handle_),
image_publisher_(image_transport.advertise("image", 10)
{
....
}
void convert_and_publish(const cv::Mat& frame)
{
sensor_msgs::msg::Image msg;
....
image_publisher_->publish(msg);
}
}
Gazebo
reopen the GUI window
from: source
When you launch gazebo, there are two programs that are run: gzserver and gzclient. The program gzserver does all the simulation, even rendering for camera simulation. The interactive window is opened by gzclient. To open a specific world, type gzserver specific.world.
I.e. simply reopen the GUI by entering the command gzclient
.
adding models
wget -q -R *index.html*,*.tar.gz --no-parent -r -x -nH http://models.gazebosim.org/cardboard_box/
download modelcardboard_box
Xacro Macros (.xacro)
- s. http://wiki.ros.org/xacro#Macros
- nicht vergessen:
*origin
inparam="suffix *origin"
ist kein Parameter und muss ein separates Element sein (s. Link oben)!
Components of SDF Models
Source: http://gazebosim.org/tutorials?tut=build_model
Links: A link contains the physical properties of one body of the model. This can be a wheel, or a link in a joint chain. Each link may contain many collision and visual elements. Try to reduce the number of links in your models in order to improve performance and stability. For example, a table model could consist of 5 links (4 for the legs and 1 for the top) connected via joints. However, this is overly complex, especially since the joints will never move. Instead, create the table with 1 link and 5 collision elements.
Collision: A collision element encapsulates a geometry that is used for collision checking. This can be a simple shape (which is preferred), or a triangle mesh (which consumes greater resources). A link may contain many collision elements.
Visual: A visual element is used to visualize parts of a link. A link may contain 0 or more visual elements.
Inertial: The inertial element describes the dynamic properties of the link, such as mass and rotational inertia matrix.
Sensor: A sensor collects data from the world for use in plugins. A link may contain 0 or more sensors.
Light: A light element describes a light source attached to a link. A link may contain 0 or more lights.
Joints: A joint connects two links. A parent and child relationship is established along with other parameters such as axis of rotation, and joint limits.
Plugins: A plugin is a shared library created by a third party to control a model.
Troubleshooting
Errors
Error 1
/usr/lib/gcc/x86_64-linux-gnu/7/../../../x86_64-linux-gnu/Scrt1.o: In function `_start':
(.text+0x20): undefined reference to `main'
collect2: error: ld returned 1 exit status
make[2]: *** [HoughLinesNode] Error 1
make[1]: *** [CMakeFiles/HoughLinesNode.dir/all] Error 2
make: *** [all] Error 2
---
Failed <<< galaxis_HoughLines_pkg [12.8s, exited with code 2]
- this simply means you forgot to write a
main.cpp
or amain()
function for your ROS node
Error 2
/home/galaxis/.local/lib/python3.6/site-packages/setuptools/command/install.py:37:
SetuptoolsDeprecationWarning: setup.py install is deprecated. Use build and pip and other standards-based tools.
- install
pip install setuptools==58.2.0
- make sure you have underscores in
setup.cfg
file and not the ‘-‘ - see solution answers.ros.org
Error 3
[0.191s] WARNING:colcon.colcon_ros.prefix_path.ament:The path '/root/docker_volume/ds_ws/install/subscriber_pkg' in the environment variable AMENT_PREFIX_PATH doesn't exist
[0.191s] WARNING:colcon.colcon_ros.prefix_path.ament:The path '/root/docker_volume/ds_ws/install/single_stream_pkg' in the environment variable AMENT_PREFIX_PATH doesn't exist
[0.191s] WARNING:colcon.colcon_ros.prefix_path.ament:The path '/root/docker_volume/ds_ws/install/multi_stream_pkg' in the environment variable AMENT_PREFIX_PATH doesn't exist
- problem: You are compiling in a shell in which you have run
source install/setup.bash
before