ROS2 поддерживает язык Python. В этой статье описывается процесс и метод работы создания узлов ROS2 в Python.
Установлено ROS2 среда
Установлено Python среда (python 3.10)
Установленный мной ros2 поставляется с Python 3.10. Если я использую другие версии Python, я получаю сообщение об ошибке.
Установить колкон
1 | pip install -U colcon-common-extensions |
---|
ros2-python-test
,Здесь будет ряд подпапок, которые будут служить пространствами Работа для разных случаев ROS2.1 | mkdir ros2_ws_demo001/ |
---|
1 | cd ros2_ws_demo001 |
---|
Определить место для работы — это все равно, что выбрать адрес и заложить фундамент для строительства дома.
Затем на этом фундаменте мы начнем строить дом и делать различные определения дома.
Как ROS2 построил этот дом? Для этого необходимо сначала создать папку «src» с единым фиксированным именем, а затем конкретно определить каждую комнату в этой папке.
12 | mkdir srccd src |
---|
Каждая комната, определенная в папке src, уже спроектирована. Непосредственное использование команд, связанных с ros2, в командной строке позволяет быстро создать базовую структуру.
1 | ros2 pkg create package_001 --build-type ament_python --dependencies rclpy |
---|
ros2 создаст серию файлов py framework. Текущая структура файлов выглядит следующим образом:
12345678910111213141516 | .└── src └── package_001 ├── package_001 │ └── __init__.py ├── package.xml ├── resource │ └── package_001 ├── setup.cfg ├── setup.py └── test ├── test_copyright.py ├── test_flake8.py └── test_pep257.py5 directories, 8 files |
---|
Хотя одновременно имеется гораздо больше папок и файлов, это стандартные функции пакета функций.
нам просто нужно быть package_001
Определите узел в setup.py
Просто настраиваем его в файле и нам нужно вызвать этот узел.
package_001
Создано в node_001.py
файл, напишите следующее содержимое:123456789 | import rclpyfrom rclpy.node import Nodedef main(args=None): rclpy.init(args=args) # init rclpy my_node = Node("node_001") # to create a Node object my_node.get_logger().info("hello, I am node_001") # to print a message. rclpy.spin(my_node) # to keep Node running rclpy.shutdown() # to close Node |
---|
setup.py
。Значение console_scripts изначально было пустым. Здесь нам нужно добавить значение console_scripts к нашему новому узлу, как показано ниже:
123 | 'console_scripts': "node_001 = package_001.node_001:main" , |
---|
Сохранить и выйти setup.py
документ.
На этом этапе часть исходного кода окончательно определена (эквивалентно определению каркаса комнаты). Далее вам нужно только скомпилировать рабочее пространство (эквивалентно быстрой заливке стены), и будет построен простейший дом.
ros2_ws_demo001
Далее просто выполните следующую команду: скомпилировать.1 | colcon build |
---|
Выход терминала:
12345 |
|
---|
После завершения компиляции мы обнаружили, что под рабочей областью находится еще несколько папок. Это сборка, установка и регистрация соответственно. В этих папках создается множество других папок и файлов.
12 | source install/setup.zshros2 run package_001 node_001 |
---|
Вы можете видеть, что на экране напечатано «привет, я node_001». Это именно то, что мы делаем в пользовательском узле.
12 |
|
---|
12 |
|
---|
Кратко подытожим весь процесс создания и запуска узла ros2 с использованием Python:
1. Создать независимое рабочее пространство (фактически создав папку);
2. Создайте папку src (папку исходного кода) в рабочей области и создайте пакет функций в src (очень просто, он создается непосредственно с помощью инструмента командной строки ros2);
3. Отредактируйте программу Node Python в пакете функций. Единственное, что требует от вас использования мозга для написания, но в нашем примере всего 8 строк кода, что чрезвычайно просто;
4. Настройте файл setup.py в пакете функций и вызовите программу узла, которую мы создали на предыдущем шаге;
5. Вернитесь в рабочую область и используйте инструмент colcon для компиляции (сборки) всего кода;
6. Запустите скомпилированный код;
фактически Python использовать ROS2 Автобус относительно гибок и не обязательно требует вышеперечисленного. ros2 run
метод, непосредственно Python запустить py То же самое касается файлов.
1234567891011121314 | import rclpyfrom rclpy.node import Nodedef main(args=None): rclpy.init(args=args) # init rclpy my_node = Node("node_001") # to create a Node object my_node.get_logger().info("hello, I am node_001") # to print a message. rclpy.spin(my_node) # to keep Node running rclpy.shutdown() # to close Nodeif __name__ == "__main__": main() |
---|
Вы можете попробовать это сами.
Немного расширьте приведенный выше код, создайте два узла ROS2, а затем запустите его.
12 | cp -rf ros2_ws_demo001/ ros2_ws_demo002_2_nodes/cd ros2_ws_demo002_2_nodes |
---|
12 | cp src/package_001/package_001/node_001.py src/package_001/package_001/node_002.pygedit src/package_001/package_001/node_002.py |
---|
Исправлять node_002.py
123456789 | import rclpyfrom rclpy.node import Nodedef main(args=None): rclpy.init(args=args) # init rclpy my_node = Node("node_002") # to create a Node object my_node.get_logger().info("hello,I am node_002") # to print a message. rclpy.spin(my_node) # to keep Node running rclpy.shutdown() # to close Node |
---|
Настройте это в файле setup.py:
1234 | 'console_scripts': "node_001 = package_001.node_001:main", "node_002 = package_001.node_002:main" , |
---|
Затем вернитесь в новую рабочую область, удалите предыдущие результаты компиляции и скомпилируйте снова.
12345 | cd ~/ROS2_study/ros2_ws_demo002_2_nodesrm -rf buildrm -rf installrm -rf logcolcon build |
---|
После завершения компиляции запустите первый узел непосредственно в текущем терминале:
12 | source install/setup.zshros2 run package_001 node_001 |
---|
Затем откройте новый терминал и запустите второй узел:
12 | source install/setup.zshros2 run package_001 node_002 |
---|
Две страницы терминала показывают строки, которые мы выводим:
1234567 | terminal 1> ros2 run package_001 node_001INFO node_001: hello, I am node_001# terminal 2> ros2 run package_001 node_002INFO node_002: hello, I am node_002 |
---|
Затем откройте терминал, чтобы подтвердить, какие узлы работают в данный момент:
1 | ros2 node list |
---|
Вы можете видеть, что два узла находятся в сети.
123 |
|
---|
На этом этапе мы создали два узла ROS2 и завершили вызов.
Функция main() существует в файле py, вызываемом файлом запуска по умолчанию. Она автоматически вызывает главную функцию и присваивает сгенерированному в ней узлу имя, настроенное в файле запуска.
123456 | Node( package='package_001', executable='node_001', name='node_001_launch', output='screen',), |
---|
Эта конфигурация будет в package_001
папка, позвони node_001.py
документ, позвони одному из main()
функцию, назовите сгенерированный узел как node_001_launch
**,называется Python используется по умолчанию в текущей среде терминала python путь к программе, то есть проходить** conda activate
Окружающая среда может воздействовать на ros2
ROS2 Можно настроить через launch
файл, настройте все узлы сразу, а затем запустите их единообразно.
12 | cp -rf ros2_ws_demo002_2_nodes/ ros2_ws_demo003_2_nodes_launch/cd ros2_ws_demo003_2_nodes_launch/ |
---|
1 | mkdir src/package_001/launch |
---|
my_multi_nodes_launch.py
, Содержание следующее:1234567891011121314151617181920 | my_multi_nodes_launch.pyfrom launch import LaunchDescriptionfrom launch_ros.actions import Nodedef generate_launch_description(): return LaunchDescription( Node( package='package_001', executable='node_001', name='node_001', output='screen', ), Node( package='package_001', executable='node_002', name='node_002', output='screen', ), ) |
---|
12345678910111213141516171819202122232425262728 | from setuptools import setuppackage_name = 'package_001'setup( name=package_name, version='0.0.0', packages=package_name, data_files=[ ('share/ament_index/resource_index/packages', 'resource/' + package_name), ('share/' + package_name, 'package.xml'), ('share/' + package_name, 'launch/my_multi_nodes_launch.py'), ], install_requires='setuptools', zip_safe=True, maintainer='goodman', maintainer_email='goodman@todo.todo', description='TODO: Package description', license='TODO: License declaration', tests_require='pytest', entry_points={ 'console_scripts': "node_001 = package_001.node_001:main", "node_002 = package_001.node_002:main" , },) |
---|
На самом деле здесь добавлено только одно предложение:
1 | ('share/' + package_name, 'launch/my_multi_nodes_launch.py'), |
---|
Наконец, вернитесь в рабочую область и скомпилируйте:
12345 | cd ros2_ws_demo003_2_nodes_launch/rm -rf buildrm -rf installrm -rf logcolcon build |
---|
12 | source install/setup.zshros2 launch package_001 my_multi_nodes_launch.py |
---|
Выход терминала:
1234567 |
|
---|
123 |
|
---|
До сих пор мы использовали метод запуска для одновременного запуска нескольких узлов.
Несколько узлов ros2 можно запустить непосредственно в файле py.
123456789101112131415161718 | import rclpyfrom rclpy.node import Nodeclass MyNode(Node): def __init__(self, name): super().__init__(name) self.get_logger().info(f'Hello from {name}')def main(args=None): rclpy.init(args=args) node1 = MyNode('Test_node1') node2 = MyNode('Test_node2') rclpy.spin(node1) rclpy.spin(node2) rclpy.shutdown()if __name__ == '__main__': main() |
---|
Запускаем это вот так py Вы можете увидеть это после программы Test_node1
Test_node2
Оба узла онлайн.
Но если вы замените этот файл приведенным выше node_001.py документ,но Сообщим об ошибке:
1 | node_001-1 1720692076.228787954: Publisher already registered for provided node name. If this is due to multiple nodes with the same name then all logs for that logger name will go out over the existing publisher. As soon as any node with that name is destructed it will unregister the publisher, preventing any further logs for that name from being published on the rosout topic. |
---|
В это время, если вы посмотрите на список узлов ros2, вы увидите:
12345 |
|
---|
То есть результаты узлов ros, запущенных с помощью метода запуска запуска ros2, и результатов запуска файла py могут отличаться. Ключ заключается в конфигурации запуска. Назовите узлы, созданные в процессе, с настроенным именем.
Ссылка на статью: https://cloud.tencent.com/developer/article/2435719