예제 #1
0
void nps_sensor_mag_run_step(struct NpsSensorMag* mag, double time, struct DoubleRMat* body_to_imu) {

  if (time < mag->next_update)
    return;
  
  /* transform magnetic field to body frame */
  struct DoubleVect3 h_body;
  FLOAT_QUAT_VMULT(h_body, fdm.ltp_to_body_quat, fdm.ltp_h);
  
  /* transform to imu frame */
  struct DoubleVect3 h_imu;
  MAT33_VECT3_MUL(h_imu, *body_to_imu, h_body );
  
  /* transform to sensor frame */
  struct DoubleVect3 h_sensor;
  MAT33_VECT3_MUL(h_sensor, mag->imu_to_sensor_rmat, h_imu );

  /* compute magnetometer reading */
  MAT33_VECT3_MUL(mag->value, mag->sensitivity, h_sensor);
  VECT3_ADD(mag->value, mag->neutral);
  /* FIXME: ADD error reading */
  
  /* round signal to account for adc discretisation */
  DOUBLE_VECT3_ROUND(mag->value);
  /* saturate                                       */
  //  VECT3_BOUND_CUBE(mag->value, 0, mag->resolution); 
  
  mag->next_update += NPS_MAG_DT;
  mag->data_available = TRUE;
}
예제 #2
0
/**
 *  Incorporate one 3D vector measurement
 */
static inline void update_state(const struct FloatVect3 *i_expected, struct FloatVect3* b_measured, struct FloatVect3* noise) {

  /* converted expected measurement from inertial to body frame */
  struct FloatVect3 b_expected;
  FLOAT_QUAT_VMULT(b_expected, ahrs_impl.ltp_to_imu_quat, *i_expected);

  // S = HPH' + JRJ
  float H[3][6] = {{           0., -b_expected.z,  b_expected.y, 0., 0., 0.},
                   { b_expected.z,            0., -b_expected.x, 0., 0., 0.},
                   {-b_expected.y,  b_expected.x,            0., 0., 0., 0.}};
  float tmp[3][6];
  MAT_MUL(3,6,6, tmp, H, ahrs_impl.P);
  float S[3][3];
  MAT_MUL_T(3,6,3, S, tmp, H);

  /* add the measurement noise */
  S[0][0] += noise->x;
  S[1][1] += noise->y;
  S[2][2] += noise->z;

  float invS[3][3];
  MAT_INV33(invS, S);

  // K = PH'invS
  float tmp2[6][3];
  MAT_MUL_T(6,6,3, tmp2, ahrs_impl.P, H);
  float K[6][3];
  MAT_MUL(6,3,3, K, tmp2, invS);

  // P = (I-KH)P
  float tmp3[6][6];
  MAT_MUL(6,3,6, tmp3, K, H);
  float I6[6][6] = {{ 1., 0., 0., 0., 0., 0. },
                    {  0., 1., 0., 0., 0., 0. },
                    {  0., 0., 1., 0., 0., 0. },
                    {  0., 0., 0., 1., 0., 0. },
                    {  0., 0., 0., 0., 1., 0. },
                    {  0., 0., 0., 0., 0., 1. }};
  float tmp4[6][6];
  MAT_SUB(6,6, tmp4, I6, tmp3);
  float tmp5[6][6];
  MAT_MUL(6,6,6, tmp5, tmp4, ahrs_impl.P);
  memcpy(ahrs_impl.P, tmp5, sizeof(ahrs_impl.P));

  // X = X + Ke
  struct FloatVect3 e;
  VECT3_DIFF(e, *b_measured, b_expected);
  ahrs_impl.gibbs_cor.qx  += K[0][0]*e.x + K[0][1]*e.y + K[0][2]*e.z;
  ahrs_impl.gibbs_cor.qy  += K[1][0]*e.x + K[1][1]*e.y + K[1][2]*e.z;
  ahrs_impl.gibbs_cor.qz  += K[2][0]*e.x + K[2][1]*e.y + K[2][2]*e.z;
  ahrs_impl.gyro_bias.p  += K[3][0]*e.x + K[3][1]*e.y + K[3][2]*e.z;
  ahrs_impl.gyro_bias.q  += K[4][0]*e.x + K[4][1]*e.y + K[4][2]*e.z;
  ahrs_impl.gyro_bias.r  += K[5][0]*e.x + K[5][1]*e.y + K[5][2]*e.z;

}
예제 #3
0
float test_quat(void) {
    struct FloatVect3 u = { 1., 2., 3.};
    FLOAT_VECT3_NORMALIZE(u);
    float angle = RadOfDeg(30.);

    struct FloatQuat q;
    FLOAT_QUAT_OF_AXIS_ANGLE(q, u, angle);
    DISPLAY_FLOAT_QUAT("q ", q);

    struct FloatQuat iq;
    FLOAT_QUAT_INVERT(iq, q);
    DISPLAY_FLOAT_QUAT("iq", iq);

    struct FloatQuat q1;
    FLOAT_QUAT_COMP(q1, q, iq);
    DISPLAY_FLOAT_QUAT("q1", q1);

    struct FloatQuat q2;
    FLOAT_QUAT_COMP(q2, q, iq);
    DISPLAY_FLOAT_QUAT("q2", q2);

    struct FloatQuat qe;
    QUAT_EXPLEMENTARY(qe, q);
    DISPLAY_FLOAT_QUAT("qe", qe);

    struct FloatVect3 a = { 2., 1., 3.};
    DISPLAY_FLOAT_VECT3("a ", a);
    struct FloatVect3 a1;
    FLOAT_QUAT_VMULT(a1, q, a);
    DISPLAY_FLOAT_VECT3("a1", a1);

    struct FloatVect3 a2;
    FLOAT_QUAT_VMULT(a2, qe, a);
    DISPLAY_FLOAT_VECT3("a2", a2);





    return 0.;

}
예제 #4
0
static void test_2(void) {

    struct Int32Vect3 v1 = { 5000, 5000, 5000 };
    DISPLAY_INT32_VECT3("v1", v1);

    struct FloatEulers euler_f = { RadOfDeg(45.), RadOfDeg(0.), RadOfDeg(0.)};
    DISPLAY_FLOAT_EULERS("euler_f", euler_f);

    struct Int32Eulers euler_i;
    EULERS_BFP_OF_REAL(euler_i, euler_f);
    DISPLAY_INT32_EULERS("euler_i", euler_i);

    struct Int32Quat quat_i;
    INT32_QUAT_OF_EULERS(quat_i, euler_i);
    DISPLAY_INT32_QUAT("quat_i", quat_i);
    INT32_QUAT_NORMALIZE(quat_i);
    DISPLAY_INT32_QUAT("quat_i_n", quat_i);

    struct Int32Vect3 v2;
    INT32_QUAT_VMULT(v2, quat_i, v1);
    DISPLAY_INT32_VECT3("v2", v2);

    struct Int32RMat rmat_i;
    INT32_RMAT_OF_QUAT(rmat_i, quat_i);
    DISPLAY_INT32_RMAT("rmat_i", rmat_i);

    struct Int32Vect3 v3;
    INT32_RMAT_VMULT(v3, rmat_i, v1);
    DISPLAY_INT32_VECT3("v3", v3);

    struct Int32RMat rmat_i2;
    INT32_RMAT_OF_EULERS(rmat_i2, euler_i);
    DISPLAY_INT32_RMAT("rmat_i2", rmat_i2);

    struct Int32Vect3 v4;
    INT32_RMAT_VMULT(v4, rmat_i2, v1);
    DISPLAY_INT32_VECT3("v4", v4);

    struct FloatQuat quat_f;
    FLOAT_QUAT_OF_EULERS(quat_f, euler_f);
    DISPLAY_FLOAT_QUAT("quat_f", quat_f);

    struct FloatVect3 v5;
    VECT3_COPY(v5, v1);
    DISPLAY_FLOAT_VECT3("v5", v5);
    struct FloatVect3 v6;
    FLOAT_QUAT_VMULT(v6, quat_f, v5);
    DISPLAY_FLOAT_VECT3("v6", v6);

}
예제 #5
0
void aos_compute_sensors(void) {

  struct FloatRates gyro;
  RATES_SUM(gyro, aos.imu_rates, aos.gyro_bias);
  //  printf("#aos.gyro_bias %f\n",DegOfRad( aos.gyro_bias.r));

  float_rates_add_gaussian_noise(&gyro, &aos.gyro_noise);

  RATES_BFP_OF_REAL(imu.gyro, gyro);
  RATES_BFP_OF_REAL(imu.gyro_prev, gyro);

  struct FloatVect3 g_ltp = {0., 0., 9.81};
  struct FloatVect3 accelero_ltp;
  VECT3_DIFF(accelero_ltp, aos.ltp_accel, g_ltp);
  struct FloatVect3 accelero_imu;
  FLOAT_QUAT_VMULT(accelero_imu, aos.ltp_to_imu_quat, accelero_ltp);

  float_vect3_add_gaussian_noise(&accelero_imu, &aos.accel_noise);
  ACCELS_BFP_OF_REAL(imu.accel, accelero_imu);
  
  
  struct FloatVect3 h_earth = {AHRS_H_X, AHRS_H_Y, AHRS_H_Z};
  struct FloatVect3 h_imu;
  FLOAT_QUAT_VMULT(h_imu, aos.ltp_to_imu_quat, h_earth);
  MAGS_BFP_OF_REAL(imu.mag, h_imu);

#ifdef AHRS_GRAVITY_UPDATE_COORDINATED_TURN
#if AHRS_TYPE == AHRS_TYPE_FCR2 || AHRS_TYPE == AHRS_TYPE_FCQ || AHRS_TYPE == AHRS_TYPE_FLQ
  VECT3_COPY(ahrs_impl.est_ltp_speed, aos.ltp_vel);
#endif
#if AHRS_TYPE == AHRS_TYPE_ICQ
  ahrs_impl.ltp_vel_norm = SPEED_BFP_OF_REAL(FLOAT_VECT3_NORM(aos.ltp_vel));
#endif
#endif


}
예제 #6
0
void   nps_sensor_accel_run_step(struct NpsSensorAccel* accel, double time, struct DoubleRMat* body_to_imu) {

  if (time < accel->next_update)
    return;
  
  /* transform gravity to body frame */
  struct DoubleVect3 g_body;
  FLOAT_QUAT_VMULT(g_body, fdm.ltp_to_body_quat, fdm.ltp_g);
  //  printf(" g_body %f %f %f\n", g_body.x, g_body.y, g_body.z);
  
  //  printf(" accel_fdm %f %f %f\n", fdm.body_ecef_accel.x, fdm.body_ecef_accel.y, fdm.body_ecef_accel.z);

  /* substract gravity to acceleration in body frame */
  struct DoubleVect3 accelero_body;
  VECT3_DIFF(accelero_body, fdm.body_ecef_accel, g_body);

  //  printf(" accelero body %f %f %f\n", accelero_body.x, accelero_body.y, accelero_body.z);

  /* transform to imu frame */
  struct DoubleVect3 accelero_imu;
  MAT33_VECT3_MUL(accelero_imu, *body_to_imu, accelero_body );
  
  /* compute accelero readings */
  MAT33_VECT3_MUL(accel->value, accel->sensitivity, accelero_imu);
  VECT3_ADD(accel->value, accel->neutral);

  /* Compute sensor error */
  struct DoubleVect3 accelero_error;
  /* constant bias */
  VECT3_COPY(accelero_error, accel->bias);
  /* white noise   */
  double_vect3_add_gaussian_noise(&accelero_error, &accel->noise_std_dev);
  /* scale */
  struct DoubleVect3 gain = {NPS_ACCEL_SENSITIVITY_XX, NPS_ACCEL_SENSITIVITY_YY, NPS_ACCEL_SENSITIVITY_ZZ};
  VECT3_EW_MUL(accelero_error, accelero_error, gain);
  /* add error */
  VECT3_ADD(accel->value, accelero_error);

  /* round signal to account for adc discretisation */
  DOUBLE_VECT3_ROUND(accel->value);
  /* saturate                                       */
  VECT3_BOUND_CUBE(accel->value, 0, accel->resolution); 
  
  accel->next_update += NPS_ACCEL_DT;
  accel->data_available = TRUE;
}