Ar'Vi

Ar'Vi 

Looking for myself in coding and in other people

51subscribers

57posts

Showcase and bundles

2
A bundle is a collection, compilation, playlist, or catalog of posts that saves you from searching through the blog and lets you buy the entire content series in a single click.
goals4
9 of 35 paid subscribers
[+]Больше смысла и времени заниматься творчеством. [!]Средства уходят на аппаратуру и развитие контента.
2 of 4
Oct 27 13:11 · AI content

Pico 4 Pro и Lighthouse без трекера на голове: порт QuestLHSync

Всё что ниже - это обработанный пересказ утренних изысканий относительно возможности избавиться от трекера на голове для синхронизации с Lighthouse девайсами в частности - базовыми станциями. Спасибо технологиям что позволяют набросать прототипы за пару часов, а не 1-2 недели плотных задротских технических вечеров. Спасибо.
Кто играет в VRChat с фулбоди на Lighthouse и шлемом не от Valve, знает эту боль: пространство трекеров и пространство шлема живут отдельно, и их приходится постоянно сводить. Обычно это SpaceCalibrator плюс трекер на голове или перекалибровка каждые полчаса. Для Quest уже есть QuestLHSync от CreoleVR: шлем сам видит базовые станции своими камерами и держит всё выровненным, без трекера на голове. Для Pico такого не было. Теперь есть: я портировал QuestLHSync на Pico 4 Pro. Ниже история целиком: как это устроено, на какие грабли наступил и как поставить себе.

⚠️ Сначала о рисках и ограничениях

  • Нужен root (Magisk) на шлеме. Как я его получал, есть в прошлом посте про раздельные глаза: разблокировка загрузчика стирает все данные в шлеме.
  • Порт экспериментальный. Проверен на одном шлеме: Pico 4 Pro, PICO OS 5.13.3S, стриминг через Virtual Desktop, три станции 2.0. На обычном Pico 4 и других прошивках не проверялся.
  • Готовых сборок пока нет, собирать из исходников. Это несложно, команды ниже.
  • Модуль на шлеме ничего не прошивает и не меняет в системе. Удаляется из Magisk одной кнопкой.

Как работает QuestLHSync

Базовые станции 2.0 крутят лазерные плоскости. Если в момент короткой экспозиции камеры шлема через неё проходит лазер, в кадре вспыхивает яркая точка. Направление на неё - это луч из камеры на станцию. Шлем знает свою позу, SteamVR знает, где стоят станции. Если набрать достаточно таких лучей, можно найти поворот и сдвиг, при которых все лучи попадают в станции. Это и есть выравнивание двух пространств, и драйвер применяет его ко всем Lighthouse-устройствам прямо на лету.
Устроено из двух частей:
  • на шлеме: модуль Magisk. Читает кадры камер трекинга, ищет яркие точки и отдаёт их по сети (TCP 47280);
  • на ПК: драйвер SteamVR. Принимает точки, решает задачу выравнивания и добавляет свою страницу в дашборд SteamVR.
Чтобы запустить это на Pico, нужно было переписать часть на шлеме под его камеры и научить драйвер понимать калибровку Pico. Дальше самое интересное.

Шаг 1. Найти камеры

У Pico 4 Pro четыре камеры трекинга OV9282: глобальный затвор, 640×480, 10 бит. Все кадры живут в системном процессе pvrtrackingservice, в кольце из 32 буферов dmabuf, по 8 на камеру. Камеры снимают 50 кадров в секунду, чередуя длинную и короткую экспозицию. Лазеры видны только в коротких.
Грабля №1: буферы не читаются снаружи. Даже из-под root /proc/pid/mem на этих областях отвечает ошибкой ввода-вывода. Пришлось делать как в оригинале для Quest: внедрять Frida прямо в процесс трекинга и искать точки там, на маленьком C-коде, скомпилированном на лету.
Грабля №2: двойные кадры. Сначала я видел около 80 кадров в секунду вместо 50: один и тот же кадр иногда засчитывался дважды. Оказалось, что в конце каждого буфера есть служебный «хвост» с номером кадра и точным временем экспозиции в наносекундах. По нему кадры идут ровно 50,0 в секунду. Заодно время каждого кадра теперь точное, без задержки опроса.
Грабля №3: какая камера какая. Калибровку Pico хранит в /mnt/vendor/persist/pvr/mav0/cam0..3/sensor.yaml (формат Kalibr). Но в каком порядке в памяти лежат буферы камер, неизвестно. Выяснял дедовским способом: закрывал камеры пальцами по одной и смотрел, какой поток темнеет. Порядок по ходу перепутал, но по логам всё равно восстановилось: 3,2,1,0.
Калибровку Pico в модели omni я пересчитываю в модель Fisheye62, которую понимает драйвер, с точностью 0,03–0,07 пикселя.

Шаг 2. Первый запуск и... «чёт жиденько вышло»

Всё подключилось: шлем нашёлся, четыре камеры отдают кадры, ярких точек больше тысячи в минуту. А захвата нет вообще. Драйвер записал сессию, и я разобрал её офлайн.
Грабля №4: 98% точек - это лампы. У меня на потолке два трековых LED-светильника, и короткие кадры Pico пересвечивают их так же, как лазер. Драйвер раз за разом принимал светильник за станцию. Отличить по размеру не получилось: лазерная вспышка у Pico крупная, 18-52 пикселя, но и лампа вблизи бывает такой же. Отличает другое: лампа видна почти в каждом кадре, а лазер мелькает в одиночных. Точки, которые держатся несколько кадров подряд, теперь считаются лампами.
Грабля №5: лазер ловится редко. Короткая экспозиция у Pico около 40 микросекунд, так что лазер попадает в неё лишь иногда: несколько раз в минуту на станцию. У Quest намного чаще. Пришлось подстроить драйвер:
  • копить данные 5 минут вместо 1;
  • использовать все четыре камеры, а не только верхние: нижние дают около 40% попаданий;
  • принимать засветки и при быстрых поворотах головы: время кадров точное, так что это безопасно.
После этого захват пошёл: 1-2 минуты при выключенных лампах.

Шаг 3. Лампы наносят ответный удар

С включёнными светильниками в одной из сессий драйвер «захватил» неверное решение: поставил две станции на два светильника и несколько минут держал трекеры не там. Пара ламповых точек всё же просачивалась, когда светильник пропадал на кадр, а потом появлялся снова.
Лечение из двух частей:
  • драйвер смотрит на два кадра вперёд: точка, которая начинает серию, тоже считается лампой;
  • лампы больше не выбрасываются, а запоминаются. Если решение ставит станцию туда, куда указывают десятки ламповых лучей, такое решение отбрасывается.
Тонкость: у станции на канале 1 лазер иногда виден в соседних кадрах, так что у настоящей станции тоже бывают «постоянные» точки. Но их не больше чем в 1,6 раза больше, чем обычных, а у ламп - в 7-20 раз. На этом разрыве и держится проверка.

Шаг 4. Докручиваем точность

Когда всё заработало, осталась средняя ошибка около 0,5°. По семи записанным сессиям нашлись две систематические поправки, одинаковые для всех четырёх камер:
  • ИК-лазер изображается на 0,58% ближе к центру кадра, чем предсказывает заводская калибровка. Скорее всего, камеры калибровали в другом свете, а линза преломляет инфракрасный чуть иначе. Похожая поправка в оригинале есть для боковых камер Quest.
  • Картинка сдвинута ровно на одну строку относительно калибровки.
С ними средняя ошибка упала до 0,2-0,3°. Чтобы не обмануть себя подгонкой, я подбирал поправки по трём записям и проверял на четвёртой: каждый раз становилось лучше.

Что в итоге

  • Захват станций: 1-3 минуты с нуля, около 3 минут при включённых лампах.
  • После захвата выравнивание держится 10+ минут, гуляет в пределах ±1 см и ±0,15°.
  • При перезапуске SteamVR сохранённое выравнивание подхватывается за секунды.
  • Проверял в зеркале VRChat, в том числе в странных позах: ноги, таз и руки на месте, без трекера на голове и без SpaceCalibrator.
  • Все семь записанных сессий проигрываются офлайн без единого ложного захвата.

Что понадобится

  • Pico 4 Pro с root (Magisk);
  • базовые станции SteamVR и хотя бы один включённый Lighthouse-трекер или контроллер (без них SteamVR не показывает станции);
  • ПК с Windows и SteamVR, шлем стримится любым способом (у меня Virtual Desktop), шлем и ПК в одной сети;
  • для сборки модуля: Python 3 и pip install ziglang;
  • для сборки драйвера: Visual Studio 2022 или новее с C++;
  • Git и adb.

Установка

Совет по PowerShell: у меня при вставке команд из браузера терялись заглавные буквы и знак $. Если команда странно падает, наберите её руками. Регистр в путях Windows неважен, можно всё маленькими.
1. Скачать исходники
git clone https://github.com/UndefinedSignal/QuestLHSync-pico4pro
cd QuestLHSync-pico4pro
git checkout pico-4-pro
2. Модуль для шлема
pip install ziglang
python pico/build_module.py
При первой сборке скрипт сам скачает Frida (около 50 МБ). Получится out/QuestLHSync-pico-module-1.26-pico4.zip. Ставим через Magisk (Модули → Установить из хранилища) или командами:
adb push out/QuestLHSync-pico-module-1.26-pico4.zip /sdcard/Download/
adb shell su -c "magisk --install-module /sdcard/Download/QuestLHSync-pico-module-1.26-pico4.zip"
adb reboot
Установщик сам проверит, что это Pico 4 Pro и что калибровка камер на месте.
3. Драйвер для ПК
SteamVR должен быть закрыт. В той же папке:
.\build.bat
powershell -executionpolicy bypass -file pico\register_driver.ps1
Скрипт регистрации сам найдёт SteamVR, в какой бы библиотеке Steam он ни стоял. Удалить драйвер: та же команда с ключом -remove. Для обновления потом хватает git pull и .\build.bat.
4. Выключить SpaceCalibrator
И вообще всё, что двигает Lighthouse-устройства. Два инструмента, которые правят одно и то же, будут драться.

Первый запуск

  • Запускаем SteamVR со шлемом. На странице QuestLHSync в дашборде должен появиться шлем и его камеры.
  • Надеваем трекеры: по ним драйвер отличает правильное решение от зеркального.
  • Стоим посреди комнаты и медленно смотрим на каждую станцию по очереди, по 20-30 секунд, иногда делая шаг. Не замирать: засветки при неподвижной голове отбрасываются.
  • Когда в логе %LOCALAPPDATA%\QuestLHSync\questlhsync.log появится строка acquired: ..., станции захвачены.
  • Если на потолке яркие LED-лампы, захват пойдёт медленнее. Можно на минуту их выключить.
Выравнивание сохраняется для конкретного шлема, так что в следующий раз всё подхватится сразу. Если после перезагрузки шлема или пересоздания границы трекеры встали криво, нажмите в дашборде Force recalibrate.

Если не работает

  • Шлем не находится: он должен быть в той же сети и проснуться. Если роутер режет широковещательные пакеты, укажите IP шлема в настройке host. Лог на шлеме: adb shell su -c cat /dev/.questlhsync/lhsyncd.log
  • Долго нет захвата: смотрите в логе строку «acquiring, last 60 s: ...». Если там в основном steady lights, мешают лампы. Если while it turned fast или while the headset was still, двигайтесь медленнее, но двигайтесь.
  • Что-то странное: в дашборде есть кнопка Record session. Запись можно прогнать через драйвер офлайн и посмотреть, что пошло не так. Учтите, что в ней есть серийные номера ваших станций и трекеров.

Что дальше

  • готовые сборки в Releases, чтобы не собирать руками;
  • подстройка поправок калибровки на лету: я подбирал их на одном шлеме, у другого экземпляра Pico они могут немного отличаться;
  • проверка на других прошивках и на обычном Pico 4.
Если повторите у себя, напишите в комментариях, как прошло, особенно если у вас другая прошивка или модель. Это сильно поможет.

Спасибо

  • CreoleVR: QuestLHSync. Весь драйвер и сама идея — их, я только добавил сторону Pico;
  • chaixshot: more-picohaxx-tool, без которого не было бы рута;
  • авторам Frida, Magisk и Zig.

Ссылки

  • Мой форк с портом (ветка pico-4-pro): https://github.com/UndefinedSignal/QuestLHSync-pico4pro
  • Оригинальный QuestLHSync: https://github.com/CreoleVR/QuestLHSync
  • more-picohaxx-tool: https://github.com/chaixshot/more-picohaxx-tool
Джип-штука +- доведена до ума, но основные тесты под нагрузкой постоянного движения и перекрытия пройдут в выходные.
Subscription levels3

ИИчко :З

$0.13 per month
Я маленькая шестерёнка в огромном механизме, хочу выразить свою признательность и внимание к автору. А ещё хочу попадать на приватные показы\просмотры видео\фильмов\аниме!
+ Мемкоин-бонус для засылки мемов на стримы!

Змеиный круг

$1.92 per month
Всё из ИИчко
+ закрытые фотосеты и ранний доступ к фото
... в процессе обдумывания своих возможностей

Чешуйчатый меценат

$25.6 per month
Ооо ты явно заинтересован чтобы кобра продолжала творить!
Всё выше +
Я в процессе.
Потенциально - возможность выбора игры для прохождения в этом месяце вне всяких очередей.
+ chat
Go up