Python (ipin_vr/export.py): - generate_bank(): levels 1–2 enumerated exhaustively (120/720 combos), level 3 random with dedup; all deduplicated per-level - run_export(): CLI --per-level / --out / --seed flags per ONDEVICE §4.1 - cli.py routes "export" subcommand before session args (backward-compat) - 14 new tests: format, dedup for all 3 levels, space caps (L1=120, L2=720), seed determinism, file output Unity scaffold (ondevice/Scripts/): - CommandBank.cs: loads commands.json from StreamingAssets (WebRequest on Android) - TtsManager.cs: sherpa-onnx integration with [SHERPA] stubs, StreamingAssets→ persistentDataPath copy, defensive Speak() with onDone callback - SessionController.cs: passthrough flow §6, level switching, busy guard on Next - ondevice/README.md: full manual Editor steps §5 (Unity setup, Meta XR SDK, sherpa-onnx install, scene wiring, font, build, metrics) pytest: 37/37 passed Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
5.1 KiB
ONDEVICE — PoC-1 na Meta Quest 3
Cel buildu dla pierwszego uruchomienia na urządzeniu. Spójny z ROADMAP.md.
1. Cel PoC-1
Uruchomić na Quest 3 minimalną aplikację, która w passthrough wyświetla i wypowiada (Piper przez sherpa-onnx) polskie polecenia, oraz zmierzyć wydajność w realu. Bez żywego LLM na urządzeniu (decyzja). Bez STT.
2. Zakres
W zakresie:
- bank poleceń wygenerowany offline (z istniejącego
ipin_vr), - TTS na urządzeniu (sherpa-onnx + głos polski),
- minimalne UI w passthrough (panel z tekstem + trigger „następne"),
- instrumentacja i pomiar wydajności.
Poza zakresem PoC-1: LLM na urządzeniu, STT, ocena wykonania, dopracowane UI/MR,
obiekty 3D. (To etap 2/3 wg ROADMAP.md.)
3. Runtime — decyzja
Unity dla PoC-1.
- Uzasadnienie: najszybsza droga do działającego passthrough + TTS; narzut RAM Unity (~1 GiB) jest nieistotny, bo bez LLM cały budżet spokojnie mieści się w limicie 5,75 GiB. Meta XR SDK daje passthrough „z pudełka", a sherpa-onnx ma gotowe wtyczki do Unity.
- Cel docelowego produktu pozostaje natywny OpenXR (lżejszy, gdy dojdzie LLM).
- To jedyna łatwo odwracalna decyzja architektoniczna tego dokumentu; reszta nie zależy od wyboru runtime.
4. Komponenty
4.1 Bank poleceń (offline)
Rozszerzyć ipin_vr o podkomendę export, która zrzuca bank gotowych,
poprawnych poleceń do JSON (reużywamy zweryfikowanego generatora — gramatyka
gwarantowana u źródła).
Wywołanie:
python -m ipin_vr export --per-level 300 --out commands.json [--seed N]
Format pliku:
{
"meta": {"version": "1", "per_level": 300},
"commands": [
{"level": 1, "text": "Połóż jabłko na stole."},
{"level": 2, "text": "Umieść niebieskie jabłko na stole."},
{"level": 3, "text": "Połóż zieloną książkę na półce i umieść klucz na biurku."}
]
}
Wymóg: deduplikacja w obrębie poziomu; --per-level to liczba unikatów na poziom
(jeśli przestrzeń jest mniejsza, tyle ile się da). Plik trafia do assetów aplikacji.
4.2 TTS na urządzeniu
- Biblioteka: sherpa-onnx przez wtyczkę Unity (np.
Ponyu-dev/Unity-Sherpa-ONNXlubEitanWong/com.eitan.sherpa-onnx-unity). - Głos:
vits-piper-pl_PL-gosia-medium(z releasutts-modelssherpa-onnx; zawiera.onnx,tokens.txt,espeak-ng-data). - ABI: arm64-v8a.
- Haczyk do obsłużenia: modele w
StreamingAssetssą spakowane w APK — przed użyciem skopiować do ścieżki zapisywalnej i podać tę nową ścieżkę do sherpa-onnx (wtyczki zwykle robią to same; zweryfikować).
4.3 Passthrough UI
- Passthrough przez Meta XR SDK (building block / komponent passthrough).
- Jeden panel (world-space lub HUD) z tekstem polecenia, czcionka z polskimi znakami.
- Trigger „następne polecenie": przycisk kontrolera albo prosty przycisk na panelu.
5. Podział pracy: kod vs Unity Editor
Część generowalna kodem (Claude Code):
- podkomenda
exportwipin_vr(+ test), - skrypty C# (ładowanie
commands.json, wybór poziomu, wyświetlanie tekstu, wywołanie TTS, obsługa triggera), ondevice/README.mdz instrukcją złożenia projektu.
Część ręczna w Unity Editorze (nie da się w pełni wygenerować plikami):
- utworzenie projektu Unity (aktualne LTS) i konfiguracja Androida/OpenXR,
- instalacja Meta XR SDK i wtyczki sherpa-onnx,
- włączenie passthrough, podpięcie skryptów do sceny, import głosu i
commands.json, - build i sideload APK na Quest.
Skrypty C# mają być samodzielne i podpinalne, nie zakładać konkretnej hierarchii sceny.
6. Przepływ aplikacji
- Start: passthrough on, wczytaj
commands.jsonz assetów. - Ustaw poziom (domyślnie 1; prosty przełącznik 1/2/3).
- Pokaż losowe polecenie danego poziomu na panelu.
- Wypowiedz je (sherpa-onnx).
- Trigger „następne" → wróć do kroku 3.
7. Pomiar wydajności (właściwy cel PoC-1)
Zmierzyć i zanotować:
- PSS aplikacji względem limitu 5,75 GiB,
- stabilność klatek przy włączonym passthrough (spadki/utracone klatki),
- latencja TTS: od wywołania do pierwszego dźwięku oraz czas pełnej syntezy,
- RAM zajmowany przez model głosu,
- moment wejścia w throttling termiczny przy dłuższym użyciu,
- zużycie baterii.
Narzędzia: OVR Metrics Tool, Perfetto, logcat (m.in. lowmemorykiller).
8. Środowisko developerskie
Najpierw sanity check bez kodu: wgrać prebudowane sherpa-onnx TTS APK z
pl_PL-gosia na telefon z Androidem (lub sideload na Quest) i potwierdzić jakość
polskiego głosu. Dopiero potem budować aplikację Unity. Iteracja skryptów/logiki
najszybsza na telefonie Snapdragon; pomiary docelowe — na Queście.
9. Definition of done
- Apka na Queście w passthrough pokazuje i wypowiada polskie polecenia z banku.
- Trigger „następne" działa; poziomy 1–3 dostępne.
- Zebrany komplet metryk z sekcji 7 (choćby zgrubnie) — to jest wynik PoC-1.
10. Dalej (poza PoC-1)
- PoC-2: dołożyć llama.cpp na urządzeniu i zmierzyć ponownie (żywy LLM).
- Etap 3: STT + ocena wykonania, sesje, statystyki.
- Ewentualne przejście runtime na natywny OpenXR pod docelowy budżet RAM z LLM.