roslaunch, rosrun управление запуском

rosrun

rosrun - это команда, которая может запустить только одну ноду в выбранном пакете. Ранее мы уже запускали ноды рос, например

rosrun turtlesim turtlesim_node

Это команды найдет пакет turtlesim и запустит в нем программу turtlesim_node

Подготовка python скриптов для запуска

В параметрах программы rosrun необходимо указать "программу", а не имя python файла. Поэтому мы должны превратить python скрипты в \"программу\". Мы рассматривали такую задачу в части введения в Python.

Если кратко, то мы должны убедиться, что python скрипт начинается со строчки

#!/usr/bin/env python

И для скрипта добавлена возможность запуска

chmod +x pub.py

Если мы сохраним программу издателя pub.py в директорию /src нашего пакета и выполним "подготовку" к запуску, то мы сможем запустить процесс публикации данных командой

rosrun my_package pub.py

Важное замечание

Важно учесть, что в нашем рабочем окружении (папка catkin_ws) место расположения исходников проекта и место расположения пакета после выполнения сборки одно и тоже.

По этой причине конкретно в нашем случае нам не нужно добавлять дополнительных команд в сборку для копирования файлов пакета. Но в реальных проектах очень часто эти директории разные. Поэтому для всех python файлов необходимо в файл CMakeLists.txt добавить задание копирования из папки с исходниками в папку для запуска.

install(PROGRAMS
  src/pub.py
  DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}
)

А ресурсные файлы и тому подобное необходимо устанавливать (переносить в рабочую папку), например, вот так

install(DIRECTORY
  launch
  DESTINATION ${CATKIN_PACKAGE_SHARE_DESTINATION}
)

Где launch - это директория с .launch файлами

roslunch , управление запуском множества нод

Раньше мы использовали для запуска утилиту rosrun, которая запускает конкретный исполняемый файл.

В реальных системах одновременно должны работать множество программ. Для их запуска и конфигурации служит утилита roslaunch

Используя roslaunch, возможно дополнительно настраивать исполняемые файлы в момент их запуска (передавать параметры, изменять имена и тп)

roslaunch использует файлы с расширением .launch, которые представляет собой обычный XML файл.

Давайте создадим файл ./launch/demo.launch

<launch>
  <node pkg="my_package" type="pub.py" name="topic_publisher1"/>
  <node pkg="my_package" type="sub.py" name="topic_subscriber1"/> 
  <node pkg="my_package" type="pub.py" name="topic_publisher2"/>
  <node pkg="my_package" type="sub.py" name="topic_subscriber2"/>
</launch>

Файлы pub.py и sub.py Можно взять из примеров работы с топиками, и их нужно сохранить в директорию src

Теги, необходимые для запуска узла с помощью команды roslaunch, описаны в теге launch. Тег node описывает ноды, который которые необходимо запускать с помощью roslaunch. Параметры включают «pkg», «type» и «name».

Параметр Описание
pkg Имя пакета
type Название ноды, которая будет выполняться
name Имя (исполняемое имя), используемое при выполнении ноды, соответствующего выше параметру type. Обычно это имя совпадает, но при его запуске можно использовать другое имя.

После сохранения файла мы можем его запустить, выполнив

$ roslaunch my_package demo.launch --screen

NODES
  /
    topic_publisher1 (my_package/topic_publisher.py)
    topic_publisher2 (my_package/topic_publisher.py)
    topic_subscriber1 (my_package/topic_subscriber)
    topic_subscriber2 (my_package/topic_subscriber)

ROS_MASTER_URI=http://localhost:11311

process[topic_publisher1-1]: started with pid [24963]
process[topic_subscriber1-2]: started with pid [24964]
process[topic_publisher2-3]: started with pid [24965]
process[topic_subscriber2-4]: started with pid [24978]

Если добавить параметр --screen, информация о работе запущенных программ будет отображена на экране текущего терминала.

Или для тестов мы можем указывать просто путь к .launch файлу

$ roslaunch /home/user/catkin_ws/src/my_package/launch/demo.launch --screen

Как мы видим, запущенно 4 процесса с разными pid. Также мы можем увидеть список запущенных нод

$ rosnode list

/rosout
/topic_publisher1
/topic_publisher2
/topic_subscriber1
/topic_subscriber2

Объединение процессов в группы

Если мы посмотрим на список топиков

$ rostopic list
===
/welcome_topic

То поймем, что оба Издателя (Publisher) публикуют данные в один топик /welcome_topic (других топиков не создана) и каждый из подписчиков получает сообщения сразу от двух Издателей. Скорее всего, такой режим работы нам не интересен.

Если мы хотим, чтобы один конкретный Издатель и Подписчик были изолированы от аналогичных процессов, мы можем объединить их в группы.

Создадим новый файл запуска ./launch/demo2.launch

<launch>
  <group ns="ns1">
    <node pkg="my_package" type="pub.py" name="topic_publisher"/>
    <node pkg="my_package" type="sub.py" name="topic_subscriber"/>
  </group>
  <group ns="ns2">
    <node pkg="my_package" type="pub.py" name="topic_publisher"/>
    <node pkg="my_package" type="sub.py" name="topic_subscriber"/>
  </group>
</launch>

Запустим новый файл

$ roslaunch my_package demo2.launch
$ rostopic list

/ns1/welcome_topic
/ns2/welcome_topic

Мы видим, что создано два отдельных топика, с которым работает один Издатель и один Подписчик.

$ rostopic info /ns1/welcome_topic


Type: std_msgs/String

Publishers:
 * /ns1/topic_publisher (http://cola:44225/)


Subscribers:
 * /ns1/topic_subscriber (http://cola:44043/)



$ rostopic info /ns2/welcome_topic

Type: std_msgs/String


Publishers:
 * /ns2/topic_publisher (http://cola:45259/)


Subscribers:
 * /ns2/topic_subscriber (http://cola:35017/)

Установка переменных окружения при запуске

Ранее мы уже разобрали, как работает Сервер Параметров. Но его использование все еще было не таким удобным, если бы мы решили изменить какой либо параметр по умолчанию, то нам бы пришлось это делать руками через утилиту rosparams при каждом запуске.

Чтобы решить данную проблему, мы можем использовать возможность передавать параметры в запускаемые программы через .launch файлы

Рассмотрим пример (для файла params.py который мы создали когда работали с параметрами)

<launch>
    <node pkg="my_package" type="params.py" name="params_demo" output="screen" >
        <param name="my_param" value="launch_file_param"/>
    </node>
</launch>

Если файл запустить, то мы увидим, что значение по умолчанию изменено на то, которое мы задали в .launch файле

process[params_demo-1]: started with pid [6825]
launch_file_param

В ветке node добавились элементы param с настройками. Открывая такой файл, сразу видно, какие параметры возможно конфигурировать, а также их значения по умолчанию.

Если запустить этот файл, то мы увидим что программа получила параметр из нашего .launch файла.

Вторым параметром в функции get_param указывается значение по умолчанию, если параметр не определен в .launch файле.

Параметры возможно передавать при запуске через rosrun

rosrun my_package params.py _my_param:=run_file_param

Подключение других .launch файлов \

В реальных проектах запускаются десятки нод. Конфигурировать каждую из них в одном файле не всегда удобно. К тому же обычно сторонние пакеты уже содержат подходящие .launch файлы. Поэтому существуют механизм include, который позволяет подключать другие файлы запуска.

Приведем пример

<launch>
 <include file="$(find my_package)/launch/test_params.launch">
     <arg name="device" value="/dev/ttyS1"/>
  </include>
  <include file="$(find navibro)/camera/camerav1_640x480.launch"/>
  <include file="$(find navibro)/launch/aruco_detect.launch"/>
  <include file="$(find navibro)/launch/fiducial_slam.launch"/>
</launch>

В этом примере мы подключаем файл test_params.launch , который находиться в нашем пакете, и настраиваем его на работу через устройство /dev/ttyS1.. А также подключаем три других .launch файла из другого пакета.

Использование условий if и unless

При написании сложный .launch файлов, очень помогают атрибуты if и unless, которые позволяют формировать простые алгоритмы ветвления при работе с roslaunch

Приведем несколько примеров

<launch>
   <arg name="have_serial" value="true"/>

   <group if="$(arg have_serial)">
     <!-- Блок выполнится только если have_serial установлено в true -->
     <node pkg="my_package" type="test_params.py" name="my_package" output="log" respawn="true">
  </group>
  <!-- Также if можно использовать для одного тега-->
  <include if="$(arg have_serial)" file="$(find my_package)/launch/test_params.launch">
    <arg name="device" value="/dev/ttyS1"/>
  </include>
</launch>

Атрибут unless работает противоположно атрибуту if. Если значение 0 то блок выполняется.

Значение атрибутов для if и unless должно быть булевым типом данных(0,1,true,false)

results matching ""

    No results matching ""