Appearance
ПР06. Модель робота, tf2 и QoS преобразований
Работа входит в общее ядро курса. Рассчитывайте на одну лабораторную пару и примерно 2 часа самостоятельной доработки.
Входные данные
В course kit дана SDF-модель models/course_ackermann/model.sdf только как источник размеров. Создайте URDF/Xacro, пакет course_description, launch-файл и тесты. Используйте метры, килограммы, секунды и соглашения осей REP-103; не копируйте из SDF плагины Gazebo как замену ROS-описанию.
QoS-шаг использует команды ros2 topic info --verbose и ros2 topic echo с флагами --qos-reliability и --qos-durability из ПР05 и лекции 06; новых пакетов он не требует. joint_state_publisher в образе osrf/ros:lyrical-desktop-full нет: он не нужен для обязательной части.
Цель
Собрать параметризованную модель Ackermann-робота в URDF/Xacro, связать корпус, камеру, лидар и IMU в одном дереве tf2, показать на /tf_static, как durability решает, увидит ли поздний подписчик преобразования, и доказать корректность геометрии и описания структурными проверками.
Критерии зачтено
Работа зачтена, когда выполнены все три стадии и прошла автопроверка:
| Стадия | Что требуется |
|---|---|
| 1 · Собрать | robot_state_publisher + развёрнутый Xacro, модель открывается в RViz, дерево связно; tf-qos.txt показывает профиль /tf_static и результат позднего чтения с transient local и volatile |
| 2 · Сломать | в отдельном commit/ветке изменить parent у lidar_link, получив неверное положение сенсора |
| 3 · Доказать | связь исправлена, frames.md фиксирует владельцев, check_urdf и тесты зелёные |
| Автопроверка | check_practice.py PR06 проверит src/**/*.urdf.xacro, evidence/pr06/{frames.md,model-check.txt,tf-qos.txt} и заявления public_tests_passed, defect_reproduced, defect_fixed |
Что получится
Вы соберёте параметризованную модель Ackermann-робота, свяжете корпус, камеру, лидар и IMU в одном дереве tf2, увидите на настоящем топике /tf_static, чем отличаются transient local и volatile, и проверите геометрию и структуру; физическую инерцию можно разобрать в расширении.
Пакеты и понятия
course_description— пакет описания робота; основной файл —urdf/vehicle.urdf.xacro(Xacro-макросы разворачиваются в URDF командойxacroперед проверкой).base_link, камера, лидар, IMU — звенья с собственными системами координат (frame); фреймы связываются преобразованиями (joint), и каждое преобразование публикует ровно один участник.visual— геометрия для отображения,collision— для столкновений,inertial— масса и тензор инерции (должен быть физически возможным).
| Понятие | Что означает |
|---|---|
robot_state_publisher | нода, которая по robot_description + joint_states публикует /tf и /tf_static |
/tf_static | канал фиксированных звеньев; издатель хранит последнее сообщение (transient local), поэтому его получает и подписчик, который подключился позже |
/tf | канал подвижных звеньев и одометрии; volatile: прошлое подписчику не отдаётся |
view_frames | инструмент: сохраняет всю картину дерева преобразований |
tf2_echo <parent> <child> | проверка одной связи дерева |
Что сделать
Сначала соберите корпус и один фиксированный lidar_link. После рабочего tf добавьте остальные звенья из контракта. Расчёт общего тензора инерции и собственные Xacro-макросы — дополнительное расширение; обязательны допустимые числа и связное дерево, объяснимое через знакомые команды.
- Запустите
robot_state_publisher, разверните Xacro в URDF и откройте модель в RViz. Модель должна соответствовать единицам СИ. - Параметризуйте базу, колею и радиус колеса (Xacro-переменные, не магические числа). Добавьте
base_link, системы координат камеры, лидара и IMU; задайте геометрию отображения и столкновений отдельно. - Пока
robot_state_publisherработает, сохраните QoS преобразований (tf-qos.txt, команды ниже)./tf_staticдолжен бытьreliableиtransient local: поздний подписчик с тем же профилем получает преобразования, подписчик сvolatile— нет. - После зелёной проверки в отдельном commit/ветке сделайте
camera_linkродителемlidar_linkвместоbase_link, сохранив прежний offset. Покажите неверное положение лидара и падение теста ожидаемого parent. Верните связь и повторите тот же тест. Самcheck_urdfможет принять ошибочное по смыслу дерево: структурная корректность не доказывает геометрию.
Колёса с continuous-сочленениями появятся в /tf только когда кто-то публикует joint_states. Для зачёта это не требуется: robot_state_publisher сразу публикует фиксированные звенья камеры, лидара и IMU. Если хотите увидеть колёса, опубликуйте положения вручную (имена сочленений замените своими):
bash
ros2 topic pub -r 10 /joint_states sensor_msgs/msg/JointState \
"{header: auto, name: [front_left_wheel_joint], position: [0.0]}"QoS преобразований
Профиль задаётся явно: без флагов ros2 topic echo сам подбирает QoS под издателя, и разницу между volatile и transient local вы не увидите.
bash
mkdir -p evidence/pr06
{
echo '## topic info /tf_static'
ros2 topic info /tf_static --verbose
echo '## echo transient_local'
timeout 4 ros2 topic echo /tf_static --once \
--qos-durability transient_local --qos-reliability reliable; echo "exit=$?"
echo '## echo volatile'
timeout 4 ros2 topic echo /tf_static --once \
--qos-durability volatile --qos-reliability reliable; echo "exit=$?"
} > evidence/pr06/tf-qos.txt 2>&1Ожидается: у robot_state_publisher Reliability: RELIABLE и Durability: TRANSIENT_LOCAL; первая подписка печатает преобразования и exit=0, вторая — ничего и exit=124. Допишите в tf-qos.txt два-три предложения: чем /tf отличается от /tf_static по профилю и почему это согласуется с тем, как меняются эти данные.
Порядок диагностики:
- В RViz прочитать
Global Statusи status конкретных Displays, не менять offset вручную. - Выбрать
Fixed Frame=base_link.mapиodomещё не публикуются: ошибка такого Fixed Frame ожидаема и не означает, что ваш URDF неверен. - Проверить одну связь через
tf2_echo, затем всё дерево черезview_frames. - Сопоставить timestamp исходного сообщения с доступным tf-буфером.
- Найти единственного владельца каждого меняющегося преобразования. Перед повторным запуском остановите прежний launch: два издателя
/tf_staticдают случайный ответ.
Сохраните .urdf.xacro и evidence/pr06/{frames.md,model-check.txt,tf-qos.txt,report.json}. frames.md фиксирует родительское и дочернее звенья каждой связи, ожидаемое преобразование и владельца публикации.
Проверка
Обязательные файлы сдачи
- В корне репозитория —
AI_USAGE.md, с отдельной записью для PR06: модель, инструмент, характер помощи и способ проверки. Если ИИ не использовался, напишите это явно и поставьтеai_used: falseв отчёте; файл всё равно нужен. Предыдущие записи сохраняйте. Правила и пример. - В
evidence/pr06/report.jsonполеcommit— SHA уже созданного коммита реализации. Отчёт фиксируется следующим коммитом; его SHA указывается при сдаче вместе со ссылкой на CI. Пошаговый пример двух коммитов.
bash
xacro src/course_description/urdf/vehicle.urdf.xacro > /tmp/vehicle.urdf
check_urdf /tmp/vehicle.urdf
colcon test --packages-select course_description
python3 .course-kit/v1/tools/check_practice.py PR06 --submission .Готово, если дерево связно и ациклично, используются единицы СИ, меняющиеся преобразования не публикуются двумя нодами, а tf-qos.txt показывает разницу между transient local и volatile для /tf_static. Дополнительно: вынесите общие геометрические параметры URDF и SDF в одну конфигурацию или проверяйте их тестом.
Для воспроизводимого отчёта сохраните команды и результаты до/после:
bash
ros2 run tf2_ros tf2_echo base_link lidar_link
ros2 run tf2_tools view_frames
ros2 topic echo /tf_static --onceКак работаем на лабораторной
Сначала разберём результат ПР05: профили QoS и повтор записи. Затем соберите Xacro-описание, запустите robot_state_publisher и сохраните tf-qos.txt. Остаток времени — на неверный parent: найдите разорванную или неверную связь через view_frames и tf2_echo, исправьте Xacro-макрос или начните таблицу систем координат сенсоров.
Общий порядок: runbook · troubleshooting.
Декларация AI_USAGE.md оформляется по правилам курса, в том числе без ИИ.
Расширения (необязательно)
Расширения не меняют критериев зачёта.
Защита tf: SROS2
Разрешите одному участнику публиковать преобразования, а другому — только читать их, и покажите, что участник без ключей ничего не видит. Это продолжение лекции 06: идентичности и права вместо доверия по номеру домена.
- Создайте keystore вне репозитория (или в каталоге, добавленном в
.gitignore) и две идентичности (enclave):/robot/state_publisherи/robot/viewer:ros2 security create_keystore,ros2 security create_enclave. - Напишите два файла политики.
/robot/state_publisherпубликуетtf,tf_static,robot_description,rosout,parameter_events, читаетjoint_statesиparameter_events;/robot/viewerчитаетtf,tf_static,parameter_events, публикует толькоrosoutиparameter_events. Службы параметров разрешите обоим. Затем выполнитеros2 security create_permission KEYSTORE ENCLAVE policy.xml. - Запустите оба участника с
ROS_SECURITY_KEYSTORE,ROS_SECURITY_ENABLE=true,ROS_SECURITY_STRATEGY=EnforceиROS_SECURITY_ENCLAVE_OVERRIDE=/robot/state_publisherили/robot/viewer. Проверьтеtf2_echoс ключами и без них. - Запишите в
evidence/pr06/security.mdкоманды, результаты и один абзац о том, чего защита не делает: она не лечит потери и несовместимость QoS.
Не добавляйте в репозиторий private/, *.key.pem и сам keystore: в Git допустимы только файлы политик. По умолчанию политика безопасности рассчитана на ROS_DOMAIN_ID=0; для другого домена отредактируйте governance.xml в keystore.
URDF и SDF
Проверьте gz sdf -k для модели из kit и для развёрнутого URDF. Выполните gz sdf -p vehicle.urdf и объясните, что случилось с lidar_link: по умолчанию фиксированные звенья склеиваются с родителем, а <gazebo reference="имя_соединения"><preserveFixedJoint>true</preserveFixedJoint></gazebo> сохраняет их.
Официальные источники
- tf2 concepts;
- REP-103: единицы и соглашения об осях;
- REP-105:
map,odom,base_link; - URDF learning path;
- robot_state_publisher;
- Справка курса: политики и профили QoS;
- ROS 2 QoS;
- SROS2: инструменты и политики.
Дополнительно: физические ограничения тензора инерции и собственные Xacro-макросы.