How we built it

DriveCoach is built on a custom wgpu → Metal rendering pipeline via pygfx, bypassing the deprecated OpenGL stack
entirely for native Apple Silicon GPU throughput at 60 FPS with a fully procedural city, cockpit geometry, and 16 autonomous NPC agents.

The force feedback subsystem required a ground-up implementation of the HID++ 2.0 protocol over IOHIDDeviceSetReport — reverse-engineered from the Linux kernel driver (hid-logitech-hidpp.c) — to drive the G920's motor on macOS where no official SDK, DirectInput layer, or ff-memless abstraction exists.

Vehicle dynamics are modeled using a kinematic bicycle model with friction-circle grip limiting, longitudinal/lateral force coupling, dynamic load transfer across the axle, and a six-speed engine with realistic torque curves. Force feedback is derived from self-aligning torque (SAT) with pneumatic trail collapse at the grip limit, combined with
viscous damping — eliminating the feedback oscillations endemic to centering-spring implementations. Audio is fully synthesized in real-time via phase-continuous harmonic oscillators and bandpass-modulated noise generators, with zero pre-recorded assets.

Challenges we ran into

The G920 on macOS is completely undocumented. macOS surfaces the device as a _GCLogitechRacingWheel through
GameController.framework but provides no FFB output path. We discovered the device answers HID++ long reports (0x11) on the very-long report ID (0x12) — a non-standard behavior that breaks every off-the-shelf HID library. The full
handshake sequence requires dynamic feature-index discovery via GET_FEATURE(0x8123), hardware effect slot allocation via DOWNLOAD_EFFECT, and a 100 Hz output loop to satisfy the G920's 200ms hardware watchdog before the motor zeros out.

The deeper challenge was FFB fidelity. Virtually all consumer-grade FFB implementations substitute a
position-proportional centering spring for real steering physics — which is both inaccurate and unstable (motor-position feedback loop → oscillation). Replacing this with a SAT model derived from live lateral tire force,
with pneumatic trail collapse scaling as the friction circle saturates, required careful calibration against real vehicle data.

Accomplishments that we're proud of

  • The only known open-source implementation of G920 force feedback on macOS that correctly handles the HID++ 2.0
    handshake, non-standard report ID mapping, and hardware watchdog timing.
  • A physically correct SAT-based FFB model that replicates the grip-limit warning felt in real hydraulic power
    steering — not a spring approximation.
  • A pure-pursuit ghost coach that haptically guides learners through correct steering geometry using the same path-following algorithm deployed in autonomous vehicle research.
  • Real-time DMV-criteria scoring mapped directly to CVC section violations, producing actionable post-session diagnostics rather than gamified point totals.

What we learned

Proprioceptive feedback dramatically accelerates skill acquisition. Testers intuitively understood understeer the
moment they felt pneumatic trail collapse through the wheel — no verbal explanation required. This validates the core hypothesis: the haptic channel encodes vehicle state information that neither visual displays nor verbal instruction
can efficiently transmit. We also learned that correct physics and correct FFB modeling are inseparable — perceptual realism emerges from physical accuracy, not from tuning subjective "feel."

What's next for MotorAxN

Expanding the procedural route engine with adverse-condition rendering (precipitation, reduced-visibility scenarios,
night driving with dynamic headlight simulation), instructor telemetry dashboards for driving school integration, and multiplayer ghost-lap infrastructure for peer benchmarking. The long-term target: positioning DriveCoach as the
standard pre-licensure training protocol for the 3.5 million Americans who take a driver's test annually — bringing simulator-grade haptic training out of professional motorsport and into mainstream driver education.

Built With

  • numpy
  • pygfx
  • pyobj-framework-gamecontroller
  • pyobjc-framework-cocoa
  • python
  • sounddevice
Share this project:

Updates