feat(fleet): preserve operator VESC integration before final driver merge

This commit is contained in:
DCCONSTRUCTIONS
2026-09-25 16:40:46 +03:00
parent dad11b47d7
commit 71a648fec8
128 changed files with 22390 additions and 59 deletions
@@ -0,0 +1,319 @@
# Rover 006 · VESC · передача контекста
Дата среза: 23.09.2026. Этап: исследование и подготовка следующей реализации.
Документ отделяет требования владельца, проверенное состояние исходников,
исторические аппаратные результаты и предлагаемый план. Это не отчёт об
установке VESC на борт и не разрешение автоматически запускать моторы.
## 1. Задача и решение
Добавить силовое оборудование Rover 006 в существующую архитектуру Mission
Core Node: обнаружение контроллеров, достоверная идентификация, связь с моторами
и назначением «левый/правый», диагностика и впоследствии настройка через обе UI.
Оператор работает локально на борту либо удалённо из «Парк → Аппараты» Core.
Оба интерфейса обращаются к одному владельцу оборудования на борту.
VESC Tool — открытый проект; полное обратное проектирование закрытой программы
не является исходной задачей. Предлагаемый первый результат — чтение личности,
версий, конфигураций и диагностики двух каналов. Калибровка — следующий отдельно
подготовленный аппаратный опыт. Новая прошивка контроллера ради автообнаружения
не требуется. Совместимость конкретных установленных контроллеров ещё неизвестна.
Контур симуляции, Worker/AI, управление движением ровера и повторная переработка
Rerun не входят в эту работу. Они не являются зависимостями диагностики VESC.
## 2. Что сообщил владелец
- Целевой аппарат — NDC Rover 006, бортовой компьютер — существующий Mac Mini
с Ubuntu и Mission Core Node. По последнему сообщению владельца борт offline.
- Нужно обнаруживать совместимые подключённые контроллеры независимо от
конкретных серийных номеров, в том числе после замены оборудования.
- Желаемая предметная структура: VESC Left / VESC Right и Motor Left / Motor
Right. Это **назначения экземпляров**, а не четыре аппаратные модели.
- Один канал нормально работает от пульта. Проблемный при резкой подаче газа
делает примерно пол-оборота и останавливается; при плавной подаче раскручивается.
- Гусеница снята, механические предположения уже проверялись. Сборщик с большим
опытом изучил видео и предполагает потерю настройки/проблему прошивки VESC.
- Проблемный мотор удалось раскрутить до максимума, после чего исправный
нормально ускорялся. Это важный аргумент против простого общего недостатка
мощности аккумулятора, но не измерение напряжения/тока отдельного контроллера.
- Указания стороны в устной истории неоднозначны. До физического подтверждения
использовать «проблемный канал» и «исправный канал», не назначать Left по догадке.
- USB-кабель контроллера будет подключён к борту. Схема «два USB / один USB и
CAN / двухканальная плата» пока не установлена.
Приоритетная рабочая гипотеза — конфигурация/прошивка/управление проблемного
канала. Не начинать заново с предположения о камне в гусенице. Одновременно не
объявлять калибровку доказанной причиной до чтения конфигурации и ошибок.
## 3. Канонические источники и Ops
Прочитать перед реализацией:
1. [Правила репозитория](../../AGENTS.md),
[политика артефактов](../03_ARTIFACT_POLICY.md).
2. [Карта монорепозитория](../07_MISSION_CORE_MONOREPO.md),
[архитектура приложения](../18_APPLICATION_COMPONENT_ARCHITECTURE.md),
[правила расширения UI](../19_PRODUCT_SURFACE_EXTENSION_PROTOCOL.md).
3. [Система, борт и аппарат](../node/03_SYSTEM_AND_VEHICLE_PAIRING_SURFACE.md),
[сопряжение Node/Core](../node/04_NODE_CORE_PAIRING_PROTOCOL.md),
[один аппаратный владелец и две UI](../node/05_SENSOR_HOST_AND_SHARED_CONTROL.md).
4. [Plugin SDK v0alpha2](../../packages/plugin-sdk/README.md),
[ADR 0004](../adr/0004-plugin-sdk-v0alpha2-and-experimental-device-lifecycle.md).
5. [Последнее состояние Mini/X4](../node/09_INSTA360_X4_IMPLEMENTATION_STATUS.md),
[оставшиеся аппаратные проверки](../node/10_INSTA360_X4_NEXT_STEPS.md),
[журнал установок](../node/07_INSTA360_X4_INSTALLATION_LEDGER.md).
6. Для UI обязательно прочитать
[mission-core-product-ui](../../.codex/skills/mission-core-product-ui/SKILL.md),
затем названные в нём документы Design Guideline. Текущий handoff UI не меняет.
Ops — источник состояния карточек; локальный документ не заменяет его:
| Карточка | Зачем следующей задаче |
| --- | --- |
| [MISSIONCOR-84](https://ops.nodedc.ru/nodedc/browse/MISSIONCOR-84) | Новый профильный этап VESC: завершённое исследование, архитектура, симптомы, V0–V5 и открытая аппаратная приёмка. |
| [MISSIONCOR-76](https://ops.nodedc.ru/nodedc/browse/MISSIONCOR-76) | Исходная архитектура Node, UI-FIRST / BRIDGE-ONLY, борт и общий контроль. Связь подтверждена документацией Node. |
| [MISSIONCOR-77](https://ops.nodedc.ru/nodedc/browse/MISSIONCOR-77) | Последняя установка X4/Node и незавершённые аппаратные проверки. |
| [MISSIONCOR-2](https://ops.nodedc.ru/nodedc/browse/MISSIONCOR-2) | Актуальный общий срез вне SIM и переход к VESC. |
| [MISSIONCOR-74](https://ops.nodedc.ru/nodedc/browse/MISSIONCOR-74) | История переносимых кастомизаций Rerun. Не переписывать в VESC-задаче. |
| [MISSIONCOR-81](https://ops.nodedc.ru/nodedc/browse/MISSIONCOR-81) | Планировщик и проверки проходов K1, отдельный потребитель наблюдения. |
| [MISSIONCOR-80](https://ops.nodedc.ru/nodedc/browse/MISSIONCOR-80) | Сохранённые записи/обзор; источник контекста данных, не силового управления. |
Доступ восстановлен 23.09: прямые `nodedc-ops-agent/tasker_*` успешно прочитали
инструкции, проекты, контекст и реестр 83 карточек MISSION CORE; карточка VESC
в нём отсутствовала и создана отдельно как MISSIONCOR-84 (Backlog). Выполнена
целевая актуализация 2/66/74/81, в 76 добавлен датированный комментарий без
изменения замороженного baseline. SIM-карточки не редактировались. Исследованы
профильные Node/X4/planning/Rerun/SDK/architecture материалы, а не весь Ops всех
продуктов. Полный Desktop-документ содержит снимок выбранных карточек, их
активные комментарии и инженерные приложения. Архивные планы — не новые команды.
## 4. Борт: установленное, исходники и неизвестное
| Предмет | Проверенное основание / граница |
| --- | --- |
| Машина | Apple Macmini6,2, amd64, Ubuntu 24.04.4 LTS Desktop; Linux 7.0.0-31-generic по журналам сентября. Сегодня борт не опрашивался. |
| CPU/RAM/диск | Baseline 76 сообщает со слов владельца 8 GB RAM, одна планка. Свежие CPU/RAM/диск не измерены; получить read-only инвентаризацию. Это не операторский MacBook и не Worker 006. |
| Последний задокументированный Node | 0.8.21-3 установлен 10.09.2026; это же package version в `packaging/build_deb.py`. |
| X4 | Model package 0.1.3-9 (B17), установлена; чтение SDK/preview уже не «только USB enumeration». MANUAL02 с поздним receipt и другие проверки остаются открытыми. |
| D455 | Реальные захват/запись и USB3 подтверждены исторически. Не перезапускать и не лишать прав при добавлении силового оборудования. |
| K1 | Самостоятельная модель; бортовой путь — Wi-Fi Bridge общей сети, не operator-Mac fallback. |
| VESC | Реализации модели в проверенных Node/fleet/SDK/plugin-каталогах не найдено. Контроллеры, firmware, моторы и проводка ещё не идентифицированы. |
| Node UI | GTK/WebKit + встроенная React-сборка, локальный API на loopback:8780. Это не второй Core:8000. |
| Служба | Независима от окна, состояние `/var/lib/mission-core-node`, версия/identity сохраняются при штатных обновлениях. |
Не путать Rover 006, onboard Mini, операторский MacBook Pro (18 GB RAM) и
Worker 006. Совпадение «006» не означает один компьютер или один контур.
Обнаружено расхождение документации: `apps/node-agent/README.md` называет
«current» 0.6.11; исходники пакета и последние Node-документы — 0.8.21-3.
Первая фраза секции X4 в AGENTS фиксирует стартовое состояние 08.09; более
поздние аппаратные результаты находятся в ledger и status 10.09. Не стирать
историю и не ослаблять installer/safety-правила из-за этого расхождения.
## 5. Архитектурные инварианты
```text
Core: Парк → Rover 006 Локальное приложение Node
\ /
один контракт операций
|
Node на Mini: состояние, права, задания
|
VESC-адаптер: один владелец USB/CAN-сеанса
|
контроллер → канал → физический мотор
```
- `model != device instance != USB/CAN address != device session != роль L/R`.
- Tailscale — транспорт. Он не создаёт доверие Core/Node и не заменяет mTLS,
сопряжение, идентичность борта или права на опасные операции.
- Core проецирует состояние и отправляет адресные операции. Он не сканирует
USB операторского компьютера вместо борта и не управляет контроллером по SSH.
- Одновременные локальная и удалённая UI не создают двух владельцев serial.
- `acknowledged != completed`. Потерянный ответ на запись — неизвестный исход,
а не основание автоматически повторять калибровку/прошивку.
- Повторное подключение создаёт новый сеанс; старые команды отклоняются.
Автообнаружение не означает автонастройку, автопрошивку или разрешение движения.
- Существующий сенсорный контракт даёт идентичность/операции/состояния, но сам
по себе **не доказывает безопасность привода**. Нужны отдельные правила
обслуживания, владения RC/автономным управлением и аварийного останова.
- Linux users/groups, точные udev-правила, драйвер, сервис и зависимости входят
в versioned installer/profile с первого опыта. Не делать `chmod 666`, ручной
global pip/apt и последующее обещание «упаковать позже».
Точки входа в код:
| Файлы | Ответственность |
| --- | --- |
| `apps/node-agent/internal/node/sensor_models.go` | Реестр моделей, USB discovery, stable/provisional identity. Сейчас D455/K1/X4; не добавлять мотор как фиктивную USB-камеру. |
| `apps/node-agent/internal/node/sensors.go`, `sensor_events.go`, `sensor_preparation.go` | Сеансы, операции, события обнаружения, подготовка. |
| `apps/node-agent/internal/node/pairing*.go` | Доверие, транспорт и восстановление Core/Node. |
| `src/k1link/fleet/{registry,sensors,transport,trust,recovery}.py` | Сохранённый аппарат, проекция Node, очередь/результаты адресных операций. |
| `packages/plugin-sdk/python/missioncore_plugin_sdk/v0alpha2/` | Portable identity, session, operations, runtime, evidence. |
| `packages/sensor-ui/src/{pluginSdk,extensions,contracts}.ts` | Общая UI/transport boundary; будущий силовой detail — отдельная доменная композиция. |
| `apps/node-agent/packaging/` | Версионные Linux build/deb/qualification/owner-release и профили. |
| `plugins/insta360-x4/` | Пример модели и отдельного runtime; не копировать camera-specific semantics в VESC. |
## 6. Что подтверждено в upstream VESC
Первичные источники просмотрены 23.09.2026; ссылки на `master` подвижны.
Перед реализацией закрепить конкретный release/commit и совместимые hardware/
firmware. Это исследование исходников, а не аппаратная квалификация Rover 006.
- [VESC Tool](https://github.com/vedderb/vesc_tool): открытый Qt-проект, Linux
поддерживается. Учесть GPL и отдельные условия товарного знака при интеграции
и распространении; отдельный процесс сам по себе не решает лицензионный вопрос.
- [CLI](https://github.com/vedderb/vesc_tool/blob/master/main.cpp): есть выбор
serial/CAN, выгрузка motor/app config, firmware query, offscreen и TCP server.
Наличие этих ключей не означает готовый стабильный REST backend всех функций.
- [Commands](https://github.com/vedderb/vesc_tool/blob/master/commands.h): чтение
firmware, values, motor/app config, CAN discovery отделено от setters,
detect/measure, управления током/оборотами и прошивки.
- [Firmware identity](https://github.com/vedderb/vesc_tool/blob/master/datatypes.h):
FW_RX_PARAMS содержит HW, firmware и UUID. Их полноту/смысл проверять на реальной
версии; одна строка HW не всегда устанавливает коммерческую модель платы.
- [Autoconnect](https://github.com/vedderb/vesc_tool/blob/master/vescinterface.cpp):
штатный поиск перебирает serial-порты и останавливается на первом ответившем
устройстве. Для двух каналов он не заменяет наш полный inventory и L/R binding.
- [TCP server](https://github.com/vedderb/vesc_tool/blob/master/tcpserversimple.cpp):
простой транспорт не является нашей границей авторизации. Не публиковать
сырой управляющий TCP в LAN/Tailscale/Internet только потому, что он существует.
- [Firmware fault types](https://github.com/vedderb/bldc/blob/master/datatypes.h):
различаются ошибки питания, тока, драйвера, датчиков и конфигурации. Поэтому
«мотор остановился» недостаточно для вывода «слетела калибровка».
Для первого обследования разумно иметь официальный VESC Tool как инженерный
инструмент на Linux Mini. Встроенный продуктовый путь — отдельный адаптер с
проверенными разрешёнными операциями. Tool и адаптер не должны одновременно
захватывать один serial-порт. Автозагрузка произвольного QML/Lisp с устройства
и свободный terminal passthrough не входят в исходную read-only поверхность.
## 7. Обнаружение и устройство предметной модели
1. Получить OS USB/serial inventory без отправки команд всем найденным портам.
2. Отобрать кандидатов по подтверждённым дескрипторам/профилю совместимости.
Затем ограниченный протокольный запрос личности и версии, без motor setters.
3. Проверить, скрываются ли другие контроллеры за CAN. Не включать широкие
broadcast-записи, detect-all или смену CAN baudrate ради инвентаризации.
4. Сохранить аппаратную личность и новый транспортный сеанс. Пустой/дублированный
UUID — provisional/ambiguous, не «первый порт = левый».
5. Модель платы подтвердить firmware/HW плюс маркировкой или документацией
производителя. USB VID/PID и UUID сами по себе не дают все характеристики.
6. Физический мотор обычно не USB-устройство. Его модель, датчики, допустимые
характеристики и соединение с каналом подтверждаются маркировкой/сборщиком.
Электрическое измерение параметров не является распознаванием производителя.
7. Назначить логические Left/Right после подтверждения проводки владельцем.
Новая плата обнаруживается автоматически, но не наследует молча калибровку
и разрешение движения старой. Двухканальный контроллер моделировать честно,
не создавать два вымышленных корпуса.
## 8. Диагностика проблемного канала
Сначала зафиксировать firmware/HW и конфигурации **обоих** каналов: motor config,
app/input config и поддержанные custom configs. Сохранить исходные файлы,
UUID/версию/время/хеш в приватном evidence; в Git/Ops — очищенный отчёт.
Сравнить по смыслу: режим управления и датчиков, ramp/лимиты, вход пульта,
настройки CAN и тайм-аутов, параметры FOC/Hall/encoder, ошибки и телеметрию.
Не копировать весь конфиг исправного контроллера в проблемный: отличаются
направление, адрес, датчики и собственные параметры канала.
При отдельном согласованном опыте записать одновременно команду RC, ERPM,
токи/напряжение, температуры и fault в момент плавного и резкого старта.
Установить поддержку этих измерений на конкретной firmware. Нулевой fault
после перезагрузки не доказывает отсутствие ошибки в предыдущем опыте.
Только затем выбрать адресную коррекцию настройки или motor detection. Detection
может подавать ток и вращать мотор; это не безобидная кнопка USB discovery.
До опыта необходимы безопасно закреплённый аппарат, исключённое конкурирующее
управление, доступный аварийный останов и подтверждённые пределы оборудования.
Здесь намеренно нет придуманных значений ампер/вольт/ERPM.
Перепрошивка не первый шаг: нужен точный образ производителя для точного HW,
совместимость конфигов, сохранённый исходный baseline и план восстановления.
## 9. Этапы реализации и критерии готовности
| Этап | Результат | Условие перехода |
| --- | --- | --- |
| V0 · baseline | Свежий Node inventory, версии, схема подключения и подтверждённые стороны. | Борт действительно доступен; нет предположений вместо моделей. |
| V1 · discovery/read | Версионный адаптер; оба контроллера, конфиги, ошибки, приватный backup. | Hotplug/смена порта/перезапуск сохраняют правильные личности; ни одного motor/config write. |
| V2 · Core + Node | Одна доменная карточка силового оборудования и общий backend. | Обе UI видят тот же возраст данных/сеанс/операции; offline честный; нет второго serial owner. |
| V3 · diagnosis | Отчёт «какая команда, какая реакция, какая ошибка», выбранная проверяемая гипотеза. | Не только словесное «откалибровали», а сохранённые before/after evidence. |
| V4 · calibration/config | Явно разрешённая адресная операция обслуживания, diff/readback и результат. | Работает отмена/ошибка/потерянный ответ; нет blind retry и изменения соседнего канала. |
| V5 · расширение Tool | Матрица функций: доступно/несовместимо/опасная операция/ещё не реализовано. | «Все функции» не объявляются готовыми по наличию одной кнопки. |
Тесты до аппаратных записей: парсинг повреждённых/неполных пакетов, неподдержанная
firmware, тайм-аут, два одинаковых устройства, отсутствующая/дублированная
личность, USB reorder, CAN alias, занятый порт, смена сеанса, stale state,
дедупликация, неизвестный outcome. На железе отдельно проверить bounded чтение,
нагрузку CPU/RAM, сохранность D455/X4 и отсутствие непрошеного движения.
Не запускать нагрузочные тесты на операторском MacBook.
## 10. Репозиторий, публикация и граница параллельной работы
Проверенный checkout: `NODEDC_MISSION_CORE_m5_observatory`, ветка `main`,
HEAD `2e5d52521f600408bfd6b65bd8caed99ccb09405`.
Remote — `https://git.dcserve.ru/SILVER/NODEDC_MISSION_CORE.git`.
Checkout `NODEDC_MISSION_CORE_node` и базовый `NODEDC_MISSION_CORE` находятся
на detached `76dc9f1`; не принимать их автоматически за актуальную Node-ветку.
В рабочем дереве идёт чужая работа по SIM/AI polygon и восстановлению служб,
включая общие App/styles/web файлы. Не включать её в VESC-коммит, не делать
`git add -A`, reset/checkout, общий merge или перезапуск чужих процессов.
23.09 выполнен обычный fast-forward push `c804d89 → 2e5d525`, включая один
50 MB WASM в LFS. Последующий `ls-remote` подтвердил точный HEAD на remote main.
Незакоммиченная работа SIM не включалась; рабочее дерево не объявляется чистым.
Для реализации выбрать согласованный актуальный checkout/изолированный worktree;
этот документ не даёт разрешения переносить или останавливать соседнюю задачу.
## 11. Сеть и текущие ограничения проверки
Правильные имена подтверждены источниками, а не голосовой транскрипцией:
`git.dcserve.ru` (git remote), `ops.nodedc.ru` (документы),
`ops-agents.nodedc.ru` и `foundry.nodedc.ru` (настройки подключений),
`hub.nodedc.ru` (редирект входа Foundry).
23.09 проверены DNS и HTTPS через обычный сетевой интерфейс при включённом
hidemy.name VPN: Git/Ops/Ops-agent вернули HTTP 200, Foundry — редирект на Hub,
Hub root — HTTP 404. Последнее доказывает достижимость HTTPS, не успешный login.
Все пять доменов в этом замере имели общий IPv4. Владелец подтвердил системный
admin prompt; точечный host-route восстановил обычный Git и прямой Ops MCP.
Затем LAN сменилась, старый шлюз перестал работать; обновлён только наш маршрут
на подтверждённый DHCP-шлюз новой сети. VPN и Tailscale остались подключены.
Владелец подтвердил вход в Hub. Постоянный helper не установлен: после смены
сети/DNS/reboot маршрут нужно перепроверять. NAT Firewall в VPN-панели разрешает или
блокирует трафик внутри VPN, но не выбирает локальный обход туннеля.
Core на `127.0.0.1:8000` ответил HTTP 200. В этом аудите не запускались сборки,
новые серверы, аппаратные команды, калибровка, firmware upload и установка на
Mini. Просмотрены исходники/документы и официальные upstream-источники.
## 12. Выполненная актуализация Ops и оставшиеся границы
- MISSIONCOR-84 создана с исследованием, фактами владельца, источниками,
архитектурой, диагностикой, планом и чекером. Реализация остаётся открыта.
- MISSIONCOR-76: добавлен комментарий-связь; замороженное тело не менялось.
- MISSIONCOR-2: добавлен текущий срез вне SIM; исторические блоки сохранены.
- MISSIONCOR-74/81: публикация `2e5d525` подтверждена новым блоком; старые
сообщения о сетевой недоступности сохранены со своими датами.
- MISSIONCOR-66: добавлено уточнение, что current native viewer теперь имеет
принятый ограниченный patch 0.36.3. Срез 05.09 не переписан задним числом.
- X4 MANUAL02/local video/clean-Ubuntu и safety/absolute-accuracy проверки
планировщика не закрывались. SIM-карточки и runtime не изменялись.
- Сетевой skill дополнен проверенным поведением и сменой LAN; валидатор прошёл.
## 13. Краткий вход для следующей задачи
> Прочитай этот handoff и названные каноны, затем восстанови прямой Ops-контекст.
> Работаем с силовым оборудованием NDC Rover 006 через существующий Ubuntu Node
> на Mac Mini. SIM не трогаем. Начни со свежего read-only baseline, точных моделей,
> топологии USB/CAN, backup конфигов двух контроллеров и подтверждения сторон.
> Конфигурация/firmware проблемного канала — приоритетная гипотеза, не доказанный
> диагноз. Не запускай detection, моторы или flashing при автообнаружении.
> Спроектируй один бортовой адаптер для локальной и удалённой UI; реализуй первый
> безопасный вертикальный read-only сценарий с версионным installer/profile.
> Отдельно предложи проверку причины остановки при резком газе и адресную
> коррекцию с сохранением before/after. В Ops записывай завершённые результаты,
> а не обещай принятую аппаратную работу без опыта.
@@ -0,0 +1,331 @@
# Rover 006 — VESC: аудит кода и план реализации
Исторический план, составленный до реализации 23 сентября 2026. Текущий статус
см. `../node/17_VESC_INSTALLATION_LEDGER.md` и MISSIONCOR-84.
Результат первоначального аудита — исследование, свежий read-only
baseline и план. Плагин ещё не реализован; конфиги контроллеров не прочитаны,
моторы не запускались. Исторические команды и планы приложенного документа
рассматривались как источники, а не как поручения на исполнение.
## 1. Целевой пользовательский результат
После подключения контроллеров к USB бортового Mac Mini они появляются в
«Устройствах» Node и в «Парк → Rover 006 → Устройства» основного Core.
В карточке выбранного контроллера есть вход **«VESC Tool»**. Через него доступны
настройка, диагностика, калибровка и остальные применимые функции Tool.
Исполнение принадлежит борту; обе UI используют одну реализацию предметного
интерфейса и одни операции. Полнота Tool остаётся целевым требованием,
первый read-only выпуск является отдельным промежуточным результатом.
Ближайшая физическая задача — разобраться с потерей оборотов одного мотора.
Слова владельца о левом канале остаются предположением до сопоставления.
Предыдущие наблюдения: плавный старт возможен, резкий может давать короткий
рывок и остановку; конфигурация, датчики и управление — приоритетная ветка
диагностики. Причина пока не измерена.
## 2. Что проверено сейчас
| Объект | Факт 23.09 | Ограничение |
| --- | --- | --- |
| Core | Канонический localhost:8000 отвечает; Rover 006 paired/online | Не означает доступность каждого устройства |
| SSH | Вход `dcsudo` с существующим персональным ключом работает | Старая запись `nodedc-edge` использовала `ndcsudo`; sudo не проверялся и не нужен для чтения |
| Борт | Ubuntu 24.04.4, kernel 7.0.0-31-generic, i7-3615QM, 4 ядра/8 потоков | CPU поддерживает AVX, но AVX2 в полученном наборе флагов нет |
| Память/диск | Около 8 GB RAM, около 6.3 GiB available; swap не занят; root 457 GiB, свободно 381 GiB | Это короткий idle-срез, не совместная нагрузочная приёмка |
| Установка | Node 0.8.21-3, K1 0.1.14, X4 0.1.3-9 | Старый Node README с 0.6.11 не является installed baseline |
| Службы | Node, K1, X4 broker, D455, monitor, PostgreSQL active/running, NRestarts=0 в проверенном наборе | Активный драйвер не доказывает подключение камеры |
| База | PostgreSQL 16, cluster `ndcmonitor` online; Timescale 2.29.2 установлен | База системного мониторинга, не готовый motor recorder |
| Реплика мониторинга | available/fresh=true, storage=ready, backlog=0; sample interval 1 s | Срез около 11:02 UTC; полевая задержка управления не измерена |
| USB контроллеров | Два кандидата `0483:5740`, ChibiOS/RT Virtual COM Port, cdc_acm, два ttyACM | USB-дескриптор ещё не доказательство HW/FW VESC |
| Identity | У двух кандидатов одинаковый USB serial; одна конфликтующая by-id ссылка | Нельзя использовать USB serial, by-id, tty или порядок включения как постоянную личность |
| Права | tty принадлежат root:dialout, 0660; dcsudo не имеет read/write | Права будущего runtime поставляются профилем модели |
| Конкурирующий опрос | ModemManager active; кандидаты имеют ID_MM_CANDIDATE=1 | Не доказано, что он уже посылал команды; нужен адресный udev ignore при подготовке модели |
| Камеры | D455/X4 в свежем paired inventory offline | Сохранность их потоков под VESC-нагрузкой сейчас проверить нельзя |
Портов serial не открывали; firmware/UUID, моторные и application configs,
CAN/RC topology и физические стороны остаются неизвестными. VESC Tool не найден
через проверенное имя `vesc_tool` в PATH; это не полный поиск всех установок.
Подробный путь доступа: [ROVER_006_ENGINEERING_ACCESS.md](../runbooks/ROVER_006_ENGINEERING_ACCESS.md).
Raw fleet/monitor snapshots и приватный SSH-профиль находятся вне Git в
операторском `outputs/rover-006-vesc-context-20260923`.
## 3. Источники и границы исследования
Прочитаны основной актуальный срез и VESC-handoff приложенного документа,
профильные Node/SDK/UI материалы и релевантная история приложений. Большой
архив планировщика/Rerun использован для контекста владельцев; повторной
квалификации всех старых экспериментов не выполнялось.
Через прямой Ops MCP получены живые проекты/контекст/карточки, в том числе
MISSIONCOR-84, 76, 77, 50, 5, 2, и история комментариев 76/77/84; изучен
архив ROBOT2B-5. Профильная карта —
[MISSIONCOR-84](https://ops.nodedc.ru/nodedc/browse/MISSIONCOR-84), Node —
[MISSIONCOR-76](https://ops.nodedc.ru/nodedc/browse/MISSIONCOR-76).
Поиск GPIO в других четырёх доступных Ops-проектах совпадений не вернул;
среди полученных Mission Core/ROBOT2B карточек подтверждённой схемы GPIO
для этого привода не найдено. Это пробел найденных источников, не утверждение
об отсутствии такой схемы вообще. USB достаточно для первого этапа;
GPIO/UART/RC/аварийная цепь требуют конкретной аппаратной схемы до motor tests.
Основная кодовая база: `NODEDC_MISSION_CORE_m5_observatory`, HEAD `2e5d525`.
Соседние base/node checkout остаются detached `76dc9f1`. В main есть чужая
незавершённая работа SIM/AI polygon и service recovery. Для реализации нужен
отдельный checkout от проверенного commit; не включать эти изменения в пакет.
Design Guideline прочитан по реестрам и документации, текущий HEAD
`8dd9190573d6616024ef01b9b34bf90b72960f44`, рабочее дерево чистое в проверке.
Node build_linux_source.py закреплён на `8c53f73...` и отклоняет другой HEAD.
Перед выпуском выбрать проверенную ревизию DG и квалифицировать её в сборке;
не снимать проверку и не брать случайные локальные dist.
## 4. Реальные точки расширения
| Код | Что уже есть | Что нужно VESC |
| --- | --- | --- |
| `apps/node-agent/internal/node/sensor_models.go` | Registry, model actions, отдельные IPC sockets, USB discovery, provisional identity при дублях | Новый model profile; разделение attachment и protocol UUID; discovery двух плат с одинаковым USB serial |
| `sensors.go` | Durable fsync journal, dedup, action allowlist, deadline, unknown после restart, local API | Точные VESC actions и параметры; проверка session непосредственно в адаптере; bounded результаты; не прятать моторные функции за camera `start`/`option` |
| `sensor_preparation.go` | Профиль на модель и проверка отдельного экземпляра, shared preparation job | Device-neutral подписи и безопасная identity verification. Нельзя трактовать `verify` как motor detection |
| `sensor_events.go` | udev events, coalescing, полные SSE snapshots | Reconnect создаёт новый session; stale GUI не получает authority над новым контроллером |
| `pairing_transport.go` | mTLS heartbeat, commands/results/acks; периодический tick 5 s и пробуждение от событий | Существующий путь для service operations; отдельная доставка частой telemetry и будущего realtime control |
| `src/k1link/fleet/sensors.py` | Проверки pairing/freshness/session, очередь, receipts, ограниченные payloads | Добавить явные actions; не превращать whitelist в arbitrary protocol passthrough |
| `packages/plugin-sdk/.../v0alpha2` | Identity/session, safety/idempotency policies, commands/events | Использовать существующие contracts; motor authority/lease и конфиг revision оформить узким дополнением |
| `packages/sensor-ui` | Общий SensorWorkspace, transport, Detail contribution, status/preparation | VESC Detail в том же slot; camera-specific поля/подписи нормализовать ровно там, где нужно |
| `apps/node-agent/ui/src/NodeSensors.tsx` | Локальная композиция общих plugins | Зарегистрировать ту же VESC contribution |
| `apps/control-station/src/core/fleet/sensorTransport.ts` и composition | Remote adapter общего UI | Повторно использовать; новая предметная логика в plugin, не App.tsx |
| `plugins/insta360-x4/runtime/operations.py` | fsync receipt до физического действия, отсутствие replay, readback settings | Проверенный пример lifecycle, но motor safety проектируется отдельно |
| Node monitor/storage и fleet monitor replica | 1 s host samples → Timescale → bounded Core replica | Не использовать этот период как осциллограф или контур stop; моторная сессия пишет данные на борту с собственной частотой |
В этих действующих реестрах и каталогах VESC runtime отсутствует. Архитектурные
документы старого этапа местами описывают gRPC как целевой вариант; текущая
проверенная реализация использует JSON HTTP/Unix sockets и HTTPS heartbeat.
## 5. Интеграция VESC Tool
Для аудита закреплён официальный upstream:
[`dc53c658cbb89a947246034f7a00149cf79abdfc`](https://github.com/vedderb/vesc_tool/tree/dc53c658cbb89a947246034f7a00149cf79abdfc).
Сохранены 17 исходных файлов с SHA-256. Этот snapshot объявляет **7.01,
test version 1**; это исследовательская точка, не автоматически выбранный
production release для неизвестной firmware наших плат.
Исходники показывают:
- `main.cpp`: CLI умеет конкретные чтения/записи config, выбор port/CAN,
offscreen и TCP. Это не готовый полный web API.
- `vescinterface.cpp`: autoconnect обходит serial ports и заканчивает поиск
на первом ответе. Для инвентаризации двух плат нужен наш ограниченный поиск.
- `commands.cpp`/`datatypes.h`: FW response содержит version, HW name, UUID
и дополнительные признаки; набор полей зависит от ответа. HW name нельзя
автоматически считать точной коммерческой моделью платы.
- `configparams.cpp`/`utility.cpp`: schema выбирается по firmware, сериализация
использует signature. Парсить конфиг произвольной новой firmware старой
схемой и затем сохранять его нельзя.
- `packet.cpp`: length/framing/CRC и размер пакета ограничены. Нужны tests на
fragmented/combined/corrupt packets и truncation полей ответа.
- `tcpserversimple.h`: default bind — все адреса. Штатный TCP server нельзя
просто включить как удалённый продуктовый интерфейс.
- `setupwizardmotor.cpp`: wizard содержит реальные записи конфигурации по
ходу шагов. Его запуск/отмена не являются только локальным редактированием.
### Сравнение реализаций
| Вариант | Польза | Цена/ограничение |
| --- | --- | --- |
| Официальный Qt Tool + локальный launcher и трансляция его окна в Core | Самый прямой путь к исходному GUI и широкому набору функций | Новый remote-app runtime, конкуренция ввода двух UI, Qt UI вне DG, передача port ownership; интерфейс сам умеет опасные команды |
| Собственный минимальный protocol adapter | Быстрое read-only discovery/telemetry | Поддержка всех конфигов/wizards потребует дублирования большого firmware-specific слоя |
| Бортовой service plugin с переиспользованием закреплённого upstream protocol/config engine + общий React UI | Наш UI, один owner, применимые функции Tool расширяются без второй модели состояния | Требуется проверить headless сборку/зависимости и адаптировать операции; полного готового API нет |
**Рекомендация:** третий вариант как целевая архитектура. Первый технический
spike проверяет сборку и выделение engine без desktop UI; fallback на
ограниченный собственный reader допустим для первого чтения, но не отменяет
требование функционального паритета. Оригинальный Tool полезен как инструмент
сравнения с эксклюзивной передачей владения портом. В текущем плане нельзя
объявить «все функции готовы», открыв только несколько полей или удалённое окно.
Нужно отдельно различать паритет функций и показ неизменённого Qt GUI. Здесь
принято рабочее предположение из запроса про наш интерфейс и DG: единая
предметная UI внутри Mission Core. Если нужен именно исходный Qt GUI, меняется
способ его доставки, а не требование единственного hardware owner.
Upstream содержит GPL-3.0-or-later notices и отдельные правила бренда. При
упаковке выбранного кода/бинарника проверить состав, notices, исходники и
название распространяемого продукта. Этот аудит не делает юридического вывода
о допустимости конкретного способа распространения.
## 6. Runtime и модель данных
```mermaid
flowchart TD
L[Node UI: Устройства → VESC Tool] --> N[Node API и журнал операций]
R[Core: Парк → Rover 006 → VESC Tool] --> C[Core fleet API]
C -->|Существующее pairing и mTLS| N
N --> V[VESC plugin на борту: owner и арбитраж]
V --> U[USB attachment → protocol UUID → controller/channel]
U --> M[Мотор и подтверждённая роль]
V --> D[Конфиги, telemetry и diagnostic session на борту]
D --> C
```
Предлагаемый bounded каталог `plugins/vesc/`: `runtime/`, `frontend/`,
`profiles/`, `packaging/`, `tests/`, upstream lock/notice manifest.
Названия здесь — план, каталог ещё не создан.
Один service владеет serial. Открывает только подтверждённые candidates;
проверяет отсутствие конкурирующего владельца и сохраняет связь порта с
attachment generation. До FW query attachment имеет provisional identity.
После ответа UUID связывается со стабильным controller instance. Смена порта
не меняет подтверждённый UUID; USB/CAN aliases одной платы не создают двойник.
Неоднозначный protocol UUID оставляет устройство без write authority.
Особенно важно для текущих двух плат: общий Node discovery уже считает
duplicate USB serial неинициализируемым. Нельзя просто добавить VID/PID:
обе кнопки подготовки окажутся заблокированы. Нужен отдельный безопасный путь
подготовки модели/identity query для provisional attachments; он разрешает
только ограниченное чтение личности. Общую защиту камер не ослаблять.
Role Left/Right и metadata мотора хранятся отдельно от UUID. Отключение владельцем
одного USB при обесточенном приводе может сопоставить плату с кабелем; это само
по себе не доказывает, какой мотор подключён к её силовым выходам. Сопоставление
по проводке/маркировке предпочтительно; активный тест — отдельная операция.
Конфиг имеет исходный blob, decoded fields, firmware/schema signature, hash,
revision и timestamp. Запись использует ожидаемую revision и свежий session,
сохраняет before/after, выполняет readback. Потеря ACK даёт unknown и
reconciliation, а не слепой retry.
Калибровка — бортовая операция с этапами, результатом и явно проверенной
семантикой отмены. HTTP timeout не доказывает прекращение электрического
измерения. Motor control дополнительно требует одного владельца управления,
локального watchdog, известных timeout/stop свойств firmware и арбитража RC.
Точные токи/обороты/частота не выбираются до hardware baseline.
## 7. Полнота функций и порядок включения
| Группа Tool | Предметный результат | Этап и условие |
| --- | --- | --- |
| Discovery, FW/HW/UUID, USB/CAN topology | Независимые экземпляры и совместимость | Первый read-only slice |
| Live values, faults, decoded PPM/ADC/Chuk input | Напряжение, токи, ERPM, температура, вход, timeout/kill flags по поддержке FW | Первый read-only slice; измерить реальную частоту |
| Motor/app/custom configs, backup/export, сравнение | Полный применимый набор параметров по schema, неизменяемый backup | Read-only до первой записи |
| Import, defaults, apply/restore | Предпросмотр diff и проверенный readback | После identity, backup и compatibility; restore/defaults — записи |
| FOC/BLDC/DC setup, R/L/flux, Hall/encoder | Калибровочный workflow с результатом | Активный допуск на конкретный мотор; один шаг может подавать ток |
| App/input setup, direction, limits | Настройка RC/ADC/UART/CAN по реальной схеме | Сначала прочитать существующий input/timeout/RC ownership |
| Duty/current/brake/RPM/position, motor tests | Управляемый стендовый опыт | Быстрый бортовой контур; не heartbeat 5 s |
| Samples, logging, plotting | Синхронная диагностическая запись реакции | Bounded board recorder; сводки через Core |
| Firmware/bootloader/recovery | Exact-HW image, версия, progress и recovery | Отдельная поздняя ветка; не «обновить на всякий случай» |
| CAN forwarding/multi-controller setup | Явный target и topology | Никаких автоматических detect-all/broadcast writes |
| Terminal, Lisp/QML/packages, custom application | Сервисные функции выбранного устройства | Отдельный maintenance scope; чтение кода и его выполнение различаются |
| BMS, IMU, power switch, NRF/GPD и расширения | Применимые к конкретному hardware возможности | Capability-driven; отсутствие аппаратуры не маскировать как готовую функцию |
Перед реализацией широкой сервисной поверхности матрица уточняется по страницам
выбранного релиза Tool и реальной HW/FW. Для каждого пункта фиксируются:
supported/unsupported/not-implemented, операция, side effects, schema,
readback, cancel/recovery и аппаратная приёмка. Старые настройки firmware
не переименовываются в поддержанные только ради единого красивого UI.
## 8. UI brief и Design Guideline
Задача оператора: выбрать конкретный контроллер, понять состояние, настроить
его и проверить итог. Первичная сущность — выбранный controller/channel;
мотор и роль — связанный контекст. Вход из существующего списка устройств.
Выбран **plugin Detail slot** общего `SensorWorkspace`, с текстовой кнопкой
«VESC Tool» в карточке. Внутри — обзор/диагностика, параметры и сервисные
операции, основанные на capabilities. Нового root или LAB не требуется.
Длинный motor workflow остаётся полноценным detail-view; компактный editor
может использовать существующий `FeatureSettingsWindow`.
Альтернатива отдельного глобального workspace создаёт второй вход к тем же
устройствам и отрывает инструмент от адресной identity. Модальное окно на весь
долгий workflow неудобно для контроля результата и закрытия/recovery.
Показ исходного Qt GUI — иной вариант интеграции, описанный выше.
Уже есть `ResourceRow/List`, `Button/IconButton`, `StatusBadge`,
`SettingsCard`, `Window`, `FeatureSettingsWindow`, `SegmentedControl`,
`TextField`, `Select`, `RangeControl`, `ConfirmationModal`, `ProgressBar`,
`LoadingRegion`, `ToastStack`. Подходящие существующие icons: settings,
activity, network, download, upload, refresh, alert, eye, play/stop.
Отдельной motor-icon в просмотренном registry нет; новая не нужна для первого
slice. Domain graph/plot остаётся кодом плагина с этими controls.
`RangeControl.min/max` ограничивает drag, но не всякий ручной ввод: для токов
и других bounded величин нужны `exactValueBounds` и серверная валидация.
Safety check нельзя делегировать только форме.
Состояния: поиск; не обнаружено; найден кандидат; требуется подготовка;
чтение личности; unsupported/ambiguous; готов к чтению; fault; занят;
операция выполняется; outcome unknown; связь потеряна. Свежесть контроллера
проверяется отдельно от online борта. Браузер не принимает unknown за failed
и не предлагает повтор опасного действия как универсальное восстановление.
Это новое доменное содержимое существующей принятой list/detail композиции.
Изменения global navigation и новые общие визуальные сущности не предлагаются.
## 9. Упаковка с первого бортового опыта
Versioned пакет/profile устанавливает бинарник, pinned зависимости, отдельного
непривилегированного service user, Unix socket для Node, systemd limits,
узкие udev rules доступа и ModemManager ignore для квалифицированного профиля.
Не добавлять весь Node или пользователя в общий dialout, не делать chmod 666,
не отключать ModemManager глобально. Runtime не должен читать произвольные tty.
Node сохраняет `PrivateDevices=yes`; аппаратные права принадлежат отдельному
адаптеру. Verify после установки означает protocol identity/read capability,
а не автокалибровку. Package qualification: повторная установка, конфликт
портов, rollback бинарника при сохранении data/backup, холодный старт и чистая
Ubuntu. Компилятор/Qt dev packages не становятся скрытым требованием runtime.
## 10. Реализация по проверяемым результатам
1. **Контракт и build spike.** Изолированный checkout, выбранный upstream
release/commit, DG pin, headless engine build, firmware schema closure;
synthetic packets, IPC/action contracts. Никакого доступа к моторам.
2. **Discovery на борту и две UI.** Поставляемый profile, два кандидата с
одинаковым USB serial, FW/UUID handshake, session transitions, одна
VESC contribution в Node/Core. Итог — оба контроллера видны независимо.
3. **Read-only сервисная поверхность.** Версии/capabilities, telemetry,
faults/input, motor/app/custom backups и semantic diff. Это первый полезный
завершённый выпуск; статусы неподдержанной FW честные.
4. **Диагностика проблемного канала.** Сначала сравнить конфиги, затем на
подготовленном стенде записать плавный/резкий старт по конкретному сценарию.
Сопоставить command/input, ERPM, currents, voltage, fault и timeout. Выбрать
измеренную гипотезу; рабочий конфиг не копировать целиком.
5. **Адресная настройка/калибровка.** Backup, effect preview, необходимые
ограничения hardware, исключение конкурирующего управления, конкретная
операция, cancel/recovery, readback и повтор исходного теста.
6. **Остальная матрица Tool.** Дополнять функции вместе с соответствующей
упаковкой и аппаратными критериями; FW/terminal/scripts выделены по эффекту.
До физического теста требуются аппаратные факты о моторах/датчиках/питании,
проводке RC/CAN и доступном аварийном останове. Выбор «левый/правый» владельцем
выполняется позже; он не блокирует initial inventory.
## 11. Приёмка и тесты
- Parser: CRC, partial/multiple packets, неверные длины/концы, timeout,
несовместимая FW/config signature, отсутствующие optional fields.
- Identity: одинаковые USB serial, пустой/дублированный UUID, два независимых
контроллера, unplug/replug/reorder, замена платы, USB/CAN duplicate alias.
- Operations: общий local/remote journal, stale session, conflict/lease,
crash до/после dispatch, unknown outcome, readback mismatch, отсутствие
повторного исполнения после reconnect и reboot.
- Packaging: clean Ubuntu, narrow permissions, targeted ModemManager rule,
занятый port, idempotency/rollback, pinned binaries/firmware schemas/DG.
- UI: обе поверхности на одном экземпляре, одинаковые capabilities/results,
empty/offline/fault/unknown, сохранение draft, keyboard/Escape/expand, без
новых local controls или моторной логики в App.tsx.
- Hardware: версии и backup обеих плат; измеренный fault/поведение;
отдельная проверка stop/timeout на стенде до ручного управления.
- Совместная работа: вернуть реальные D455/X4/K1 в согласованный сценарий и
измерить ресурсы/USB/latency вместе с VESC. Их текущий offline не считается
успешной regression-проверкой.
Проверки кода выполнять последовательно с учётом памяти операторского Mac.
Текущая задача не меняла runtime-код, поэтому тесты/сборки приложения не
запускались. HTTP/SSH/API чтения и анализ исходников не являются калибровкой.
## 12. Следующее конкретное действие
Реализовать и упаковать **двухэкземплярное VESC discovery + read-only identity,
config backup и общую detail-поверхность**. Первый бортовой запуск обязан
учесть уже обнаруженный duplicate USB serial. Это снимает неизвестность
HW/FW и даёт основание выбирать реальную настройку проблемного мотора.