mirror of
https://github.com/DeeJanuz/frametop.git
synced 2026-10-06 04:04:09 +02:00
Make hand tracking a Frametop component
- Programs: ft-camd (the camera broker), ft-hands (the tracker), and ft-handreplay and ft-ringplay for recordings, built by hands/build.sh into hands/build/ with one Makefile. The first build fetches ncnn at frame-hands' pinned tag and builds it with the same options. - ft-camd gets its privileges from file capabilities (CAP_SYS_PTRACE, CAP_PERFMON, CAP_DAC_READ_SEARCH) that hands/run.sh install sets with sudo, and drops them once set up. It still works under sudo. It runs on the host, linked statically, as frametop-camd.service. ft-hands runs in the dev container as frametop-hands.service. Both start and stop with SteamVR. - Files move to /run/user/UID/frametop/ (cam-ring, hands, gestures), not $XDG_RUNTIME_DIR, which a terminal in the Frametop desktop has its own of. SIGUSR1 recordings go to ~/.local/share/frametop/hands. - The calibration is read through /run/host in the container. - Settings: HANDS_SWAP_SIDES and HANDS_CPUS in frametop.conf. - install.sh offers hand tracking as an optional last step. - The container gets jsoncpp-devel, glibc-static, and NumPy and OpenCV for the Python tools. - tools/ring.py reads the ring, and models/NOTICE credits the Apache-2.0 models. Checked: ft-handreplay gives identical summaries and byte-identical depth dumps to frame-hands' fh-replay on both 2026-09-29 recordings. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
3e3d31c728
commit
499035216c
41 files changed
+727
-402
No files matched your search
+18
-5
@@ -13,6 +13,7 @@ the image.
|
||||
Everything here returns metres in the head frame.
|
||||
"""
|
||||
import json
|
||||
import os
|
||||
|
||||
import numpy as np
|
||||
|
||||
@@ -91,11 +92,23 @@ class Camera:
|
||||
return np.degrees(np.arccos(np.clip(self.unproject(uv)[:, 2], -1, 1)))
|
||||
|
||||
|
||||
def device_path(path):
|
||||
"""A headset file such as /persist/xrservice.json. In the dev container the host's / is
|
||||
at /run/host (distrobox doesn't mount /persist); off the Frame, FRAME_JOB_DEVICE_ROOT can
|
||||
point at a folder with copies of them."""
|
||||
root = os.environ.get('FRAME_JOB_DEVICE_ROOT')
|
||||
if root:
|
||||
return root + path
|
||||
if not os.access(path, os.R_OK) and os.access('/run/host' + path, os.R_OK):
|
||||
return '/run/host' + path
|
||||
return path
|
||||
|
||||
|
||||
def load(xrservice=XRSERVICE_JSON, device=DEVICE_JSON):
|
||||
"""{calibration name: Camera} for the tracking cameras, posed in the head frame."""
|
||||
with open(xrservice) as f:
|
||||
with open(device_path(xrservice)) as f:
|
||||
rig = json.load(f)
|
||||
with open(device) as f:
|
||||
with open(device_path(device)) as f:
|
||||
dev = json.load(f)
|
||||
cad_from_cam0 = _pose(dev['cv']['cad_from_cal'])
|
||||
head_from_cad = np.linalg.inv(_pose(dev['head']))
|
||||
@@ -110,18 +123,18 @@ def load(xrservice=XRSERVICE_JSON, device=DEVICE_JSON):
|
||||
|
||||
def load_color(eeprom=ARCTURUS_EEPROM, device=DEVICE_JSON, scale=2, crop='subtract'):
|
||||
"""{"passthrough_left"/"passthrough_right": Camera} for the Arcturus color cameras, posed in
|
||||
the head frame, for fh-camd --with-color's images (luma at 1/scale size).
|
||||
the head frame, for ft-camd --with-color's images (luma at 1/scale size).
|
||||
|
||||
Their calibration is in the CAD frame (mm) with pixel coordinates on the full 2464x2464
|
||||
sensor; each camera also has a cropRegion. crop says how that maps to the delivered
|
||||
image: 'subtract' (image x = sensor x - cropRegion.x) or 'none'. tools/check_color.py
|
||||
tells which fits.
|
||||
"""
|
||||
with open(eeprom, 'rb') as f:
|
||||
with open(device_path(eeprom), 'rb') as f:
|
||||
raw = f.read()
|
||||
i = raw.rfind(b'{', 0, raw.find(b'"alignment_method"'))
|
||||
rig, _ = json.JSONDecoder().raw_decode(raw[i:].decode('latin1'))
|
||||
with open(device) as f:
|
||||
with open(device_path(device)) as f:
|
||||
dev = json.load(f)
|
||||
head_from_cad = np.linalg.inv(_pose(dev['head']))
|
||||
cams = {}
|
||||
|
||||
Reference in new issue
Block a user