Pārlūkot izejas kodu

Reverted Accelerometer and Gyro displays to throttled display (10hz)

Also made accelerometer threshold for drift calibration more lenient for very noisy accelerometers.

The testcontroller tool could eventually be used to come up with a better way to profile an IMU's "stationary" noise so that this threshold can be as tight as necessary for the sake of automatic drift calibration.

(thanks @HilariousCow!)
Sam Lantinga 1 mēnesi atpakaļ
vecāks
revīzija
f62c982bcf
3 mainītis faili ar 26 papildinājumiem un 25 dzēšanām
  1. 15 16
      test/gamepadutils.c
  2. 1 1
      test/gamepadutils.h
  3. 10 8
      test/testcontroller.c

+ 15 - 16
test/gamepadutils.c

@@ -42,7 +42,7 @@ typedef struct
 
 struct Quaternion
 {
-    float x, y, z, w; 
+    float x, y, z, w;
 };
 
 static const Vector3 debug_cube_vertices[] = {
@@ -227,15 +227,15 @@ void DrawAccelerometerDebugArrow(SDL_Renderer *renderer, const Quaternion *gyro_
     SDL_FPoint accel_screen = ProjectVec3ToRect(&rotated_accel, bounds);
 
     /* Draw the line from origin to the rotated accelerometer vector */
-    SDL_SetRenderDrawColor(renderer, GYRO_COLOR_ORANGE); 
+    SDL_SetRenderDrawColor(renderer, GYRO_COLOR_ORANGE);
     SDL_RenderLine(renderer, origin_screen.x, origin_screen.y, accel_screen.x, accel_screen.y);
 
     const float head_width = 4.0f;
     SDL_FRect arrow_head_rect;
-    arrow_head_rect.x = accel_screen.x - head_width * 0.5f; 
+    arrow_head_rect.x = accel_screen.x - head_width * 0.5f;
     arrow_head_rect.y = accel_screen.y - head_width * 0.5f;
-    arrow_head_rect.w = head_width;                  
-    arrow_head_rect.h = head_width;                 
+    arrow_head_rect.w = head_width;
+    arrow_head_rect.h = head_width;
     SDL_RenderRect(renderer, &arrow_head_rect);
 
     /* Restore current color */
@@ -1024,7 +1024,7 @@ void SetGyroDisplayArea(GyroDisplay *ctx, const SDL_FRect *area)
     }
 
     SDL_copyp(&ctx->area, area);
-        
+
     /* Place the reset button to the bottom right of the gyro display area.*/
     SDL_FRect reset_button_area;
     reset_button_area.w = SDL_max(MINIMUM_BUTTON_WIDTH, GetGamepadButtonLabelWidth(ctx->reset_gyro_button) + 2 * BUTTON_PADDING);
@@ -1611,8 +1611,7 @@ void RenderGamepadDisplay(GamepadDisplay *ctx, SDL_Gamepad *gamepad)
         has_gyro = SDL_GamepadHasSensor(gamepad, SDL_SENSOR_GYRO);
 
         if (has_accel || has_gyro) {
-            const float gyro_sensor_rate = has_gyro ? SDL_GetGamepadSensorDataRate(gamepad, SDL_SENSOR_GYRO) : 0;
-            const int SENSOR_UPDATE_INTERVAL_MS = gyro_sensor_rate > 0.0f ? (int)( 1000.0f / gyro_sensor_rate ) : 100;
+            const int SENSOR_UPDATE_INTERVAL_MS = 100;
             Uint64 now = SDL_GetTicks();
 
             if (now >= ctx->last_sensor_update + SENSOR_UPDATE_INTERVAL_MS) {
@@ -1622,6 +1621,7 @@ void RenderGamepadDisplay(GamepadDisplay *ctx, SDL_Gamepad *gamepad)
                 if (has_gyro) {
                     SDL_GetGamepadSensorData(gamepad, SDL_SENSOR_GYRO, ctx->gyro_data, SDL_arraysize(ctx->gyro_data));
                 }
+                ctx->last_sensor_update = now;
             }
 
             if (has_accel) {
@@ -1637,10 +1637,9 @@ void RenderGamepadDisplay(GamepadDisplay *ctx, SDL_Gamepad *gamepad)
                 SDLTest_DrawString(ctx->renderer, x + center - SDL_strlen(text) * FONT_CHARACTER_SIZE, y, text);
                 SDL_snprintf(text, sizeof(text), "[%.2f,%.2f,%.2f]%s/s", ctx->gyro_data[0] * RAD_TO_DEG, ctx->gyro_data[1] * RAD_TO_DEG, ctx->gyro_data[2] * RAD_TO_DEG, DEGREE_UTF8);
                 SDLTest_DrawString(ctx->renderer, x + center + 2.0f, y, text);
-           
 
-                /* Display a smoothed version of the above for the sake of turntable tests */
 
+                /* Display the testcontroller tool's evaluation of drift. This is also useful to get an average rate of turn in calibrated turntable tests. */
                 if (ctx->gyro_drift_correction_data[0] != 0.0f && ctx->gyro_drift_correction_data[2] != 0.0f && ctx->gyro_drift_correction_data[2] != 0.0f )
                 {
                     y += ctx->button_height + 2.0f;
@@ -1652,7 +1651,7 @@ void RenderGamepadDisplay(GamepadDisplay *ctx, SDL_Gamepad *gamepad)
 
             }
 
-            ctx->last_sensor_update = now;
+
         }
     }
     SDL_free(mapping);
@@ -1782,7 +1781,7 @@ void RenderGyroDriftCalibrationButton(GyroDisplay *ctx, GamepadDisplay *gamepad_
 
         /* Drift progress bar */
         /* Demonstrate how far we are through the drift progress, and how it resets when there's "high noise", i.e if flNoiseFraction == 1.0f */
-        SDL_FRect progress_bar_rect; 
+        SDL_FRect progress_bar_rect;
         progress_bar_rect.x = recalibrate_button_area.x + BUTTON_PADDING;
         progress_bar_rect.y = recalibrate_button_area.y + recalibrate_button_area.h * 0.5f + BUTTON_PADDING * 0.5f;
         progress_bar_rect.w = recalibrate_button_area.w - BUTTON_PADDING * 2.0f;
@@ -1798,7 +1797,7 @@ void RenderGyroDriftCalibrationButton(GyroDisplay *ctx, GamepadDisplay *gamepad_
 
         /* Set the color based on the drift calibration progress fraction */
         SDL_SetRenderDrawColor(ctx->renderer, GYRO_COLOR_GREEN);        /* red when too much noise, green when low noise*/
-                                                                        
+
         /* Now draw the bars with the filled, then empty rectangles */
         SDL_RenderFillRect(ctx->renderer, &progress_bar_fill);          /* draw the filled rectangle*/
         SDL_SetRenderDrawColor(ctx->renderer, 100, 100, 100, 255);      /* gray box*/
@@ -1830,12 +1829,12 @@ float RenderEulerReadout(GyroDisplay *ctx, GamepadDisplay *gamepad_display )
 
     /* Yaw Readout */
     log_y += new_line_height;
-    SDL_snprintf(text, sizeof(text), "Yaw: %6.2f%s", ctx->euler_displacement_angles[1], DEGREE_UTF8);
+    SDL_snprintf(text, sizeof(text), "  Yaw: %6.2f%s", ctx->euler_displacement_angles[1], DEGREE_UTF8);
     SDLTest_DrawString(ctx->renderer, log_gyro_euler_text_x + 2.0f, log_y, text);
 
     /* Roll Readout */
     log_y += new_line_height;
-    SDL_snprintf(text, sizeof(text), "Roll: %6.2f%s", ctx->euler_displacement_angles[2], DEGREE_UTF8);
+    SDL_snprintf(text, sizeof(text), " Roll: %6.2f%s", ctx->euler_displacement_angles[2], DEGREE_UTF8);
     SDLTest_DrawString(ctx->renderer, log_gyro_euler_text_x + 2.0f, log_y, text);
 
     return log_y + new_line_height; /* Return the next y position for further rendering */
@@ -1907,7 +1906,7 @@ void RenderGyroDisplay(GyroDisplay *ctx, GamepadDisplay *gamepadElements, SDL_Ga
     if (bHasCachedDriftSolution) {
         float bottom = RenderEulerReadout(ctx, gamepadElements);
         RenderGyroGizmo(ctx, gamepad, bottom);
-        
+
     }
     SDL_SetRenderDrawColor(ctx->renderer, r, g, b, a);
 }

+ 1 - 1
test/gamepadutils.h

@@ -143,7 +143,7 @@ extern void DestroyGamepadButton(GamepadButton *ctx);
 
 /* Gyro element Display */
 /* If you want to calbirate against a known rotation (i.e. a turn table test) Increase ACCELEROMETER_NOISE_THRESHOLD to about 5, or drift correction will be constantly reset.*/
-#define ACCELEROMETER_NOISE_THRESHOLD 0.125f
+#define ACCELEROMETER_NOISE_THRESHOLD 0.5f
 typedef struct Quaternion Quaternion;
 typedef struct GyroDisplay GyroDisplay;
 

+ 10 - 8
test/testcontroller.c

@@ -147,7 +147,7 @@ typedef struct
     Uint64 gyro_packet_number;
     Uint64 accelerometer_packet_number;
     /* When both gyro and accelerometer events have been processed, we can increment this and use it to calculate polling rate over time.*/
-    Uint64 imu_packet_counter; 
+    Uint64 imu_packet_counter;
 
     Uint64 starting_time_stamp_ns; /* Use this to help estimate how many packets are received over a duration */
     Uint16 imu_estimated_sensor_rate; /* in Hz, used to estimate how many packets are received over a duration */
@@ -244,7 +244,7 @@ void SampleGyroPacketForDrift( IMUState *imustate )
         if (imustate->gyro_drift_sample_count >= SDL_GAMEPAD_IMU_MIN_GYRO_DRIFT_SAMPLE_COUNT) {
             FinalizeDriftSolution(imustate);
         }
-    }    
+    }
 }
 
 void ApplyDriftSolution(float *gyro_data, const float *drift_solution)
@@ -1409,24 +1409,26 @@ static void UpdateGamepadOrientation( Uint64 delta_time_ns )
 
 static void HandleGamepadSensorEvent( SDL_Event* event )
 {
-    if (!controller)
-        return;   
+    if (!controller) {
+        return;
+    }
 
-    if (controller->id != event->gsensor.which)
+    if (controller->id != event->gsensor.which) {
         return;
+    }
 
     if (event->gsensor.sensor == SDL_SENSOR_GYRO) {
         HandleGamepadGyroEvent(event);
     } else if (event->gsensor.sensor == SDL_SENSOR_ACCEL) {
         HandleGamepadAccelerometerEvent(event);
-    }  
+    }
 
     /*
     This is where we can update the quaternion because we need to have a drift solution, which requires both
     accelerometer and gyro events are received before progressing.
     */
     if ( controller->imu_state->accelerometer_packet_number == controller->imu_state->gyro_packet_number ) {
-        
+
         EstimatePacketRate();
         Uint64 sensorTimeStampDelta_ns = event->gsensor.sensor_timestamp - controller->imu_state->last_sensor_time_stamp_ns ;
         UpdateGamepadOrientation(sensorTimeStampDelta_ns);
@@ -2071,7 +2073,7 @@ SDL_AppResult SDLCALL SDL_AppEvent(void *appstate, SDL_Event *event)
                 event->gsensor.data[1],
                 event->gsensor.data[2],
                 event->gsensor.sensor_timestamp);
-        
+
 #endif /* VERBOSE_SENSORS */
         HandleGamepadSensorEvent(event);
         break;