208 lines
9.5 KiB
Markdown
208 lines
9.5 KiB
Markdown
# 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)]()
|
|
* [Create CMake Package]()
|
|
* [Create Message Files]()
|
|
* [Configure CMakeLists.txt]()
|
|
* [Configure package.xml]()
|
|
* [Build Package]()
|
|
* [Source newly built workspace]()
|
|
* [Check functionality]()
|
|
* [Python Package (eg. /pubsub)]()
|
|
* [Create Python Package]()
|
|
* [Write Python Scripts]()
|
|
* [Configure package.xml]()
|
|
* [Build Package]()
|
|
* [Source newly built workspace]()
|
|
* [Run scripts]()
|
|
* [Sources]()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
## 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](https://index.ros.org/doc/ros2/Tutorials/Custom-ROS2-Interfaces/#cmakelists-txt)
|
|
* package.xml:
|
|
* This file contains meta information about this package
|
|
* Configure this file according to this [instruction](https://index.ros.org/doc/ros2/Tutorials/Custom-ROS2-Interfaces/#package-xml)
|
|
|
|
|
|
### 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_:
|
|
```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](https://github.com/patrickw135/pubsub/blob/master/bashrc_addons.txt) 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
|
|
```python
|
|
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](https://github.com/patrickw135/pubsub/blob/master/instructions_custom_topics.md#cmake-package-eg-pubsub_msg) 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_:
|
|
```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.:
|
|
```xml
|
|
<depend>std_msgs</depend>
|
|
<!-- CUSTOM LINE -->
|
|
<!-- This is custom for the package you depend on -->
|
|
<exec_depend>pubsub_msg</exec_depend>
|
|
```
|
|
|
|
### 4. Configure setup.py
|
|
The file setup.py is used to create entry points, meaning you link your python scripts to names which you can be called through `ros2 run ...`. In order for this to work your python scripts must be written using the following mechanism
|
|
```python
|
|
def main():
|
|
# main code
|
|
|
|
if __name__ == "__main__":
|
|
main()
|
|
```
|
|
in which you put all of your code inside `main()`. This prevents any code from being run, if this script is not run as *"__main__"*.
|
|
Linking your scripts to names is done inside the file _setup.py_ by defining entry points:
|
|
```python
|
|
entry_points={
|
|
'console_scripts': [
|
|
'talker = pubsub.talker:main',
|
|
'listener = pubsub.listener:main'
|
|
],
|
|
},
|
|
```
|
|
The _setup.py_-excerp above links the the function `main()` from the scripts _talker.py_ and _listener.py_ from inside `/pubsub` to the names _talker_ and _listener_. This way they can be called using `ros2 run pubsub talker` or `ros2 run pubsub listener`.
|
|
|
|
### 5. Build Package
|
|
Now you can build the Python package.
|
|
* Move to your workspace's root: `cd ~/<workspace_path>`
|
|
* Build workspace: `colcon build --symlink-install`
|
|
|
|
### 6. Source newly built workspace
|
|
* Run: `source ~/<workspace_path>/install/local_setup.bash`
|
|
* If you already [updated your .bashrc file](https://github.com/patrickw135/pubsub/blob/master/bashrc_addons.txt) 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. 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](https://index.ros.org/doc/ros2/Tutorials/Custom-ROS2-Interfaces/#creating-custom-ros-2-msg-and-srv-files)
|
|
[theconstructsim custom messages](https://www.theconstructsim.com/ros2-tutorials-7-how-to-create-a-ros2-custom-message-new/)
|