engine: platform: sdl2: implement continuous background recalibration for gyroscope

This commit is contained in:
Alibek Omarov
2026-04-08 11:31:01 +05:00
parent b8bd906832
commit ffa53f14e5

View File

@@ -52,15 +52,16 @@ static SDL_GameController *g_current_gamepad;
static SDL_GameController **g_gamepads;
static size_t g_num_gamepads;
#define CALIBRATION_TIME 10.0f
#define CALIBRATION_TIME 5.0f
static struct
{
float time;
vec3_t data;
vec3_t calibrated_values;
float data_rate;
int samples;
float time;
vec3_t data;
vec3_t calibrated_values;
float data_rate;
int samples;
qboolean continuous; // true after first successful calibration
} gyrocal;
static void SDLash_RestartCalibration( void )
@@ -77,7 +78,7 @@ static void SDLash_RestartCalibration( void )
if( !gyrocal.data_rate )
gyrocal.data_rate = 10.0f;
Con_Printf( "Starting gyroscope calibration at %g data rate...\n", gyrocal.data_rate );
Con_Printf( S_NOTE "Starting gyroscope calibration at %g data rate for %g seconds...\n", gyrocal.data_rate, CALIBRATION_TIME );
}
static void SDLash_FinalizeCalibration( void )
@@ -87,14 +88,53 @@ static void SDLash_FinalizeCalibration( void )
// we waited for few seconds and got too few samples
if( gyrocal.samples <= min_samples )
{
Joy_SetCalibrationState( JOY_FAILED_TO_CALIBRATE );
Con_Printf( "Calibration failed, got samples %d < %d\n", gyrocal.samples, min_samples );
return;
if( !gyrocal.continuous )
{
Joy_SetCalibrationState( JOY_FAILED_TO_CALIBRATE );
Con_Printf( S_ERROR "Calibration failed, got samples %d < %d\n", gyrocal.samples, min_samples );
gyrocal.time = 0.0f;
return;
}
// Con_Reportf( S_WARN "Continuous calibration: too few samples (%d < %d), retrying\n", gyrocal.samples, min_samples );
}
else
{
VectorScale( gyrocal.data, 1.0f / gyrocal.samples, gyrocal.calibrated_values );
Joy_SetCalibrationState( JOY_CALIBRATED );
if( !gyrocal.continuous )
Con_Printf( "Calibration done. Result: %f %f %f at %d samples\n", gyrocal.calibrated_values[0], gyrocal.calibrated_values[1], gyrocal.calibrated_values[2], gyrocal.samples );
// else
// Con_Reportf( "Continuous calibration done. Result: %f %f %f at %d samples\n", gyrocal.calibrated_values[0], gyrocal.calibrated_values[1], gyrocal.calibrated_values[2], gyrocal.samples );
gyrocal.continuous = true;
}
VectorScale( gyrocal.data, 1.0f / gyrocal.samples, gyrocal.calibrated_values );
Joy_SetCalibrationState( JOY_CALIBRATED );
Con_Printf( "Calibration done. Result: %f %f %f at %d samples\n", gyrocal.calibrated_values[0], gyrocal.calibrated_values[1], gyrocal.calibrated_values[2], gyrocal.samples );
// schedule next calibration window
VectorClear( gyrocal.data );
gyrocal.samples = 0;
gyrocal.time = host.realtime + CALIBRATION_TIME;
}
static void SDLash_AccumulateCalibrationData( vec3_t data )
{
// for continuous background calibration only listen for noise
// by comparing it with calibrated values
//
// for first calibration this might be hurtful as device might
// output offset data
if( gyrocal.continuous )
{
vec3_t calibrated;
VectorSubtract( data, gyrocal.calibrated_values, calibrated );
if( VectorLength( calibrated ) > 0.1f )
return;
}
VectorAdd( gyrocal.data, data, gyrocal.data );
gyrocal.samples++;
if( !gyrocal.continuous )
Joy_SetCalibrationState( JOY_CALIBRATING );
}
static void SDLash_GameControllerAddMappings( const char *name )
@@ -239,17 +279,13 @@ static void SDLash_GameControllerSensorUpdate( SDL_ControllerSensorEvent sensor
if( gyrocal.time != 0.0f )
{
if( host.realtime > gyrocal.time )
{
SDLash_FinalizeCalibration();
gyrocal.time = 0.0f;
}
else
{
VectorAdd( gyrocal.data, sensor.data, gyrocal.data );
gyrocal.samples++;
Joy_SetCalibrationState( JOY_CALIBRATING );
}
return;
SDLash_AccumulateCalibrationData( sensor.data );
// block gyro events only during initial calibration
if( !gyrocal.continuous )
return;
}
VectorSubtract( sensor.data, gyrocal.calibrated_values, data );