Системы координат и 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 учитывает время: преобразования хранятся в буфере истории.