ROS2_pubsub/instructions_custom_topics.md

8.5 KiB

How to create custom ROS topics

This is a short instruction on how to create custom interfaces using ROS topics.

For this at least two packages will be required:

  • The python package contains your scripts (eg. ROS nodes)
  • The CMake package contains the custom msg/srv/act files

The CMake package is required because the custom msg/srv/act files cannot be created inside the python package as this is not supported yet.

Table of Content

CMake Package (eg. /pubsub_msg)

This package makes up the basis for custom ROS interfaces and contains all custom msg/srv/act files. Additionally, the special files (CMakeLists.txt and package.xml) describe how these interface files are to be used.

This package must be created as a CMake package: ros2 pkg create --build-type ament-cmake <package_name>

This will result in an empty package structure:

  • msg/srv/act directory:
    • This directory contains the custom msg files (eg. CustomMsg1.msg)
  • CMakeLists.txt:
    • This file describes how to build this package
    • Configure this file according to this instruction
  • package.xml:
    • This file contains meta information about this package
    • Configure this file according to this instruction

1. Create CMake Package

  • Move to your colcon workspace's src directory: cd <workspace_path>/src
  • (For example: cd ~/colcon_ws/src)
  • Create CMake package: ros2 pkg create --build-type ament_cmake <package_name>
  • (Here: ros2 pkg create --build-type ament_cmake pubsub_msg)

2. Create Message Files

  • If not already available create msg directory inside package directory.
    Resulting structure: <workspace_name>/src/<package_name>/msg
  • Move to newly created msg direcrory
  • Create your own custom message files, eg. CustomMsg1.msg.
    Give your files comprehensible names, eg. Epossetvalues.msg

3. Configure CMakeLists.txt

Open CMakeLists.txt and ad these lines before if(BUILD_TESTING):
find_package(builtin_interfaces REQUIRED)
find_package(rosidl_default_generators REQUIRED)
find_package(std_msgs REQUIRED)
find_package(rclcpp REQUIRED)
Then also add custom lines depending your package, here the custom message/service files are added:
rosidl_generate_interfaces(${PROJECT_NAME}
"msg/CustomMsg1.msg"
"msg/CustomMsg2.msg"
DEPENDENCIES builtin_interfaces
)

4. Configure package.xml

In order to let the build system know what this package depends on add these lines to package.xml:

   <!-- ADD THESE LINES: START HERE -->
   <build_depend>builtin_interfaces</build_depend>
   <build_depend>rosidl_default_generators</build_depend>
   <exec_depend>builtin_interfaces</exec_depend>
   <exec_depend>rosidl_default_runtime</exec_depend>
   <member_of_group>rosidl_interface_packages</member_of_group>
   <!-- END HERE -->

5. Build Package

  • Move back to the workspace's most top layer: cd ~/<workspace_path>
  • Build workspace: colcon build
  • Sucessful response:
    Starting >>> pubsub
    Starting >>> pubsub_msg
    Finished <<< pubsub [0.85s]
    Finished <<< pubsub_msg [1.09s]
    Summary: 2 packages finished [1.56s]

6. Source newly built workspace

  • Run: source ~/<workspace_path>/install/local_setup.bash
  • If you already updated your .bashrc file you can close all open consoles and start a new console (Ctrl+Alt+T). This will source your workspace automatically, as .bashrc is run every time you start a console.
    Important: If you use multiple workspaces make sure you have the wanted workspace defined in .bashrc! Otherwise the changes introduced when building will not be available.

7. Check functionality

Check functionality of your messages by creataing a topic using your newly created message:

  • CustomMsg1:
    ros2 topic pub /chatter1 pubsub_msg/CustomMsg1 "{temperature: {24.1234, 25.9876}, pressure: {1012.556, 1013.987}, humidity: {0.002, 0.001}}" --rate 1

  • Response:
    publisher: beginning loop
    publishing #1: pubsub_msg.msg.CustomMsg1(temperature=[24.12339973449707, 25.987600326538086], pressure=[1012.5560302734375, 1013.9869995117188], humidity=[0.0020000000949949026, 0.0010000000474974513])...

  • CustomMsg2:
    ros2 topic pub /chatter2 pubsub_msg/CustomMsg2 "{pitch_ctrl: 33.33, yaw_ctrl: 0.5}" --rate 1

  • Response:
    publisher: beginning loop
    publishing #1: pubsub_msg.msg.CustomMsg2(pitch_ctrl=33.33, yaw_ctrl=0.5)...

Python Package (eg. /pubsub)

This package contains your scripts, programs and libraries. After building the workspace (colcon build) the custom messages are available to all other packages.

This package can be created as a CMake (C++) package or as a python package depending on your coding preference, e.g.

  • C++: ros2 pkg create --build-type ament_cmake <package_name>
  • Python: ros2 pkg create --build-type ament_python <package_name>

<package_name> directory:

  • This directory contains your python scripts (eg. listener.py)
  • Also place non-standard libraries in this directory and import them in your python scripts

1. Create Python Package

  • Move to your workspace's source directory: cd <workspace_path>/src
  • Create python package: ros2 pkg create --build-type ament_python <pkg_name>

2. Write Python Scripts

When using custom interfaces in python scripts these must be imported into the python script first

from <package_name>.msg import <message_name>

replacing <package_name> with the package containing the custom message and <message_name> with the message file name (excluding the file ending .msg).
However, in order to be able to import the custom message types, <message_name> must first be known to the ROS system. This was established when creating the CMake package containing the custom message. Additionally, you must add this dependency to the package.xml of this package as stated in the next chapter.

3. Configure package.xml

In addition to importing the message type into your python script you must also configure package.xml adding the package dependency of where you inherite the custom message from. Add this line to package.xml:

   <depend>std_msgs</depend>
   <!-- CUSTOM LINE -->
   <!-- This is custom for the package you depend on -->
   <exec_depend>package_name</exec_depend>

exchanging package_name with the source package of the custom message type (here pubsub_msg), e.g.:

   <depend>std_msgs</depend>
   <!-- CUSTOM LINE -->
   <!-- This is custom for the package you depend on -->
   <exec_depend>pubsub_msg</exec_depend>

4. Build Package

Now you can build the Python package.

  • Move to your workspace's root: cd ~/<workspace_path>
  • Build workspace: colcon build --symlink-install

5. Source newly built workspace

  • Run: source ~/<workspace_path>/install/local_setup.bash
  • If you already updated your .bashrc file you can close all open consoles and start a new console (Ctrl+Alt+T). This will source your workspace automatically, as .bashrc is run every time you start a console.
    Important: If you use multiple workspaces make sure you have the wanted workspace defined in .bashrc! Otherwise the changes introduced when building will not be available.

6. Run scripts

  • Run Talker: ros2 run pubsub talker
  • Run Listener: ros2 run pubsub listener

The talker console should print the sent data while the listener console should print the received data. These should match.

If anything is unclear, compare this instruction material to the files in /pubsub and /pubsub_msg.

Sources

ROS2 Tutorial
theconstructsim custom messages