Files
Frametop--frametop/hands/ft-handsctl
T
DeeJanuzandClaude Opus 5.5 2ae1a36b33 Hands: flag tracking failures (ft-handsctl flag, a rolling buffer in ft-hands)
ft-hands keeps the last 12 s of hand crops (each view's landmark crop, 1.6x, at most
224 px), its hands, gestures and landmarks in RAM (track/flagbuf.h, HANDS_FLAG_BUFFER=1).
`ft-handsctl flag [note]` asks for them through run_dir/flag; ft-hands writes them and the
next 2 s to HANDS_FLAG_DIR/flag-<time> from a low-priority thread, for frame-hands'
offline tools. ft-handsctl also saves a /dev/video99 frame and ft-handview's head poses,
and the drawn hands pulse cyan when a flag is taken (ft-handview's new flash and poses
commands). ft-handreplay --flag-at/--flag-every makes the same flags from recordings.
Measured on a replayed ring: +58 MB peak RSS, 0.1 ms a crop on an A720 (about 1% of a
core). Unit tests: tests/flagbuf_test.cpp (make check), tests/test_handsflag.py.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 16:11:53 -06:00

55 lines
2.6 KiB
Bash
Executable File

#!/usr/bin/env bash
# ft-handsctl: turn hand tracking on and off by hand, on the Frame. With it on, your hands show
# through Frametop's screens (the hand cutouts); pinches and grips only move the pointer with
# POINTER_HANDS=1. HANDS_MODE says when it starts by itself (off, the default: never); on lasts
# until SteamVR stops, or with HANDS_MODE=frametop, the desktop.
#
# ft-handsctl on | off | status | log [lines]
# ft-handsctl mode [frametop|always|off] HANDS_MODE: with the Frametop desktop, with SteamVR, or off
# ft-handsctl cutouts on|off|state ft-screens' hand cutouts, without stopping tracking
# ft-handsctl gestures watch pinches and grips live (Ctrl+C to stop)
# ft-handsctl flag [note...] flag a tracking failure: the last seconds of hand crops and
# ft-hands' output go to HANDS_FLAG_DIR/flag-<time> (handsflag.py)
#
# Needs the services installed once: hands/run.sh install (it sets ft-camd's capabilities).
set -euo pipefail
here=$(cd "$(dirname "$(readlink -f "${BASH_SOURCE[0]}")")" && pwd)
units="frametop-camd.service frametop-hands.service"
ask_screens() { # a command to ft-screens' control socket, and its reply
python3 - "$1" <<'EOF'
import socket, sys
s = socket.socket(socket.AF_UNIX, socket.SOCK_DGRAM)
s.bind("")
s.settimeout(2)
try:
s.sendto(sys.argv[1].encode(), "\0ft_screens")
print(s.recv(512).decode())
except OSError as e:
sys.exit("ft-screens didn't answer (is the Frametop desktop running?): %s" % e)
EOF
}
case ${1:-status} in
on)
systemctl --user -q is-active steamvr.service || { echo "SteamVR isn't running" >&2; exit 1; }
systemctl --user start $units
sleep 4
"$0" status ;;
off)
systemctl --user stop $units
echo "hand tracking off" ;;
status)
for u in $units; do echo "$u: $(systemctl --user is-active $u || true)"; done
journalctl --user -u frametop-hands.service --no-pager -o cat -n 40 |
grep -E '^ *[0-9.]+s |sets with a hand|cameras:' | tail -2 | cut -c1-160 || true ;;
mode) # hands/handsmode.py; the Hands page of Frametop Input Settings does the same
if [ -n "${2:-}" ]; then python3 "$here/handsmode.py" set "$2"; else python3 "$here/handsmode.py" status; fi ;;
log) journalctl --user -u frametop-camd.service -u frametop-hands.service --no-pager -o short -n "${2:-30}" ;;
cutouts)
ask_screens "cutouts ${2:-state}" ;;
gestures) exec python3 "$here/tools/watch_gestures.py" --distance ;;
flag) shift; exec python3 "$here/handsflag.py" "$@" ;;
*) sed -n '2,14p' "$0" | sed 's/^# \{0,1\}//'; exit 2 ;;
esac