#include #include "AP_InertialSensor_SITL.h" #include #include #if CONFIG_HAL_BOARD == HAL_BOARD_SITL const extern AP_HAL::HAL& hal; AP_InertialSensor_SITL::AP_InertialSensor_SITL(AP_InertialSensor &imu) : AP_InertialSensor_Backend(imu) { } /* detect the sensor */ AP_InertialSensor_Backend *AP_InertialSensor_SITL::detect(AP_InertialSensor &_imu) { AP_InertialSensor_SITL *sensor = new AP_InertialSensor_SITL(_imu); if (sensor == nullptr) { return nullptr; } if (!sensor->init_sensor()) { delete sensor; return nullptr; } return sensor; } bool AP_InertialSensor_SITL::init_sensor(void) { sitl = AP::sitl(); if (sitl == nullptr) { return false; } // grab the used instances for (uint8_t i=0; iregister_timer_process(FUNCTOR_BIND_MEMBER(&AP_InertialSensor_SITL::timer_update, void)); return true; } /* generate an accelerometer sample */ void AP_InertialSensor_SITL::generate_accel(uint8_t instance) { // minimum noise levels are 2 bits, but averaged over many // samples, giving around 0.01 m/s/s float accel_noise = 0.01f; if (sitl->motors_on) { // add extra noise when the motors are on accel_noise += instance==0?sitl->accel_noise:sitl->accel2_noise; } // add accel bias and noise Vector3f accel_bias = instance==0?sitl->accel_bias.get():sitl->accel2_bias.get(); float xAccel = sitl->state.xAccel + accel_bias.x; float yAccel = sitl->state.yAccel + accel_bias.y; float zAccel = sitl->state.zAccel + accel_bias.z; const Vector3f &vibe_freq = sitl->vibe_freq; if (vibe_freq.is_zero()) { xAccel += accel_noise * rand_float(); yAccel += accel_noise * rand_float(); zAccel += accel_noise * rand_float(); } else { float t = AP_HAL::micros() * 1.0e-6f; xAccel += sinf(t * 2 * M_PI * vibe_freq.x) * accel_noise; yAccel += sinf(t * 2 * M_PI * vibe_freq.y) * accel_noise; zAccel += sinf(t * 2 * M_PI * vibe_freq.z) * accel_noise; } // correct for the acceleration due to the IMU position offset and angular acceleration // correct for the centripetal acceleration // only apply corrections to first accelerometer Vector3f pos_offset = sitl->imu_pos_offset; if (!pos_offset.is_zero()) { // calculate sensed acceleration due to lever arm effect // Note: the % operator has been overloaded to provide a cross product Vector3f angular_accel = Vector3f(radians(sitl->state.angAccel.x) , radians(sitl->state.angAccel.y) , radians(sitl->state.angAccel.z)); Vector3f lever_arm_accel = angular_accel % pos_offset; // calculate sensed acceleration due to centripetal acceleration Vector3f angular_rate = Vector3f(radians(sitl->state.rollRate), radians(sitl->state.pitchRate), radians(sitl->state.yawRate)); Vector3f centripetal_accel = angular_rate % (angular_rate % pos_offset); // apply corrections xAccel += lever_arm_accel.x + centripetal_accel.x; yAccel += lever_arm_accel.y + centripetal_accel.y; zAccel += lever_arm_accel.z + centripetal_accel.z; } if (fabsf(sitl->accel_fail) > 1.0e-6f) { xAccel = sitl->accel_fail; yAccel = sitl->accel_fail; zAccel = sitl->accel_fail; } Vector3f accel = Vector3f(xAccel, yAccel, zAccel); _rotate_and_correct_accel(accel_instance[instance], accel); uint8_t nsamples = enable_fast_sampling(accel_instance[instance])?4:1; for (uint8_t i=0; imotors_on) { // add extra noise when the motors are on gyro_noise += ToRad(sitl->gyro_noise); } float p = radians(sitl->state.rollRate) + gyro_drift(); float q = radians(sitl->state.pitchRate) + gyro_drift(); float r = radians(sitl->state.yawRate) + gyro_drift(); const Vector3f &vibe_freq = sitl->vibe_freq; if (vibe_freq.is_zero()) { p += gyro_noise * rand_float(); q += gyro_noise * rand_float(); r += gyro_noise * rand_float(); } else { float t = AP_HAL::micros() * 1.0e-6f; p += sinf(t * 2 * M_PI * vibe_freq.x) * gyro_noise; q += sinf(t * 2 * M_PI * vibe_freq.y) * gyro_noise; r += sinf(t * 2 * M_PI * vibe_freq.z) * gyro_noise; } Vector3f gyro = Vector3f(p, q, r); // add in gyro scaling Vector3f scale = sitl->gyro_scale; gyro.x *= (1 + scale.x*0.01f); gyro.y *= (1 + scale.y*0.01f); gyro.z *= (1 + scale.z*0.01f); _rotate_and_correct_gyro(gyro_instance[instance], gyro); uint8_t nsamples = enable_fast_sampling(gyro_instance[instance])?8:1; for (uint8_t i=0; i 5e6 && now < 6e6) { return; } #endif for (uint8_t i=0; i= next_accel_sample[i]) { if (((1U<accel_fail_mask) == 0) { generate_accel(i); while (now >= next_accel_sample[i]) { next_accel_sample[i] += 1000000UL / accel_sample_hz[i]; } } } if (now >= next_gyro_sample[i]) { if (((1U<gyro_fail_mask) == 0) { generate_gyro(i); while (now >= next_gyro_sample[i]) { next_gyro_sample[i] += 1000000UL / gyro_sample_hz[i]; } } } } } float AP_InertialSensor_SITL::gyro_drift(void) { if (is_zero(sitl->drift_speed) || is_zero(sitl->drift_time)) { return 0; } double period = sitl->drift_time * 2; double minutes = fmod(AP_HAL::micros64() / 60.0e6, period); if (minutes < period/2) { return minutes * ToRad(sitl->drift_speed); } return (period - minutes) * ToRad(sitl->drift_speed); } bool AP_InertialSensor_SITL::update(void) { for (uint8_t i=0; i