7.6.3. Скрипт с выдержкой времени и обратно

Вот полный скрипт для тайм-аута и обратного узла. После листинга мы будем разбивать его на более мелкие части.

Ссылка на источник: timed_out_and_back.py

#!/usr/bin/env pythonimport rospyfrom geometry_msgs.msg import Twist from math import piclass OutAndBack(): def __init__(self):        # Give the node a namerospy.init_node('out_and_back', anonymous=False)# Set rospy to execute a shutdown function when exiting rospy.on_shutdown(self.shutdown)  # Publisher to control the robot's speed self.cmd_vel = rospy.Publisher('/cmd_vel', Twist, queue_size=5)​ # How fast will we update the robot's movement? rate = 50​ # Set the equivalent ROS rate variable r = rospy.Rate(rate)​ # Set the forward linear speed to 0.2 meters per second linear_speed = 0.2​ # Set the travel distance to 1.0 meters goal_distance = 1.0​ # How long should it take us to get there? linear_duration = goal_distance / linear_speed​ # Set the rotation speed to 1.0 radians per second angular_speed = 1.0​ # Set the rotation angle to Pi radians (180 degrees) goal_angle = pi​ # How long should it take to rotate? angular_duration = goal_angle / angular_speed​ # Loop through the two legs of the trip for i in range(2): # Initialize the movement command move_cmd = Twist()​ # Set the forward speed move_cmd.linear.x = linear_speed​ # Move forward for a time to go 1 meter ticks = int(linear_duration * rate)​ for t in range(ticks): self.cmd_vel.publish(move_cmd) r.sleep()​ # Stop the robot before the rotation move_cmd = Twist() self.cmd_vel.publish(move_cmd) rospy.sleep(1)​ # Now rotate left roughly 180 degrees 63 # Set the angular speed move_cmd.angular.z = angular_speed​ # Rotate for a time to go 180 degrees ticks = int(goal_angle * rate)for t in range(ticks): self.cmd_vel.publish(move_cmd) r.sleep()            # Stop the robot before the next legmove_cmd = Twist() self.cmd_vel.publish(move_cmd) rospy.sleep(1)        # Stop the robotself.cmd_vel.publish(Twist())def shutdown(self):# Always stop the robot when shutting down the node. rospy.loginfo("Stopping the robot...") self.cmd_vel.publish(Twist())rospy.sleep(1)if __name__ == '__main__': try:        OutAndBack()    except:rospy.loginfo("Out-and-Back node terminated.")

Так как это наш первый скрипт, давайте посмотрим на него построчно, начиная сверху:

#!/usr/bin/env python import rospy

Если вы делали Учебники для начинающих ROS в Python, вы уже знаете, что все наши узлы ROS начинаются с этих двух строк. Первая строка гарантирует, что программа будет работать как скрипт Python, а вторая импортирует основную библиотеку ROS для Python.

from geometry_msgs.msg import Twistfrom math import pi

Здесь мы позаботимся о любом другом импорте, который нам нужен для скрипта. В этом случае нам понадобится тип сообщения Twist из пакета ROS geometry_msgs и константа pi из математического модуля Python. Обратите внимание, что общий источник ошибок при импорте - забыть включить необходимую строку ROS в файл package.xml вашего пакета. В этом случае наш файл package.xml должен содержать строку:

<run_depend>geometry_msgs</run_depend>

так что мы можем импортировать Twist из geometry_msgs.msg.

class OutAndBack():def __init__(self):

Здесь мы начинаем основную часть нашего узла ROS, определяя его как класс Python вместе со стандартной линией инициализации класса.

# Give the node a namerospy.init_node('out_and_back', anonymous=False)# Set rospy to execute a shutdown function when exitingrospy.on_shutdown(self.shutdown)

Каждый узел ROS требует вызова rospy.init_node (), и мы также устанавливаем обратный вызов для функции on_shutdown (), чтобы мы могли выполнить любую необходимую очистку, когда сценарий завершается, например когда пользователь нажимает Ctrl-C. В случае мобильного робота самая важная задача очистки - остановить робота! Мы увидим, как это сделать позже в скрипте.

# Publisher to control the robot's speedself.cmd_vel = rospy.Publisher('/cmd_vel', Twist, queue_size=5)# How fast will we update the robot's movement?rate = 50# Set the equivalent ROS rate variabler = rospy.Rate(rate)

Здесь мы определяем нашего издателя ROS для отправки команд Twist в раздел / cmd_vel. Мы также устанавливаем скорость, с которой мы хотим обновить движение робота, 50 раз в секунду, а параметр queue_size равным 5.

Параметр queue_size был введен в ROS Hydro и будет обязательным в ROS Jade. В ROS Indigo ваш код выдаст предупреждение, если издатель инициализируется без этого параметра. Вы можете узнать больше о параметре queue_size в ROS Wiki. Самый важный факт, который нужно иметь в виду, это то, что если этот параметр не указан или не установлен в значение «Нет», издатель будет вести себя синхронно. Это означает, что если имеется несколько подписчиков на тему издателя, и один из подписчиков зависает - например, он находится на другом конце ненадежного беспроводного соединения - тогда публикация будет блокировать всех подписчиков этой темы, пока подписчик не зависнет возвращается к жизни. Как правило, это нежелательный результат. Установка для параметра queue_size числового значения приводит к тому, что издатель ведет себя асинхронно, так что каждый подписчик получает сообщения в отдельном потоке без подписчика и блокирует всю систему.

# Set the forward linear speed to 0.2 meters per secondlinear_speed = 0.2# Set the travel distance to 1.0 metersgoal_distance = 1.0# How long should it take us to get there?linear_duration = linear_distance / linear_speed

Мы инициализируем скорость движения вперед относительно безопасную 0,2 метра в секунду и целевое расстояние до 1,0 метра. Затем мы вычисляем, сколько времени это займет.

Аналогично, мы устанавливаем скорость вращения 1,0 радиан в секунду, а целевой угол - 180 градусов или Pi радиан.

Это петля, которая фактически перемещает робота - один цикл для каждой из двух ног. Напомним, что некоторые роботы требуют, чтобы сообщение Twist постоянно публиковалось, чтобы оно продолжало двигаться. Поэтому, чтобы продвинуть робота вперед метры linear_distance со скоростью метра linear_speed в секунду, мы публикуем сообщение move_cmd каждые 1 раз в секунду в течение соответствующей продолжительности. Выражение r.sleep () является сокращением для rospy.sleep (1 / скорость), так как мы определили переменную r = rospy.Rate (скорость).

Во второй части цикла мы вращаем робота со скоростью angular_speed радиан в секунду в течение соответствующей продолжительности (в данном случае Pi секунд), которая должна дать 180 градусов.

Когда робот завершил обратный путь, мы останавливаем его, публикуя пустое сообщение Twist (все поля равны 0).

Это наша функция обратного вызова выключения. Если выполнение сценария прекращается по какой-либо причине, мы останавливаем робота, публикуя пустое сообщение Twist.

Наконец, это стандартный блок Python для запуска скрипта. Мы просто создаем экземпляр класса OutAndBack, который запускает скрипт (и робота).

Last updated

Was this helpful?