# mvch — подготовка к ЧВТ-2026 Репозиторий для самостоятельного изучения и тренировок по модулям ЧВТ. - `module2/module_b.py` — модуль **Б**, навигация РМК-2 по ArUco. - `module3/` — модуль **В**, датасет и распознавание инструментов. - `module4/` — модуль **Г**, веб-FMS для двух роверов на React/Bun. - `module5/` — модуль **Д**, единый сценарий RMC1 + RMC2. Все актуальные модули находятся в `main`. Ветки `module2`–`module5` сохранены как промежуточные этапы разработки. ## Запуск в Ubuntu VM Нужен установленный официальный симулятор, ROS 2 Jazzy, `rclpy`, `tf2_ros`. Дополнительные pip-пакеты и сборка colcon самого решения не нужны. Терминал 1 — штатный симулятор (один экземпляр): ```bash source /opt/ros/jazzy/setup.bash source ~/ros2_ws/install/setup.bash ros2 launch ar_webots_fms_ros2 module2.launch.py ``` Терминал 2 — решение: ```bash cd ~/mvch git pull --ff-only source /opt/ros/jazzy/setup.bash source ~/ros2_ws/install/setup.bash python3 module2/module_b.py --target 14 --sim ``` 1. Робот должен стоять **центром над известной меткой**. Начальная ориентация любая: она определяется по TF метки. Программа ждёт odometry, lidar, TF и ArUco. 2. Программа печатает `ROUTE`. Эксперт фиксирует маршрут; **Enter** разрешает движение. 3. После `TARGET_REACHED` робот стоит. Выставьте препятствие штатным инструментом симулятора. 4. **Enter** строит и выводит обратный маршрут с учётом видимого препятствия. 5. Ещё **Enter** разрешает возврат. Успех — `MISSION_FINISHED`. Если за время подтверждения маршрут изменился, программа покажет новый и снова дождётся Enter. Время паузы между этапами не входит в `movement_seconds`. Команды в том же терминале: `stop`, `resume`, `return`, `go`, `quit`. Ctrl+C немедленно инициирует остановку и завершение с ненулевым кодом. Для внешнего интерфейса: `/mvch/command` (`std_msgs/String`), `/mvch/emergency_stop` (`std_msgs/Bool`, true фиксирует стоп), `/mvch/status` (JSON в `std_msgs/String`). После потери датчиков программа останавливается и требует `resume`. Автоматическая тренировка без подтверждений (только симулятор): ```bash python3 module2/module_b.py --target 14 --sim --auto --return-delay 10 ``` Цель координатами и конечная ориентация, в системе **поля**: ```bash python3 module2/module_b.py --xy -2 2 --target-yaw 1.57 --sim ``` На физическом роботе `--sim` не указывать: ```bash python3 module2/module_b.py --target 14 ``` Тогда используется подтверждённый документацией профиль: поле 5×5 (ID 0–24), ArUco `/RMC2/camera_bottom/aruco_id`, TF `/RMC2/tf` и `/RMC2/tf_static`, габарит RMC2 до 0.870 м. С `--sim` остаётся прежний профиль Webots 6×6 (ID 0–35), `/RMC2/aruco_id` и глобальные `/tf`/`/tf_static`. Перед физическим заездом всё равно проверить частоту топиков, имена frame_id, шаг сетки, тормозной путь и аппаратную аварийную остановку. Документ не сообщает шаг между маркерами и точные имена TF-фреймов. Испытания в Webots не подтверждают готовность к реальному полю. Если значения отличаются, код менять не нужно: ```bash python3 module2/module_b.py --target 14 --rows 5 --columns 5 --spacing 1.0 \ --base-frame RMC2/base_link --odom-frame RMC2/odom ``` У штатного Webots-драйвера нет таймаута последней команды: при SIGKILL/обрыве питания процесса программная остановка не гарантируется; остановить симулятор вручную. ## Как устроен код Весь модуль находится в одном файле `module2/module_b.py`: сверху параметры поля и скоростей, затем геометрия и Дейкстра, ниже ROS-узел, безопасность и логи. Читайте в таком порядке: `Field.route` → `localize` → `scan_points` → `plan` → `drive` → `tick`. Координаты реального поля: `0=(0,0)`, `5=(-1,0)`, `1=(0,1)`; в Webots 6×6: `0=(0,0)`, `6=(-1,0)`, `1=(0,1)`. Поворот `yaw` каждой метки — ориентация её TF-системы относительно поля. Измеренное положение метки в odom сравнивается с её известным положением на поле; так получаем преобразование `map_from_odom`. Между метками движение идёт по одометрии. У каждой промежуточной точки нужна свежая метка и попадание в допуск; «успех по таймауту» отсутствует. Лидар переводится через TF с учётом `angle_min`, `angle_increment` и времени скана. У текущего симулятора `laser_merged` повёрнут относительно корпуса на **120°**. Планировщик исключает рёбра, проходящие слишком близко к точкам препятствий. Он не знает ID или место будущего препятствия заранее и сам ничего не спавнит. Если преграда появилась во время движения, робот тормозит, возвращается задним ходом к предыдущему маркеру по своему ребру и публикует новый маршрут `ROUTE_REPLANNED`. Если отступить безопасно нельзя, он стоит и завершает попытку по таймауту. Профили сетки находятся в `REAL_FIELD` и `SIM_FIELD`, известные занятые клетки — в `BLOCKED_MARKERS`. Все длины — метры. ## Проверки и логи ```bash python3 module2/module_b.py --target 14 --dry-run # реальное поле 5x5 python3 module2/module_b.py --target 35 --sim --dry-run # Webots 6x6 ``` `reports/module_b_*.jsonl` содержат маршрут, движение, ошибки, препятствия, точность попадания по меткам и время. Логи исключены из Git. Условия финального КЗ: один запускаемый скрипт решения; маршруты в терминале и файле; явные `movement_start` / `movement_stop`; подтверждение эксперта перед каждым этапом. Фактические баллы определяют эксперты по заезду, а не наличие функций в коде. ## Обновление VM с хоста GitHub: `git@github.com:mavxa/mvch.git` (приватный). Для текущей VM используется локальное зеркало хостового Git без передачи ключей GitHub. На хосте запущен read-only Git daemon только для этого репозитория: ```bash git daemon --reuseaddr --export-all --listen=127.0.0.1 --port=9418 \ --base-path=/home/mavxa/zed/chvtFinal /home/mavxa/zed/chvtFinal/mvch ``` В VM с QEMU user networking хост доступен как `10.0.2.2`: ```bash git clone --branch module2 git://10.0.2.2:9418/mvch ~/mvch cd ~/mvch git pull --ff-only ``` SSH VM: `ssh -p 2222 -o HostKeyAlias=chvt-3735b9fd mavxa@127.0.0.1`. Проброс действует до выключения VM. Восстановить на хосте: ```bash virsh -c qemu:///system qemu-monitor-command ubuntu24.04-chvt \ --hmp 'hostfwd_add hostnet0 tcp:127.0.0.1:2222-:22' ``` Пароли и ключи в репозитории не хранятся.