ipin-vr/docs/ONDEVICE.md
Oskar Kapala 921a85d30b Add export subcommand and Unity PoC-1 scaffold (ONDEVICE §4)
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>
2026-06-09 16:11:53 +02:00

5.1 KiB
Raw Blame History

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-ONNX lub EitanWong/com.eitan.sherpa-onnx-unity).
  • Głos: vits-piper-pl_PL-gosia-medium (z releasu tts-models sherpa-onnx; zawiera .onnx, tokens.txt, espeak-ng-data).
  • ABI: arm64-v8a.
  • Haczyk do obsłużenia: modele w StreamingAssets są 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 export w ipin_vr (+ test),
  • skrypty C# (ładowanie commands.json, wybór poziomu, wyświetlanie tekstu, wywołanie TTS, obsługa triggera),
  • ondevice/README.md z 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

  1. Start: passthrough on, wczytaj commands.json z assetów.
  2. Ustaw poziom (domyślnie 1; prosty przełącznik 1/2/3).
  3. Pokaż losowe polecenie danego poziomu na panelu.
  4. Wypowiedz je (sherpa-onnx).
  5. 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 13 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.