# Издатель команд для робота

{% embed url="<https://youtu.be/ZFB5oourBfg>" %}

### Введение

В отличие от прошлой программы, где наши сигналы не несли какой-то технической смысловой нагрузки и были просто сообщениями “**Hello ROS**”, сейчас мы будем отправлять реальные команды для робота. Однако как вы увидите, принципы построения программы при этом останутся такими же. Для сохранения преемственности мы даже используем нашу прошлую программу Издатель (*publisher.py*) в качестве заготовки.

### Пишем код

{% hint style="info" %}
Писать новую программу вы можете как на компьютере в ранее созданной папке */ros\_course* или же используя расширение [Remote-SSH](/new_bazovyi-kurs-po-ros/lesson1/nastroika-vscode.md)[ ](broken://pages/fUoNje70ynTEsPDe8LyE)подключиться к файловой системе робота, создать там папку */ros\_course* и писать программу там.
{% endhint %}

Назовем нашу программу: *publisher\_for\_robot.py* и перейдем непосредственно к программированию.&#x20;

Сформулируем нашу задачу - заставим робота двигаться вперед в течение 1 секунды со скоростью 5 сантиметров в секунду, затем поворачивать направо в течение 2-х секунд с угловой скоростью 0.5 радиана в секунду, и дальше двигаться налево по дуге с угловой скоростью 1 радиан в секунду и линейной скоростью 10 сантиметров в секунду.

Итак, как мы и говорили давайте возьмем программу *Издатель* из нашего прошлого занятия и немного ее модифицируем:

```python
#прошлая программа publisher.py

#! /usr/bin/env python3
# -*- coding: utf-8 -*-

import rospy
from std_msgs.msg import String

rospy.init_node("welcome_node")
pub = rospy.Publisher("welcome_topic", String, queue_size=10)

s = String()
s.data = "Hello ROS"

while not rospy.is_shutdown():
    pub.publish(s)
    rospy.sleep(1)
```

Импорт библиотеки **rospy** - остается. Это неизменный атрибут любой программы под ROS.

```python
#! /usr/bin/env python3
# -*- coding: utf-8 -*-

import rospy
```

А вот вместо *String*, который мы использовали, чтобы публиковать “**Hello ROS**”, мы будем импортировать структуру данных для управления скоростями - *Twist*:

```python
from geometry_msgs.msg import Twist
```

Для создания *ноды* мы используем стандартный метод *init\_node()*, но давайте назовем ее, например - **moving\_node**:

```python
rospy.init_node("moving_node")
```

Ну а раз управляем параметрами угловой скорости мы через публикацию структуры данных *Twist* в топик **/cmd\_vel**, то и Издатель сконфигурируем на этот топик и эту структуру данных. Вот так:

```python
pub = rospy.Publisher("cmd_vel", Twist, queue_size=10)
```

Теперь вместо объекта *String*, создадим объект *Twist*, который и будем публиковать:

```python
vel = Twist()
```

Мы не будем использовать стандартный цикл *while not rospy.is\_shutdown():* потому что хотим, чтобы робот произвел последовательность передвижений только один раз, а не повторял ее бесконечно. Так что цикл - стираем.

А вот дальше, построчно, мы будем заполнять нашу структуру данных - *vel*, значениями угловых и линейных скоростей и публиковать ее при помощи созданного нами Издателя **pub** с той временной задержкой, которая нам нужна.

Заставим робота двигаться вперед в течение 1 секунды со скоростью 5 сантиметров в секунду.  Перед тем, как поехать, сделаем небольшую задержку в 1 секунду. Заполним значение линейной скорости по Х нашей структуры данных *vel*, значением 0.05. Опубликуем ее и сделаем паузу на 1 секунду:

```python
rospy.sleep(1)
vel.linear.x = 0.05
pub.publish(vel)
rospy.sleep(1)
```

Теперь, дадим роботу команду поворачивать направо в течение 2-х секунд с угловой скоростью 0.5 радиана в секунду. Обратите внимание, что нам надо обнулить линейное значение скорости, иначе оно останется равным 0.05 и робот поедет по дуге, а не будет разворачиваться на месте как мы этого хотим. Снова опубликуем *vel* при помощи того же паблишера **pub** и сделаем паузу на 2 секунды:

```python
vel.linear.x = 0.00
vel.angular.z = -0.5
pub.publish(vel)
rospy.sleep(2)
```

И последнее - дуга налево.

Линейная скорость по Х: 0,1 метр в секунду, а угловая по Z: 1 радиан в секунду. Заполняем значения и публикуем.&#x20;

```python
vel.linear.x = 0.1
vel.angular.z = 1
pub.publish(vel)
rospy.sleep(2)
```

Теперь остановим нашего робота и выйдем из программы. Чтобы остановить робота, надо обнулить значения угловой и линейной скорости, а затем опубликовать нашу структуру данных:

```python
vel.linear.x = 0
vel.angular.z = 0
pub.publish(vel)
```

### Запускаем и тестируем

Вот и все, сохраним нашу программу. Теперь нам надо запустить это все на роботе и посмотреть как оно будет работать.

{% hint style="info" %}
В случае, если вы сохранили программу на компьютере, то вам необходимо перенести её на робота. Для этого можно воспользоваться командой **scp:**

`scp /home/$USER/ros_course/publisher_for_robot.py pi@turtlebro37.local:/home/pi/ros_course/publisher_for_robot.py`

При копировании файла робот запросит пароль, по умолчанию, на наших роботах пароль ***brobro***
{% endhint %}

Теперь зайдем на самого робота и запустим файл. Перед запуском убедитесь, что перед роботом достаточно места и он не стоит на столе.&#x20;

```python
ssh pi@turtlebro37.local

python3 ros_course/publisher_for_robot.py
```

Все работает так как мы хотели !


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://voltbro.gitbook.io/new_bazovyi-kurs-po-ros/lesson3/robot-publisher.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
