Skip to content

Commit 34616d1

Browse files
HilariousCowslouken
authored andcommitted
A little more tidying. Better notes around how the absolute maximum threshold was arrived at.
1 parent 8863e5e commit 34616d1

File tree

3 files changed

+24
-26
lines changed

3 files changed

+24
-26
lines changed

test/gamepadutils.c

Lines changed: 11 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -236,7 +236,7 @@ void DrawGyroDebugAxes(SDL_Renderer *renderer, const Quaternion *orientation, co
236236
SDL_RenderLine(renderer, origin_screen.x, origin_screen.y, up_screen.x, up_screen.y);
237237
SDL_SetRenderDrawColor(renderer, GYRO_COLOR_BLUE);
238238
SDL_RenderLine(renderer, origin_screen.x, origin_screen.y, back_screen.x, back_screen.y);
239-
239+
240240
/* Restore current color */
241241
SDL_SetRenderDrawColor(renderer, r, g, b, a);
242242
}
@@ -1053,7 +1053,7 @@ GyroDisplay *CreateGyroDisplay(SDL_Renderer *renderer)
10531053
ctx->next_reported_sensor_time = 0;
10541054
ctx->current_calibration_phase = GYRO_CALIBRATION_PHASE_OFF;
10551055
ctx->calibration_phase_progress_fraction = 0.0f; /* [0..1] */
1056-
ctx->accelerometer_noise_sq = 0.0f;
1056+
ctx->accelerometer_noise_sq = 0.0f;
10571057
ctx->accelerometer_noise_tolerance_sq = ACCELEROMETER_NOISE_THRESHOLD; /* Will be overwritten but this avoids divide by zero. */
10581058
ctx->reset_gyro_button = CreateGamepadButton(renderer, "Reset View");
10591059
ctx->calibrate_gyro_button = CreateGamepadButton(renderer, "Recalibrate Drift");
@@ -1678,7 +1678,6 @@ void RenderGamepadDisplay(GamepadDisplay *ctx, SDL_Gamepad *gamepad)
16781678
SDLTest_DrawString(ctx->renderer, x + center - SDL_strlen(text) * FONT_CHARACTER_SIZE, y, text);
16791679
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);
16801680
SDLTest_DrawString(ctx->renderer, x + center + 2.0f, y, text);
1681-
16821681

16831682
/* Display the testcontroller tool's evaluation of drift. This is also useful to get an average rate of turn in calibrated turntable tests. */
16841683
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 )
@@ -1758,7 +1757,6 @@ void RenderGyroDriftCalibrationButton(GyroDisplay *ctx, GamepadDisplay *gamepad_
17581757
const float new_line_height = gamepad_display->button_height + 2.0f;
17591758
GamepadButton *start_calibration_button = GetGyroCalibrateButton(ctx);
17601759

1761-
17621760
/* Show the recalibration progress bar. */
17631761
float recalibrate_button_width = GetGamepadButtonLabelWidth(start_calibration_button) + 2 * BUTTON_PADDING;
17641762
SDL_FRect recalibrate_button_area;
@@ -1784,27 +1782,27 @@ void RenderGyroDriftCalibrationButton(GyroDisplay *ctx, GamepadDisplay *gamepad_
17841782

17851783
SetGamepadButtonLabel(start_calibration_button, label_text);
17861784
SetGamepadButtonArea(start_calibration_button, &recalibrate_button_area);
1787-
RenderGamepadButton(start_calibration_button);
1785+
RenderGamepadButton(start_calibration_button);
17881786

17891787
bool bExtremeNoise = ctx->accelerometer_noise_sq > ACCELEROMETER_MAX_NOISE_G_SQ;
17901788
/* Explicit warning message if we detect too much movement */
17911789
if (ctx->current_calibration_phase == GYRO_CALIBRATION_PHASE_OFF) {
1792-
1793-
if (bExtremeNoise)
1794-
{
1790+
if (bExtremeNoise) {
17951791
SDL_strlcpy(label_text, "GamePad Must Be Still", sizeof(label_text));
17961792
SDLTest_DrawString(ctx->renderer, recalibrate_button_area.x, recalibrate_button_area.y + recalibrate_button_area.h + new_line_height, label_text);
17971793
SDL_strlcpy(label_text, "Place GamePad On Table", sizeof(label_text));
17981794
SDLTest_DrawString(ctx->renderer, recalibrate_button_area.x, recalibrate_button_area.y + recalibrate_button_area.h + new_line_height * 2, label_text);
17991795
}
18001796
}
18011797

1802-
if (ctx->current_calibration_phase == GYRO_CALIBRATION_PHASE_NOISE_PROFILING
1803-
|| ctx->current_calibration_phase == GYRO_CALIBRATION_PHASE_DRIFT_PROFILING)
1798+
if (ctx->current_calibration_phase == GYRO_CALIBRATION_PHASE_NOISE_PROFILING ||
1799+
ctx->current_calibration_phase == GYRO_CALIBRATION_PHASE_DRIFT_PROFILING)
18041800
{
18051801
float flAbsoluteNoiseFraction = SDL_clamp(ctx->accelerometer_noise_sq / ACCELEROMETER_MAX_NOISE_G_SQ, 0.0f, 1.0f);
18061802
float flAbsoluteToleranceFraction = SDL_clamp(ctx->accelerometer_noise_tolerance_sq / ACCELEROMETER_MAX_NOISE_G_SQ, 0.0f, 1.0f);
1807-
float flRelativeNoiseFraction = SDL_clamp(ctx->accelerometer_noise_sq / ctx->accelerometer_noise_tolerance_sq, 0.0f, 1.0f);
1803+
1804+
float flMaxNoiseForThisPhase = ctx->current_calibration_phase == GYRO_CALIBRATION_PHASE_NOISE_PROFILING ? ACCELEROMETER_MAX_NOISE_G_SQ : ctx->accelerometer_noise_tolerance_sq;
1805+
float flRelativeNoiseFraction = SDL_clamp(ctx->accelerometer_noise_sq / flMaxNoiseForThisPhase, 0.0f, 1.0f);
18081806

18091807
float noise_bar_height = gamepad_display->button_height;
18101808
SDL_FRect noise_bar_rect;
@@ -1813,7 +1811,7 @@ void RenderGyroDriftCalibrationButton(GyroDisplay *ctx, GamepadDisplay *gamepad_
18131811
noise_bar_rect.w = recalibrate_button_area.w;
18141812
noise_bar_rect.h = noise_bar_height;
18151813

1816-
SDL_snprintf(label_text, sizeof(label_text), "Noise Tolerance: %3.3fG ", SDL_sqrtf(ctx->accelerometer_noise_tolerance_sq) );
1814+
SDL_snprintf(label_text, sizeof(label_text), "Accelerometer Noise Tolerance: %3.3fG ", SDL_sqrtf(ctx->accelerometer_noise_tolerance_sq) );
18171815
SDLTest_DrawString(ctx->renderer, recalibrate_button_area.x, recalibrate_button_area.y + recalibrate_button_area.h + new_line_height * 2, label_text);
18181816

18191817
/* Adjust the noise bar rectangle based on the accelerometer noise value */
@@ -1837,7 +1835,7 @@ void RenderGyroDriftCalibrationButton(GyroDisplay *ctx, GamepadDisplay *gamepad_
18371835
tolerance_bar_rect.w = tolerance_bar_fill_width;
18381836
tolerance_bar_rect.h = noise_bar_height;
18391837

1840-
SDL_SetRenderDrawColor(ctx->renderer, 128, 128, 0, 255);
1838+
SDL_SetRenderDrawColor(ctx->renderer, 128, 128, 0, 255);
18411839
SDL_RenderRect(ctx->renderer, &tolerance_bar_rect); /* draw the tolerance rectangle */
18421840

18431841
SDL_SetRenderDrawColor(ctx->renderer, 100, 100, 100, 255); /* gray box */
@@ -1985,7 +1983,6 @@ void RenderGyroDisplay(GyroDisplay *ctx, GamepadDisplay *gamepadElements, SDL_Ga
19851983
float bottom = RenderEulerReadout(ctx, gamepadElements);
19861984
RenderGyroGizmo(ctx, gamepad, bottom);
19871985
}
1988-
19891986
SDL_SetRenderDrawColor(ctx->renderer, r, g, b, a);
19901987
}
19911988

test/gamepadutils.h

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -143,9 +143,12 @@ extern void DestroyGamepadButton(GamepadButton *ctx);
143143

144144
/* Gyro element Display */
145145

146-
/* This is used as the initial noise tolernace threshold. It's set very close to zero to avoid divide by zero while we're evaluating the noise profile. Each controller may have a very different noise profile.*/
146+
/* This is used as the initial noise tolerance threshold. It's set very close to zero to avoid divide by zero while we're evaluating the noise profile. Each controller may have a very different noise profile.*/
147147
#define ACCELEROMETER_NOISE_THRESHOLD 1e-6f
148-
#define ACCELEROMETER_MAX_NOISE_G_SQ ( 0.125f * 0.125f )
148+
/* The value below is based on observation of a Dualshock controller. Of all gamepads observed, the Dualshock (PS4) tends to have one of the noisiest accelerometers. Increase this threshold if a controller is failing to pass the noise profiling stage while stationary on a table. */
149+
#define ACCELEROMETER_MAX_NOISE_G 0.075f
150+
#define ACCELEROMETER_MAX_NOISE_G_SQ (ACCELEROMETER_MAX_NOISE_G * ACCELEROMETER_MAX_NOISE_G)
151+
149152
/* Gyro Calibration Phases */
150153
typedef enum
151154
{

test/testcontroller.c

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -211,7 +211,7 @@ void ResetGyroOrientation(IMUState *imustate)
211211
}
212212

213213
/* More time = more accurate drift correction*/
214-
#define SDL_GAMEPAD_IMU_NOISE_SETTLING_PERIOD_NS (1 * SDL_NS_PER_SECOND)
214+
#define SDL_GAMEPAD_IMU_NOISE_SETTLING_PERIOD_NS ( SDL_NS_PER_SECOND / 2)
215215
#define SDL_GAMEPAD_IMU_NOISE_EVALUATION_PERIOD_NS (4 * SDL_NS_PER_SECOND)
216216
#define SDL_GAMEPAD_IMU_NOISE_PROFILING_PHASE_DURATION_NS (SDL_GAMEPAD_IMU_NOISE_SETTLING_PERIOD_NS + SDL_GAMEPAD_IMU_NOISE_EVALUATION_PERIOD_NS)
217217
#define SDL_GAMEPAD_IMU_CALIBRATION_PHASE_DURATION_NS (5 * SDL_NS_PER_SECOND)
@@ -222,12 +222,11 @@ void ResetGyroOrientation(IMUState *imustate)
222222
void CalibrationPhase_NoiseProfiling(IMUState *imustate)
223223
{
224224
/* If we have really large movement (i.e. greater than a fraction of G), then we want to start noise evaluation over. The frontend will warn the user to put down the controller. */
225-
const float flAbsoluteMaxAccelerationG = 0.125f;
226-
if (imustate->accelerometer_length_squared > (flAbsoluteMaxAccelerationG * flAbsoluteMaxAccelerationG) ) {
225+
if (imustate->accelerometer_length_squared > ACCELEROMETER_MAX_NOISE_G_SQ) {
227226
BeginNoiseCalibrationPhase(imustate);
228227
return;
229228
}
230-
229+
231230
Uint64 now = SDL_GetTicksNS();
232231
Uint64 delta_ns = now - imustate->calibration_phase_start_time_ticks_ns;
233232

@@ -1433,7 +1432,7 @@ static void HandleGamepadGyroEvent(SDL_Event *event)
14331432
/* Two strategies for evaluating polling rate - one based on a fixed packet count, and one using a fixed time window.
14341433
* Smaller values in either will give you a more responsive polling rate estimate, but this may fluctuate more.
14351434
* Larger values in either will give you a more stable average but they will require more time to evaluate.
1436-
* Generally, wired connections tend to give much more stable
1435+
* Generally, wired connections tend to give much more stable
14371436
*/
14381437
/* #define SDL_USE_FIXED_PACKET_COUNT_FOR_ESTIMATION */
14391438
#define SDL_GAMEPAD_IMU_MIN_POLLING_RATE_ESTIMATION_COUNT 2048
@@ -1479,7 +1478,7 @@ static void UpdateGamepadOrientation( Uint64 delta_time_ns )
14791478
static void HandleGamepadSensorEvent( SDL_Event* event )
14801479
{
14811480
if (!controller)
1482-
return;
1481+
return;
14831482

14841483
if (controller->id != event->gsensor.which)
14851484
return;
@@ -1504,15 +1503,15 @@ static void HandleGamepadSensorEvent( SDL_Event* event )
15041503

15051504
/* Show how far we are through the current phase. When off, just default to zero progress */
15061505
Uint64 now = SDL_GetTicksNS();
1507-
float duration = 0.0f;
1506+
Uint64 duration = 0;
15081507
if (controller->imu_state->calibration_phase == GYRO_CALIBRATION_PHASE_NOISE_PROFILING) {
15091508
duration = SDL_GAMEPAD_IMU_NOISE_PROFILING_PHASE_DURATION_NS;
15101509
} else if (controller->imu_state->calibration_phase == GYRO_CALIBRATION_PHASE_DRIFT_PROFILING) {
15111510
duration = SDL_GAMEPAD_IMU_CALIBRATION_PHASE_DURATION_NS;
15121511
}
15131512

15141513
Uint64 delta_ns = now - controller->imu_state->calibration_phase_start_time_ticks_ns;
1515-
float drift_calibration_progress_frac = duration > 0.0f ? ((float)delta_ns / (float)duration) : 0.0f;
1514+
float drift_calibration_progress_fraction = duration > 0.0f ? ((float)delta_ns / (float)duration) : 0.0f;
15161515

15171516
int reported_polling_rate_hz = sensorTimeStampDelta_ns > 0 ? (int)(SDL_NS_PER_SECOND / sensorTimeStampDelta_ns) : 0;
15181517

@@ -1524,10 +1523,9 @@ static void HandleGamepadSensorEvent( SDL_Event* event )
15241523
reported_polling_rate_hz,
15251524
controller->imu_state->imu_estimated_sensor_rate,
15261525
controller->imu_state->calibration_phase,
1527-
drift_calibration_progress_frac,
1526+
drift_calibration_progress_fraction,
15281527
controller->imu_state->accelerometer_length_squared,
15291528
controller->imu_state->accelerometer_tolerance_squared
1530-
15311529
);
15321530

15331531
/* Also show the gyro correction next to the gyro speed - this is useful in turntable tests as you can use a turntable to calibrate for drift, and that drift correction is functionally the same as the turn table speed (ignoring drift) */

0 commit comments

Comments
 (0)