Skip to content

Comments

Fix character movement jank and drift#1

Open
ixaxaar wants to merge 1 commit intomasterfrom
claude/fix-janky-drifty-movement-01WnEUDWKXfrDZLAzGC6S9Vu
Open

Fix character movement jank and drift#1
ixaxaar wants to merge 1 commit intomasterfrom
claude/fix-janky-drifty-movement-01WnEUDWKXfrDZLAzGC6S9Vu

Conversation

@ixaxaar
Copy link
Member

@ixaxaar ixaxaar commented Nov 15, 2025

Major improvements to mouse movement quality:

  1. Fixed drift issue: Changed from acceleration-based to angle-based control

    • Old: integrated acceleration → velocity → position (double integration = rapid drift)
    • New: use orientation angles (pitch/roll) directly for velocity
    • No more continuous drift when holding device still
  2. Fixed jankiness: Added exponential smoothing filter

    • Smooths raw angle inputs with alpha=0.3 (30% new, 70% old)
    • Reduces jitter while maintaining responsiveness
  3. Better dead zone: Applied to tilt angles instead of acceleration

    • Ignores tilts below 3 degrees (was 0.05g acceleration)
    • More effective at filtering unintentional movements
  4. Improved sensitivity: Updated to 8.0 pixels/degree

    • Clear units: tilt angle → cursor speed
    • More intuitive tuning (was using acceleration units)
  5. Optimized AHRS fusion parameters:

    • Reduced gain to 0.5 for better stability
    • Increased acceleration rejection to 20.0
    • Better suited for slow, deliberate tilt movements

Technical details:

  • driver/src/uinput.c: Rewrite process_sensor_data() to use Euler angles
  • driver/src/main.c: Update config defaults (sensitivity, dead_zone units)
  • Movement now smooth, predictable, and drift-free

Major improvements to mouse movement quality:

1. **Fixed drift issue**: Changed from acceleration-based to angle-based control
   - Old: integrated acceleration → velocity → position (double integration = rapid drift)
   - New: use orientation angles (pitch/roll) directly for velocity
   - No more continuous drift when holding device still

2. **Fixed jankiness**: Added exponential smoothing filter
   - Smooths raw angle inputs with alpha=0.3 (30% new, 70% old)
   - Reduces jitter while maintaining responsiveness

3. **Better dead zone**: Applied to tilt angles instead of acceleration
   - Ignores tilts below 3 degrees (was 0.05g acceleration)
   - More effective at filtering unintentional movements

4. **Improved sensitivity**: Updated to 8.0 pixels/degree
   - Clear units: tilt angle → cursor speed
   - More intuitive tuning (was using acceleration units)

5. **Optimized AHRS fusion parameters**:
   - Reduced gain to 0.5 for better stability
   - Increased acceleration rejection to 20.0
   - Better suited for slow, deliberate tilt movements

Technical details:
- driver/src/uinput.c: Rewrite process_sensor_data() to use Euler angles
- driver/src/main.c: Update config defaults (sensitivity, dead_zone units)
- Movement now smooth, predictable, and drift-free
Copilot AI review requested due to automatic review settings November 15, 2025 16:14
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR refactors the mouse movement control from an acceleration-based system to an angle-based system to eliminate drift and improve smoothness. The key changes include using device orientation angles (pitch/roll) directly instead of integrating acceleration, adding exponential smoothing to reduce jitter, and updating configuration defaults for the new control scheme.

Key changes:

  • Switched from double-integration of acceleration to direct angle-based control using Euler angles from AHRS quaternion
  • Added exponential smoothing filter (alpha=0.3) to velocity calculations
  • Updated dead zone to operate on tilt angles (3°) instead of acceleration (0.05g)

Reviewed Changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 4 comments.

File Description
driver/src/uinput.c Major rewrite of process_sensor_data() to use orientation angles instead of linear acceleration, added smoothed velocity fields and exponential smoothing filter
driver/src/main.c Updated configuration defaults: movement_sensitivity from 2.0 to 8.0, dead_zone from 0.05 to 3.0 with updated units and comments

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +196 to +198
syslog(LOG_INFO, "Angles: Roll:%.1f° Pitch:%.1f° Yaw:%.1f° | Vel(%.1f, %.1f) px/s | dt:%.4f",
euler.angle.roll, euler.angle.pitch, euler.angle.yaw,
world_acceleration.axis.x, world_acceleration.axis.y, world_acceleration.axis.z, dt);
}

// Apply dead zone to filter small movements (in g units)
float dead_zone_g = config.dead_zone; // e.g., 0.03 g
if (fabsf(world_acceleration.axis.x) < dead_zone_g) world_acceleration.axis.x = 0.0f;
if (fabsf(world_acceleration.axis.y) < dead_zone_g) world_acceleration.axis.y = 0.0f;

// Map world-space acceleration to cursor velocity
// World X acceleration → horizontal cursor movement
// World Y acceleration → vertical cursor movement
// Z acceleration ignored (vertical in world frame)
float cursor_vel_x = world_acceleration.axis.x * config.movement_sensitivity; // World X → Screen X
float cursor_vel_y = -world_acceleration.axis.y * config.movement_sensitivity; // World Y → Screen Y (inverted)

// Integrate velocity to position
fusion_state.cursor_x += cursor_vel_x * dt;
fusion_state.cursor_y += cursor_vel_y * dt;

// Debug velocity and accumulation
if (debug_count % 10 == 0) {
syslog(LOG_INFO, "VEL: (%.2f, %.2f) px/s | cursor_accum: (%.2f, %.2f) | sens:%.1f deadzone:%.3f g",
cursor_vel_x, cursor_vel_y,
fusion_state.cursor_x, fusion_state.cursor_y,
config.movement_sensitivity, dead_zone_g);
fusion_state.smoothed_vel_x, fusion_state.smoothed_vel_y, dt);
Copy link

Copilot AI Nov 15, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Inconsistent velocity units in the log message. The comment says "px/s" (pixels per second) but based on the actual code calculation, smoothed_vel_x and smoothed_vel_y are in pixels (not pixels/second) due to the unit mismatch bug. Either fix the underlying bug or update this logging to reflect the actual units.

Copilot uses AI. Check for mistakes.
if (++log_count % 50 == 0) {
syslog(LOG_INFO, "FUSION Angular Vel: (%.2f, %.2f) | Cursor: (%.2f, %.2f) -> dx:%d dy:%d",
cursor_vel_x, cursor_vel_y,
syslog(LOG_INFO, "Movement: Vel(%.1f, %.1f) px/s | Accum(%.2f, %.2f) | Delta dx:%d dy:%d",
Copy link

Copilot AI Nov 15, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same unit inconsistency as in the debug log above - the "px/s" label is incorrect given the current implementation. This should match the actual units of the variables.

Suggested change
syslog(LOG_INFO, "Movement: Vel(%.1f, %.1f) px/s | Accum(%.2f, %.2f) | Delta dx:%d dy:%d",
syslog(LOG_INFO, "Movement: Vel(%.1f, %.1f) px/packet | Accum(%.2f, %.2f) | Delta dx:%d dy:%d",

Copilot uses AI. Check for mistakes.
.gain = 0.5f, // Moderate gain (balance speed vs stability)
.gyroscopeRange = 2000.0f, // ±2000 degrees/s range
.accelerationRejection = 10.0f, // Lower rejection for mouse movements
.accelerationRejection = 20.0f, // Moderate rejection (filter fast movements)
Copy link

Copilot AI Nov 15, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The comment says "Moderate rejection (filter fast movements)" but accelerationRejection is used to reject accelerometer readings that deviate from gravity (indicating external acceleration). The higher the value, the more it trusts the gyroscope over the accelerometer. The comment is misleading as it suggests this filters fast movements, when it actually filters non-gravitational acceleration.

Consider clarifying: // Moderate rejection (trust gyro more during acceleration)

Suggested change
.accelerationRejection = 20.0f, // Moderate rejection (filter fast movements)
.accelerationRejection = 20.0f, // Moderate rejection (trust gyro more during acceleration)

Copilot uses AI. Check for mistakes.
Comment on lines +190 to +191
fusion_state.cursor_x += fusion_state.smoothed_vel_x * dt;
fusion_state.cursor_y += fusion_state.smoothed_vel_y * dt;
Copy link

Copilot AI Nov 15, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unit mismatch: The comment at line 178 says the mapping produces "pixels/second", but the calculation roll * config.movement_sensitivity produces pixels (degrees × pixels/degree = pixels), not pixels/second. Then integrating with dt at line 190 gives incorrect units (pixels × seconds).

Either:

  1. Remove the * dt multiplication at lines 190-191, treating the angles as direct position offsets
  2. OR change the sensitivity units to pixels/second/degree and update the comment at main.c:15 accordingly

The first option is likely what was intended based on the comment "Pixels per degree of tilt" in main.c.

Suggested change
fusion_state.cursor_x += fusion_state.smoothed_vel_x * dt;
fusion_state.cursor_y += fusion_state.smoothed_vel_y * dt;
fusion_state.cursor_x += fusion_state.smoothed_vel_x;
fusion_state.cursor_y += fusion_state.smoothed_vel_y;

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants