ROS — Урок 3 — Создание пакета для ROS
Прежде чем создать пакет, давайте посмотрим, как работает утилита roscreate-pkg.
Эта утилита создает новый пакет ROS. Все пакеты ROS содержат набор схожих файлов: манифесты, CMakeLists.txt, mainpage.dox, и Makefile. roscreate-pkg берёт на себя большую часть утомительных задач, которые нужно выполнить при создании нового пакета вручную, и тем самым устраняет распространённые ошибки, вызванные ручным созданием файлов сборки и манифестов.
Чтобы создать новый пакет в текущем каталоге нужно выполнить команду:
Также сразу можно указать зависимости этого пакета:
1.2 Создание нового пакета ROS
Теперь, перейдём в наш домашний каталог или каталог проекта и создадим наш пакет под названием beginner_tutorials. Наш тестовый пакет будет зависеть от std_msgs, roscpp, и rospy, которые являются общими пакетами ROS.
Обратите внимание, что каталог с установленной ROS, вероятно, защищен от записи, но в любом случае, неразумно изменять базовую систему без особых причин. Вместо этого, вам следует создать новый каталог в своей домашней директории и добавить его в ROS_PACKAGE_PATH, как это будет показано ниже, и создавать дополнительные пакеты уже там. Прописывание дополнительного пути в начале ROS_PACKAGE_PATH заставит все утилиты rosbash, такие как roscd, искать пакеты сначала по этому пути, прежде чем переходить к следующему каталогу по списку (дефолтный каталог обычно оставляют в списке последним).
Обратите внимание, что экспорт в ROS_PACKAGE_PATH произведённый командой выше, должны быть выполнен при каждом открытии нового терминала (если только вы не измените ваш файл .bashrc чтобы он делал это автоматически).
Теперь перейдём в каталог
/ros_tutorials и создадим там наш первый пакет:
Вы увидите что-то вроде:
Вы можете потратить пару минут и посмотреть содержимое файла beginner_tutorials/manifest.xml. Манифест играет важную роль в ROS, так как он определяет, как пакеты собираются, выполняются и документируются.
Теперь давайте убедимся, что ROS может найти свой новый пакет. Часто бывает полезным вызвать rospack профиля после внесения изменений в директориях своего проекта, чтобы новые каталоги были корректно найдены:
Если это не сработало, значит ROS не может найти свой новый пакет. Обычно проблема кроется в ROS_PACKAGE_PATH. Обратитесь к инструкции по установке из SVN или из пакетов, в зависимости от того, как вы установили ROS. Если вы создали или добавили пакет, который находится за пределами существующих путей в ROS_PACKAGE_PATH, вы должны изменить свою переменную окружения ROS_PACKAGE_PATH, чтобы включить в неё новый каталог.
Попробуем перейти в каталог нашего пакета.
1.3 Зависимости пакета первого порядка
При использовании roscreate-pkg, мы указали несколько зависимостей нашего пакета. Это зависимости первого порядка, теперь мы можем их посмотреть с помощью утилиты rospack.
Как вы можете видеть, rospack вывел список тех же зависимостей, которые были заданы в качестве аргументов при запуске roscreate-pkg. Эти зависимости пакета хранятся в файле манифеста. Взгляните на файл манифеста.
1.4 Косвенные зависимости пакета
В большинстве случаев, зависимость также будет иметь свои собственные зависимости. Например, rospy зависит от других пакетов.
Пакет может иметь довольно много косвенных зависимостей. К счастью, rospack может рекурсивно определить все вложенные зависимости.
1.5 Клиентские библиотеки ROS
Вы можете быть удивлены, что rospy и roscpp зависят от других пакетов, как это видно по предыдущему примеру. Дело в том, что rospy и roscpp являются клиентскими библиотеками (Client Libraries). Клиентские библиотеки позволяют различным языкам программирования, общаться через ROS. rospy — это клиентская библиотека для Python, а roscpp — это клиентская библиотека для C++.
Перечислим команды, с которыми мы познакомились:
roscreate-pkg = ros + create-pkg: генерирует все файлы, необходимые для создания пакета ROS
rospack = ros+pack(age): предоставляет информацию, связанную с пакетами ROS
rosstack = ros+stack: предоставляет информацию, связанную со стеками ROS
Overview
Make sure you follow the article and try the steps mentioned hands-on so that you can get a first hand experience.
Also, stay till the end because there is some bonus content I’ll be sharing with you all which will make your ROS package creation and build simpler!
1. catkin Build System
Before we start creating and building our first ROS package, it is essential for us to understand what the catkin build system is.
catkin is the official build system of ROS and the successor to the original ROS build system called rosbuild.
catkin is responsible for generating ‘targets’ from raw source code that can be used by an end user. These targets may be in the form of libraries, executable programs, generated scripts, exported interfaces (e.g. C++ header files) or anything else that is not static code.
In ROS terminology, source code is organized into ‘packages’ where each package typically consists of one or more targets when built.
So, to check if catkin is installed or not, just type catkin on your terminal and press the Tab key double time. You should be able to see this.
By default, catkin is installed whenever you install ros but if it is not installed, you can run the following command:
Using the catkin build system, we will be creating, initializing and compiling the ROS workspaces and the ROS packages.
2. Understanding catkin Workspace
Now that we have understood the catkin build system, we will understand the catkin workspace and its components so that it becomes easier for us to store our files, modify, build and maintain clean & accessible directory structure.
As you can see in the above diagram, a typical catkin workspace contains up to four different spaces (source space, build space, development space and install space) where each space serves a different role in the software development process.
- Source space: The source space contains the source code of catkin packages. This is where you can extract/checkout/clone source code for the packages you want to build. Each folder within the source space contains one or more catkin packages and each package has its set of ROS Computational Graph components**. The root of the source space contains a symbolic link to catkin’s boiler-plate ‘toplevel’ CMakeLists.txt file. This file is invoked by CMake during the configuration of the catkin projects in the workspace. It can be created by calling catkin_init_workspace in the source space directory.
- Build space: The build space is where CMake is invoked to build the catkin packages in the source space. CMake and catkin keep their cache information and other intermediate files here.
- Development space: The development space (or devel space) is where built targets are placed prior to being installed. The way targets are organized in the devel space is the same as their layout when they are installed. This provides a useful testing and development environment which does not require invoking the installation step.
- Install space: Once the targets are built, they can be installed into the install space by invoking the install target, usually with make install. The install space does not have to be contained within the workspace.
** Note: Please refer my previous article about the ROS Computational Graph if want to know more about the components of the same. Link is provided below.
Part 1: Getting Started with ROS — Overview, Installation and ROS Computational Graph Model | by Arsalan Anwar | Analytics Vidhya (medium.com)
3. Creating and building our ROS Package
Essentially, ROS packages are catkin packages which means that they should follow a particular directory structure and contain a couple of files that identify them as a ROS package and help us build the code in the packages.
ROS packages reside in directories called catkin workspaces and therefore, we would have to create and initialize a catkin workspace first.
Note: catkin packages can be built as a standalone project but catkin also provides the concept of workspaces, where you can build multiple, interdependent packages together all at once.
And by the end of these 7 steps, you will be able to create and build your own ROS Package. So lets get started!
Step 1: Create a catkin workspace and a source folder
Lets create a catkin workspace by the name ‘catkin_ws’ and then create a source folder inside this workspace. All our ROS packages will reside in this source folder!
Step 2: Initialize the catkin workspace
Once we have created the workspace and the source folder, we will have to initialize our current directory as a catkin workspace. This is done by moving inside the src folder and running the catkin_init_workspace command.
After this, when we list out the contents of the directory, we notice that a new file called CMakeLists.txt is present inside the src folder as shown above.
This means that our empty workspace is ready to go through its first compilation.
Step 3: Compile your workspace
To compile our workspace, we will navigate to the root of our catkin workspace and use the catkin_make command to start the build process.
You will see a bunch of compiler debug messages on your screen but you don’t need to worry about that (unless there’s an error! xD)
Once the workspace was successfully built you will find two new folders called build and devel in the root of your workspace.
Please feel free to explore the contents of these directories. But note that we won’t be modifying anything in these two directories (build and devel).
Now that we have created and initialized our catkin workspace, Lets create our first ROS Package!
Step 4: Create our new ROS Package
To create a new ROS package, we use the command catkin_create_pkg followed by the name of the package and then followed by the package dependencies — std_msgs, roscpp and rospy.
- std_msgs indicates that we will be using standard message types like int 8, int 64, string or float
- roscpp indicates usage of C++ code
- rospy indicates usage of Python code
Once we execute the catkin_create_package command, a skeleton ROS package will be created for us.
We will then find a new package called ros_package inside our source folder and a bunch of other files (ex: CMakeLists.txt, package.xml, etc.) inside our package as shown above.
- CMakeLists.txt -This file contains information about how to build our ROS package
- package.xml -This file contains meta information about our package like the description, version, dependencies, executables, etc.
Step 5: Build the workspace with the new empty package
To build the workspace with the new package, we would have to go to the root of the workspace and run the catkin_make command.
As you can see, our ROS package was identified and built.
Step 6: Make the workspace visible to the file system
To make the workspace and its packages visible to the file system so that we can access these packages from anywhere, we would have to run the following command:
Now, lets try to find our package that we just created using the command rospack find <package_name>
We see that the file system was able to find our newly created ROS package!
Step 7: Create executable nodes within the package
First lets write a piece of code and then try to get the executable for it. For this, follow the steps given below:
7.1 Go to the src folder within the ROS package
7.2 Create a small C++ program called hello.cpp which prints out some message. A sample is given below.
7.3 Open the CMakeLists.txt file within the ROS package and add the following line:
Syntax: add_executable(<node_name> <path_to_cpp_script>)
- node_name: It can be any name that you wish to have for your executable node
- path_to_cpp_script: This is the path to the C++ script within the ROS package
7.4 Go to the root of the catkin workspace and build the workspace again by running the catkin_make command.
You will notice that your executable has been created under devel/lib/rospackage
7.5 Source the workspace and run the node from anywhere
Source the workspace by running the following command
Then, run the ROS node that we created by using the following command:
Syntax: rosrun <package_name> <node_name>
- package_name: Name of the ROS package where the executable node resides in.
- node_name: Name of the executable node
As you can see, our node has been executed and we can see the message on the screen.
Congratulations. We have successfully created our first catkin workspace and our first ROS package!
Note: This is a basic ROS Package that we have created, you can add the functionality you require and build on the same.
Bonus Information:
Thanks for reading the article till the end! I hope you like it and as mentioned, here are some commands which you can use to save a lot of time while creating ROS packages!
- To enter your package from anywhere, use the command $roscd
2. To list the contents of the package from anywhere, use the command $rosls
3. Log of a ROS process is stored in the hidden directory .ros, to jump to it directly we can use roscd log.
Creating Packages and Nodes¶
The basis of ROS communication is that multiple executables called nodes are running in an environment and communicating with each other in various ways. These nodes exist within a structure called a package. In this module we will create a node inside a newly created package.
Reference Example¶
Further Information and Resources¶
Scan-N-Plan Application: Problem Statement¶
We’ve installed ROS, created a workspace, and even built a few times. Now we want to create our own package and our own node to do what we want to do.
Your goal is to create your first ROS node:
- First you need to create a package inside your catkin workspace.
- Then you can write your own node
Scan-N-Plan Application: Guidance¶
Create a Package¶
cd into the catkin workspace src directory Note: Remember that all packages should be created inside a workspace src directory.
Use the ROS command to create a package called myworkcell_core with a dependency on roscpp
See the catkin_tools documentation for more details on this command.
- This command creates a directory and required files for a new ROS package.
- The first argument is the name of the new ROS package.
- Use —catkin-deps to specify packages which the newly created package depends on.
There will now be a folder named myworkcell_core. Change into that folder and edit the package.xml file. Edit the file and change the description, author, etc., as desired.
If you forget to add a dependency when creating a package, you can add additional dependencies in the package.xml file.
STOP! We’ll go through a few more lecture slides before continuing this exercise.¶
Create a Node¶
In the package folder, create the file src/vision_node.cpp (using gedit).
Add the ros header (include ros.h).
Add a main function (typical in c++ programs).
Initialize your ROS node (within the main).
Create a ROS node handle.
Print a “Hello World” message using ROS print tools.
Do not exit the program automatically — keep the node alive.
ROS_INFO is one of the many logging methods.
- It will print the message to the terminal output, and send it to the /rosout topic for other nodes to monitor.
- There are 5 levels of logging: DEBUG, INFO, WARNING, ERROR, & FATAL.
- To use a different logging level, replace INFO in ROS_INFO or ROS_INFO_STREAM with the appropriate level.
- Use ROS_INFO for printf-style logging, and ROS_INFO_STREAM for cout-style logging.
Now that you have created the source code for the node, we need to add instructions for building it into an executable program. In the package folder, edit the CMakeLists.txt file. Browse through the example rules, and add an executable ( add_executable ) named vision_node with the source file named src/vision_node.cpp . Also within the CMakeLists.txt , make sure your new vision_node executable gets linked ( target_link_libraries ) to the catkin libraries.
These lines should be added to the CMakeLists.txt in the order and location specified above. The commands already exist in the template CMakeLists.txt file and can be uncommented and slightly modified
- Uncomment existing template examples for add_compile_options near the top (just below project() )
- Uncomment and edit existing template examples for add_executable and target_link_libraries near the bottom in the BUILD section
- This helps make sure these rules are defined in the correct order, and makes it easy to remember the proper syntax.
Note: You’re also allowed to spread most of the CMakeLists rules across multiple lines, as shown in the target_link_libraries template code
Build your program (node), by running catkin build in a terminal window
- Remember that you must run catkin build from within your catkin_ws (or any subdirectory)
- This will build all of the programs, libraries, etc. in myworkcell_core
- In this case, it’s just a single ROS node vision_node
Run a Node¶
Open a terminal and start the ROS master.
The ROS Master must be running before any ROS nodes can function.
Open a second terminal to run your node.
In a previous exercise, we added a line to our .bashrc to automatically source devel/setup.bash in new terminal windows
This will automatically export the results of the build into your new terminal session.
If you’re reusing an existing terminal, you’ll need to manually source the setup files (since we added a new node):
This runs the program we just created. Remember to use TAB to help speed-up typing and reduce errors.
In a third terminal, check what nodes are running.
In addition to the /rosout node, you should now see a new /vision_node listed.
Enter rosnode kill /vision_node. This will stop the node.
Note: It is more common to use Ctrl+C to stop a running node in the current terminal window.
Challenge¶
Goal: Modify the node so that it prints your name. This will require you to run through the build process again.
Create a ROS2 Python package
In this tutorial you’ll learn how to create and setup a ROS2 Python package.
I’ll show you every step, and explain the relation between files, where to write your nodes, how to add launch files, etc.
>> Here’s a video tutorial that recaps the first part of this article. Watch it as an additional resource:
After watching the video, subscribe to the Robotics Back-End Youtube channel so you don’t miss the next tutorials!
Table of Contents
Setup your ROS2 Python package
Before you can create a ROS2 Python package, make sure you have :
You want to learn ROS2 efficiently?
Check out ROS2 For Beginners and learn ROS2 step by step, in 1 week.
- correctly installed ROS2,
- setup your environment (add source /opt/ros/ROS_VERSION/setup.bash in your .bashrc – don’t forget to replace “ROS_VERSION”),
- and created a ROS2 workspace ( $ mkdir -p
Now, to create a Python package:
Use ros2 pkg create followed by the name of your package. Then add the option —build-type ament_python to precise that you’re building a package specifically for Python.
A bunch of files will be created inside the new package.
Explanation of files inside a ROS2 Python package
Here’s a quick explanation for each file, and what you have to do to set them up.
package.xml
This file provides some information and required dependencies for the package.
You need to manually edit lines 5-8. Everything will work if you don’t do it, but if you decide to share or publish your package, then those info are mandatory.
- version.
- description: a brief description of what your package does.
- maintainer: name and email of current maintainer. You can add multiple maintainer tags. Also, you can add some author tags (with name and email) if you want to make the distinction between authors and maintainers.
- license: if you ever want to publish your package you’ll need a license (for example BSD, MIT, GPLv3).
setup.py
If you know what a CMakeLists.txt file is, well the setup.py is basically the same but for Python. When you compile your package it will tell what to install, where to install it, how to link dependencies, etc.
We’ll come back to this file later in this tutorial. For now you can see that the 4 lines we had to setup in the package.xml are also here. Modify those lines if you intent to share or publish the package.
setup.cfg
This file will tell where the scripts will be installed. Right now you have nothing to change.
<package_name>/ folder
This folder will be different every time, because it will always have the same name as your package. In this case the name of the package is “my_python_pkg”, so the name of the folder is also “my_python_pkg”.
You will create all your ROS2 Python nodes in this folder. Note that it already contains an empty __init__.py file.
resource/<package_name> file
This is needed for ROS2 to find your package. For our example the file name is “resource/my_python_pkg”.
Nothing to change here for now.
test/ folder
This folder, as its name suggests, is for testing. When you create a package it already contains 3 Python files.
Compile your package
To compile your package, go into your workspace directory and execute colcon build . We’ll tell ROS2 to only build our Python package with the option —packages-select .
Note: When working with Python, you may think that you don’t need to compile anything. That’s true, you can directly execute the Python files that you create without colcon build . But compiling a package is much more than that: it will install the scripts in a place where they can find other modules from other packages, where they can be found by other scripts. It will also allow you to start a node with ros2 run , add it in a launch file, pass parameters to it, etc.
Now that you know how to create and compile a package, let’s make a few examples to see what you can do with this package.
Build a Python node inside a ROS2 Python package
Let’s see how to build, install, and use a Python node, with our freshly created ROS2 Python package.
Create a file named my_python_node.py in the my_python_pkg/ folder.
Here’s a simple Python code you can use for testing purposes.
The node will just print a message on startup, and then it will spin indefinitely until you kill the node. If you want to know more about the code, check out how to write a ROS2 Python node.
Now that we have a Python file, we need to add an entry point in the setup.py file.
Find the “entry_points” dictionary and add one line in the “console_scripts” array.
- “test” will be the name of the executable after the script is installed.
- “my_python_pkg.my_python_node:main” means: execute the main() function inside the my_python_node.py file, inside the my_python_pkg. So, the entry point is the main(). If you want to start your node with a different function, make sure to set the function name accordingly in setup.py.
- Don’t mix everything: executable name != file name != node name. Those are 3 different things. In our example: “test” is the executable, “my_python_node” is the file, and “my_node_name” is the node name. Note that you can also choose to use the same name for all 3.
- The executable script will be installed in
One more thing you need to do: add a <depend>rclpy</depend> tag in package.xml, because we use a dependency to rclpy in our code.
You only need to do this once per dependency for the whole package. If you create another node you’ll need to update setup.py, but not package.xml if you don’t have any new dependency.
And now you can compile your package with colcon build —packages-select my_python_pkg . Then, open a new terminal, source your ROS2 workspace and execute the node with ros2 run .
Install other files in a ROS2 Python package
You can virtually put everything you want in a ROS2 package. There is no hard rule about what to do, but some conventions make it easier for you. Let’s see how to install launch files and YAML config files. Those are among the most common things you’ll add to packages when you develop your ROS2 application.
Launch files
Create a launch/ folder at the root of your package. You’ll put all your launch files inside this folder.
Now, to install those launch files, you need to modify setup.py.
For our example, with package name “my_python_pkg”, this will install all launch files from the launch/ folder, into
Note: you only need to modify setup.py once. After that, every time you add a launch file you’ll just need to compile your package so that the file is installed, that’s it.
Then, to start a launch file: ros2 launch package_name launch_file_name .
YAML config files
You can follow the same technique to install YAML config files.
Create a config/ folder at the root of your package. You’ll put all your YAML files here.
To install YAML files, again, modify setup.py. Add a new line in the “data_files” array:
Still with the “my_python_pkg” example, the YAML files will be installed into
You can follow this technique to add any other folder into the install/ folder of your ROS2 workspace.
ROS2 Python package: going further
In this tutorial you have seen how to setup a ROS2 Python package, and how to make it grow with nodes, launch files, YAML files.
Here’s the final package architecture after all the additions we made:
Understanding how to work with ROS2 packages is important so that you’re not stuck whenever you want to add something to your application.
