Подглава 11.2.3 Понимание кода отслеживания объектов
#!/usr/bin/env python
import rospy
from sensor_msgs.msg import RegionOfInterest, CameraInfo
from geometry_msgs.msg import Twist
import thread
class ObjectTracker():
def __init__(self):
rospy.init_node("object_tracker")
# Вызовем функцию выключения (остановите робота)
rospy.on_shutdown(self.shutdown)
# Как часто мы должны обновлять движение робота?
self.rate = rospy.get_param("~rate", 10)
r = rospy.Rate(self.rate)
# Максимальная скорость вращения в рад/с
self.max_rotation_speed = rospy.get_param("~max_rotation_speed", 2.0)
# Минимальная скорость вращения в рад/с
self.min_rotation_speed = rospy.get_param("~min_rotation_speed", 0.5)
# Чувствительность к целевым смещениям. Установка слишком высокого
# уровня может привести к колебаниям робота.
self.gain = rospy.get_param("~gain", 2.0)
# x threshold (%от ширины изображения) указывает, как
# далеко от центра ROI должен быть в направлении x,
# прежде чем мы отреагируем
self.x_threshold = rospy.get_param("~x_threshold", 0.1)
# Publisher для управления движения робота
self.cmd_vel_pub = rospy.Publisher('cmd_vel', Twist, queue_size=5)
# Инициализируем команду перемещения
self.move_cmd = Twist()
# Получаем блокировку для обновлений значений self.move_cmd
self.lock = thread.allocate_lock()
# Получим ширину и высоту изображения из топика camera_info
self.image_width = 0
self.image_height = 0
# Установим флаг, указывающий, когда ROI прекращает обновления
self.target_visible = False
# Ждем пока топик camera_info станет доступным
rospy.loginfo("Waiting for camera_info topic...")
rospy.wait_for_message('camera_info', CameraInfo)
# Подпишемся на топик camera_info, чтобы получить ширину и высоту изображения
rospy.Subscriber('camera_info', CameraInfo, self.get_camera_info, queue_size=1)
# Подождем, пока действительно не получим данные с камеры
while self.image_width == 0 or self.image_height == 0:
rospy.sleep(1)
# Подпишемся на топик ROI и установим обратный вызов(callback) для обновления движения робота
rospy.Subscriber('roi', RegionOfInterest, self.set_cmd_vel, queue_size=1)
# Ждем пока не получим сообщений от ROI
rospy.loginfo("Waiting for messages on /roi...")
rospy.wait_for_message('roi', RegionOfInterest)
rospy.loginfo("ROI messages detected. Starting tracker...")
# Начнем цикл отслеживания
while not rospy.is_shutdown():
# Захватим замок, пока устанавливаем скорость робота
self.lock.acquire()
try:
# Если цель не видна, остановим робота
if not self.target_visible:
self.move_cmd = Twist()
else:
# Сбросим флаг на False по умолчанию
self.target_visible = False
# Отправим команду Twist(поворота) роботу
self.cmd_vel_pub.publish(self.move_cmd)
finally:
# Снимем блокировку
self.lock.release()
# Сон на 1/self.rate секунд
r.sleep()
def set_cmd_vel(self, msg):
# Захватим замок, пока устанавливаем скорость робота
self.lock.acquire()
try:
# Если ROI имеет ширину или высоту 0, мы потеряли цель
if msg.width == 0 or msg.height == 0:
self.target_visible = False
return
# Если ROI перестанет обновлять, следующее не произойдет
self.target_visible = True
# Вычислим смещение ROI от центра изображения
target_offset_x = msg.x_offset + msg.width / 2 - self.image_width / 2
try:
percent_offset_x = float(target_offset_x) / (float(self.image_width) / 2.0)
except:
percent_offset_x = 0
# Вращаем робота только в том случае, если смещение цели
# превышает пороговое значение
if abs(percent_offset_x) > self.x_threshold:
# Установим скорость вращения,
# пропорциональную перемещению мишени
try:
speed = self.gain * percent_offset_x
if speed < 0:
direction = -1
else:
direction = 1
self.move_cmd.angular.z = -direction * max(self.min_rotation_speed,
min(self.max_rotation_speed, abs(speed)))
except:
self.move_cmd = Twist()
else:
# Иначе остановим робота
self.move_cmd = Twist()
finally:
# Снимем блокировку
self.lock.release()
def get_camera_info(self, msg):
self.image_width = msg.width
self.image_height = msg.height
def shutdown(self):
rospy.loginfo("Stopping the robot...")
self.cmd_vel_pub.publish(Twist())
rospy.sleep(1)
if __name__ == '__main__':
try:
ObjectTracker()
rospy.spin()
except rospy.ROSInterruptException:
rospy.loginfo("Object tracking node terminated.")PreviousПодглава 11.2.2 Тестирование трекера объекта с помощью имитированного роботаNextПодглава 11.2.4 Отслеживание объектов на реальном роботе
Last updated