mirror of
https://github.com/libsdl-org/SDL.git
synced 2026-10-02 16:23:57 +08:00
Reverted Accelerometer and Gyro displays to throttled display (10hz)
Build (All) / Create test plan (push) Has been cancelled
Build (All) / level1 (push) Has been cancelled
Build (All) / level2 (push) Has been cancelled
Build (All) / Create test plan (push) Has been cancelled
Build (All) / level1 (push) Has been cancelled
Build (All) / level2 (push) Has been cancelled
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!)
This commit is contained in:
+15
-16
@@ -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
@@ -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;
|
||||
|
||||
|
||||
+11
-9
@@ -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->id != event->gsensor.which)
|
||||
if (!controller) {
|
||||
return;
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
Reference in New Issue
Block a user