diff --git a/docs/assets/ros.svg b/docs/assets/ros.svg new file mode 100644 index 00000000..4462c8e0 --- /dev/null +++ b/docs/assets/ros.svg @@ -0,0 +1,183 @@ + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/en/ros.md b/docs/en/ros.md index 298e6d9a..866e9f42 100644 --- a/docs/en/ros.md +++ b/docs/en/ros.md @@ -1,33 +1,28 @@ -ROS -=== +# ROS -Main article: http://wiki.ros.org + -ROS is a widely used framework for developing complex and distributed robotic systems. +Main documentation: https://wiki.ros.org. -Installation ---- +**ROS** is a widely used framework for developing complex and distributed robotic systems. The [Clover autonomous flights platform](programming.md) is based on ROS. -Main article: http://wiki.ros.org/melodic/Installation/Ubuntu +## Installation ROS is already installed on [the RPi image](image.md). -To use ROS on a PC, we recommend using Ubuntu Linux [or a virtual machine such as Parallels Desktop Lite](https://itunes.apple.com/ru/app/parallels-desktop-lite/id1085114709?mt=12) or [VirtualBox](https://www.virtualbox.org)). +To install ROS on your PC you may address the [official installation documentation](https://wiki.ros.org/noetic/Installation/Ubuntu). For a quick start it's recommended to use [the virtual machine image with ROS and Clover simulator](simulation_vm.md). -> **Note** For ROS Melodic distribution, we recommend using Ubuntu 18.04. - -Concepts ---- +## Concepts ### Nodes -Main article: http://wiki.ros.org/Nodes +Main article: https://wiki.ros.org/Nodes. -ROS node is a special program (usually written in Python or C++) that communicates with other nodes via ROS topics and ROS services. Dividing complex robotic systems into isolated nodes provides certain advantages: reduced coupling of the code, increases re-usability and reliability. +ROS node is a special program (usually written in Python or C++) that communicates with other nodes via ROS topics and ROS services. Dividing complex robotic systems into isolated nodes provides certain advantages: reduced coupling of the code, increased reusability and reliability. -Many robotic libraries and the drivers are executed in the form of ROS-nodes. +Many robotic libraries and drivers are made as ROS nodes. -In order to turn an ordinary program into a ROS node, include a `rospy` or `roscpp` library, and insert the initialization code. +In order to turn an ordinary program into a ROS node, include the `rospy` (Python) or `roscpp` (C++) library, and insert the initialization code. An example of a ROS node in Python: @@ -36,32 +31,52 @@ import rospy rospy.init_node('my_ros_node') # the name of the ROS node -rospy.spin() # entering an endless cycle... +rospy.spin() # entering an infinite loop... ``` +> **Info** Any [autonomous flight script](programming.md) for Clover is a ROS node. + ### Topics -Main article: http://wiki.ros.org/Topics +Main article: https://wiki.ros.org/Topics -A topic is a named data bus used by the nodes for exchanging messages. Any node can *post* a message in a random topic, and *subscribe* to an arbitrary topic. +A topic is a named data bus used by the nodes for exchanging messages. Any node can *publish* a message to any topic, and *subscribe* to any topic. -An example of [`std_msgs/String`](http://docs.ros.org/api/std_msgs/html/msg/String.html) (line) message type posting in topic `/foo` in Python: +Для каждого созданного топика должен быть задан тип сообщений, которые по нему передаются. ROS включает в себя большое количество стандартных типов сообщений, покрывающих различные аспекты робототехники, но при необходимости возможно создание собственных типов сообщений. Примеры стандартных типов сообщений: + +Each topic has the a of messages it passes. ROS include a lot of standard message types, covering different aspects of robotics. Creating custom message types is also possible. Example of standard message types: + +|Message type|Description| +|-|-| +|[`std_msgs/Int64`](https://docs.ros.org/api/std_msgs/html/msg/Int64.html)|Integer number.| +|[`std_msgs/Float64`](https://docs.ros.org/api/std_msgs/html/msg/Float64.html)|Double-precision floating-point number| +|[`std_msgs/String`](https://docs.ros.org/api/std_msgs/html/msg/String.html)|String.| +|[`geometry_msgs/PoseStamped`](https://docs.ros.org/api/geometry_msgs/html/msg/PoseStamped.html)|Position and orientation of an object in a given [coordinate system](frames.md) and a time stamp (widely used for passing the robot pose or some robot's part pose).| +|[`geometry_msgs/TwistStamped`](https://docs.ros.org/api/geometry_msgs/html/msg/TwistStamped.html)|Linear and angular velocity of an object in a given coordinate system and a time stamp.| +|[`sensor_msgs/Image`](https://docs.ros.org/api/sensor_msgs/html/msg/Image.html)|Image (see the [article on working with the camera](camera.md)).| + +> **Info** See the rest of standard message types in packages: [`common_msgs`](http://wiki.ros.org/common_msgs), [`std_msgs`](https://wiki.ros.org/std_msgs), [`geometry_msgs`](https://wiki.ros.org/geometry_msgs), [`sensor_msgs`](https://wiki.ros.org/sensor_msgs), and others. + +Example of publishing a message of type [`String`]((https://docs.ros.org/api/std_msgs/html/msg/String.html)) in a topic `/foo` in Python: ```python from std_msgs.msg import String -# ... +rospy.init_node('my_ros_node') foo_pub = rospy.Publisher('/foo', String, queue_size=1) # creating a Publisher -# ... - -foo_pub.publish(data='Hello, world!') # posting the message +foo_pub.publish(data='Hello, world!') # publishing the message ``` -An example of subscription to topic `/foo`: +Example of subscription to a topic `/foo`: ```python +import rospy +from std_msgs.msg import String + +rospy.init_node('my_ros_node') + def foo_callback(msg): print(msg.data) @@ -69,7 +84,13 @@ def foo_callback(msg): rospy.Subscriber('/foo', String, foo_callback) ``` -You can also work with topics using the the `rostopic` utility. For example, using the following command, you can view messages published in topic `/mavros/state`: +You can read a topic message once, using `wait_for_message` function: + +```python +msg = rospy.wait_for_message('/foo', String, timeout=3) # wait for a message in /foo topic with timeout of 3 seconds +``` + +You can also work with topics using the `rostopic` utility. For example, using the following command, you can view messages published in topic `/mavros/state`: ```bash rostopic echo /mavros/state @@ -77,36 +98,87 @@ rostopic echo /mavros/state The `rostopic info` command shows the type of messages in the topic, and `rostopic hz` shows frequency of published messages. +Also you can monitor and visualize topics using [graphical tools of ROS](rviz.md). + ### Services -Main article: http://wiki.ros.org/Services +Main article: https://wiki.ros.org/Services A service can be assimilated to the a function that can be called from one node, and processed in another one. The service has a name that is similar to the name of the topic, and 2 message types: request type and response type. -An example ROS service invoking from Python: +Thus, ROS services implement [remote procedure call (RPC)](https://en.wikipedia.org/wiki/Remote_procedure_call) pattern. + +Example of invoking a ROS service in Python: ```python +import rospy from clover.srv import GetTelemetry -# ... +rospy.init_node('my_ros_node') # Creating a wrapper for the get_telemetry service of the clover package with the GetTelemetry type: get_telemetry = rospy.ServiceProxy('get_telemetry', srv.GetTelemetry) -# Invoking the service, and receiving the quadcopter telemetry: +# Invoking the service, and getting the quadcopter telemetry: telemetry = get_telemetry() ``` You can also work with the services using the `rosservice` utility. For instance, you can call service `/get_telemetry` from the command line: -```(bash) +```bash rosservice call /get_telemetry "{frame_id: ''}" ``` More examples of using the services for Clover quadcopter autonomous flights are available in the [documentation for node simple_offboard](simple_offboard.md). -Working on several PCs ---- +### Names + +Main article: https://wiki.ros.org/Names. + +Any topic, service or a parameter is identified with a unique name. A ROS name is hierarchical structure with a `/` symbol as a separator (which is close to a file name in a file system). + +Examples of ROS names: + +* `/` (global namespace) +* `/foo` +* `/stanford/robot/name` +* `/wg/node1` + +This names are global (close to global names in a file system). In practice, it's recommended to use *private* or *relative* names. + +#### Private name + +Each node can use its own private namespace (corresponding its name) for its resources. For example, `aruco_detect` node may publish such topics: + +* `/aruco_detect/markers` +* `/aruco_detect/visualization` +* `/aruco_detect/debug` + +When a node is referring its private resource, instead of `/aruco_detect/` namespace it may use `~` symbol: + +* `~markers` +* `~visualization` +* `~debug` + +Thus, creating a `foo` topic and the private namespace would look like this: + +```python +private_foo_pub = rospy.Publisher('~foo', String, queue_size=1) +``` + +#### Relative name + +Several nodes may group into a common namespace (for example, when there are several robots in the network). For referring topics and services in the current namespace, the opening `/` symbol is omitted. + +Example of create a `foo` topic in the current namespace: + +```python +relative_foo_pub = rospy.Publisher('foo', String, queue_size=1) +``` + +> **Hint** Generally, it's recommended to use private or relative names instead of global ones. + +### Working on several PCs Main article: http://wiki.ros.org/ROS/Tutorials/MultipleMachines. diff --git a/docs/ru/ros.md b/docs/ru/ros.md index a803cf74..b268da95 100644 --- a/docs/ru/ros.md +++ b/docs/ru/ros.md @@ -1,33 +1,28 @@ -ROS -=== +# ROS -Основная статья: http://wiki.ros.org + -ROS – это широко используемый фреймворк для создания сложных и распределенных робототехнических систем. +Основная документация: https://wiki.ros.org. -Установка ---- +**ROS** – это широко используемый фреймворк для создания сложных, распределенных робототехнических систем. На ROS основана [программная платформа Клевера](programming.md). -Основная статья: http://wiki.ros.org/melodic/Installation/Ubuntu +## Установка -ROS уже установлен на [образе для RPi](image.md). +ROS уже установлен на [образе для RPi для Клевера](image.md). -Для использования ROS на компьютере рекомендуется ОС Ubuntu Linux (либо виртуальная машина, например [Parallels Desktop Lite](https://itunes.apple.com/ru/app/parallels-desktop-lite/id1085114709?mt=12) или [VirtualBox](https://www.virtualbox.org)). +Для установки инструментов ROS на компьютере вы можете обратиться к [официальной документации](https://wiki.ros.org/noetic/Installation/Ubuntu) по установке. Для быстрого старта рекомендуется воспользоваться [образом виртуальной машины с ROS и симулятором Клевера](simulation_vm.md). -> **Note** Для дистрибутива ROS Melodic рекомендуется Ubuntu версии 18.04. - -Концепции ---- +## Концепции ### Ноды -Основная статья: http://wiki.ros.org/Nodes +Основная статья: https://wiki.ros.org/Nodes. -ROS-нода – это специальная программа (обычно написанная на Python или C++), которая взаимодействует с другими нодами посредством ROS-топиков и ROS-сервисов. Разделение сложных робототехнических систем на изолированные ноды дает определенные преимущества: понижается связанность кода, повышается переиспользуемость и надежность. +ROS-нода[^1] – это специальная программа (обычно написанная на Python или C++), которая взаимодействует с другими нодами посредством ROS-топиков и ROS-сервисов. Разделение сложных робототехнических систем на изолированные ноды дает определенные преимущества: понижается связанность кода, повышается переиспользуемость и надежность. Очень многие робототехнические библиотеки и драйвера выполнены именно в виде ROS-нод. -Для того, чтобы превратить обычную программу в ROS-ноду, необходимо подключить к ней библиотеку `rospy` или `roscpp` и добавить инициализирующий код. +Для того, чтобы превратить обычную программу в ROS-ноду, необходимо подключить к ней библиотеку `rospy` (Python) или `roscpp` (C++) и добавить инициализирующий код. Пример ROS-ноды на языке Python: @@ -39,22 +34,36 @@ rospy.init_node('my_ros_node') # имя ROS-ноды rospy.spin() # входим в бесконечный цикл... ``` +> **Info** Любая [программа для автономного полета Клевера](programming.md) является ROS-нодой. + ### Топики -Основная статья: http://wiki.ros.org/Topics +Основная статья: https://wiki.ros.org/Topics. Топик – это именованная шина данных, по которой ноды обмениваются сообщениями. Любая нода может *опубликовать* сообщение в произвольный топик, а также *подписаться* на произвольный топик. -Пример публикации сообщения типа [`std_msgs/String`](http://docs.ros.org/api/std_msgs/html/msg/String.html) (строка) в топик `/foo` на языке Python: +Для каждого созданного топика должен быть задан тип сообщений, которые по нему передаются. ROS включает в себя большое количество стандартных типов сообщений, покрывающих различные аспекты робототехники, но при необходимости возможно создание собственных типов сообщений. Примеры стандартных типов сообщений: + +|Тип сообщения|Описание| +|-|-| +|[`std_msgs/Int64`](https://docs.ros.org/api/std_msgs/html/msg/Int64.html)|Целое число.| +|[`std_msgs/Float64`](https://docs.ros.org/api/std_msgs/html/msg/Float64.html)|Число с плавающей точкой (дробное) двойной точности.| +|[`std_msgs/String`](https://docs.ros.org/api/std_msgs/html/msg/String.html)|Строка.| +|[`geometry_msgs/PoseStamped`](https://docs.ros.org/api/geometry_msgs/html/msg/PoseStamped.html)|Позиция и ориентация объекта с заданной [системой координат](frames.md) и временной меткой (широко используется для передачи текущей позиции робота и его частей).| +|[`geometry_msgs/TwistStamped`](https://docs.ros.org/api/geometry_msgs/html/msg/TwistStamped.html)|Линейная и угловая скорость объекта с заданной системой координат и временной меткой.| +|[`sensor_msgs/Image`](https://docs.ros.org/api/sensor_msgs/html/msg/Image.html)|Изображение (см. [статью о работе с камерой](camera.md))| + +> **Info** Смотрите остальные стандартные типы сообщений в пакетах [`common_msgs`](http://wiki.ros.org/common_msgs), [`std_msgs`](https://wiki.ros.org/std_msgs), [`geometry_msgs`](https://wiki.ros.org/geometry_msgs), [`sensor_msgs`](https://wiki.ros.org/sensor_msgs) и других. + +Пример публикации сообщения типа [`std_msgs/String`](https://docs.ros.org/api/std_msgs/html/msg/String.html) (строка) в топик `/foo` на языке Python: ```python +import rospy from std_msgs.msg import String -# ... +rospy.init_node('my_ros_node') -foo_pub = rospy.Publisher('/foo', String, queue_size=1) # создаем Publisher'а - -# ... +foo_pub = rospy.Publisher('/foo', String, queue_size=1) # создаем Publisher foo_pub.publish(data='Hello, world!') # публикуем сообщение ``` @@ -62,14 +71,27 @@ foo_pub.publish(data='Hello, world!') # публикуем сообщение Пример подписки на топик `/foo`: ```python +import rospy +from std_msgs.msg import String + +rospy.init_node('my_ros_node') + def foo_callback(msg): print(msg.data) # Подписываемся. При получении сообщения в топик /foo будет вызвана функция foo_callback. rospy.Subscriber('/foo', String, foo_callback) + +rospy.spin() # входим в бесконечный цикл, чтобы программа не завершила работу ``` -Также, существует возможность работы с топиками с помощью утилиты `rostopic`. Например, с помощью следующей команды можно просматривать сообщения, публикуемые в топик `/mavros/state`: +Вы можете прочитать данные из топика однократно, используя функцию `wait_for_message`: + +```python +msg = rospy.wait_for_message('/foo', String, timeout=3) # ждать сообщения в топике /foo в таймаутом 3 с +``` + +Также существует возможность работы с топиками с помощью утилиты `rostopic`. Например, с помощью следующей команды можно просматривать сообщения, публикуемые в топик `/mavros/state`: ```bash rostopic echo /mavros/state @@ -77,18 +99,23 @@ rostopic echo /mavros/state Команда `rostopic info` позволяет узнать тип сообщений в топике, команда `rostopic hz` — частоту публикуемых в топике сообщений. +Также данные в топиках можно визуализировать и в [графических инструментах ROS](rviz.md). + ### Сервисы -Основная статья: http://wiki.ros.org/Services +Основная статья: https://wiki.ros.org/Services. Сервис – это некоторый аналог функции, которая может быть вызвана из одной ноды, а обработана в другой. У сервиса есть имя, аналогичное имени топика, и 2 типа сообщений: тип запроса и тип ответа. +Таким образом, сервисы реализуют паттерн [*удаленного вызова процедур*](https://ru.wikipedia.org/wiki/Удалённый_вызов_процедур). + Пример вызова ROS-сервиса из языка Python: ```python +import rospy from clover.srv import GetTelemetry -# ... +rospy.init_node('my_ros_node') # Создаем обертку над сервисом get_telemetry пакета clover с типом GetTelemetry: get_telemetry = rospy.ServiceProxy('get_telemetry', srv.GetTelemetry) @@ -105,9 +132,62 @@ rosservice call /get_telemetry "{frame_id: ''}" Больше примеров использования сервисов для автономных полетов квадрокоптера Клевер можно посмотреть в [документации ноды simple_offboard](simple_offboard.md). -Работа на нескольких машинах ---- +### Имена -Основная статья: http://wiki.ros.org/ROS/Tutorials/MultipleMachines. +Основная статья: https://wiki.ros.org/Names. + +Любой топик, сервис или параметр идентифицируется с помощью уникального имени. ROS-имя представляет собой иерархическую структуру с символом `/` в качестве разделителя (сходно с именами в файловой системе). + +Примеры ROS-имен: + +* `/` (глобальное пространство имен) +* `/foo` +* `/stanford/robot/name` +* `/wg/node1` + +Эти имена является глобальными (аналогично полному пути в файлу в файловой системе). На практике рекомендуется использование *приватных* или *относительных* имен. + +#### Приватное имя + +Каждая нода может использовать собственное приватное пространство имен (соответствующее имени ноды) для своих ресурсов. Например, нода `aruco_detect` может публиковать такие топики: + +* `/aruco_detect/markers` +* `/aruco_detect/visualization` +* `/aruco_detect/debug` + +Когда нода ссылается на свой приватный ресурс, вместо пространства имен (`/aruco_detect/`) используется символ `~`, например: + +* `~markers` +* `~visualization` +* `~debug` + +Таким образом, создание топика `foo` в приватном пространство имен из Python будет выглядеть так: + +```python +private_foo_pub = rospy.Publisher('~foo', String, queue_size=1) +``` + +#### Относительное имя + +Несколько нод также могут объединяться в общее пространство имен (например, при одновременной работе нескольких роботов). Для того, чтобы ссылаться на топики с учетом общего пространства имен, в названии ресурса опускается начальный символ `/`. + +Пример создание топика `foo` с учетом общего пространства имен: + +```python +relative_foo_pub = rospy.Publisher('foo', String, queue_size=1) +``` + +> **Hint** В общем случае всегда рекомендуется использовать приватные или относительные имена ресурсов и никогда не использовать глобальные. + +## Работа на нескольких машинах + +Основная статья: https://wiki.ros.org/ROS/Tutorials/MultipleMachines. Преимуществом использования ROS является возможность распределения нод на несколько машин в сети. Например, ноду, осуществляющую распознавание образом на изображении можно запустить на более мощном компьютере; ноду, управляющую коптером можно запустить непосредственно на Raspberry Pi, подключенном к полетному контроллеру и т. д. + +## Дополнительные материалы + +* Учебник по ROS от Voltbro - http://docs.voltbro.ru/starting-ros/. +* Другие книги по ROS - https://wiki.ros.org/Books. + +[^1]: Также встречается перевод "узел".