Глава 4. ROS publisher

1. Цель занятия и обзор плана

На этом занятии мы напишем свою первую ноду, посылающую команды для управления катамараном, а также вспомним азы языка Python.

2. Теоретический материал

2.1. Язык Python

Язык Python является высокоуровневым интерпретируемым языком программирования, ориентированным на читаемость и простоту написания кода. Его синтаксис минималистичен и стремится отражать логику программы в максимально прозрачной форме, что делает Python удобным как для начинающих, так и для разработчиков, работающих над крупными проектами. Стандартная библиотека предоставляет широкий набор инструментов, а экосистема сторонних пакетов охватывает практически любые области применения: научные вычисления, веб-разработку, автоматизацию, работу с данными и многое другое.

Популярность Python объясняется сочетанием низкого порога входа, мощных возможностей и активного сообщества, создающего и развивающего инфраструктуру библиотек. Он активно используется в образовательных и исследовательских средах, в промышленной автоматизации, робототехнике и машинном обучении. В рамках ROS Python является одним из основных языков для написания нод, взаимодействия с системой сообщений, создания инструментов мониторинга и разработки быстрых прототипов. Благодаря простоте интеграции и наличию пакета rclpy, разработчик может создавать полноценные коммуникационные узлы, таймеры, сервисы и действия, используя выразительный и лаконичный синтаксис Python.

В курс не входит изучение непосредственно языка Python (предполагается, что слушатель его уже знает или изучит самостоятельно). Однако, мы кратко напомним основные конструкции языка, применяемые на курсе.

Переменные, операции, комментарии, вывод на консоль

Переменные создаются при присваивании и могут принимать значения любых типов; операции позволяют выполнять вычисления и формировать строки, комментарии начинаются символом #, а вывод осуществляется через print().

x = 10 # переменная
y = x + 5 # операция
print("Результат:", y)

Массивы, кортежи

Списки являются изменяемыми последовательностями, а кортежи — неизменяемыми; оба вида структур позволяют хранить наборы данных и обращаться к ним по индексу.

arr = [1, 2, 3]
tpl = (10, 20, 30)
print(arr[1], tpl[2])

Операция ветвления

Ветвление выполняется через if…​elif…​else, что позволяет выбирать различные ветви выполнения в зависимости от условий.

x = 7
if x > 10:
    print("Больше 10")
elif x == 7:
    print("Равно 7")
else:
    print("Другое значение")

Подключение библиотек

Импорт модулей через import позволяет использовать внешние функции и объекты.

import math
print(math.sqrt(25))

Функции

Функции, определяемые ключевым словом def, позволяют структурировать код и многократно переиспользовать его логику.

def add(a, b):
    return a + b

print(add(3, 4))

Точка входа в программу

Условие if name == "main": определяет участок кода (место начала выполнения программы), выполняющийся только при прямом запуске файла, но не при его импорте как модуля.

def run():
    print("Старт программы")

if __name__ == "__main__":
    run()

Цикл for

Цикл for перебирает элементы последовательностей или диапазоны значений.

for i in range(3):
    print("Итерация", i)

Цикл while

Цикл while выполняется, пока истинно условие, что удобно при неопределённом числе повторений.

x = 3
while x > 0:
    print(x)
    x -= 1

Классы и понятие self

Классы объединяют данные и методы; параметр self используется для доступа к свойствам конкретного экземпляра.

class Counter:
    def __init__(self):
        self.value = 0

    def inc(self):
        self.value += 1

c = Counter()
c.inc()
print(c.value)

Наследование

Наследование позволяет создавать новые классы на базе существующих. Базовый класс может определять интерфейс, а дочерние классы реализуют конкретную логику.

class Figure:
    def square(self):
        raise NotImplementedError("Метод square() должен быть реализован в подклассе")

class Rectangle(Figure):
    def __init__(self, w, h):
        self.w = w
        self.h = h

    def square(self):
        return self.w * self.h


class Circle(Figure):
    def __init__(self, r):
        self.r = r

    def square(self):
        return math.pi * self.r * self.r

figures = [Rectangle(3, 4), Circle (10)]

for f in figures:
    print(f.square())

Когда говорят о наследовании, в смысле программирования, то часто упоминают принцип подстановки Барбары Лисков:

если q(x) является свойством, верным относительно объектов x некоторого типа T, тогда q(y) также должно быть верным для объектов y типа S, где S является подтипом типа T
— Барбара Лисков
Liskov

Но можно выразиться и более понятно:

Всякая селёдка — рыба, но не всякая рыба — селёдка
— капитан Врунгель
Vrungel

Говоря о нашем примере: любой прямоугольник(круг) - фигура, но не любая фигура - прямоугольник (круг).

2.2. IDE

Интегрированная среда разработки (IDE) представляет собой программный инструмент, объединяющий в одном интерфейсе редактор кода, средства отладки, систему подсветки синтаксиса, работу с файлами и механизм запуска программ. В контексте Python одной из наиболее удобных и универсальных сред считается Visual Studio Code (VSCode). Она сочетает лёгкость, высокую скорость работы и широкие возможности расширения: плагины для Python добавляют интеллектуальные подсказки, автоматическое форматирование, анализ ошибок, встроенный терминал и средства отладки. VSCode хорошо подходит как для быстрого прототипирования небольших скриптов, так и для работы над крупными ROS-проектами, обеспечивая комфортную навигацию по структуре пакетов, удобную интеграцию с Git и гибкую настройку рабочего окружения.

2.3. ИИ-технологии в помощь изучающему Python

Современные нейросетевые инструменты позволяют эффективно изучать Python благодаря интерактивному формату обучения: пользователь может задавать уточняющие вопросы, просить объяснить незнакомый фрагмент кода, получить альтернативные варианты решения или подбор примеров для конкретной задачи. Такой подход обеспечивает индивидуальный темп освоения материала и снимает барьер перед сложными концепциями, поскольку нейросеть может разбирать код построчно, комментировать логику, предлагать исправления и дополнения. В результате изучение языка становится более доступным и прикладным: обучающийся не просто читает теорию, а сразу получает подробные ответы по своей собственной проблеме или сценарию использования.

Далее приведены примеры запросов (их ещё называют "промпты") к нейросети https://chat.deepseek.com/ и её ответы.

Напиши на python программу для перевода градусов в радианы и поясни что значит каждая строчка для человека, никогда не писавшего на python

# Эта строка запрашивает у пользователя ввод числа (количество градусов)
# input() - функция для получения ввода с клавиатуры
# "Введите градусы: " - текст, который увидит пользователь перед вводом
# Результат (то что введет пользователь) сохраняется в переменную degrees_input
degrees_input = input("Введите градусы: ")

# input() всегда возвращает текст (строку), а нам нужно число
# float() преобразует текст в дробное число (например, 180.5)
# Теперь у нас есть числовое значение градусов
degrees = float(degrees_input)

# Это важная математическая константа - число π (пи)
# Она нужна для перевода градусов в радианы
pi = 3.141592653589793

# Формула перевода градусов в радианы:
# радианы = градусы × π ÷ 180
# Мы умножаем градусы на π, делим на 180
# Результат сохраняем в переменную radians
radians = degrees * pi / 180

# Выводим результат на экран
# str() преобразует число в текст для вывода
# "Градусы: " + str(degrees) - склеиваем текст и значение градусов
# "Радианы: " + str(radians) - склеиваем текст и значение радиан
print("Градусы: " + str(degrees))
print("Радианы: " + str(radians))

Напиши программу на python выводящую первые 10 чисел Фибоначчи и поясни что значит каждая строчка для человека, никогда не писавшего на python

# Создаем список (набор) для хранения чисел Фибоначчи
# В квадратных скобках [] хранятся последовательности значений
# Начинаем с первых двух чисел: 0 и 1
fibonacci = [0, 1]

# Цикл for выполнится 8 раз (от 2 до 9 включительно)
# range(2, 10) создает последовательность чисел: 2, 3, 4, 5, 6, 7, 8, 9
# i будет поочередно принимать каждое из этих значений
for i in range(2, 10):
    # Вычисляем новое число как сумму двух предыдущих
    # fibonacci[i-1] - предпоследнее число в списке
    # fibonacci[i-2] - число перед предпоследним
    new_number = fibonacci[i-1] + fibonacci[i-2]

    # Добавляем новое число в конец списка
    fibonacci.append(new_number)

# Выводим все числа Фибоначчи
# enumerate(fibonacci) дает нам два значения для каждого элемента:
# index - номер (начиная с 0)
# value - само число Фибоначчи
# Мы добавляем 1 к index, чтобы нумерация была с 1, а не с 0
for index, value in enumerate(fibonacci):
    print(f"Число {index + 1}: {value}")

3. Практические занятия

4. Работа с катамараном

4.1. В симуляторе

Описание сценариев в симуляторе, параметры, последовательность действий, критерии успешности.

4.2. В реальном катамаране

Чек-лист подготовки, техника безопасности, порядок выполнения работ, сбор диагностических данных.

5. Домашнее задание

  1. Написать код, который заставит катамаран пройти через ворота, развернуться вокруг одного из шаров и вернуться на исходную точку

  2. Базовый код: https://sdb.smtu.ru/gitlab/marinerobotics/lesson-04/

  3. Работаем как и ранее - в своей ветке

  4. Задача со звёздочкой: высказать гипотезу, почему наше движение по квадрату не срабатывает

6. Дополнительные материалы

Официальная справка https://docs.ros.org/en/jazzy/Tutorials/Beginner-Client-Libraries.html

https://docs.ros.org/en/jazzy/Tutorials/Beginner-Client-Libraries.html