Orvix
Hardware- 5 Devlogs
- 20 Total hours
Control your computer with hand gestures using a motion detector!
Control your computer with hand gestures using a motion detector!
alright so it’s been a minute since the last update. spent a bunch more time going through orvix looking for stuff that’s broken, and honestly found more than i expected given how much i already fixed last time.
found a really annoying pattern this round. a bunch of settings have a “this number has to be smaller than that number or it breaks” rule, and i never actually checked for that anywhere. if your release threshold ends up higher than your trigger threshold, a pinch or grab fires and then immediately releases itself on the next frame, so you get a click but can never actually hold it or drag anything, no crash no error, it just doesn’t work. same deal with the calibration box, if min and max on an axis ever get flipped your cursor just starts moving backwards on that axis with zero explanation. the tilt deadzone had the same issue, could turn a smooth speed ramp into an instant jump to max speed. and there’s a “freeze the cursor so clicks don’t drift” feature that could get silently disabled if two of its settings were misordp as a crash, they just make the app feelsubtly broken, which is honestly worse. fixed all of them so bad values get corrected automatically instead of
just trusting the config file blindly.
two actual bad ones too. if you hand edit ym or volume step to 0, the app straight upfreezes the next time you do that gesture, stuck in a loop that can never finish, only way out is force quitting.
separately, a bad enough cutoff value in thuld cause a real divide by zero and crash the whole thing mid session. both way worse than the silent stuff above since the app just dies with no warning.
this one took a while to track down: there’s exactly one way the tracking loop is supposed to end on its own
without an error, which is the sensor conne session. turns out that looked identical toyou just pressing stop yourself, in literally every part of the app. so if your sensor dropped, it’d silently die
and say “stopped” like nothing happened insng broke. fixed it everywhere, then found the funniest bug of the batch: right after fixing the error message for the menu bar version, there was leftover code
resetting the status back to “stopped” imme fix i’d just made. that one made me laugh.
feels like every session i find a new way tuck down. this time: starting a grab whilealready mid pinch could leave the button held down forever, quitting the app didn’t wait for shutdown to actually
finish so it could kill things mid cleanup, events don’t carry a screen position, andthe code was throwing away any event without one, silently dropping the release too.
other stuff: calibration and live tracking could both start at once and step on each other’s state, same with
loading a profile mid calibration, so i add. a broken config file used to crash theterminal app, the calibration tool, and one of the visualizers even though the menu bar version already handled it
gracefully, now they all fall back the same leaking the sensor connection on close.volume control has no timeout and runs right in the main gesture loop, so a stray permission popup could freeze
the whole app. ctrl-c in the terminal versitead of exiting clean. the radial menu wascaching your screen size once and never updating it, so unplugging a monitor left it positioned wrong for the rest
of the session, found basically the same bua different variable. and i found a variable named like it held pixels that was actually always holding millimeters, with a comment literally admitting it was
wrong, so i renamed it.
also cleaned up a pile of stale docs, caught myslef making a bad fix and reverted it before it did damage, anddeleted a config setting that turned out completely dead.
Welcome to devlog #2 for Orvix. here’s what was done today:
profiles + gui
cursor ring
gesture tuning
bug fixes, mostly config/crash related
fixed a bunch of ways a bad or hand edited config.yaml could crash orvix silently, since the menu bar app
has no terminal to show errors in:
also:
cli fixes found by actually running things
test coverage + cleanup
verification passes that found nothing
DEVLOG #3 Orvix THIS IS STRAIGHT OUT OF IRON MAN today was mainly just playing around with the tool and calibrating it locally.
orvix (iron man - type computer control using hand gestures) devlog #2
gestures 3 to 9, tests 22 to 115, 5 new modules, 3 real bugs fixed, 2 on-screen cocoa bits (radial wheel + cursor dwell ring).
last time orvix could move, click, drag and scroll. this round i brainstormed a big list of gestures, cut it down, and shipped six new ones:
all six toggle from the menu bar. same architecture as before: the gesture logic is pure modules with no leap or mac code so it tests unplugged, and gui and cli still share one run_live().
three bugs that were actually broken:
cant test the hardware path so i faked leap frames through the real run_live with a recording mouse to confirm the wiring.
tuning by feel: circle-to-open was too easy so its 400 degrees now (a full loop plus), the wheel is pinch-only, and dwell click
sits at 1.5s.
still rough: fist-twist volume and grab-scroll shahells to osascript, two-hand tracking is iffy onthe old leap, and #1s open items (bad two-point calibration, dry run read at start, untested gui calibration) are still there.
started this as a “can i control my mac with just my hand” thing using an og Leap Motion (LM-010) from like 2013, and as of today it’s a working prototype that actually moves my real cursor.
what it does right now
leapd streams hand data as json over a local websocket, and then it’s leap_client to gesture_interpreter to coord_mapper to mouse_control, ending in real CGEvents through Quartz. the gesture interpreter is a state machine with separate press and release thresholds so a pinch sitting right on the boundary doesn’t rapid fire, and the coord mapper runs a One Euro Filter so the cursor isn’t jittery at rest but still keeps up when you move fast. gui and cli both call the same run_live() so they can’t drift apart on what a gesture means. 22 tests, and the pure logic modules have no hardware or macos calls in them so they test fine with nothing plugged in.
the whole pipeline was written blind before i ever had the hardware hooked up and it held up better than it had any right to, the only genuinely broken thing was the default calibration box, which capped at y_max=300 while my hand naturally sits at like 295 to 337, so every position clamped to screen y=0 and the cursor would’ve been welded to the top of my ultrawide. found it in dry run before going live thankfully. fixed by sweeping my hand around for 15s and recording the real range. also drag_hold_seconds was 0.15 which is way too fast to pinch and release, logs showed 568 drag frames against 6 pinches, so that’s 0.3 now.
the two point calibration flow in calibration.py is worse than the sweep i did by hand and should probably just get replaced. dry run gets read at Start time so unticking it mid run does nothing, which is a footgun. saw a stray grab_scroll once on an open hand so grab_threshold might need tuning. gui calibration path exists but has never been run against real hardware.
core pipeline and gui are merged into main. launcher is on feat/launcher, not pushed.