Methodology & Math
Transparent technical documentation for StickDriftLab's diagnostic engine
Executive Summary
StickDriftLab is a browser-based diagnostic suite that measures analog stick drift, circularity error, deadzone thresholds, and polling rates for game controllers. All computation runs entirely in your browser using the W3C Gamepad API and HTML5 Canvas. No data is transmitted to any server; no cookies, no tracking, no external dependencies.
This document describes the mathematical foundations, implementation details, and calibration procedures so that engineers, reviewers, and power users can verify the results independently.
1. Data Source: W3C Gamepad API
The navigator.getGamepads() method returns a snapshot of connected gamepads. Each Gamepad object exposes:
axes— Array of normalized values[-1.0, 1.0]for analog sticks (typically indices 0-3 for LX, LY, RX, RY)buttons— Array ofGamepadButtonobjects withpressed(boolean) andvalue(analog[0.0, 1.0]for triggers)id— Vendor-provided identifier string (e.g., "Xbox Wireless Controller (STANDARD GAMEPAD Vendor: 045e Product: 02fd)")index— Browser-assigned slot indexvibrationActuator/hapticActuators— Haptic feedback interfaces (where supported)
Sampling Strategy: The main loop uses requestAnimationFrame (~60 Hz) to poll the API. For polling-rate measurement, frame timestamps are recorded and a rolling window of 30 frames computes actualHz = (frames - 1) / (lastTimestamp - firstTimestamp) * 1000.
2. Stick Drift Detection
2.1 Rest Position Magnitude
When the user is not touching the stick, the axes should report (0, 0). Manufacturing tolerances and wear cause a non-zero rest vector. The drift magnitude is the Euclidean distance from origin:
magnitude = sqrt(x² + y²)
Where x = axes[0] (left stick X) and y = axes[1] (left stick Y).
2.2 Threshold Classification
A 0.05 (5%) magnitude threshold separates "healthy" from "drifting":
if (magnitude > 0.05) → DRIFT DETECTED
else → HEALTHY
This 5% threshold is derived from industry-standard deadzone recommendations (most games default to 5-10% inner deadzone). A stick drifting beyond 5% at rest will cause visible in-game movement without user input.
2.3 Grade Bands
| Grade | Magnitude Range | Interpretation | Action |
|---|---|---|---|
| A (Clean) | 0.000 – 0.025 | No measurable drift | None needed |
| B (Minor) | 0.025 – 0.065 | Compensable via deadzone | In-game deadzone 5-10% |
| C (Heavy) | > 0.065 | Hardware wear likely | Contact cleaner / replacement |
3. Circularity Error Benchmark
3.1 Theory
When a user rotates an analog stick through 360°, the ideal path is a perfect unit circle (radius = 1.0). Real sticks deviate due to:
- Potentiometer non-linearity
- Mechanical asymmetry
- Dust/contamination on the resistive track
- ADC quantization error
3.2 Angular Binning Algorithm
The engine records the maximum radius observed at each 1° angular bin during a user-initiated 360° rotation:
// For each sampled point (x, y):
magnitude = sqrt(x² + y²)
if (magnitude >= 0.70) { // ignore inner deadzone
angle = atan2(y, x) * 180/PI // [-180, 180]
bin = (angle + 360) % 360 // [0, 359]
bins[bin] = max(bins[bin] || 0, magnitude)
}
3.3 Error Metrics
Average Circularity Error: Mean absolute deviation from unit radius across all populated bins:
totalError = Σ |bins[i] - 1.0| for all i where bins[i] !== null
avgError = (totalError / populatedBins) * 100 // percentage
Outer Coverage: Percentage of 360 bins with at least one sample:
coverage = (populatedBins / 360) * 100
3.4 Grade Interpretation
| Avg Error | Grade | Meaning |
|---|---|---|
| < 2.5% | A | Excellent — near-perfect circle |
| 2.5% – 6.5% | B | Acceptable — minor asymmetry |
| 6.5% – 12% | C | Worn — deadzone adjustment helps |
| > 12% | F | Severe — hardware replacement |
4. Deadzone Calibration Procedure
4.1 Measurement Phase
- Connect controller; wait for "Active" state.
- Release sticks completely; let them settle for 2 seconds.
- Read Rest Drift Offset from telemetry (magnitude × 100 = %).
4.2 Deadzone Calculation
// Rule: Set in-game deadzone to the NEXT whole percentage above measured drift
// Examples:
drift = 0.038 (3.8%) → deadzone = 4%
drift = 0.052 (5.2%) → deadzone = 6%
drift = 0.081 (8.1%) → deadzone = 9%
4.3 Verification
Enable "Test Circularity" and rotate the stick 360°. The recorded trace should show a closed loop. If the circularity error exceeds 8%, consider cleaning or replacement.
5. Polling Rate Measurement
The browser's requestAnimationFrame callback fires at the display refresh rate (typically 60 Hz). To measure the controller's actual report rate:
let timestamps = []
function poll() {
const now = performance.now()
timestamps.push(now)
if (timestamps.length > 30) timestamps.shift()
if (timestamps.length >= 4) {
const duration = timestamps[timestamps.length - 1] - timestamps[0]
const hz = ((timestamps.length - 1) / duration) * 1000
}
requestAnimationFrame(poll)
}
The tier classification uses fixed bins: 125 Hz, 250 Hz, 500 Hz, 1000 Hz. Wired Xbox controllers typically report 1000 Hz; Bluetooth often drops to 250-500 Hz.
6. Trigger Gauge Accuracy
Analog triggers (LT/RT, L2/R2) report buttons[6].value and buttons[7].value in [0.0, 1.0]. The visual gauge maps this linearly to a 0-100% bar. No interpolation is applied — the raw API value is displayed.
7. Diagnostic Certificate (PNG Export)
The "Download PNG" button renders a certificate to an offscreen 800×460 canvas using the exact same drawing primitives as the live UI. The certificate includes:
- Device name (from
Gamepad.id) - UTC timestamp
- Left/right stick canvas snapshots (200×200 each)
- Rest drift offsets and circularity errors
- Watermark: "VERIFIED BY STICKDRIFTLAB.COM · BROWSER HARDWARE API AUDIT"
Export uses canvas.toBlob('image/png') → URL.createObjectURL() for a reliable binary download. No server round-trip.
8. Privacy & Security (E-E-A-T)
| Principle | Implementation |
|---|---|
| No Network Requests | All logic in app.js; no fetch/XMLHttpRequest |
| No Cookies / LocalStorage | Zero persistent storage |
| No Third-Party Scripts | Single style.css + app.js only |
| User Consent | Gamepad API requires explicit user gesture (press any button) |
| Verifiable Output | PNG contains raw telemetry; anyone can reproduce |
9. Limitations & Known Issues
- Bluetooth Jitter: Wireless controllers may report 250-500 Hz instead of 1000 Hz due to OS Bluetooth stack buffering.
- Browser Support: Gamepad API requires secure context (HTTPS or localhost). Safari requires user gesture before
getGamepads()returns devices. - Axis Mapping: Non-standard controllers may map axes differently; the tool assumes standard layout (LX=0, LY=1, RX=2, RY=3).
- No Firmware Access: Cannot read controller firmware version or calibration tables.
10. Reproducibility Checklist
To independently verify a certificate:
- Open
https://StickDriftLab.comin a Chromium-based browser. - Connect the same controller via USB.
- Press any button to activate.
- Wait 2 seconds at rest; note Rest Drift Offset.
- Run Circularity Test (360° rotation).
- Compare PNG telemetry values.
All source code is visible in DevTools (Sources → app.js). No minification, no obfuscation.