1 of 27

Введение в Robot Operating System

Антон Филатов, СПБГЭТУ “ЛЭТИ”

2 of 27

Что такое ROS (Robot Operating System)?

  • “Мета-” операционная система для роботов
  • Основная цель в обеспечении переиспользования кода в робототехнике
  • Широко используется
  • Open source
  • Поддерживается Open Source Robotics Foundation (OSRF)
  • Мощный, гибкий, но сложный

2

3 of 27

Где ROS используется

PR2 Turtlebot HERB STAIR

Автономное движение и взаимодействие

3

4 of 27

Установка ROS

Полная инструкция для установки

http://wiki.ros.org/ROS/Installation

  1. Настроить репозитории
  2. sudo apt-get install ros-noetic-desktop-full
  3. Установить дополнительные утилиты

4

5 of 27

Основы ROS

5

6 of 27

Как запустить ROS

Основная команда, запускающая мастер-процесс ROS

По команде roscore запустятся:

  • ROS мастер процесс
  • Сервер параметров ROS
  • Утилиты логов rosout

6

user@user-pc:~$ roscore

7 of 27

Структура каталогов рабочей области

example_ws/ -- Корень каталога

src/ -- Исходные коды

build/ -- Генерируется

devel/ -- автоматически

  • src - необходимо создать вручную, содержит исходные коды
  • build - содержит артефакты сборки пакетов
  • devel - содержит скрипты и библиотеки для запуска программ из пакетов

7

8 of 27

Структура каталогов пакетов

example_package/ -- Каталог пакета

include/ -- C++ headers

msg/ -- Директория для своих типов сообщений

src/ -- Директория для исходных кодов

srv/ -- Директория для своих типов сервисов

scripts/ -- Директория для исполнимых скриптов

CMakeLists.txt -- CMake файл пакета

Package.xml -- Файл с описанием зависимостей

8

9 of 27

Задача 1. Создать собственное рабочее пространство и пакет

Создать рабочее пространство и пакет с такой структурой:

/catkin_ws

/devel [генерируется командой catkin_make]/build [генерируется командой catkin_make]

/src/ros_exercises [Пустой пакет]�

9

10 of 27

Publishers, Subscribers, Topics

10

11 of 27

Nodes and topics.

Программная единица в ROS - нода.

Одна нода = один исполняемый файл.

У нод нет общей памяти.

Ноды обмениваются информацией через топики.

Топик - “канал” между нодами.

Единица переданной информации - сообщение

11

Node

Node

Node

Node

Topic

Topic

Topic

12 of 27

Topics

  • Мы не знаем, кто пишет сообщения в топик
  • Мы не знаем, кто читает сообщения из топика

12

13 of 27

Topics.

Мастер процесс ROS знает, какие ноды подписаны на существующие в системе топики и передаёт им сообщения, когда кто-то публикует сообщение в топик.

Атрибуты топика:

  • Имя
  • Тип передаваемого сообщения

13

Node

Node

Node

Node

Node

14 of 27

Publishers и subscribers.

Атрибуты subscriber-а:

  • Имя топика
  • Тип сообщения
  • Функция-обработчик сообщения

Атрибуты publisher-а:

  • Имя топика
  • Тип сообщения

14

Node

Subscriber

Subscriber

Publisher

15 of 27

Запуск нод

Чтобы узнать, какие ноды запущены

Чтобы узнать информацию о ноде

Для запуска ноды

15

user@user-pc:~$ rosnode list

user@user-pc:~$ rosnode info <node name>

В новом терминале

user@user-pc:~$ rosrun <package> <node> [__name:=<node name>]

16 of 27

Publisher. Python example

#! /usr/bin/env python

import rospy

from geometry_msgs.msg import Twist

rospy.init_node('commander')

pub=rospy.Publisher('/command',

Twist,

queue_size=10)

msg=Twist()

msg.linear.x=1

pub.publish(msg)

16

Notes:

  • Twist == geometry_msgs/Twist
  • publish() не выполнится, если publisher не успел создаться

[пользоваться sleep()]

17 of 27

Subscriber. Python example.

#! /usr/bin/env python

import rospy

from geometry_msgs.msg import Twist

def callback(msg):

rospy.loginfo(msg)

rospy.init_node('command_listener')

rospy.Subscriber('/listener',

Twist,

callback)

rospy.spin()

17

Notes:

  • Twist == geometry_msgs/Twist
  • type(msg) == Twist
  • spin() - для засыпания основного потока

18 of 27

Сервисы.

18

Node#1

Node#2

Request

Response

Time

Топики

Сервисы

многие-ко-многим

один-к-одному

Не ждём ответа

Ждём ответа

Не получаем ответа

Получаем ответ

user@user-pc:~$ rosservice call <service name> <message>

user@user-pc:~$ rosservice info <service name>

user@user-pc:~$ rossrv show <service type>

19 of 27

Клиент Service. Python example.

#! /usr/bin/env python

import rospy

from turtlesim.srv import Spawn

rospy.init_node('spawn_caller')

rospy.wait_for_service('/spawn')

spawn_func=rospy.ServiceProxy('/spawn',Spawn)

res = spawn_func(4.0, 4.0, 0.0, 'victim')

# isinstance(res, SpawnResponse) == True

19

Spawn == turtlesim/Spawn

Service:

  • ServiceRequest
  • ServiceResponse

user@user-pc:~$ rosservice call /spawn "{x: 0.0, y: 0.0,

theta: 0.0, name: 'victim'}"

20 of 27

Сервер Service. Python example.

#! /usr/bin/env python

import rospy

from turtlesim.srv import Spawn

from turtlesim.srv import SpawnResponse

def callback(req):

# isinstance(req, SpawnRequest) == True

rospy.loginfo('spawn request: %s',str(req))

return SpawnResponse(req.name)

rospy.init_node('spawn_handler')

rospy.Service('/spawn',

Spawn,

callback)

rospy.spin()

20

Service:

  • ServiceRequest
  • ServiceResponse

21 of 27

Дополнительные возможности

21

22 of 27

Rqt_graph

22

user@user-pc:~$ rqt_graph

user@user-pc:~$ rosrun rqt_graph rqt_graph

23 of 27

Launch файлы.

  • Быстрый запуск нескольких нод
  • Передать нодам параметры
  • Включение одних файлов в другие

23

user@user-pc:~$ roslaunch <package> <launch file name>

user@user-pc:~$ roslaunch <full path to launch file name>

24 of 27

Launch files. Body

24

<launch>

<param name="speed" value="5"/>

<arg name="external_arg" default="optional_val">

<node pkg="turtlesim"

type="turtlesim_node"

name="$(arg external_arg)"

output="screen"/>

<node pkg="my_package" type="program.py" name="exec">

<param name="speed" value="2"/>

<remap from="old_topic_name"

to="new_topic_name"/>

</node>

</launch>

25 of 27

Include in launch file

<launch>

<include file="/home/user/ex_ws/src/file.launch" />

<include file="$(find my_package)/other.launch" />

</launch>

25

26 of 27

Пример кода ноды, использующей параметры

#! /usr/bin/env python

#this is pointless example of program.py

import rospy

import time

from std_msgs.msg import String

rospy.init_node('pointless thing')

pub=rospy.Publisher('/old_topic_name',String,queue_size=10)

time.sleep(1)

msg=String()

msg.data=rospy.get_param('~private_param') + str(rospy.get_param('/global_param'))

pub.publish(msg)

26

27 of 27

Rosbag

Утилита для записи сообщений из топиков в файл

В launch-файле:

27

user@user-pc:~$ rosrun rosbag play <file.bag>

user@user-pc:~$ rosbag play <file.bag>

user@user-pc:~$ rosbag record -a -o <outfile.bag>

<node pkg=”rosbag” type=”record” name=”rec”

args=”-o <folder> /topic1 /topic2” />