123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225 |
- #include <AP_HAL/AP_HAL.h>
- #include "AP_InertialSensor_SITL.h"
- #include <SITL/SITL.h>
- #include <stdio.h>
- #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; i<INS_SITL_INSTANCES; i++) {
- gyro_instance[i] = _imu.register_gyro(gyro_sample_hz[i],
- AP_HAL::Device::make_bus_id(AP_HAL::Device::BUS_TYPE_SITL, i, 1, DEVTYPE_SITL));
- accel_instance[i] = _imu.register_accel(accel_sample_hz[i],
- AP_HAL::Device::make_bus_id(AP_HAL::Device::BUS_TYPE_SITL, i, 2, DEVTYPE_SITL));
- if (enable_fast_sampling(accel_instance[i])) {
- _set_accel_raw_sample_rate(accel_instance[i], accel_sample_hz[i]*4);
- }
- if (enable_fast_sampling(gyro_instance[i])) {
- _set_gyro_raw_sample_rate(gyro_instance[i], gyro_sample_hz[i]*8);
- }
- }
- hal.scheduler->register_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; i<nsamples; i++) {
- _notify_new_accel_raw_sample(accel_instance[instance], accel);
- }
- }
- /*
- generate a gyro sample
- */
- void AP_InertialSensor_SITL::generate_gyro(uint8_t instance)
- {
- // minimum gyro noise is less than 1 bit
- float gyro_noise = ToRad(0.04f);
-
- if (sitl->motors_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<nsamples; i++) {
- _notify_new_gyro_raw_sample(gyro_instance[instance], gyro);
- }
- }
- void AP_InertialSensor_SITL::timer_update(void)
- {
- uint64_t now = AP_HAL::micros64();
- #if 0
- // insert a 1s pause in IMU data. This triggers a pause in EK2
- // processing that leads to some interesting issues
- if (now > 5e6 && now < 6e6) {
- return;
- }
- #endif
- for (uint8_t i=0; i<INS_SITL_INSTANCES; i++) {
- if (now >= next_accel_sample[i]) {
- if (((1U<<i) & sitl->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<<i) & sitl->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<INS_SITL_INSTANCES; i++) {
- update_accel(accel_instance[i]);
- update_gyro(gyro_instance[i]);
- }
- return true;
- }
- #endif // HAL_BOARD_SITL
|