Skip to content

Commit b6d75ca

Browse files
committed
movement fucked up
1 parent eea5314 commit b6d75ca

3 files changed

Lines changed: 32 additions & 46 deletions

File tree

config/m5-mouse.yaml

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
11
# M5 Atom Matrix Mouse Controller Configuration
22

3-
# Movement sensitivity (multiplier for accelerometer values)
4-
movement_sensitivity: 1000.0
3+
# Movement sensitivity (pixels per g of acceleration)
4+
# Recommended range: 100-1000 (higher = more sensitive)
5+
movement_sensitivity: 500.0
56

6-
# Dead zone threshold (ignore small movements below this value)
7-
dead_zone: 0.1
7+
# Dead zone threshold (g units - ignore acceleration below this)
8+
# Recommended range: 0.01-0.1 (lower = more precise, higher = more stable)
9+
dead_zone: 0.03
810

911
# Invert axis directions
1012
invert_x: false

driver/src/main.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,9 @@
1212
#include "uinput.h"
1313

1414
MouseConfig config = {
15-
.movement_sensitivity = 2.0f, // pixels per degree/second
15+
.movement_sensitivity = 2.0f, // Default: pixels per degree/second
1616
.scroll_sensitivity = 1.0f,
17-
.dead_zone = 0.05f, // degrees/second threshold for angular velocity
17+
.dead_zone = 0.05f, // Default: degrees/second threshold for angular velocity
1818
.scroll_threshold = 0.3f,
1919
.invert_x = false,
2020
.invert_y = false,

driver/src/uinput.c

Lines changed: 24 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,6 @@ static uint8_t last_button_state = 0;
3030
// IMU state with Fusion AHRS
3131
typedef struct {
3232
FusionAhrs ahrs; // Fusion AHRS algorithm
33-
FusionQuaternion prev_quaternion; // Previous quaternion for angular velocity
3433
double t_last;
3534
float cursor_x, cursor_y; // Virtual cursor position (accumulated)
3635
int initialized;
@@ -139,20 +138,19 @@ void process_sensor_data(UInputDevice* device, const SensorPacket* packet) {
139138
// Initialize Fusion AHRS
140139
FusionAhrsInitialise(&fusion_state.ahrs);
141140

142-
// Set AHRS settings for optimized mouse control
141+
// Set AHRS settings optimized for fast, accurate mouse control
143142
FusionAhrsSettings settings = {
144143
.convention = FusionConventionNwu, // North-West-Up coordinate system
145-
.gain = 0.5f, // Moderate gain for stability
144+
.gain = 1.0f, // Higher gain for faster convergence
146145
.gyroscopeRange = 2000.0f, // ±2000 degrees/s range
147-
.accelerationRejection = 90.0f, // Reject high accelerations
146+
.accelerationRejection = 10.0f, // Lower rejection for mouse movements
148147
.magneticRejection = 0.0f, // No magnetometer
149-
.recoveryTriggerPeriod = 5 * 100 // 5 seconds at 100Hz
148+
.recoveryTriggerPeriod = 2 * 200 // 2 seconds at 200Hz (faster recovery)
150149
};
151150
FusionAhrsSetSettings(&fusion_state.ahrs, &settings);
152151

153152
fusion_state.cursor_x = 0.0f;
154153
fusion_state.cursor_y = 0.0f;
155-
fusion_state.prev_quaternion = FUSION_IDENTITY_QUATERNION;
156154
fusion_state.initialized = 1;
157155
return; // Skip first frame
158156
}
@@ -163,59 +161,45 @@ void process_sensor_data(UInputDevice* device, const SensorPacket* packet) {
163161
// Get current quaternion
164162
FusionQuaternion quaternion = FusionAhrsGetQuaternion(&fusion_state.ahrs);
165163

166-
// Calculate angular velocity from quaternion difference
167-
// This gives us the rotation rate independent of device orientation
164+
// Get linear acceleration (with gravity removed by Fusion)
165+
FusionVector linear_acceleration = FusionAhrsGetLinearAcceleration(&fusion_state.ahrs);
168166

169-
// Manually create conjugate of previous quaternion (negate x,y,z components)
170-
FusionQuaternion prev_conjugate = {
171-
.element.w = fusion_state.prev_quaternion.element.w,
172-
.element.x = -fusion_state.prev_quaternion.element.x,
173-
.element.y = -fusion_state.prev_quaternion.element.y,
174-
.element.z = -fusion_state.prev_quaternion.element.z
175-
};
176-
177-
FusionQuaternion quaternion_diff = FusionQuaternionMultiply(quaternion, prev_conjugate);
178-
179-
// Extract angular velocity from quaternion difference
180-
// Small angle approximation: angular_velocity ≈ 2 * quaternion_vector / dt
181-
float angular_vel_x = 2.0f * quaternion_diff.element.x / dt; // Roll rate
182-
float angular_vel_y = 2.0f * quaternion_diff.element.y / dt; // Pitch rate
183-
float angular_vel_z = 2.0f * quaternion_diff.element.z / dt; // Yaw rate
184-
185-
fusion_state.prev_quaternion = quaternion;
167+
// Transform linear acceleration from device frame to world frame using current orientation
168+
// This makes movement independent of device rotation - move device left = cursor left
169+
FusionMatrix rotation_matrix = FusionQuaternionToMatrix(quaternion);
170+
FusionVector world_acceleration = FusionMatrixMultiplyVector(rotation_matrix, linear_acceleration);
186171

187172
// Debug: log sensor fusion values
188173
static int debug_count = 0;
189174
if (++debug_count % 10 == 0) { // Every 10 frames (~200ms)
190175
FusionEuler euler = FusionQuaternionToEuler(quaternion);
191-
syslog(LOG_INFO, "FUSION: Roll:%.1f° Pitch:%.1f° Yaw:%.1f° | AngVel(%.2f, %.2f, %.2f) dt:%.4f",
176+
syslog(LOG_INFO, "FUSION: Roll:%.1f° Pitch:%.1f° Yaw:%.1f° | WorldAccel(%.3f, %.3f, %.3f) dt:%.4f",
192177
euler.angle.roll, euler.angle.pitch, euler.angle.yaw,
193-
angular_vel_x, angular_vel_y, angular_vel_z, dt);
178+
world_acceleration.axis.x, world_acceleration.axis.y, world_acceleration.axis.z, dt);
194179
}
195180

196-
// Apply dead zone FIRST to filter noise/drift (in degrees/second)
197-
float dead_zone_deg_per_sec = config.dead_zone; // e.g., 0.1 deg/s
198-
if (fabsf(angular_vel_x) < dead_zone_deg_per_sec) angular_vel_x = 0.0f;
199-
if (fabsf(angular_vel_y) < dead_zone_deg_per_sec) angular_vel_y = 0.0f;
200-
if (fabsf(angular_vel_z) < dead_zone_deg_per_sec) angular_vel_z = 0.0f;
181+
// Apply dead zone to filter small movements (in g units)
182+
float dead_zone_g = config.dead_zone; // e.g., 0.03 g
183+
if (fabsf(world_acceleration.axis.x) < dead_zone_g) world_acceleration.axis.x = 0.0f;
184+
if (fabsf(world_acceleration.axis.y) < dead_zone_g) world_acceleration.axis.y = 0.0f;
201185

202-
// Map angular velocity to cursor movement (velocity-based control)
203-
// Yaw (Z) rotation → horizontal cursor movement
204-
// Pitch (Y) rotation → vertical cursor movement
205-
// Roll (X) is ignored for 2D mouse control
206-
float cursor_vel_x = -angular_vel_z * config.movement_sensitivity; // Yaw → X (negated to fix inversion)
207-
float cursor_vel_y = -angular_vel_y * config.movement_sensitivity; // Pitch → Y (inverted)
186+
// Map world-space acceleration to cursor velocity
187+
// World X acceleration → horizontal cursor movement
188+
// World Y acceleration → vertical cursor movement
189+
// Z acceleration ignored (vertical in world frame)
190+
float cursor_vel_x = world_acceleration.axis.x * config.movement_sensitivity; // World X → Screen X
191+
float cursor_vel_y = -world_acceleration.axis.y * config.movement_sensitivity; // World Y → Screen Y (inverted)
208192

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

213197
// Debug velocity and accumulation
214198
if (debug_count % 10 == 0) {
215-
syslog(LOG_INFO, "VEL: (%.2f, %.2f) px/s | cursor_accum: (%.2f, %.2f) | sens:%.1f deadzone:%.3f deg/s",
199+
syslog(LOG_INFO, "VEL: (%.2f, %.2f) px/s | cursor_accum: (%.2f, %.2f) | sens:%.1f deadzone:%.3f g",
216200
cursor_vel_x, cursor_vel_y,
217201
fusion_state.cursor_x, fusion_state.cursor_y,
218-
config.movement_sensitivity, dead_zone_deg_per_sec);
202+
config.movement_sensitivity, dead_zone_g);
219203
}
220204

221205
// Extract integer deltas for mouse movement

0 commit comments

Comments
 (0)