Мы в лаборатории 361.Robotics учим китайского гуманоида Walker Tienkung TK2301 работать голосом по‑русски — в прошлых статьях был сам голосовой стек, внешний микрофон и программное вставание по голосовой команде. У робота есть штатный пульт дистанционного управления, обычная радиосистема с рычажками, джойстиками и кнопками; приёмник стоит внутри корпуса. Один из рычажков у нас включает голосовой режим: поднял, и робот слушает и говорит, опустил, и он глохнет и замолкает. По пути к рабочему голосовому пайплайну пришлось провести отдельное расследование. Начиналось оно как рядовая задача, а закончилось выводом, который в общем‑то можно было предсказать заранее: софт не может знать того, чего ему не показывает железо. Эта история о том, как долгий методичный перебор гипотез заводит в тупик и как из него выйти.

Пульт выключен или рычажок опущен?
Для удобства взаимодействия с роботом было решено различать два разных состояния: пульт выключен целиком и пульт включен, а голосовой режим выключен рычажком. На первый взгляд разница незначительная, но для оператора это совсем не одно и то же. Если он сам переключил рычажок, это осознанное действие, и подсказывать ничего не нужно. Если же пульт выключен или у него сел аккумулятор, роботу стоило бы подсказать об этом голосом.
Задача выглядела решаемой. Приёмник публикует положение рычажков в поток сообщений каждые 23 миллисекунды, чуть больше сорока раз в секунду. Казалось бы, «рычажок физически в среднем положении» и «приёмник вообще ничего не получает» должны как‑то отличаться в этом потоке.
Что мы только не проверяли
Начали с очевидного: приёмник, потеряв сигнал с пульта, обязан как‑то сообщить об этом дальше по цепочке. Проверили: нет. Он продолжает публиковать данные с той же частотой, просто подставляет значения безопасного состояния. Так устроена любая радиосистема: при потере сигнала она переходит в заранее заданное безопасное положение, чтобы, например, в случае с дроном он не улетел неизвестно куда, а плавно завис или сел. Проблема в том, что по формату сообщений эти безопасные значения ничем не отличаются от настоящего положения рычажка.

Потом попробовали зацепиться за события переключения: в потоке есть специальные пометки о переходах между положениями рычажка. Тоже мимо. При потере сигнала приёмник сам генерирует такие же пометки, как будто рычажок кто‑то физически подвинул.
Дальше таймауты между сообщениями. Может, при потере связи паузы между сообщениями станут длиннее или как‑то изменятся? Замерили за длительный период: интервал те же 23 миллисекунды, публикация не прерывается никогда.
Была гипотеза поинтереснее, про траекторию. Когда рычажок двигает человек, палец проводит его через промежуточные положения, а подстановка безопасного значения при потере связи должна перескакивать на конечную величину мгновенно. Значит, разницу можно поймать по форме перехода в данных. Оказалось, нет. Рычажок трёхступенчатый, он переключается между фиксированными положениями, и промежуточных значений в потоке не было ни при живом движении, ни при потере связи. В обоих случаях переход выглядит как мгновенный скачок.
Попробовали зайти со стороны логов самого приёмника. Его программный модуль поставляется закрытым бинарником, но текстовым поиском по нему нашли упоминание функции с подходящим названием. Проверили, пишет ли она что‑нибудь в системный журнал при срабатывании. Файл журнала оказался пустым: либо функция в реальности не вызывается, либо мы не нашли журнал, куда на самом деле идут записи.
Последняя идея была совсем прямолинейной: подключиться к тому же физическому порту параллельно и почитать сырые байты самим, в обход всей системы. Оказалось, что порт монопольно занят тем самым процессом‑приёмником, второму читателю туда просто не подключиться.
Шесть разных гипотез, и все шесть упёрлись в один факт: production‑система приёмника отдаёт наверх только финальное положение рычажка, без признака, настоящее это положение или подстановка на случай потери связи.

Практика не дала решения, но что ещё можно сделать теоретически?
После этой серии проверок вывод был сформулирован однозначно: на программном уровне в текущей конфигурации железа отличить «пульт выключен» от «оператор осознанно переключил рычажок» невозможно. Речь не о том, что мы не нашли способ. Необходимая нам информация никогда не попадает в поток данных, к которому у нас есть доступ, поэтому способа просто не существует.
Оставались три теоретических пути, и все они уже не софтверные, а аппаратные или организационные.
Первый. У приёмника есть своё мобильное приложение для тонкой настройки. В теории там можно задать для состояния «потеря связи» нестандартное значение за пределами обычного рабочего диапазона, и тогда его получится отличить программно.
Второй. У приёмника есть отдельный, пока никак не задействованный порт служебной телеметрии. Туда теоретически можно припаять ещё один переходник и попробовать с нуля реверс‑инжинирить закрытый протокол производителя пульта. Этот вариант имел реальный риск повредить рабочее железо ради, по сути, косметического улучшения UX. Решили, что оно того не стоит.
Третий. Обратиться к производителю робота с просьбой добавить в официальный формат сообщений явный флаг «потеряна связь». Самый правильный путь, но он зависит от того, насколько быстро и охотно вендор реагирует на такие запросы. Гарантий нет, и быстро не будет.
Итоговое решение — чинить не программно, а объяснить пользователю
Раз программно проблему нам решить не удалось, решение сместилось в область UX. Приняли простое правило для оператора: после включения или выключения пульта один раз провести рычажком через среднее положение, и только потом поднимать его для включения голоса. Так рычажок гарантированно делает настоящий физический переход, который система точно заметит, и двусмысленность исчезает. Не самое изящное решение, но работает и оператору понятно, что делать.

Когда шесть провалов всё равно дают результат
Расследование шло методично: список конкретных проверяемых гипотез, проверка каждой на живом железе, и только после того, как все разумные и реализуемые гипотезы исчерпаны, признание, что программными методами дальше задачу не решить. Помогла не ещё одна попытка в том же направлении, а готовность сделать шаг назад и сменить уровень, на котором принимается решение. Вместо «починить программно то, что должно быть видно в потоке» мы признали, что источника данных нет, и решили задачу иначе: простым соглашением с оператором вместо технического обхода.
Не каждая инженерная проблема решается в лоб, особенно когда упираешься в закрытое стороннее железо. Шесть гипотез понадобились, чтобы честно убедиться: программным путём идти действительно некуда.
Это четвёртая история из работы с этим роботом: голосовой стек, внешний микрофон, вставание по голосовой команде — и вот теперь пульт как чёрный ящик. Впереди ещё несколько — если тема интересна, подписывайтесь, расскажем.
Буду рад вопросам в комментариях, и отдельно интересно мнение тех, кто работал с RC‑радиосистемами в проде: удавалось ли вам вытащить признак потери связи из закрытого приёмника, или все в итоге приходят к такому же организационному обходу?
Сейчас у нас в лаборатории работают четыре платформы: гуманоиды Unitree G1 EDU+, Leju Kuavo 4Pro и UBTech Walker Tienkung — Embodied Intelligence, а также промышленный квадрупед Unitree B2. Мы активно экспериментируем с ними и обучаем роботов сценариям реального применения и решению бизнес‑задач. О других кейсах расскажем в будущих статьях на Хабре. А пока мы их пишем, читайте наш Telegram‑канал 361.Robotics о робототехнике, воплощенном ИИ и новой экономике вокруг них.
Если вы хотите приобрести робота для своей компании или личного использования, мы можем помочь с поставкой гуманоидов, квадрупедов и другой робототехники из Китая, а также адаптировать оборудование под задачи заказчика.
Мы открыты к обмену опытом, сотрудничеству, совместной работе над интересными проектами и просто знакомству с увлеченными людьми. Хотите увидеть современных роботов воочию — напишите нам и приезжайте на экскурсию в лабораторию 361.Robotics в Москву (м. Павелецкая).
Комментарии (2)

Wesha
26.10.2026 17:57После этой серии проверок вывод был сформулирован однозначно: на программном уровне в текущей конфигурации железа отличить «пульт выключен» от «оператор осознанно переключил рычажок» невозможно. Речь не о том, что мы не нашли способ. Необходимая нам информация никогда не попадает в поток данных, к которому у нас есть доступ, поэтому способа просто не существует.
А вставить посох крепкий, деревянный кетайцам ушлым в отверстие подобающее — не вариант?
Wesha
Что-то ужасно знакомое...
— Питер Уоттс. «Морские звезды»