Files
lightweight-cobot/docs/superpowers/plans/2026-11-08-grant-reference-control.md
T

42 KiB
Raw Blame History

План реализации эталонного управления Grant

Для агента-разработчика: выполняйте задачи по порядку, отмечайте выполненные шаги в чекбоксах.

Цель: обеспечить воспроизводимое эталонное движение робота во всех 20 экспериментах Grant и добавить к существующей команде запуска режимы view и execute.

Архитектура: существующий спавнер создаёт начальную сцену. Отдельный supervisor пакета iiwa_experement управляет захватом и позами объектов в Webots. Эталонный исполнитель синхронизирует его с геометрией MoveIt, вызывает существующий сервер движения cobot/move_to_pose/cobot/move_to_named и записывает действия в машинно-читаемый журнал.

Стек: Ubuntu 24.04, ROS 2 Jazzy, rclpy, MoveIt 2/moveit_msgs, Webots R2025a, Python Supervisor, webots_ros2_driver, PyYAML, pytest.

Спецификация: Описание согласованной архитектуры.

Общие ограничения

  • Работать в существующей ветке experement. Перед правками проверить git status. В файле src/iiwa_experement/worlds/grant/iiwa-grant.wbt уже есть чужие незакоммиченные изменения и побочные файлы Webots: сохранить их, не сбрасывать и не перезаписывать целиком.
  • Весь новый исполняемый код, конфигурация, launch, тесты и документация пакета размещаются в src/iiwa_experement/. OBJ/MTL использовать из src/iiwa_description/objects/grant/. Постоянный patron остаётся на роботе.
  • mode:=view — режим по умолчанию; робот не движется. mode:=execute начинает движение только после scene_ready, готовности контроллера, MoveIt и supervisor, появления свежего состояния робота и задержки 3,0 секунды симуляционного времени.
  • Запуск только в Webots: в включаемом bringup остаётся simulate:=true. Не отправлять эталонные траектории на физический робот через FRI.
  • Винты не вставляются и не затягиваются. Робот подносит винт к конкретному отверстию, отпускает его виртуальному оператору, после чего винт удаляется из сцены, а отверстие остаётся пустым. В эталонных маршрутах робот берёт затяжной инструмент и дотягивает винты, предварительно наживлённые человеком. Считается, что человек установил винты неплотно; окончательную затяжку выполняет робот.
  • Перемещения к инструментам, извлечение инструмента, перенос люка и винтов, посадка люка, проход соплом вдоль контура и подход к отверстиям выполняются реальными траекториями робота. Без движения меняются только состояние захвата и состояние передачи винта оператору.
  • Единицы: метры и радианы. Явно задавать преобразования world, base_link, patron, tcp, точки крепления и рабочего кончика инструмента. Использовать активный TF/настройки, а не координаты основания, переписанные из текста.
  • Перед каждым движением в MoveIt должны быть все препятствия и прикреплённые объекты; обновление сцены подтверждается до планирования. Контакт допускается только для нужного инструмента и цели на нужном этапе.
  • При неопределённой геометрии, столкновении, устаревшем состоянии, неудачном захвате или ошибке движения остановиться и записать причину. Не повторять движение вслепую.

Что прочитать перед правками

  1. src/iiwa_experement/config/scenes.yaml; src/iiwa_experement/iiwa_experement/{scenario.py,scene_spawner.py,webots_nodes.py,runtime_config.py}; src/iiwa_experement/launch/experiment.launch.py; src/iiwa_experement/doc/{experements.md,experiment-scenes.md,README.md}.
  2. src/iiwa_description/urdf/tools/patron.xacro; src/iiwa_description/worlds/iiwa.wbt; src/iiwa_description/resource/protos/CollaborativeRobotTable.proto; модели src/iiwa_description/objects/grant/ и изображения output/reference_photo/grant/.
  3. src/iiwa_planning/scripts/move_to_pose_server.py; src/iiwa_msgs/action/MoveToPose.action; src/iiwa_msgs/srv/MoveToNamedPose.srv; src/iiwa_config/config/moveit/iiwa7.srdf; src/iiwa_bringup/launch/supported/{moveit_nodes.py,webots_spawn.launch.py}.
  4. Исходные описания экспериментов: docs/superpowers/specs/2026-11-08-grant-experiments.md и сцен: docs/superpowers/specs/2026-11-08-grant-scenes.md. После задачи 1 актуальной версией новых правил про винты будут файлы src/iiwa_experement/doc/.

Назначение файлов

Файлы Назначение
config/scenes.yaml, iiwa_experement/scenario.py, doc/experements.md, doc/experiment-scenes.md Обновлённые 20 заданий, состав инструментов и сбои; без установки и затяжки винтов
config/geometry.yaml, iiwa_experement/geometry.py Крепление и рабочие кончики инструментов, захват/посадка люка, контур, отверстия, точки передачи, измеренные зазоры
worlds/grant/iiwa-grant.wbt, iiwa_experement/webots_nodes.py Отдельный supervisor и устойчивые имена управляемых объектов
iiwa_experement/grant_supervisor.py, iiwa_experement/object_state.py Следование захваченных объектов за роботом, команды и автомат состояний
iiwa_experement/planning_scene.py Препятствия и прикреплённые объекты MoveIt
iiwa_experement/motion.py Вызовы существующего сервера движения, проверка фактической позы и остановка
iiwa_experement/operations.py Захват, возврат инструмента, перенос, герметик, люк, передача винтов
iiwa_experement/reference_scenarios.py Маршруты 1–20 и ограниченное восстановление после сбоев
iiwa_experement/reference_runner.py, iiwa_experement/trace.py Ожидание готовности, выполнение, остановка, журнал JSONL и итог
iiwa_experement/runtime_config.py, launch/experiment.launch.py, setup.py, package.xml, doc/README.md Режимы запуска, зависимости, исполняемые файлы и инструкция
test/test_*.py Проверки контрактов, геометрии, запуска, состояний, сцены MoveIt и маршрутов

Проверки по всем задачам

Каждая задача ниже содержит собственные тесты и проверку результата. Таблица показывает, какой результат проверяется сразу после задачи; задача 10 повторяет проверки в полных прогонах Webots.

Задача Что проверить
1. Контракт опытов Все 20 заданий согласованы с передачей винта; в 11–20 по десять винтов, нет затяжки
2. Геометрия Инструмент крепится на конце patron; позы люка, контура и отверстий меняются вместе с объектами
3. Supervisor Захват и отпускание меняют состояние одного нужного объекта; при ошибке состояние не меняется
4. MoveIt Геометрия препятствий и прикреплённых объектов совпадает с Webots и подтверждена сервером движения
5. Движение Устаревшие /joint_states/TF, неподтверждённая сцена и отказ action блокируют следующую траекторию
6. Люк и герметик Робот действительно переносит люк и ведёт сопло по нужным участкам; объекты не скачут к цели
7. Винты Винт переносится магнитом к заданному отверстию и передаётся оператору; отверстие остаётся пустым
8. Маршруты Все 20 последовательностей различаются по задаче; grasp_failed использует текущую позу и одну повторную попытку
9. Запуск view не создаёт клиента движения, execute ждёт готовности и заданной задержки перед первым движением
10. Итог Все 20 прогонов проверены в Webots; сбои останавливают небезопасное продолжение

Задача 1. Исправить контракт 20 экспериментов

Файлы: изменить src/iiwa_experement/config/scenes.yaml, src/iiwa_experement/iiwa_experement/scenario.py, src/iiwa_experement/doc/experements.md, src/iiwa_experement/doc/experiment-scenes.md и затронутые test/test_scenario.py, test/test_webots_nodes.py, test/test_package_layout.py. Исторические копии спецификаций не переписывать молча; из документации пакета дать ссылку на новую спецификацию.

Интерфейс: load_scenario(experiment_id, manifest_path) -> ScenarioSpec остаётся единственным источником начальных поз; сбои описываются в YAML.

  • Шаг 1. Написать проверки, которые пока не проходят. В 14–15 и 16–20 нет torque_tool; в 11–20 ровно десять винтов. Нет сбоев tighten и seat_screw. В 15 сохранён grab:grasp_failed для третьего выбранного винта. Смещения сцены 3 и 19 сохранены.
  • Шаг 2. Убедиться, что проверки падают. source /opt/ros/jazzy/setup.bash && source install/setup.bash && pytest -q src/iiwa_experement/test/test_scenario.py src/iiwa_experement/test/test_webots_nodes.py.
  • Шаг 3. Обновить YAML и описания. 11 — передать один винт у hole_1; 12 — два по диагонали; 13 — три разных отверстия; 14 — четыре в порядке hole_1→hole_3→hole_2→hole_4; 15 — те же четыре, отказ третьего захвата и одна повторная попытка. 16 — участок герметика, люк, одна передача; 17 — полный контур, люк, две диагональные передачи; 18 — полный контур, люк, четыре передачи; 19 — то же со смещёнными люком и лотком; 20 — то же с прерыванием герметика, ошибкой первой посадки люка и неудачным захватом винта. Удалить затяжку и ошибку момента из 15. Каталог TOOL_NAMES менять только после проверки зависимостей; неиспользуемая модель может остаться в ASSETS, но не должна появляться в этих опытах.
  • Шаг 4. Повторить тесты. Все тесты сцен проходят; документация пакета не называет переданный винт установленным.
  • Шаг 5. Зафиксировать изменение контракта отдельным коммитом.

Задача 2. Измерить и описать рабочую геометрию

Файлы: создать config/geometry.yaml, iiwa_experement/geometry.py, test/test_geometry.py; при необходимости обновить setup.py.

Интерфейсы: load_geometry(path) -> GeometrySpec; world_target(spec: ScenarioSpec, geometry: GeometrySpec, name: str) -> Transform; tcp_goal(target: Transform, tcp_to_work_tip: Transform) -> Transform. В GeometrySpec хранить tool_mounts, tool_work_tips, cap_grip, cap_seat, sealant_segments, holes, зазоры подхода/передачи/переноса, допуски позы и ограниченные скорости. Единицы и исходный фрейм обязательны для каждого преобразования.

  • Шаг 1. Написать проверки геометрии. После масштаба Webots длина инструментов по вертикали 0–0,14 м; у герметика OBJ 0–0,014 м и масштаб ×10. tcp расположен на 0,0552 м от patron. Десять винтов имеют разные ID. Отверстия смещаются с корпусом в опыте 3, винты с лотком в 19. Проверить равенство T_world_tcp · T_tcp_mount = T_world_tool_mount.
  • Шаг 2. Убедиться, что тест падает. pytest -q src/iiwa_experement/test/test_geometry.py.
  • Шаг 3. Измерить точки в OBJ и Webots. Найти конец инструмента, входящий в patron, рабочий кончик, плоскость захвата люка, высоту посадки, начало/конец и углы контура, оси и высоты отверстий. Записать численные преобразования и консервативные габариты столкновений в geometry.yaml. Сверить XY отверстий стандартного корпуса с (0.2243,0.1052), (0.2852,0.0443), (0.3757,0.1348), (0.3148,0.1957). Не придумывать неизвестную высоту Z: измерить и занести её вместе с результатом проверки.
  • Шаг 4. Реализовать загрузку и композицию преобразований. Отвергать отсутствующие фреймы, нечисловые значения и неположительные зазоры. Позы смещённых целей вычислять из ScenarioSpec.
  • Шаг 5. Прогнать тесты и визуально проверить все инструменты на конце tcp. Результат измерений записать в документацию пакета.
  • Шаг 6. Зафиксировать геометрию отдельным коммитом.

Задача 3. Добавить supervisor для захвата и перемещения объектов

Файлы: изменить worlds/grant/iiwa-grant.wbt, iiwa_experement/webots_nodes.py, launch/experiment.launch.py, test/test_world.py, test/test_webots_nodes.py, test/test_launch.py; создать iiwa_experement/grant_supervisor.py, iiwa_experement/object_state.py, test/test_object_state.py, test/test_grant_supervisor.py; обновить setup.py и зависимости в package.xml.

Интерфейс: добавить в мир второй Robot { name "GrantAttachmentSupervisor" supervisor TRUE controller "<extern>" }. Встроенный /Ros2Supervisor продолжает создавать объекты. Сервис /iiwa_experement/object_command использует webots_ros2_msgs/srv/SetString: в JSON-поле value передаются request_id, op, object, target, expected_state. Топик /iiwa_experement/object_state типа std_msgs/msg/String публикует JSON с возрастающим номером версии, фактической позой, владельцем объекта и last_request_id. Команды: attach_tool, dock_tool, grab_cap, place_cap, grab_screw, handoff_screw, inspect.

  • Шаг 1. Написать проверки автомата состояний. Начальные состояния tool=none, cap=free|installed|absent, 10 доступных винтов. Запрещены захват без нужного инструмента, второй инструмент, второй переносимый объект, неверное отверстие и повторная передача. Переданный винт расходуется, отверстие остаётся empty. Отклонённая команда не меняет версию состояния.
  • Шаг 2. Убедиться, что тесты падают. pytest -q src/iiwa_experement/test/test_object_state.py src/iiwa_experement/test/test_grant_supervisor.py.
  • Шаг 3. Сделать объекты адресуемыми. У каждого управляемого Solid должен быть устойчивый DEF и прежнее поле name. Добавить невидимый внешний supervisor, сохранив стол, основного робота и встроенный Ros2Supervisor. Обновить тест мира: в шаблоне есть только один новый supervisor Robot, а iiwa и детали по-прежнему не предустановлены.
  • Шаг 4. Реализовать и подключить внешний контроллер. Использовать отдельное имя Robot и шаблон окружения Ros2SupervisorLauncher (WEBOTS_CONTROLLER_URL, WEBOTS_HOME); добавить его процесс к существующему launch без автоматических команд движения. После scene_ready найти объекты, получить фактическую позу patron/tcp из Webots либо проверенной TF-цепи. На каждом шаге Webots пересчитывать позу удерживаемого объекта по калиброванному преобразованию. Менять locked/физику только там, где это нужно. Во время переноса объект следует за роботом и не переносится скачком к цели. Публиковать новое состояние после подтверждения Webots; при недоступной позе или объекте отказывать.
  • Шаг 5. Проверить модуль и выполнить пробу Webots без движения робота. Supervisor находит tcp и все объекты начальной сцены, публикует их позы и отклоняет захват инструмента, когда робот ещё далеко от гнезда. Захват и следование инструмента при реальном движении проверить после задач 4–6, когда готовы сцена столкновений и адаптер движения.
  • Шаг 6. Зафиксировать supervisor и автомат состояний.

Задача 4. Отразить мир Webots в сцене MoveIt

Файлы: создать iiwa_experement/planning_scene.py, test/test_planning_scene.py; добавить нужные зависимости moveit_msgs и геометрических сообщений в package.xml.

Интерфейс: PlanningSceneBridge.initialize(spec, geometry), attach(object_id, link_name, relative_pose, touch_links), detach(object_id, world_pose), remove(object_id), assert_synchronized(expected_ids). Использовать /apply_planning_scene, /get_planning_scene или подтверждённый в установленном Jazzy эквивалент MoveItPy. Траектория допускается только после синхронизации сцены с сервером движения.

  • Шаг 1. Написать проверки изменений сцены. В мире MoveIt есть стол, стапель, корпус, стойка, лоток, люк, инструменты и все десять винтов, если они присутствуют в Webots. attach удаляет объект из мира и создаёт один прикреплённый к tcp/нужному звену объект. detach выполняет обратное действие; передача удаляет только выбранный винт. Разрешения на контакт не отключают проверки для всего робота.
  • Шаг 2. Убедиться, что тест падает. pytest -q src/iiwa_experement/test/test_planning_scene.py.
  • Шаг 3. Реализовать обновление и подтверждение. Габариты брать из webots_nodes.py и измерений задачи 2; учесть стол с верхом Z=0.793 и запас безопасности. Отправлять изменения и читать сцену обратно. Проверить, что отдельный монитор MoveItPy в move_to_pose_server.py получил те же объекты до движения. В текущем moveit_cpp.yaml указан /moveit_cpp/monitored_planning_scene; он может не совпадать с топиком move_group. Если связь отсутствует, создать исправленную временную копию moveit_cpp.yaml в пакете и указать её во временном setting.yaml; глобальный iiwa_config не менять. Если Webots и MoveIt расходятся — остановиться и сообщить ошибку синхронизации.
  • Шаг 4. Сверить RViz и Webots. Начальные объекты совпадают по позам; прикреплённые инструмент/люк/винт движутся с роботом; оставшиеся винты остаются препятствиями.
  • Шаг 5. Зафиксировать мост к MoveIt.

Задача 5. Сделать адаптер безопасных перемещений

Файлы: создать iiwa_experement/motion.py, test/test_motion.py; добавить в package.xml зависимости iiwa_msgs, sensor_msgs, tf2_ros и другие фактически используемые.

Интерфейс: MotionAdapter.move_pose(goal: Transform, planner: Literal['ptp','lin'], speed: float, label: str) -> MotionResult; move_named('home', speed) -> MotionResult; stop(reason). Вызывать cobot/move_to_pose, cobot/move_to_named, cobot/stop. Целевую позу tcp переводить через активный TF в base_link, затем в углы KUKA ABC (ZYX, радианы) из MoveToPose.action.

  • Шаг 1. Написать тесты с поддельными клиентами. Цель не отправляется при устаревших joint_states/TF, неподтверждённой сцене, недопустимой скорости или уже остановленном роботе. Отказ, отмена и тайм-аут вызывают stop и блокируют следующий участок. После успеха проверяются фактические положение и ориентация TCP.
  • Шаг 2. Убедиться, что тест падает. pytest -q src/iiwa_experement/test/test_motion.py.
  • Шаг 3. Реализовать адаптер. Свободный перенос — через ptp/OMPL с полной сценой столкновений; короткий осевой подход/отход и стороны контура — через lin. Ограничить время планирования/выполнения, проверять свежесть обратной связи и готовность контроллера. Не применять iiwa_planning/direct_trajectory.py и TCP gizmo для эталона. При execute выключать gizmo во временной конфигурации запуска, чтобы робот имел один источник команд.
  • Шаг 4. Проверить движение в Webots без захвата. Из дома пройти в измеренную свободную точку над рабочей зоной и вернуться. Сверить путь и пределы суставов.
  • Шаг 5. Зафиксировать адаптер движения.

Задача 6. Реализовать операции с инструментами, люком и герметиком

Файлы: создать iiwa_experement/operations.py, test/test_operations.py.

Интерфейс: take_tool(tool_name), dock_tool(tool_name), pick_cap(), place_cap(target_pose), dispense(segment_name, start_fraction=0.0), inspect_cap(), inspect_sealant(). take_tool вставляет инструмент в patron; dock_tool возвращает его в гнездо. Каждая операция возвращает исход и пишет события. Владельцы состояния — только supervisor и мост MoveIt.

  • Шаг 1. Написать тесты последовательностей. Взятие инструмента: дом/безопасная высота→точка над гнездом→осевое опускание→крепление→осевое извлечение; возврат — обратный маршрут. Люк: над люком→опускание→захват→подъём→перенос над корпусом→совмещение→опускание до посадки→отпускание→отход. Люк должен двигаться вместе с TCP, без скачка к корпусу. Сопло проходит реальные 3D-участки четырёх сторон и смежные углы на рабочей высоте; сторона считается выполненной только после успешного движения.
  • Шаг 2. Убедиться, что тест падает. pytest -q src/iiwa_experement/test/test_operations.py.
  • Шаг 3. Реализовать операции через калиброванные фреймы. Позы TCP вычислять по целевой позе рабочего кончика. Подходить и отходить вдоль локальной оси цели; безопасную высоту переноса вычислять по габаритам переносимого объекта и препятствий. Перед захватом/отпусканием проверять фактическую близость и состояние. В 5 выполнить первую смещённую посадку и одну корректировку. В 9/20 хранить последнюю подтверждённую точку герметика и продолжать от неё.
  • Шаг 4. Проверить отдельные операции в Webots через проверочный клиент. Убедиться, что движутся робот, инструмент, люк и сопло, а объект не скачет к цели. Полные опыты 1, 6, 9 и 10 прогнать в задаче 10 после подключения эталонного исполнителя.
  • Шаг 5. Зафиксировать операции.

Задача 7. Реализовать магнитный захват и передачу винта

Файлы: дополнить iiwa_experement/operations.py, iiwa_experement/object_state.py, test/test_operations.py, test/test_object_state.py.

Интерфейс: pick_screw(screw_id), handoff_screw(screw_id, hole_id). Итоговое событие — delivered(screw_id,hole_id); состояний seated и tightened нет.

  • Шаг 1. Написать тесты. Можно выбрать любой из десяти доступных винтов. Взятый винт следует за рабочим концом магнита. Подход к отверстию выполняется по его оси. Передача запрещена, если винт не удерживается или фактическая поза TCP вне допуска у нужного отверстия. Успешная передача удаляет только один винт из Webots и MoveIt, оставляет отверстие пустым, другие винты — в лотке.
  • Шаг 2. Убедиться, что тесты падают. pytest -q src/iiwa_experement/test/test_operations.py src/iiwa_experement/test/test_object_state.py.
  • Шаг 3. Реализовать маршрут робота. над выбранным винтом→осевое опускание→захват→осевой подъём→перенос на безопасной высоте→над отверстием→совмещение осей→короткое опускание до точки передачи→отпускание оператору→осевой отход. Не опускать винт внутрь люка или корпуса. Между отверстиями проходить через проверенную безопасную область, не перемещаться поперёк люка на контактной высоте.
  • Шаг 4. Проверить отдельную операцию передачи в Webots через проверочный клиент. Робот и винт движутся вместе; сначала видны десять винтов, исчезает только переданный. Полные опыты 11, 12 и 14 прогнать в задаче 10.
  • Шаг 5. Зафиксировать передачу винтов.

Задача 8. Описать 20 эталонных маршрутов и восстановление

Файлы: создать iiwa_experement/reference_scenarios.py, test/test_reference_scenarios.py; при необходимости дополнить operations.py проверкой inspect_state.

Интерфейс: build_reference_sequence(spec: ScenarioSpec) -> tuple[Operation, ...]; execute_sequence(sequence, context) -> RunResult. Имена целей соответствуют doc/experements.md. Успешный маршрут заканчивается возвратом инструмента и переходом в home.

  • Шаг 1. Написать табличные тесты для всех 20 ID. Проверить порядок операций из задачи 1, возврат инструмента перед сменой, разные винты и нужное число отверстий. Для 3/19 брать смещённые реальные позы. Для 4/15/20: grasp_failed→stop→inspect_state→повторное обнаружение→одна попытка; для 5: not_ok→одна корректировка люка; для 9/20: продолжение с точки разрыва герметика. Повторный отказ и неизвестное состояние дают stopped без последующих движений. В журнале нет seat_screw и tighten.
  • Шаг 2. Убедиться, что тесты падают. pytest -q src/iiwa_experement/test/test_reference_scenarios.py.
  • Шаг 3. Реализовать выбор маршрута и управляемые сбои. Применять ScenarioSpec.failures по навыку, цели и номеру попытки. В view сбои не меняют сцену. Перед повтором читать фактическое состояние Webots и решать, повторить действие, пропустить уже выполненную передачу или остановиться.
  • Шаг 4. Проверить тесты и список операций для всех ID. В 13 три передачи, в 14/15 четыре; в 19 используются смещённые люк и лоток.
  • Шаг 5. Зафиксировать маршруты.

Задача 9. Добавить view и execute в существующий launch

Файлы: изменить iiwa_experement/runtime_config.py, launch/experiment.launch.py, setup.py, package.xml, test/test_launch.py, test/test_runtime_config.py; создать iiwa_experement/reference_runner.py, iiwa_experement/trace.py, test/test_reference_runner.py.

Интерфейс команды: ros2 launch iiwa_experement experiment.launch.py experiment_id:=N mode:=view|execute start_delay_sec:=3.0 trace_dir:=~/.ros/iiwa_experement/runs. По умолчанию mode=view и указанный каталог журнала. В execute запускаются grant_supervisor и reference_runner; в view runner отсутствует, supervisor может работать только в режиме чтения. Журнал JSONL и RunResult содержат ID опыта, время симуляции, операцию, объект, цель, позы до/после, исход и изменение состояния.

  • Шаг 1. Написать тесты запуска. Неверный режим и отрицательная/нечисловая задержка отклоняются до Webots. В view нет клиента движения и целей. В execute отсутствие scene_ready, MoveIt/контроллера, свежих joint_states или остановленные часы симуляции не допускают старт. Первое движение — не раньше scene_ready + start_delay_sec по времени симуляции. Тайм-аут готовности завершает runner с ошибкой без движения.
  • Шаг 2. Убедиться, что тесты падают. pytest -q src/iiwa_experement/test/test_launch.py src/iiwa_experement/test/test_reference_runner.py.
  • Шаг 3. Реализовать ожидание и журнал. Ждать scene_ready, supervisor, MoveIt, сервисы/действия движения, свежие TF и joint_states; затем выдержать задержку по /clock. Публиковать краткий прогресс. Писать JSONL в trace_dir/experiment_<id>_<UTC-время>.jsonl, раскрывая ~, и сбрасывать данные после каждой операции. При успехе или остановке записать итог; Webots оставлять открытым для осмотра финальной сцены.
  • Шаг 4. Проверить режимы вручную. view показывает неизменную сцену сколько угодно; execute ждёт три секунды симуляции и начинает видимое движение. Проверить также start_delay_sec:=0 и start_delay_sec:=10.
  • Шаг 5. Зафиксировать launch и журнал.

Задача 10. Проверить безопасность и все 20 прогонов

Файлы: обновить src/iiwa_experement/doc/README.md; создать src/iiwa_experement/doc/reference-control-qa.md с измерениями, результатами проверки столкновений и таблицей 20 опытов. Тесты дополнять по найденным конкретным ошибкам.

Интерфейс: команда запуска и формат журнала из задачи 9 — контракт для последующего сравнения эталона с планами LLM.

  • Шаг 1. Собрать пакет и запустить тесты. source /opt/ros/jazzy/setup.bash && colcon build --base-paths src --packages-up-to iiwa_experement --symlink-install; затем source install/setup.bash && colcon test --base-paths src --packages-select iiwa_experement && colcon test-result --verbose. Исправить ошибки до заявления о готовности.
  • Шаг 2. Проверить view для 1, 11, 16, 19, 20. Сверить состав объектов, десять винтов, постоянный patron, отсутствие движения робота и изменений объектов после 10 секунд симуляции.
  • Шаг 3. Запустить execute для каждого ID 1–20. Для каждого записать: видимые движения, точность крепления инструмента к TCP, журнал, отсутствие запрещённых столкновений и проникновений, итоговую позу люка, участки герметика, пары переданных винтов, возврат инструмента и home. Если поза недостижима или опасна, исправить геометрию/сцену и повторить опыт и соседние затронутые варианты. Не обходить проверку столкновений.
  • Шаг 4. Проверить ветви отказов 4, 5, 9, 15, 20. Ровно одна разрешённая попытка восстановления; повторный отказ или неизвестное состояние останавливает робот. Винт не вставляется, отверстие пустое, затяжной инструмент не движется.
  • Шаг 5. Описать команды запуска, параметры, формат журнала, численные калибровки, результаты тестов, ограничения и режим только симуляции. Примеры: ros2 launch iiwa_experement experiment.launch.py experiment_id:=1 mode:=view и ros2 launch iiwa_experement experiment.launch.py experiment_id:=1 mode:=execute start_delay_sec:=3.0.
  • Шаг 6. Зафиксировать документацию и проверенные исправления. Просмотреть git diff; не включать посторонние изменения рабочего дерева.

Критерии готовности

В view сцена остаётся неподвижной. В execute робот выполняет все нужные движения для всех 20 сценариев; инструмент виден на кончике patron, люк перемещается вместе с роботом и оказывается на корпусе, сопло идёт по заданным участкам, каждый винт реально переносится к отверстию и передаётся виртуальному оператору без установки и затяжки. Сборка, тесты и документированные прогоны Webots успешны. Небезопасный или неудачный опыт остаётся незавершённым с явной причиной.