@@ -1031,8 +1031,10 @@ struct GyroDisplay
1031
1031
int estimated_sensor_rate_hz ; /*hz - our estimation of the actual polling rate by observing packets received*/
1032
1032
float euler_displacement_angles [3 ]; /* pitch, yaw, roll */
1033
1033
Quaternion gyro_quaternion ; /* Rotation since startup/reset, comprised of each gyro speed packet times sensor delta time. */
1034
- float drift_calibration_progress_frac ; /* [0..1] */
1034
+ EGyroCalibrationPhase current_calibration_phase ;
1035
+ float calibration_phase_progress_fraction ; /* [0..1] */
1035
1036
float accelerometer_noise_sq ; /* Distance between last noise and new noise. Used to indicate motion.*/
1037
+ float accelerometer_noise_tolerance_sq ; /* Maximum amount of noise detected during the Noise Profiling Phase */
1036
1038
1037
1039
GamepadButton * reset_gyro_button ;
1038
1040
GamepadButton * calibrate_gyro_button ;
@@ -1049,6 +1051,10 @@ GyroDisplay *CreateGyroDisplay(SDL_Renderer *renderer)
1049
1051
ctx -> gyro_quaternion = quat_identity ;
1050
1052
ctx -> reported_sensor_rate_hz = 0 ;
1051
1053
ctx -> next_reported_sensor_time = 0 ;
1054
+ ctx -> current_calibration_phase = GYRO_CALIBRATION_PHASE_OFF ;
1055
+ ctx -> calibration_phase_progress_fraction = 0.0f ; /* [0..1] */
1056
+ ctx -> accelerometer_noise_sq = 0.0f ;
1057
+ ctx -> accelerometer_noise_tolerance_sq = ACCELEROMETER_NOISE_THRESHOLD ; /* Will be overwritten but this avoids divide by zero. */
1052
1058
ctx -> reset_gyro_button = CreateGamepadButton (renderer , "Reset View" );
1053
1059
ctx -> calibrate_gyro_button = CreateGamepadButton (renderer , "Recalibrate Drift" );
1054
1060
}
@@ -1362,17 +1368,7 @@ static void RenderGamepadElementHighlight(GamepadDisplay *ctx, int element, cons
1362
1368
}
1363
1369
}
1364
1370
1365
- bool BHasCachedGyroDriftSolution (GyroDisplay * ctx )
1366
- {
1367
- if (!ctx ) {
1368
- return false;
1369
- }
1370
- return (ctx -> gyro_drift_solution [0 ] != 0.0f ||
1371
- ctx -> gyro_drift_solution [1 ] != 0.0f ||
1372
- ctx -> gyro_drift_solution [2 ] != 0.0f );
1373
- }
1374
-
1375
- void SetGamepadDisplayIMUValues (GyroDisplay * ctx , float * gyro_drift_solution , float * euler_displacement_angles , Quaternion * gyro_quaternion , int reported_senor_rate_hz , int estimated_sensor_rate_hz , float drift_calibration_progress_frac , float accelerometer_noise_sq )
1371
+ void SetGamepadDisplayIMUValues (GyroDisplay * ctx , float * gyro_drift_solution , float * euler_displacement_angles , Quaternion * gyro_quaternion , int reported_senor_rate_hz , int estimated_sensor_rate_hz , EGyroCalibrationPhase calibration_phase , float drift_calibration_progress_frac , float accelerometer_noise_sq , float accelerometer_noise_tolerance_sq )
1376
1372
{
1377
1373
if (!ctx ) {
1378
1374
return ;
@@ -1391,8 +1387,10 @@ void SetGamepadDisplayIMUValues(GyroDisplay *ctx, float *gyro_drift_solution, fl
1391
1387
SDL_memcpy (ctx -> gyro_drift_solution , gyro_drift_solution , sizeof (ctx -> gyro_drift_solution ));
1392
1388
SDL_memcpy (ctx -> euler_displacement_angles , euler_displacement_angles , sizeof (ctx -> euler_displacement_angles ));
1393
1389
ctx -> gyro_quaternion = * gyro_quaternion ;
1394
- ctx -> drift_calibration_progress_frac = drift_calibration_progress_frac ;
1390
+ ctx -> current_calibration_phase = calibration_phase ;
1391
+ ctx -> calibration_phase_progress_fraction = drift_calibration_progress_frac ;
1395
1392
ctx -> accelerometer_noise_sq = accelerometer_noise_sq ;
1393
+ ctx -> accelerometer_noise_tolerance_sq = accelerometer_noise_tolerance_sq ;
1396
1394
}
1397
1395
1398
1396
extern GamepadButton * GetGyroResetButton (GyroDisplay * ctx )
@@ -1713,7 +1711,7 @@ void RenderSensorTimingInfo(GyroDisplay *ctx, GamepadDisplay *gamepad_display)
1713
1711
/* Sensor timing section */
1714
1712
char text [128 ];
1715
1713
const float new_line_height = gamepad_display -> button_height + 2.0f ;
1716
- const float text_offset_x = ctx -> area .x + ctx -> area .w / 4.0f + 40 .0f ;
1714
+ const float text_offset_x = ctx -> area .x + ctx -> area .w / 4.0f + 35 .0f ;
1717
1715
/* Anchor to bottom left of principle rect. */
1718
1716
float text_y_pos = ctx -> area .y + ctx -> area .h - new_line_height * 2 ;
1719
1717
/*
@@ -1759,7 +1757,7 @@ void RenderGyroDriftCalibrationButton(GyroDisplay *ctx, GamepadDisplay *gamepad_
1759
1757
float log_y = ctx -> area .y + BUTTON_PADDING ;
1760
1758
const float new_line_height = gamepad_display -> button_height + 2.0f ;
1761
1759
GamepadButton * start_calibration_button = GetGyroCalibrateButton (ctx );
1762
- bool bHasCachedDriftSolution = BHasCachedGyroDriftSolution ( ctx );
1760
+
1763
1761
1764
1762
/* Show the recalibration progress bar. */
1765
1763
float recalibrate_button_width = GetGamepadButtonLabelWidth (start_calibration_button ) + 2 * BUTTON_PADDING ;
@@ -1769,24 +1767,46 @@ void RenderGyroDriftCalibrationButton(GyroDisplay *ctx, GamepadDisplay *gamepad_
1769
1767
recalibrate_button_area .w = GetGamepadButtonLabelWidth (start_calibration_button ) + 2.0f * BUTTON_PADDING ;
1770
1768
recalibrate_button_area .h = gamepad_display -> button_height + BUTTON_PADDING * 2.0f ;
1771
1769
1772
- if (!bHasCachedDriftSolution ) {
1773
- SDL_snprintf (label_text , sizeof (label_text ), "Progress: %3.0f%% " , ctx -> drift_calibration_progress_frac * 100.0f );
1774
- } else {
1775
- SDL_strlcpy (label_text , "Calibrate Drift" , sizeof (label_text ));
1770
+ /* Above button */
1771
+ SDL_strlcpy (label_text , "Gyro Orientation:" , sizeof (label_text ));
1772
+ SDLTest_DrawString (ctx -> renderer , recalibrate_button_area .x , recalibrate_button_area .y - new_line_height , label_text );
1773
+
1774
+ /* Button label vs state */
1775
+ if (ctx -> current_calibration_phase == GYRO_CALIBRATION_PHASE_OFF ) {
1776
+ SDL_strlcpy (label_text , "Start Gyro Calibration" , sizeof (label_text ));
1777
+ } else if (ctx -> current_calibration_phase == GYRO_CALIBRATION_PHASE_NOISE_PROFILING ) {
1778
+ SDL_snprintf (label_text , sizeof (label_text ), "Noise Progress: %3.0f%% " , ctx -> calibration_phase_progress_fraction * 100.0f );
1779
+ } else if (ctx -> current_calibration_phase == GYRO_CALIBRATION_PHASE_DRIFT_PROFILING ) {
1780
+ SDL_snprintf (label_text , sizeof (label_text ), "Drift Progress: %3.0f%% " , ctx -> calibration_phase_progress_fraction * 100.0f );
1781
+ } else if (ctx -> current_calibration_phase == GYRO_CALIBRATION_PHASE_COMPLETE ) {
1782
+ SDL_strlcpy (label_text , "Recalibrate Gyro" , sizeof (label_text ));
1776
1783
}
1777
1784
1778
1785
SetGamepadButtonLabel (start_calibration_button , label_text );
1779
1786
SetGamepadButtonArea (start_calibration_button , & recalibrate_button_area );
1780
- RenderGamepadButton (start_calibration_button );
1787
+ RenderGamepadButton (start_calibration_button );
1781
1788
1782
- /* Above button */
1783
- SDL_strlcpy (label_text , "Gyro Orientation:" , sizeof (label_text ));
1784
- SDLTest_DrawString (ctx -> renderer , recalibrate_button_area .x , recalibrate_button_area .y - new_line_height , label_text );
1785
-
1786
- if (!bHasCachedDriftSolution ) {
1789
+ const float flAbsoluteMaxAccelerationG = 0.125f ;
1790
+ bool bExtremeNoise = ctx -> accelerometer_noise_sq > (flAbsoluteMaxAccelerationG * flAbsoluteMaxAccelerationG );
1791
+ /* Explicit warning message if we detect too much movement */
1792
+ if (ctx -> current_calibration_phase == GYRO_CALIBRATION_PHASE_OFF ) {
1793
+
1794
+ if (bExtremeNoise )
1795
+ {
1796
+ SDL_strlcpy (label_text , "GamePad Must Be Still" , sizeof (label_text ));
1797
+ SDLTest_DrawString (ctx -> renderer , recalibrate_button_area .x , recalibrate_button_area .y + recalibrate_button_area .h + new_line_height , label_text );
1798
+ SDL_strlcpy (label_text , "Place GamePad On Table" , sizeof (label_text ));
1799
+ SDLTest_DrawString (ctx -> renderer , recalibrate_button_area .x , recalibrate_button_area .y + recalibrate_button_area .h + new_line_height * 2 , label_text );
1800
+ }
1801
+ }
1787
1802
1788
- float flNoiseFraction = SDL_clamp (SDL_sqrtf (ctx -> accelerometer_noise_sq ) / ACCELEROMETER_NOISE_THRESHOLD , 0.0f , 1.0f );
1789
- bool bTooMuchNoise = (flNoiseFraction == 1.0f );
1803
+ if (ctx -> current_calibration_phase == GYRO_CALIBRATION_PHASE_NOISE_PROFILING
1804
+ || ctx -> current_calibration_phase == GYRO_CALIBRATION_PHASE_DRIFT_PROFILING )
1805
+ {
1806
+ float flAbsoluteNoiseFraction = SDL_clamp (ctx -> accelerometer_noise_sq / (flAbsoluteMaxAccelerationG * flAbsoluteMaxAccelerationG ), 0.0f , 1.0f );
1807
+ float flAbsoluteToleranceFraction = SDL_clamp (ctx -> accelerometer_noise_tolerance_sq / (flAbsoluteMaxAccelerationG * flAbsoluteMaxAccelerationG ), 0.0f , 1.0f );
1808
+ float flRelativeNoiseFraction = SDL_clamp (ctx -> accelerometer_noise_sq / ctx -> accelerometer_noise_tolerance_sq , 0.0f , 1.0f );
1809
+ bool bTooMuchNoise = (flAbsoluteNoiseFraction == 1.0f );
1790
1810
1791
1811
float noise_bar_height = gamepad_display -> button_height ;
1792
1812
SDL_FRect noise_bar_rect ;
@@ -1795,21 +1815,35 @@ void RenderGyroDriftCalibrationButton(GyroDisplay *ctx, GamepadDisplay *gamepad_
1795
1815
noise_bar_rect .w = recalibrate_button_area .w ;
1796
1816
noise_bar_rect .h = noise_bar_height ;
1797
1817
1818
+ //SDL_strlcpy(label_text, "Place GamePad On Table", sizeof(label_text));
1819
+ SDL_snprintf (label_text , sizeof (label_text ), "Noise Tolerance: %3.3fG " , SDL_sqrtf (ctx -> accelerometer_noise_tolerance_sq ) );
1820
+ SDLTest_DrawString (ctx -> renderer , recalibrate_button_area .x , recalibrate_button_area .y + recalibrate_button_area .h + new_line_height * 2 , label_text );
1821
+
1798
1822
/* Adjust the noise bar rectangle based on the accelerometer noise value */
1799
1823
1800
- float noise_bar_fill_width = flNoiseFraction * noise_bar_rect .w ; /* Scale the width based on the noise value */
1824
+ float noise_bar_fill_width = flAbsoluteNoiseFraction * noise_bar_rect .w ; /* Scale the width based on the noise value */
1801
1825
SDL_FRect noise_bar_fill_rect ;
1802
1826
noise_bar_fill_rect .x = noise_bar_rect .x + (noise_bar_rect .w - noise_bar_fill_width ) * 0.5f ;
1803
1827
noise_bar_fill_rect .y = noise_bar_rect .y ;
1804
1828
noise_bar_fill_rect .w = noise_bar_fill_width ;
1805
1829
noise_bar_fill_rect .h = noise_bar_height ;
1806
1830
1807
- /* Set the color based on the noise value */
1808
- Uint8 red = (Uint8 )(flNoiseFraction * 255.0f );
1809
- Uint8 green = (Uint8 )((1.0f - flNoiseFraction ) * 255.0f );
1831
+ /* Set the color based on the noise value vs the tolerance */
1832
+ Uint8 red = (Uint8 )(flRelativeNoiseFraction * 255.0f );
1833
+ Uint8 green = (Uint8 )((1.0f - flRelativeNoiseFraction ) * 255.0f );
1810
1834
SDL_SetRenderDrawColor (ctx -> renderer , red , green , 0 , 255 ); /* red when high noise, green when low noise */
1811
1835
SDL_RenderFillRect (ctx -> renderer , & noise_bar_fill_rect ); /* draw the filled rectangle */
1812
1836
1837
+ float tolerance_bar_fill_width = flAbsoluteToleranceFraction * noise_bar_rect .w ; /* Scale the width based on the noise value */
1838
+ SDL_FRect tolerance_bar_rect ;
1839
+ tolerance_bar_rect .x = noise_bar_rect .x + (noise_bar_rect .w - tolerance_bar_fill_width ) * 0.5f ;
1840
+ tolerance_bar_rect .y = noise_bar_rect .y ;
1841
+ tolerance_bar_rect .w = tolerance_bar_fill_width ;
1842
+ tolerance_bar_rect .h = noise_bar_height ;
1843
+
1844
+ SDL_SetRenderDrawColor (ctx -> renderer , 128 , 128 , 0 , 255 );
1845
+ SDL_RenderRect (ctx -> renderer , & tolerance_bar_rect ); /* draw the tolerance rectangle */
1846
+
1813
1847
SDL_SetRenderDrawColor (ctx -> renderer , 100 , 100 , 100 , 255 ); /* gray box */
1814
1848
SDL_RenderRect (ctx -> renderer , & noise_bar_rect ); /* draw the outline rectangle */
1815
1849
@@ -1828,7 +1862,7 @@ void RenderGyroDriftCalibrationButton(GyroDisplay *ctx, GamepadDisplay *gamepad_
1828
1862
progress_bar_rect .h = BUTTON_PADDING * 0.5f ;
1829
1863
1830
1864
/* Adjust the drift bar rectangle based on the drift calibration progress fraction */
1831
- float drift_bar_fill_width = bTooMuchNoise ? 1.0f : ctx -> drift_calibration_progress_frac * progress_bar_rect .w ;
1865
+ float drift_bar_fill_width = bTooMuchNoise ? 1.0f : ctx -> calibration_phase_progress_fraction * progress_bar_rect .w ;
1832
1866
SDL_FRect progress_bar_fill ;
1833
1867
progress_bar_fill .x = progress_bar_rect .x ;
1834
1868
progress_bar_fill .y = progress_bar_rect .y ;
@@ -1947,14 +1981,14 @@ void RenderGyroDisplay(GyroDisplay *ctx, GamepadDisplay *gamepadElements, SDL_Ga
1947
1981
SDL_GetRenderDrawColor (ctx -> renderer , & r , & g , & b , & a );
1948
1982
1949
1983
RenderSensorTimingInfo (ctx , gamepadElements );
1950
-
1951
1984
RenderGyroDriftCalibrationButton (ctx , gamepadElements );
1952
1985
1953
- bool bHasCachedDriftSolution = BHasCachedGyroDriftSolution ( ctx );
1954
- if (bHasCachedDriftSolution ) {
1986
+ /* Render Gyro calibration phases */
1987
+ if (ctx -> current_calibration_phase == GYRO_CALIBRATION_PHASE_COMPLETE ) {
1955
1988
float bottom = RenderEulerReadout (ctx , gamepadElements );
1956
1989
RenderGyroGizmo (ctx , gamepad , bottom );
1957
1990
}
1991
+
1958
1992
SDL_SetRenderDrawColor (ctx -> renderer , r , g , b , a );
1959
1993
}
1960
1994
0 commit comments