You are browsing as a guest. Sign up (or log in) to start making projects!

58m 35s logged

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

  • move your hand, cursor follows
  • pinch to click, hold the pinch past 0.3s and it becomes a drag
  • grab to scroll, speed comes off your palm velocity
  • take your hand away and the cursor just freezes where it is instead of jumping somewhere dumb
  • menu bar app so you don’t need a terminal open, has start/stop, a dry run toggle, live display of the last gesture, and calibration
  • you can remap what pinch and grab actually do (click/drag, scroll, or just off) from the menu
  • one word launcher, you type orvix and it goes, plus orvix cli, orvix calibrate, and orvix status which tells you if leapd and the device are alive without launching anything
  • calibration saves to ~/.orvix/config.yaml so it sticks between runs

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.

1
14

Comments 0

No comments yet. Be the first!