# Motion Sensor Driver - API Reference

## Core Data Types

### Vec3
3D vector representing sensor data in three axes.

**Constructor:**
- `Vec3::new(x: Double, y: Double, z: Double) -> Vec3`
- `Vec3::zero() -> Vec3` - Returns (0, 0, 0)

**Methods:**
- `magnitude() -> Double` - Length of vector
- `normalize() -> Vec3` - Unit vector
- `add(other: Vec3) -> Vec3` - Vector addition
- `sub(other: Vec3) -> Vec3` - Vector subtraction
- `scale(scalar: Double) -> Vec3` - Scalar multiplication
- `dot(other: Vec3) -> Double` - Dot product
- `cross(other: Vec3) -> Vec3` - Cross product

### Quaternion
Represents 3D rotation using quaternions.

**Constructor:**
- `Quaternion::identity() -> Quaternion` - No rotation
- `Quaternion::from_axis_angle(axis: Vec3, angle: Double) -> Quaternion`

**Methods:**
- `multiply(other: Quaternion) -> Quaternion` - Quaternion multiplication
- `normalize() -> Quaternion` - Normalize to unit quaternion
- `to_euler() -> (Double, Double, Double)` - Convert to (roll, pitch, yaw)

### SensorConfig
Configuration for sensor ranges and sample rate.

**Constructor:**
- `SensorConfig::default() -> SensorConfig`

**Fields:**
- `accel_range: Double` - Accelerometer range (±g)
- `gyro_range: Double` - Gyroscope range (±rad/s)
- `mag_range: Double` - Magnetometer range (±μT)
- `sample_rate: Int` - Sample rate (Hz)

## Sensor Drivers

### Accelerometer
Measures linear acceleration.

**Constructor:**
- `Accelerometer::new(config: SensorConfig) -> Accelerometer`

**Methods:**
- `read(raw: Vec3, timestamp: Int64) -> AccelReading` - Read and calibrate
- `add_calibration_sample(raw: Vec3)` - Add sample for calibration
- `calibrate()` - Calculate and apply calibration
- `get_gravity() -> Vec3` - Get gravity vector
- `get_linear_acceleration(gravity: Vec3) -> Vec3` - Remove gravity
- `is_freefall() -> Bool` - Detect free fall
- `detect_impact() -> Double?` - Detect impact (returns force if detected)
- `get_tilt() -> (Double, Double)` - Get (pitch, roll) angles
- `detect_shake(recent_readings: ArrayView[AccelReading]) -> Bool`

### Gyroscope
Measures angular velocity.

**Constructor:**
- `Gyroscope::new(config: SensorConfig) -> Gyroscope`

**Methods:**
- `read(raw: Vec3, timestamp: Int64) -> GyroReading` - Read and calibrate
- `add_calibration_sample(raw: Vec3)` - Add sample for calibration
- `calibrate()` - Calculate bias offset
- `get_angular_velocity() -> Vec3` - Get current rotation rate
- `integrate(dt: Double) -> Vec3` - Integrate to rotation angle
- `reset_integration()` - Reset integrated angle
- `is_rotating(threshold: Double) -> Bool` - Check if rotating
- `get_rotation_quaternion(dt: Double) -> Quaternion` - Get rotation
- `detect_rotation_type() -> (String, Double)?` - Detect rotation axis
- `apply_lowpass_filter(previous: Vec3, alpha: Double) -> Vec3`

### Magnetometer
Measures magnetic field for compass heading.

**Constructor:**
- `Magnetometer::new(config: SensorConfig) -> Magnetometer`

**Methods:**
- `read(raw: Vec3, timestamp: Int64) -> MagReading` - Read and calibrate
- `add_calibration_sample(raw: Vec3)` - Add sample for calibration
- `calibrate_simple()` - Hard-iron calibration
- `get_magnetic_field() -> Vec3` - Get field vector
- `get_heading() -> Double` - Get heading (radians)
- `get_tilt_compensated_heading(pitch: Double, roll: Double) -> Double`
- `detect_interference() -> Bool` - Detect magnetic interference
- `get_field_strength() -> Double` - Get field magnitude
- `apply_declination(declination: Double) -> Double` - Apply declination

## Sensor Fusion

### ComplementaryFilter
Fast and efficient orientation estimation.

**Constructor:**
- `ComplementaryFilter::new(alpha: Double) -> ComplementaryFilter`
  - `alpha`: Weight for accel/mag (0.01-0.05 typical)

**Methods:**
- `update(accel: Vec3, gyro: Vec3, mag: Vec3, dt: Double) -> Quaternion`
- `get_orientation() -> Quaternion`

### KalmanFilter
Optimal state estimation with noise modeling.

**Constructor:**
- `KalmanFilter::new(process_noise: Double, measurement_noise: Double) -> KalmanFilter`

**Methods:**
- `update(accel: Vec3, gyro: Vec3, mag: Vec3, dt: Double) -> Quaternion`
- `get_orientation() -> Quaternion`

### MadgwickFilter
High-performance gradient descent algorithm.

**Constructor:**
- `MadgwickFilter::new(beta: Double) -> MadgwickFilter`
  - `beta`: Filter gain (0.1 typical)

**Methods:**
- `update(accel: Vec3, gyro: Vec3, mag: Vec3, dt: Double) -> Quaternion`
- `get_orientation() -> Quaternion`

## Motion Controller

### MotionController
High-level controller integrating all sensors.

**Constructor:**
- `MotionController::new(config: SensorConfig) -> MotionController`

**Methods:**

**Update:**
- `update(accel_raw: Vec3, gyro_raw: Vec3, mag_raw: Vec3, timestamp: Int64, dt: Double) -> MotionState`

**State Access:**
- `get_state() -> MotionState` - Get current state
- `get_euler_angles() -> (Double, Double, Double)` - Get (roll, pitch, yaw) in radians
- `get_euler_degrees() -> (Double, Double, Double)` - Get (roll, pitch, yaw) in degrees

**Gesture Detection:**
- `detect_gesture() -> Gesture` - Detect current gesture

**Navigation:**
- `get_heading() -> Double` - Tilt-compensated heading (radians)
- `get_heading_degrees() -> Double` - Tilt-compensated heading (degrees)

**Motion:**
- `is_moving() -> Bool` - Check if device is moving

**Calibration:**
- `calibrate()` - Calibrate all sensors
- `add_calibration_sample(accel_raw: Vec3, gyro_raw: Vec3, mag_raw: Vec3)`
- `reset()` - Reset sensor fusion

## Gesture Enum

```moonbit
enum Gesture {
  Stationary                    // No motion
  Shaking                       // Shake detected
  Tilting(Double, Double)       // Tilted (pitch, roll)
  Rotating(Double)              // Rotating (angular velocity)
  FreeFall                      // In free fall
  Impact(Double)                // Impact detected (force)
}
```

## MotionState Struct

```moonbit
struct MotionState {
  acceleration: Vec3        // Current acceleration (m/s²)
  angular_velocity: Vec3    // Current rotation rate (rad/s)
  magnetic_field: Vec3      // Current magnetic field (μT)
  orientation: Quaternion   // Current orientation
  timestamp: Int64          // Reading timestamp (ms)
}
```

## Typical Workflow

1. **Initialize**
   ```moonbit
   let controller = MotionController::new(SensorConfig::default())
   ```

2. **Calibrate** (optional but recommended)
   ```moonbit
   for i = 0; i < 100; i = i + 1 {
     controller.add_calibration_sample(accel_raw, gyro_raw, mag_raw)
   }
   controller.calibrate()
   ```

3. **Update Loop**
   ```moonbit
   let state = controller.update(accel_raw, gyro_raw, mag_raw, timestamp, dt)
   ```

4. **Query State**
   ```moonbit
   let gesture = controller.detect_gesture()
   let (roll, pitch, yaw) = controller.get_euler_degrees()
   let heading = controller.get_heading_degrees()
   ```

## Units Reference

- **Acceleration**: m/s² (meters per second squared)
- **Angular Velocity**: rad/s (radians per second)
- **Magnetic Field**: μT (microtesla)
- **Angles**: radians or degrees (as specified)
- **Time**: seconds (Double) or milliseconds (Int64)
- **Gravity**: 9.81 m/s² (Earth's gravity)

## Error Handling

All sensor functions are designed to handle edge cases gracefully:
- Zero vectors return identity/zero as appropriate
- Division by zero is avoided with magnitude checks
- Calibration requires minimum sample count

## Performance Notes

- Complementary filter: ~0.1ms per update
- Kalman filter: ~0.2ms per update
- Madgwick filter: ~0.5ms per update
- Recommended update rate: 100-200Hz
- Memory usage: ~1KB per MotionController instance
