Системы координат и TF2

У робота десятки систем координат — TF2 связывает их в единое дерево и переводит данные между ними.

TF2 — система ROS для отслеживания множества систем координат (frames) во времени и автоматического пересчёта точек и поз между ними.

Зачем нужны несколько систем координат

Лидар измеряет «препятствие в 0.5 м прямо передо мной». Но «передо мной» — это относительно лидара, который стоит на крыше робота со смещением. А планировщику нужно знать положение препятствия относительно карты комнаты. Чтобы перевести одно в другое, надо знать, где лидар относительно центра робота, и где робот относительно карты. Каждый такой «относительно» — это система координат (frame), а связи между ними — преобразования (transforms).

Стандартные кадры робота

КадрЧто обозначает
mapнеподвижная карта мира
odomточка старта одометрии (плавно дрейфует)
base_linkцентр робота
laserсам лидар
camera_linkкамера

Дерево TF

Кадры связаны в дерево: у каждого кадра ровно один родитель. Это гарантирует, что путь между любыми двумя кадрами единственный, и TF2 может его найти.

        map
         |  (где старт одометрии на карте)
        odom
         |  (как робот сместился от старта)
      base_link
       /     \
   laser    camera_link
  (жёстко закреплены на корпусе)

Связи map -> odom -> base_link меняются во времени (робот едет), а base_link -> laser постоянна (лидар прикручен жёстко).

Зачем разделять map и odom

Одометрия (по колёсам) точна на коротком интервале, но накапливает ошибку: за 10 метров робот «думает», что проехал 10.3. Поэтому odom -> base_link плавная, но дрейфует. Локализация (по лидару и карте) грубее по шагам, но не накапливает ошибку. Связь map -> odom как раз и есть поправка, которую локализация подкручивает, компенсируя дрейф одометрии. Так робот получает и плавность, и долговременную точность.

Осмотр TF

# вывести преобразование между двумя кадрами
ros2 run tf2_ros tf2_echo map base_link

# нарисовать дерево TF в PDF
ros2 run tf2_tools view_frames

Как работает под капотом

Узлы публикуют преобразования в топики /tf (динамические, меняющиеся) и /tf_static (постоянные). TF2 у подписчика собирает из них дерево и хранит буфер по времени — историю преобразований за последние секунды. Когда вы спрашиваете «где была точка лидара в системе map в момент времени T», TF2 берёт преобразования, актуальные именно на момент T, и перемножает их вдоль пути в дереве. Учёт времени критичен: лидар и одометрия приходят с разной задержкой, и брать «текущее» преобразование для старых данных — ошибка.

Частые ошибки

  • Кадр с двумя родителями. Дерево ломается; у каждого frame ровно один родитель.
  • Игнорировать время (stamp). Преобразование данных без учёта их времени даёт смещения и «прыжки».
  • Забыть опубликовать static transform. Если base_link -> laser не задано, TF2 не свяжет лидар с роботом — «frame does not exist».

Итоги

  • TF2 отслеживает системы координат робота и переводит данные между ними.
  • Кадры образуют дерево: у каждого один родитель.
  • map -> odom -> base_link разделяют точность и плавность.
  • TF2 учитывает время: преобразования хранятся в буфере истории.
Проверьте себя
1. Что делает TF2?
AСжимает изображения
BОтслеживает системы координат и переводит данные между ними
CКомпилирует пакеты
DУправляет моторами
2. Сколько родителей у каждого кадра в дереве TF?
AСколько угодно
BРовно один
CРовно два
DНи одного
3. Зачем разделяют кадры map и odom?
AДля красоты визуализации
Bodom плавный, но дрейфует; map -> odom — поправка от локализации против дрейфа
CЧтобы было два робота
DЧтобы ускорить лидар