LCOV - code coverage report
Current view: top level - AP_InertialSensor - AP_InertialSensor_SITL.cpp (source / functions) Hit Total Coverage
Test: lcov.info Lines: 207 306 67.6 %
Date: 2026-09-09 11:02:08 Functions: 12 18 66.7 %

          Line data    Source code
       1             : #include <AP_HAL/AP_HAL.h>
       2             : #include "AP_InertialSensor_SITL.h"
       3             : #include <AP_Logger/AP_Logger.h>
       4             : #include <SITL/SITL.h>
       5             : #include <AP_Filesystem/AP_Filesystem.h>
       6             : 
       7             : #if AP_SIM_INS_ENABLED
       8             : 
       9             : const extern AP_HAL::HAL& hal;
      10             : 
      11        4177 : AP_InertialSensor_SITL::AP_InertialSensor_SITL(AP_InertialSensor &imu, const uint16_t sample_rates[]) :
      12             :     AP_InertialSensor_Backend(imu),
      13        4177 :     gyro_sample_hz(sample_rates[0]),
      14        4177 :     accel_sample_hz(sample_rates[1])
      15             : {
      16        4177 : }
      17             : 
      18             : /*
      19             :   detect the sensor
      20             :  */
      21        4177 : AP_InertialSensor_Backend *AP_InertialSensor_SITL::detect(AP_InertialSensor &_imu, const uint16_t sample_rates[])
      22             : {
      23        4177 :     AP_InertialSensor_SITL *sensor = NEW_NOTHROW AP_InertialSensor_SITL(_imu, sample_rates);
      24        4177 :     if (sensor == nullptr) {
      25           0 :         return nullptr;
      26             :     }
      27        4177 :     if (!sensor->init_sensor()) {
      28           0 :         delete sensor;
      29           0 :         return nullptr;
      30             :     }
      31        4177 :     return sensor;
      32             : }
      33             : 
      34        4177 : bool AP_InertialSensor_SITL::init_sensor(void)
      35             : {
      36        4177 :     sitl = AP::sitl();
      37        4177 :     if (sitl == nullptr) {
      38           0 :         return false;
      39             :     }
      40        4177 :     return true;
      41             : }
      42             : 
      43             : // calculate a noisy noise component
      44   506668140 : static float calculate_noise(float noise, float noise_variation) {
      45   506668140 :     return noise * (1.0f + noise_variation * rand_float());
      46             : }
      47             : 
      48  2330818600 : float AP_InertialSensor_SITL::get_temperature(void)
      49             : {
      50             : #if HAL_INS_TEMPERATURE_CAL_ENABLE
      51  2330818600 :     if (!is_zero(sitl->imu_temp_fixed)) {
      52             :         // user wants fixed temperature
      53      544698 :         return sitl->imu_temp_fixed;
      54             :     }
      55  2330273902 :     uint32_t now = AP_HAL::millis();
      56  2330273902 :     if (temp_start_ms == 0) {
      57        4177 :         temp_start_ms = now;
      58             :     }
      59             :     // follow a curve with given start, end and time constant
      60  2330273902 :     const float tsec = (AP_HAL::millis() - temp_start_ms) * 0.001f;
      61  2330273902 :     const float T0 = sitl->imu_temp_start;
      62  2330273902 :     const float T1 = sitl->imu_temp_end;
      63  2330273902 :     const float tconst = sitl->imu_temp_tconst;
      64  2330273902 :     return T1 - (T1 - T0) * expf(-tsec / tconst);
      65             : #else
      66             :     return 20.0f;
      67             : #endif
      68             : }
      69             : 
      70             : /*
      71             :   generate an accelerometer sample
      72             :  */
      73   275666665 : void AP_InertialSensor_SITL::generate_accel()
      74             : {
      75   275666665 :     Vector3f accel_accum;
      76   275666665 :     uint8_t nsamples = enable_fast_sampling(accel_instance) ? 4 : 1;
      77             : 
      78  1004322527 :     for (uint8_t j = 0; j < nsamples; j++) {
      79             : 
      80   728655862 :         Vector3f accel = Vector3f(sitl->state.xAccel,
      81   728655862 :                                   sitl->state.yAccel,
      82   728655862 :                                   sitl->state.zAccel);
      83             : 
      84             :         // SIM_BRD_TRIM: simulate a rigid board mounting offset by rotating
      85             :         // the sensor frame.  Applied to both accel (here) and gyro so the two
      86             :         // stay consistent, as a real tilted mount would.
      87   728655862 :         const Vector3f &board_trim = sitl->board_trim.get();
      88   728655862 :         if (!board_trim.is_zero()) {
      89     3571670 :             Matrix3f trim_rotation;
      90     3571670 :             trim_rotation.from_euler(board_trim.x, board_trim.y, board_trim.z);
      91     3571670 :             accel = trim_rotation.transposed() * accel;
      92             :         }
      93             : 
      94             :         // add scaling
      95   728655862 :         Vector3f accel_scale = sitl->accel_scale[accel_instance].get();
      96             :         // note that we divide so the SIM_ACC values match the
      97             :         // INS_ACCSCAL values
      98   728655862 :         if (!is_zero(accel_scale.x)) {
      99      393099 :             accel.x /= accel_scale.x;
     100             :         }
     101   728655862 :         if (!is_zero(accel_scale.y)) {
     102      392138 :             accel.y /= accel_scale.y;
     103             :         }
     104   728655862 :         if (!is_zero(accel_scale.z)) {
     105      392042 :             accel.z /= accel_scale.z;
     106             :         }
     107             : 
     108             :         // apply bias
     109   728655862 :         const Vector3f &accel_bias = sitl->accel_bias[accel_instance].get();
     110   728655862 :         accel += accel_bias;
     111             : 
     112             :         // minimum noise levels are 2 bits, but averaged over many
     113             :         // samples, giving around 0.01 m/s/s
     114   728655862 :         float accel_noise = 0.01f;
     115   728655862 :         float noise_variation = 0.05f;
     116             :         // this smears the individual motor peaks somewhat emulating physical motors
     117   728655862 :         float freq_variation = 0.12f;
     118             : 
     119             :         // add in sensor noise
     120   728655862 :         accel += Vector3f{rand_float(), rand_float(), rand_float()} * accel_noise;
     121             : 
     122   728655862 :         bool motors_on = sitl->throttle > sitl->ins_noise_throttle_min;
     123             : 
     124             :         // on a real 180mm copter gyro noise varies between 0.8-4 m/s/s for throttle 0.2-0.8
     125             :         // giving a accel noise variation of 5.33 m/s/s over the full throttle range
     126   728655862 :         if (motors_on) {
     127             :             // add extra noise when the motors are on
     128   425797318 :             accel_noise = sitl->accel_noise[accel_instance];
     129             :         }
     130             : 
     131             :         // VIB_FREQ is a static vibration applied to each axis
     132   728655862 :         const Vector3f &vibe_freq = sitl->vibe_freq;
     133             : 
     134   728655862 :         if (!vibe_freq.is_zero() && motors_on) {
     135     5470023 :             accel.x += sinf(accel_time * 2 * M_PI * vibe_freq.x) * calculate_noise(accel_noise, noise_variation);
     136     5470023 :             accel.y += sinf(accel_time * 2 * M_PI * vibe_freq.y) * calculate_noise(accel_noise, noise_variation);
     137     5470023 :             accel.z += sinf(accel_time * 2 * M_PI * vibe_freq.z) * calculate_noise(accel_noise, noise_variation);
     138     5470023 :             accel_time += 1.0f / (accel_sample_hz * nsamples);
     139             :         }
     140             : 
     141             :         // VIB_MOT_MAX is a rpm-scaled vibration applied to each axis
     142   728655862 :         if (!is_zero(sitl->vibe_motor) && motors_on) {
     143     9668776 :             uint32_t mask = sitl->state.motor_mask;
     144             :             uint8_t mbit;
     145    52854509 :             while ((mbit = __builtin_ffs(mask)) != 0) {
     146    43185733 :                 const uint8_t motor = mbit-1;
     147    43185733 :                 mask &= ~(1U<<motor);
     148    43185733 :                 uint32_t harmonics = uint32_t(sitl->vibe_motor_harmonics);
     149    43185733 :                 const float base_freq = calculate_noise(sitl->state.rpm[motor] / 60.0f, freq_variation);
     150    86371466 :                 while (harmonics != 0) {
     151    43185733 :                     const uint8_t bit = __builtin_ffs(harmonics);
     152    43185733 :                     harmonics &= ~(1U<<(bit-1U));
     153    43185733 :                     const float phase = accel_motor_phase[motor] * float(bit);
     154    43185733 :                     accel.x += sinf(phase) * calculate_noise(accel_noise * sitl->vibe_motor_scale, noise_variation);
     155    43185733 :                     accel.y += sinf(phase) * calculate_noise(accel_noise * sitl->vibe_motor_scale, noise_variation);
     156    43185733 :                     accel.z += sinf(phase) * calculate_noise(accel_noise * sitl->vibe_motor_scale, noise_variation);
     157             :                 }
     158    43185733 :                 const float phase_incr = base_freq * 2 * M_PI / (accel_sample_hz * nsamples);
     159    43185733 :                 accel_motor_phase[motor] = wrap_PI(accel_motor_phase[motor] + phase_incr);
     160             :             }
     161             :         }
     162             : 
     163             :         // correct for the acceleration due to the IMU position offset and angular acceleration
     164             :         // correct for the centripetal acceleration
     165             :         // only apply corrections to first accelerometer
     166   728655862 :         Vector3f pos_offset = sitl->imu_pos_offset;
     167   728655862 :         if (!pos_offset.is_zero()) {
     168             :             // calculate sensed acceleration due to lever arm effect
     169             :             // Note: the % operator has been overloaded to provide a cross product
     170           0 :             Vector3f angular_accel = Vector3f(radians(sitl->state.angAccel.x), radians(sitl->state.angAccel.y), radians(sitl->state.angAccel.z));
     171           0 :             Vector3f lever_arm_accel = angular_accel % pos_offset;
     172             : 
     173             :             // calculate sensed acceleration due to centripetal acceleration
     174           0 :             Vector3f angular_rate = Vector3f(radians(sitl->state.rollRate), radians(sitl->state.pitchRate), radians(sitl->state.yawRate));
     175           0 :             Vector3f centripetal_accel = angular_rate % (angular_rate % pos_offset);
     176             : 
     177             :             // apply corrections
     178           0 :             accel += lever_arm_accel + centripetal_accel;
     179             :         }
     180             : 
     181   728655862 :         if (fabsf(sitl->accel_fail[accel_instance]) > 1.0e-6f) {
     182           0 :             accel.x = accel.y = accel.z = sitl->accel_fail[accel_instance];
     183             :         }
     184             : 
     185             : #if HAL_INS_TEMPERATURE_CAL_ENABLE
     186   728655862 :         const float T = get_temperature();
     187   728655862 :         sitl->imu_tcal[gyro_instance].sitl_apply_accel(T, accel);
     188             : #endif
     189             : 
     190   728655862 :         _notify_new_accel_sensor_rate_sample(accel_instance, accel);
     191             : 
     192             : #if AP_SIM_INS_FILE_ENABLED
     193   728655862 :         if (sitl->accel_file_rw == SITL::SIM::INSFileMode::INS_FILE_WRITE) {
     194           0 :             write_accel_to_file(accel);
     195             :         }
     196             : #endif
     197   728655862 :         accel_accum += accel;
     198             :     }
     199             : 
     200   275666665 :     accel_accum /= nsamples;
     201             : 
     202   275666665 :     accel_accum.rotate(sitl->imu_orientation);
     203             : 
     204   275666665 :     _rotate_and_correct_accel(accel_instance, accel_accum);
     205   275666665 :     _notify_new_accel_raw_sample(accel_instance, accel_accum, AP_HAL::micros64());
     206             : 
     207   275666665 :     _publish_temperature(accel_instance, get_temperature());
     208   275666665 : }
     209             : 
     210             : /*
     211             :   generate a gyro sample
     212             :  */
     213   269614695 : void AP_InertialSensor_SITL::generate_gyro()
     214             : {
     215   269614695 :     Vector3f gyro_accum;
     216   269614695 :     uint8_t nsamples = enable_fast_sampling(gyro_instance) ? 8 : 1;
     217             : 
     218   269614695 :     const float _gyro_drift = gyro_drift();
     219  1596110768 :     for (uint8_t j = 0; j < nsamples; j++) {
     220  1326496073 :         float p = radians(sitl->state.rollRate) + _gyro_drift;
     221  1326496073 :         float q = radians(sitl->state.pitchRate) + _gyro_drift;
     222  1326496073 :         float r = radians(sitl->state.yawRate) + _gyro_drift;
     223             : 
     224             :         // minimum gyro noise is less than 1 bit
     225  1326496073 :         float gyro_noise = radians(0.04f);
     226  1326496073 :         constexpr float noise_variation = 0.05f;
     227             :         // this smears the individual motor peaks somewhat emulating physical motors
     228  1326496073 :         constexpr float freq_variation = 0.12f;
     229             :         // add in sensor noise
     230  1326496073 :         p += gyro_noise * rand_float();
     231  1326496073 :         q += gyro_noise * rand_float();
     232  1326496073 :         r += gyro_noise * rand_float();
     233             : 
     234  1326496073 :         bool motors_on = sitl->throttle > sitl->ins_noise_throttle_min;
     235             :         // on a real 180mm copter gyro noise varies between 0.2-0.4 rad/s for throttle 0.2-0.8
     236             :         // giving a gyro noise variation of 0.33 rad/s or 20deg/s over the full throttle range
     237  1326496073 :         if (motors_on) {
     238             :             // add extra noise when the motors are on
     239   774730280 :             gyro_noise = radians(sitl->gyro_noise[gyro_instance]) * sitl->throttle;
     240             :         }
     241             : 
     242             :         // VIB_FREQ is a static vibration applied to each axis
     243  1326496073 :         const Vector3f &vibe_freq = sitl->vibe_freq;
     244             : 
     245  1326496073 :         if (vibe_freq.is_zero() && is_zero(sitl->vibe_motor)) {
     246             :             // no rpm noise, so add in background noise if any
     247  1301708601 :             p += gyro_noise * rand_float();
     248  1301708601 :             q += gyro_noise * rand_float();
     249  1301708601 :             r += gyro_noise * rand_float();
     250             :         }
     251             : 
     252  1326496073 :         if (!vibe_freq.is_zero() && motors_on) {
     253     8963001 :             p += sinf(gyro_time * 2 * M_PI * vibe_freq.x) * calculate_noise(gyro_noise, noise_variation);
     254     8963001 :             q += sinf(gyro_time * 2 * M_PI * vibe_freq.y) * calculate_noise(gyro_noise, noise_variation);
     255     8963001 :             r += sinf(gyro_time * 2 * M_PI * vibe_freq.z) * calculate_noise(gyro_noise, noise_variation);
     256     8963001 :             gyro_time += 1.0f / (gyro_sample_hz * nsamples);
     257             :         }
     258             : 
     259             :         // VIB_MOT_MAX is a rpm-scaled vibration applied to each axis
     260  1326496073 :         if (!is_zero(sitl->vibe_motor) && motors_on) {
     261    16106052 :             uint32_t mask = sitl->state.motor_mask;
     262             :             uint8_t mbit;
     263    88762586 :             while ((mbit = __builtin_ffs(mask)) != 0) {
     264    72656534 :                 const uint8_t motor = mbit-1;
     265    72656534 :                 mask &= ~(1U<<motor);
     266    72656534 :                 uint32_t harmonics = uint32_t(sitl->vibe_motor_harmonics);
     267    72656534 :                 const float base_freq = calculate_noise(sitl->state.rpm[motor] / 60.0f, freq_variation);
     268   145313068 :                 while (harmonics != 0) {
     269    72656534 :                     const uint8_t bit = __builtin_ffs(harmonics);
     270    72656534 :                     harmonics &= ~(1U<<(bit-1U));
     271    72656534 :                     const float phase = gyro_motor_phase[motor] * float(bit);
     272    72656534 :                     p += sinf(phase) * calculate_noise(gyro_noise * sitl->vibe_motor_scale, noise_variation);
     273    72656534 :                     q += sinf(phase) * calculate_noise(gyro_noise * sitl->vibe_motor_scale, noise_variation);
     274    72656534 :                     r += sinf(phase) * calculate_noise(gyro_noise * sitl->vibe_motor_scale, noise_variation);
     275             :                 }
     276    72656534 :                 const float phase_incr = base_freq * 2 * M_PI / (gyro_sample_hz * nsamples);
     277    72656534 :                 gyro_motor_phase[motor] = wrap_PI(gyro_motor_phase[motor] + phase_incr);
     278             :             }
     279             :         }
     280             : 
     281  1326496073 :         Vector3f gyro {p, q, r};
     282             : 
     283             :         // SIM_BRD_TRIM: rigid board mounting offset, same rotation as accel:
     284  1326496073 :         const Vector3f &board_trim = sitl->board_trim.get();
     285  1326496073 :         if (!board_trim.is_zero()) {
     286     6518658 :             Matrix3f trim_rotation;
     287     6518658 :             trim_rotation.from_euler(board_trim.x, board_trim.y, board_trim.z);
     288     6518658 :             gyro = trim_rotation.transposed() * gyro;
     289             :         }
     290             : 
     291             : #if HAL_INS_TEMPERATURE_CAL_ENABLE
     292  1326496073 :         sitl->imu_tcal[gyro_instance].sitl_apply_gyro(get_temperature(), gyro);
     293             : #endif
     294             : 
     295             :         // add in gyro scaling
     296  1326496073 :         const Vector3f &scale = sitl->gyro_scale[gyro_instance];
     297  1326496073 :         gyro.x *= (1 + scale.x * 0.01f);
     298  1326496073 :         gyro.y *= (1 + scale.y * 0.01f);
     299  1326496073 :         gyro.z *= (1 + scale.z * 0.01f);
     300             : 
     301             :         // apply bias
     302  1326496073 :         const Vector3f &gyro_bias = sitl->gyro_bias[gyro_instance].get();
     303  1326496073 :         gyro += gyro_bias;
     304             : 
     305  1326496073 :         gyro_accum += gyro;
     306  1326496073 :         _notify_new_gyro_sensor_rate_sample(gyro_instance, gyro);
     307             : 
     308             : #if AP_SIM_INS_FILE_ENABLED
     309  1326496073 :         if (sitl->gyro_file_rw == SITL::SIM::INSFileMode::INS_FILE_WRITE) {
     310     3166744 :             write_gyro_to_file(gyro);
     311             :         }
     312             : #endif
     313             :     }
     314   269614695 :     gyro_accum /= nsamples;
     315             : 
     316   269614695 :     gyro_accum.rotate(sitl->imu_orientation);
     317             : 
     318   269614695 :     _rotate_and_correct_gyro(gyro_instance, gyro_accum);
     319   269614695 :     _notify_new_gyro_raw_sample(gyro_instance, gyro_accum, AP_HAL::micros64());
     320   269614695 : }
     321             : 
     322   367689203 : void AP_InertialSensor_SITL::timer_update(void)
     323             : {
     324             :     // on some simulations (RealFlight) the aircraft sim decides when a new sample is available.
     325   367689203 :     if (sitl->state.flightaxis_imu_frame_num > 0) {
     326           0 :         update_from_frame();
     327           0 :         return;
     328             :     }
     329             : 
     330   367689203 :     uint64_t now = AP_HAL::micros64();
     331             : #if 0
     332             :     // insert a 1s pause in IMU data. This triggers a pause in EK2
     333             :     // processing that leads to some interesting issues
     334             :     if (now > 5e6 && now < 6e6) {
     335             :         return;
     336             :     }
     337             : #endif
     338   367689203 :     if (sitl == nullptr) {
     339           0 :         return;
     340             :     }
     341             : 
     342   367689203 :     if (now >= next_accel_sample) {
     343   275666665 :         if (((1U << accel_instance) & sitl->accel_fail_mask) == 0) {
     344             : #if AP_SIM_INS_FILE_ENABLED
     345   275666665 :             if (sitl->accel_file_rw == SITL::SIM::INSFileMode::INS_FILE_READ
     346   275666665 :                 || sitl->accel_file_rw == SITL::SIM::INSFileMode::INS_FILE_READ_STOP_ON_EOF) {
     347           0 :                 read_accel_from_file();
     348             :             } else
     349             : #endif
     350   275666665 :             generate_accel();
     351   275666665 :             if (next_accel_sample == 0) {
     352        4177 :                 next_accel_sample = now + 1000000UL / accel_sample_hz;
     353             :             } else {
     354   551334957 :                 while (now >= next_accel_sample) {
     355   275672469 :                     next_accel_sample += 1000000UL / accel_sample_hz;
     356             :                 }
     357             :             }
     358             :         }
     359             :     }
     360   367689203 :     if (now >= next_gyro_sample) {
     361   269614695 :         if (((1U << gyro_instance) & sitl->gyro_fail_mask) == 0) {
     362             : #if AP_SIM_INS_FILE_ENABLED
     363   269614695 :             if (sitl->gyro_file_rw == SITL::SIM::INSFileMode::INS_FILE_READ
     364   269614695 :                 || sitl->gyro_file_rw == SITL::SIM::INSFileMode::INS_FILE_READ_STOP_ON_EOF) {
     365           0 :                 read_gyro_from_file();
     366             :             } else
     367             : #endif
     368   269614695 :             generate_gyro();
     369             : 
     370   269614695 :             if (next_gyro_sample == 0) {
     371        4177 :                 next_gyro_sample = now + 1000000UL / gyro_sample_hz;
     372             :             } else {
     373   539229218 :                 while (now >= next_gyro_sample) {
     374   269618700 :                     next_gyro_sample += 1000000UL / gyro_sample_hz;
     375             :                 }
     376             :             }
     377             :         }
     378             :     }
     379             : }
     380             : 
     381           0 : void AP_InertialSensor_SITL::update_from_frame(void)
     382             : {
     383           0 :     if (sitl == nullptr) {
     384           0 :         return;
     385             :     }
     386             : 
     387           0 :     if (flightaxis_imu_frame_num == sitl->state.flightaxis_imu_frame_num) {
     388           0 :         return;
     389             :     }
     390             : 
     391           0 :     flightaxis_imu_frame_num = sitl->state.flightaxis_imu_frame_num;
     392             : 
     393           0 :     if (((1U << accel_instance) & sitl->accel_fail_mask) == 0) {
     394           0 :         generate_accel();
     395             :     }
     396           0 :     if (((1U << gyro_instance) & sitl->gyro_fail_mask) == 0) {
     397           0 :         generate_gyro();
     398             :     }
     399             : }
     400             : 
     401   269614695 : float AP_InertialSensor_SITL::gyro_drift(void) const
     402             : {
     403   534638203 :     if (is_zero(sitl->drift_speed) ||
     404   265023508 :         is_zero(sitl->drift_time)) {
     405     4591196 :         return 0;
     406             :     }
     407   265023499 :     double period  = sitl->drift_time * 2;
     408   265023499 :     double minutes = fmod(AP_HAL::micros64() / 60.0e6, period);
     409   265023499 :     if (minutes < period/2) {
     410   218397667 :         return minutes * radians(sitl->drift_speed);
     411             :     }
     412    46625832 :     return (period - minutes) * radians(sitl->drift_speed);
     413             : }
     414             : 
     415             : 
     416    83728473 : bool AP_InertialSensor_SITL::update(void) 
     417             : {
     418    83728473 :     update_accel(accel_instance);
     419    83728473 :     update_gyro(gyro_instance);
     420    83728473 :     return true;
     421             : }
     422             : 
     423             : uint8_t AP_InertialSensor_SITL::bus_id = 0;
     424             : 
     425        4177 : void AP_InertialSensor_SITL::start()
     426             : {
     427        4177 :     if (!_imu.register_gyro(gyro_instance, gyro_sample_hz,
     428        8354 :                             AP_HAL::Device::make_bus_id(AP_HAL::Device::BUS_TYPE_SITL, bus_id, 1, DEVTYPE_SITL)) ||
     429        4177 :         !_imu.register_accel(accel_instance, accel_sample_hz,
     430             :                              AP_HAL::Device::make_bus_id(AP_HAL::Device::BUS_TYPE_SITL, bus_id, 2, DEVTYPE_SITL))) {
     431           0 :         return;
     432             :     }
     433        4177 :     bus_id++;
     434        4177 :     hal.scheduler->register_timer_process(FUNCTOR_BIND_MEMBER(&AP_InertialSensor_SITL::timer_update, void));
     435             : 
     436             : #if AP_SIM_INS_FILE_ENABLED
     437        4177 :     if (sitl->accel_file_rw == SITL::SIM::INSFileMode::INS_FILE_READ
     438        4177 :         || sitl->accel_file_rw == SITL::SIM::INSFileMode::INS_FILE_READ_STOP_ON_EOF) {
     439           0 :         hal.console->printf("Reading accel data from file for IMU[%u]\n", accel_instance);
     440             :     }
     441        4177 :     if (sitl->gyro_file_rw == SITL::SIM::INSFileMode::INS_FILE_READ
     442        4177 :         || sitl->gyro_file_rw == SITL::SIM::INSFileMode::INS_FILE_READ) {
     443           0 :         hal.console->printf("Reading gyro data from file for IMU[%u]\n", gyro_instance);
     444             :     }
     445             : #endif
     446             : }
     447             : 
     448             : /*
     449             :   temporary method to use file as GPS data
     450             :  */
     451             : #if AP_SIM_INS_FILE_ENABLED
     452           0 : void AP_InertialSensor_SITL::read_gyro_from_file()
     453             : {
     454           0 :     if (gyro_fd == -1) {
     455             :         char namebuf[32];
     456           0 :         snprintf(namebuf, sizeof(namebuf), "/tmp/gyro%d.dat", gyro_instance);
     457           0 :         gyro_fd = AP::FS().open(namebuf, O_RDONLY);
     458           0 :         if (gyro_fd == -1) {
     459           0 :             AP_HAL::panic("gyro data file %s not found", namebuf);
     460             :         }
     461             :     }
     462             : 
     463             :     float buf[8 * 3 * sizeof(float)];
     464             : 
     465           0 :     uint8_t nsamples = enable_fast_sampling(gyro_instance) ? 8 : 1;
     466           0 :     ssize_t ret = ::read(gyro_fd, buf, nsamples * 3 * sizeof(float));
     467           0 :     if (ret == (ssize_t)(nsamples * 3 * sizeof(float))) {
     468           0 :         read_gyro(buf, nsamples);
     469             :     }
     470             : 
     471           0 :     if (ret <= 0) {
     472           0 :         if (sitl->gyro_file_rw == SITL::SIM::INSFileMode::INS_FILE_READ_STOP_ON_EOF) {
     473             : #if HAL_LOGGING_ENABLED
     474             :             //stop logging
     475           0 :             if (AP_Logger::get_singleton()) {
     476           0 :                 AP::logger().StopLogging();
     477             :             }
     478             : #endif
     479           0 :             exit(0);
     480             :         }
     481           0 :         lseek(gyro_fd, 0, SEEK_SET);
     482             :     }
     483           0 : }
     484             : 
     485           0 : void AP_InertialSensor_SITL::read_gyro(const float* buf, uint8_t nsamples)
     486             : {
     487           0 :     Vector3f gyro_accum;
     488             : 
     489           0 :     for (uint8_t j = 0; j < nsamples; j++) {
     490           0 :         float p = buf[j*3];
     491           0 :         float q = buf[j*3+1];
     492           0 :         float r = buf[j*3+2];
     493             : 
     494           0 :         Vector3f gyro = Vector3f(p, q, r);
     495             : 
     496           0 :         _notify_new_gyro_sensor_rate_sample(gyro_instance, gyro);
     497             : 
     498           0 :         gyro_accum += gyro;
     499             :     }
     500           0 :     gyro_accum /= nsamples;
     501           0 :     _rotate_and_correct_gyro(gyro_instance, gyro_accum);
     502           0 :     _notify_new_gyro_raw_sample(gyro_instance, gyro_accum, AP_HAL::micros64());
     503           0 : }
     504             : 
     505     3166744 : void AP_InertialSensor_SITL::write_gyro_to_file(const Vector3f& gyro)
     506             : {
     507     3166744 :     if (gyro_fd == -1) {
     508             :         char namebuf[32];
     509           8 :         snprintf(namebuf, sizeof(namebuf), "/tmp/gyro%d.dat", gyro_instance);
     510           8 :         gyro_fd = open(namebuf, O_WRONLY|O_TRUNC|O_CREAT, S_IRWXU|S_IRGRP|S_IROTH);
     511             :     }
     512             : 
     513     3166744 :     float buf[] { gyro.x, gyro.y, gyro.z };
     514             : 
     515     3166744 :     if (::write(gyro_fd, (void*)buf, sizeof(float) * 3) < 0) {
     516           0 :         ::printf("Could not write to file\n");
     517             :     }
     518     3166744 : }
     519             : 
     520           0 : void AP_InertialSensor_SITL::read_accel_from_file()
     521             : {
     522           0 :     if (accel_fd == -1) {
     523             :         char namebuf[32];
     524           0 :         snprintf(namebuf, sizeof(namebuf), "/tmp/accel%d.dat", accel_instance);
     525           0 :         accel_fd = open(namebuf, O_RDONLY|O_CLOEXEC);
     526           0 :         if (accel_fd == -1) {
     527           0 :             AP_HAL::panic("accel data file %s not found", namebuf);
     528             :         }
     529             :     }
     530             : 
     531             :     float buf[4*3*sizeof(float)];
     532             : 
     533           0 :     uint8_t nsamples = enable_fast_sampling(accel_instance) ? 4 : 1;
     534           0 :     ssize_t ret = ::read(accel_fd, buf, nsamples * 3 * sizeof(float));
     535           0 :     if (ret == (ssize_t)(nsamples * 3 * sizeof(float))) {
     536           0 :         read_accel(buf, nsamples);
     537             :     }
     538             : 
     539           0 :     if (ret <= 0) {
     540           0 :         if (sitl->accel_file_rw == SITL::SIM::INSFileMode::INS_FILE_READ_STOP_ON_EOF) {
     541             : #if HAL_LOGGING_ENABLED
     542             :             //stop logging
     543           0 :             if (AP_Logger::get_singleton()) {
     544           0 :                 AP::logger().StopLogging();
     545             :             }
     546             : #endif
     547           0 :             exit(0);
     548             :         }
     549           0 :         lseek(accel_fd, 0, SEEK_SET);
     550             :     }
     551           0 : }
     552             : 
     553           0 : void AP_InertialSensor_SITL::read_accel(const float* buf, uint8_t nsamples)
     554             : {
     555           0 :     Vector3f accel_accum;
     556             : 
     557           0 :     for (uint8_t j = 0; j < nsamples; j++) {
     558           0 :         float p = buf[j*3];
     559           0 :         float q = buf[j*3+1];
     560           0 :         float r = buf[j*3+2];
     561             : 
     562           0 :         Vector3f accel = Vector3f(p, q, r);
     563             : 
     564           0 :         _notify_new_accel_sensor_rate_sample(accel_instance, accel);
     565             : 
     566           0 :         accel_accum += accel;
     567             :     }
     568             : 
     569           0 :     accel_accum /= nsamples;
     570           0 :     _rotate_and_correct_accel(accel_instance, accel_accum);
     571           0 :     _notify_new_accel_raw_sample(accel_instance, accel_accum, AP_HAL::micros64());
     572             : 
     573           0 :     _publish_temperature(accel_instance, get_temperature());
     574           0 : }
     575             : 
     576           0 : void AP_InertialSensor_SITL::write_accel_to_file(const Vector3f& accel)
     577             : {
     578             : 
     579           0 :     if (accel_fd == -1) {
     580             :         char namebuf[32];
     581           0 :         snprintf(namebuf, sizeof(namebuf), "/tmp/accel%d.dat", accel_instance);
     582           0 :         accel_fd = open(namebuf, O_WRONLY|O_TRUNC|O_CREAT, S_IRWXU|S_IRGRP|S_IROTH);
     583             :     }
     584             : 
     585           0 :     float buf[] { accel.x, accel.y, accel.z };
     586             : 
     587           0 :     if (::write(accel_fd, (void*)buf, sizeof(float) * 3) < 0) {
     588           0 :         ::printf("Could not write to file\n");
     589             :     }
     590           0 : }
     591             : 
     592             : #endif  // AP_SIM_INS_FILE_ENABLED
     593             : 
     594             : #endif // AP_SIM_INS_ENABLED

Generated by: LCOV version 1.14