pixhawk position_estimator_inav.cpp思路整理及数据流

113 篇文章 174 订阅

写在前面:

这篇blog主要参考pixhawk的高度解算算法解读,并且加以扩展,扩展到其他传感器,其实里面处理好多只是记录了流程,至于里面实际物理意义并不是很清楚,也希望大牛能够指导一下。

概述:

整个算法的核心思想是由地理坐标系下的加速度通过积分,来获得速度、位置信息;经过2次修正产生可利用的信息,第一次是利用传感器计算修正系数产生加速度的偏差修正加速度,第二次是利用修正系数修正位置;最后可利用速度经过加速度修正,可利用的位置经过了加速度和位置修正。加速度的修正过程是由机体测量的加速度通过减去偏差,再转换到地理坐标系;位置的修正统一利用inertial_filter_correct()函数。

这里传感器的作用就是计算一个校正系数来对加速度偏移量进行校正。

代码思路

1. 变量初始化。

  1. float z_est[2] = { 0.0f, 0.0f }; // z轴的高度、速度  
  2. float acc[] = { 0.0f, 0.0f, 0.0f }; //地理坐标系(NED)的加速度数据  
  3. float acc_bias[] = { 0.0f, 0.0f, 0.0f }; // 机体坐标系下的加速度偏移量  
  4.   
  5. float corr_baro = 0.0f;     // D  
  6. float corr_gps[3][2] = {  
  7.     { 0.0f, 0.0f },     // N (pos, vel)  
  8.     { 0.0f, 0.0f },     // E (pos, vel)  
  9.     { 0.0f, 0.0f },     // D (pos, vel)  
  10. };  
  11. float corr_vision[3][2] = {  
  12.     { 0.0f, 0.0f },     // N (pos, vel)  
  13.     { 0.0f, 0.0f },     // E (pos, vel)  
  14.     { 0.0f, 0.0f },     // D (pos, vel)  
  15. };  
  16. float corr_mocap[3][1] = {  
  17.     { 0.0f },       // N (pos)  
  18.     { 0.0f },       // E (pos)  
  19.     { 0.0f },       // D (pos)  
  20. };  
  21. float corr_lidar = 0.0f;//据说是超声波  
  22. float corr_flow[] = { 0.0f, 0.0f }; // N E  
  23.   
  24. bool gps_valid = false;         // GPS is valid  
  25. bool lidar_valid = false;       // lidar is valid  
  26. bool flow_valid = false;        // flow is valid  
  27. bool flow_accurate = false;     // flow should be accurate (this flag not updated if flow_valid == false)  
  28. bool vision_valid = false;      // vision is valid  
  29. bool mocap_valid = false;       // mocap is valid  

2. 计算气压计高度的零点偏移,主要是取200个数据求平均。

  1. baro_offset += sensor.baro_alt_meter;  
  2. baro_offset /= (float) baro_init_cnt;  

3.各传感器计算得带各自的修正系数和权重

  1. corr_baro = baro_offset - sensor.baro_alt_meter[0] - z_est[0];  
  2. corr_lidar = lidar_offset - dist_ground - z_est[0];  
  3. corr_flow[0] = flow_v[0] - x_est[1]; /* velocity correction */  
  4. corr_flow[1] = flow_v[1] - y_est[1];  
  5. corr_vision[0][0] = vision.x - x_est[0]; /* calculate correction for position */  
  6. corr_vision[1][0] = vision.y - y_est[0];  
  7. corr_vision[2][0] = vision.z - z_est[0];  
  8. corr_vision[0][1] = vision.vx - x_est[1]; /* calculate correction for velocity */  
  9. corr_vision[1][1] = vision.vy - y_est[1];  
  10. corr_vision[2][1] = vision.vz - z_est[1];  
  11. corr_mocap[0][0] = mocap.x - x_est[0]; /* calculate correction for position */  
  12. corr_mocap[1][0] = mocap.y - y_est[0];  
  13. corr_mocap[2][0] = mocap.z - z_est[0];  
  14. corr_gps[0][0] = gps_proj[0] - est_buf[est_i][0][0]; /* calculate correction for position */  
  15. corr_gps[1][0] = gps_proj[1] - est_buf[est_i][1][0];  
  16. corr_gps[2][0] = local_pos.ref_alt - alt - est_buf[est_i][2][0];  
  17. corr_gps[0][1] = gps.vel_n_m_s - est_buf[est_i][0][1];/* calculate correction for velocity */  
  18. corr_gps[1][1] = gps.vel_e_m_s - est_buf[est_i][1][1];  
  19. corr_gps[2][1] = gps.vel_d_m_s - est_buf[est_i][2][1];  
  20. w_gps_xy = min_eph_epv / fmaxf(min_eph_epv, gps.eph);  
  21. w_gps_z = min_eph_epv / fmaxf(min_eph_epv, gps.epv);  

4.判断是否超时

  1. if ((flow_valid || lidar_valid) && t > (flow_time + flow_topic_timeout))  
  2. if (gps_valid && (t > (gps.timestamp_position + gps_topic_timeout)))  
  3. if (vision_valid && (t > (vision.timestamp_boot + vision_topic_timeout)))  
  4. if (mocap_valid && (t > (mocap.timestamp_boot + mocap_topic_timeout)))  
  5. if (lidar_valid && (t > (lidar_time + lidar_timeout)))  

5.判断是用哪一个传感器

  1. /* use GPS if it's valid and reference position initialized */  
  2. bool use_gps_xy = ref_inited && gps_valid && params.w_xy_gps_p > MIN_VALID_W;  
  3. bool use_gps_z = ref_inited && gps_valid && params.w_z_gps_p > MIN_VALID_W;  
  4. /* use VISION if it's valid and has a valid weight parameter */  
  5. bool use_vision_xy = vision_valid && params.w_xy_vision_p > MIN_VALID_W;  
  6. bool use_vision_z = vision_valid && params.w_z_vision_p > MIN_VALID_W;  
  7. /* use MOCAP if it's valid and has a valid weight parameter */  
  8. bool use_mocap = mocap_valid && params.w_mocap_p > MIN_VALID_W && params.att_ext_hdg_m == mocap_heading; //check if external heading is mocap  
  9. if (params.disable_mocap) { //disable mocap if fake gps is used  
  10.     use_mocap = false;  
  11. }  
  12. /* use flow if it's valid and (accurate or no GPS available) */  
  13. bool use_flow = flow_valid && (flow_accurate || !use_gps_xy);  
  14. /* use LIDAR if it's valid and lidar altitude estimation is enabled */  
  15. use_lidar = lidar_valid && params.enable_lidar_alt_est;  

6.计算权重

  1. float flow_q = flow.quality / 255.0f;  
  2. float flow_q_weight = (flow_q - params.flow_q_min) / (1.0f - params.flow_q_min);  
  3. w_flow = PX4_R(att.R, 2, 2) * flow_q_weight / fmaxf(1.0f, flow_dist);  
  4. if (!flow_accurate) {  
  5.     w_flow *= 0.05f;  
  6. }  
  7.   
  8. float w_xy_gps_p = params.w_xy_gps_p * w_gps_xy;  
  9. float w_xy_gps_v = params.w_xy_gps_v * w_gps_xy;  
  10. float w_z_gps_p = params.w_z_gps_p * w_gps_z;  
  11. float w_z_gps_v = params.w_z_gps_v * w_gps_z;  
  12.   
  13. float w_xy_vision_p = params.w_xy_vision_p;  
  14. float w_xy_vision_v = params.w_xy_vision_v;  
  15. float w_z_vision_p = params.w_z_vision_p;  
  16.   
  17. float w_mocap_p = params.w_mocap_p;  
  18. /* reduce GPS weight if optical flow is good */  
  19. if (use_flow && flow_accurate) {  
  20.     w_xy_gps_p *= params.w_gps_flow;  
  21.     w_xy_gps_v *= params.w_gps_flow;  
  22. }  
  23. /* baro offset correction */  
  24. if (use_gps_z) {  
  25.     float offs_corr = corr_gps[2][0] * w_z_gps_p * dt;  
  26.     baro_offset += offs_corr;  
  27.     corr_baro += offs_corr;  
  28. }  
  29. /* accelerometer bias correction for GPS (use buffered rotation matrix) */  
  30. float accel_bias_corr[3] = { 0.0f, 0.0f, 0.0f };  

7.根据使用的传感器计算加速度偏差

  1. if (use_gps_xy) {  
  2.     accel_bias_corr[0] -= corr_gps[0][0] * w_xy_gps_p * w_xy_gps_p;  
  3.     accel_bias_corr[0] -= corr_gps[0][1] * w_xy_gps_v;  
  4.     accel_bias_corr[1] -= corr_gps[1][0] * w_xy_gps_p * w_xy_gps_p;  
  5.     accel_bias_corr[1] -= corr_gps[1][1] * w_xy_gps_v;  
  6. }  
  7.   
  8. if (use_gps_z) {  
  9.     accel_bias_corr[2] -= corr_gps[2][0] * w_z_gps_p * w_z_gps_p;  
  10.     accel_bias_corr[2] -= corr_gps[2][1] * w_z_gps_v;  
  11. }  
  12.   
  13. /* transform error vector from NED frame to body frame */  
  14. for (int i = 0; i < 3; i++) {  
  15.     float c = 0.0f;  
  16.   
  17.     for (int j = 0; j < 3; j++) {  
  18.         c += R_gps[j][i] * accel_bias_corr[j];  
  19.     }  
  20.   
  21.     if (PX4_ISFINITE(c)) {  
  22.         acc_bias[i] += c * params.w_acc_bias * dt;  
  23.     }  
  24. }  
  25.   
  26. /* accelerometer bias correction for VISION (use buffered rotation matrix) */  
  27. accel_bias_corr[0] = 0.0f;  
  28. accel_bias_corr[1] = 0.0f;  
  29. accel_bias_corr[2] = 0.0f;  
  30.   
  31. if (use_vision_xy) {  
  32.     accel_bias_corr[0] -= corr_vision[0][0] * w_xy_vision_p * w_xy_vision_p;  
  33.     accel_bias_corr[0] -= corr_vision[0][1] * w_xy_vision_v;  
  34.     accel_bias_corr[1] -= corr_vision[1][0] * w_xy_vision_p * w_xy_vision_p;  
  35.     accel_bias_corr[1] -= corr_vision[1][1] * w_xy_vision_v;  
  36. }  
  37.   
  38. if (use_vision_z) {  
  39.     accel_bias_corr[2] -= corr_vision[2][0] * w_z_vision_p * w_z_vision_p;  
  40. }  
  41.   
  42. /* accelerometer bias correction for MOCAP (use buffered rotation matrix) */  
  43. accel_bias_corr[0] = 0.0f;  
  44. accel_bias_corr[1] = 0.0f;  
  45. accel_bias_corr[2] = 0.0f;  
  46.   
  47. if (use_mocap) {  
  48.     accel_bias_corr[0] -= corr_mocap[0][0] * w_mocap_p * w_mocap_p;  
  49.     accel_bias_corr[1] -= corr_mocap[1][0] * w_mocap_p * w_mocap_p;  
  50.     accel_bias_corr[2] -= corr_mocap[2][0] * w_mocap_p * w_mocap_p;  
  51. }  
  52.   
  53. /* transform error vector from NED frame to body frame */  
  54. for (int i = 0; i < 3; i++) {  
  55.     float c = 0.0f;  
  56.   
  57.     for (int j = 0; j < 3; j++) {  
  58.         c += PX4_R(att.R, j, i) * accel_bias_corr[j];  
  59.     }  
  60.   
  61.     if (PX4_ISFINITE(c)) {  
  62.         acc_bias[i] += c * params.w_acc_bias * dt;  
  63.     }  
  64. }  
  65.   
  66. /* accelerometer bias correction for flow and baro (assume that there is no delay) */  
  67. accel_bias_corr[0] = 0.0f;  
  68. accel_bias_corr[1] = 0.0f;  
  69. accel_bias_corr[2] = 0.0f;  
  70.   
  71. if (use_flow) {  
  72.     accel_bias_corr[0] -= corr_flow[0] * params.w_xy_flow;  
  73.     accel_bias_corr[1] -= corr_flow[1] * params.w_xy_flow;  
  74. }  
  75.   
  76. if (use_lidar) {  
  77.     accel_bias_corr[2] -= corr_lidar * params.w_z_lidar * params.w_z_lidar;  
  78. else {  
  79.     accel_bias_corr[2] -= corr_baro * params.w_z_baro * params.w_z_baro;  
  80. }  
  81.   
  82. /* transform error vector from NED frame to body frame */  
  83. for (int i = 0; i < 3; i++) {  
  84.     float c = 0.0f;  
  85.   
  86.     for (int j = 0; j < 3; j++) {  
  87.         c += PX4_R(att.R, j, i) * accel_bias_corr[j];  
  88.     }  
  89.   
  90.     if (PX4_ISFINITE(c)) {  
  91.         acc_bias[i] += c * params.w_acc_bias * dt;  
  92.     }  
  93. }  

这里得到的acc_bias[]用于前面程序(500行左右)(2016.08.23加)

  1. /* sensor combined */  
  2. orb_check(sensor_combined_sub, &updated);  
  3.   
  4. if (updated) {  
  5.     orb_copy(ORB_ID(sensor_combined), sensor_combined_sub, &sensor);  
  6.   
  7.     if (sensor.accelerometer_timestamp[0] != accel_timestamp) {  
  8.         if (att.R_valid) {  
  9.             /* correct accel bias */  
  10.             sensor.accelerometer_m_s2[0] -= acc_bias[0];  
  11.             sensor.accelerometer_m_s2[1] -= acc_bias[1];  
  12.             sensor.accelerometer_m_s2[2] -= acc_bias[2];  
  13.   
  14.             /* transform acceleration vector from body frame to NED frame */  
  15.             for (int i = 0; i < 3; i++) {  
  16.                 acc[i] = 0.0f;  
  17.   
  18.                 for (int j = 0; j < 3; j++) {  
  19.                     acc[i] += PX4_R(att.R, i, j) * sensor.accelerometer_m_s2[j];  
  20.                 }  
  21.             }  
  22.   
  23.             acc[2] += CONSTANTS_ONE_G;  
  24.   
  25.         } else {  
  26.             memset(acc, 0, sizeof(acc));  
  27.         }  
  28.   
  29.         accel_timestamp = sensor.accelerometer_timestamp[0];  
  30.         accel_updates++;  
  31.     }  
这里得到修正后的加速度,之后用此加速度进行一次、二次积分得到预计速度和位置(2016.08.23加)

8.预计位置

  1. /* inertial filter prediction for altitude */  
  2. if (can_estimate_xy) {  
  3. {  
  4. inertial_filter_predict(dt, x_est, acc[0]);  
  5. inertial_filter_predict(dt, y_est, acc[1]);  
  6. }  
  7. inertial_filter_predict(dt, z_est, acc[2]);  

函数解析

这里x_esty_estz_est通过float x[2]传进来来后,经过函数处理直接传回来给x_esty_estz_est(这里和C语法有点不同,但是不这么解释就说不过去了)

  1. void inertial_filter_predict(float dt, float x[2], float acc)  
  2. {  
  3.     if (isfinite(dt)) {  
  4.         if (!isfinite(acc)) {  
  5.             acc = 0.0f;  
  6.         }  
  7.         x[0] += x[1] * dt + acc * dt * dt / 2.0f;  
  8.         x[1] += acc * dt;  
  9.     }  
  10. }  

9.修正位置

利用传感器得到的速度和位置修正

  1. /* inertial filter correction for altitude */  
  2. if (use_lidar) {  
  3.     inertial_filter_correct(corr_lidar, dt, z_est, 0, params.w_z_lidar);  
  4. else {  
  5.     inertial_filter_correct(corr_baro, dt, z_est, 0, params.w_z_baro);  
  6. }  
  7. if (use_gps_z) {  
  8.     epv = fminf(epv, gps.epv);  
  9.     inertial_filter_correct(corr_gps[2][0], dt, z_est, 0, w_z_gps_p);  
  10.     inertial_filter_correct(corr_gps[2][1], dt, z_est, 1, w_z_gps_v);  
  11. }  
  12. if (use_vision_z) {  
  13.     epv = fminf(epv, epv_vision);  
  14.     inertial_filter_correct(corr_vision[2][0], dt, z_est, 0, w_z_vision_p);  
  15. }  
  16. if (use_mocap) {  
  17.     epv = fminf(epv, epv_mocap);  
  18.     inertial_filter_correct(corr_mocap[2][0], dt, z_est, 0, w_mocap_p);  
  19. }  
  20. if (can_estimate_xy) {  
  21.     /* inertial filter correction for position */  
  22.     if (use_flow) {  
  23.         eph = fminf(eph, eph_flow);  
  24.         inertial_filter_correct(corr_flow[0], dt, x_est, 1, params.w_xy_flow * w_flow);  
  25.         inertial_filter_correct(corr_flow[1], dt, y_est, 1, params.w_xy_flow * w_flow);  
  26.     }  
  27.     if (use_gps_xy) {  
  28.         eph = fminf(eph, gps.eph);  
  29.         inertial_filter_correct(corr_gps[0][0], dt, x_est, 0, w_xy_gps_p);  
  30.         inertial_filter_correct(corr_gps[1][0], dt, y_est, 0, w_xy_gps_p);  
  31.         if (gps.vel_ned_valid && t < gps.timestamp_velocity + gps_topic_timeout) {  
  32.             inertial_filter_correct(corr_gps[0][1], dt, x_est, 1, w_xy_gps_v);  
  33.             inertial_filter_correct(corr_gps[1][1], dt, y_est, 1, w_xy_gps_v);  
  34.         }  
  35.     }  
  36.     if (use_vision_xy) {  
  37.         eph = fminf(eph, eph_vision);  
  38.         inertial_filter_correct(corr_vision[0][0], dt, x_est, 0, w_xy_vision_p);  
  39.         inertial_filter_correct(corr_vision[1][0], dt, y_est, 0, w_xy_vision_p);  
  40.         if (w_xy_vision_v > MIN_VALID_W) {  
  41.             inertial_filter_correct(corr_vision[0][1], dt, x_est, 1, w_xy_vision_v);  
  42.             inertial_filter_correct(corr_vision[1][1], dt, y_est, 1, w_xy_vision_v);  
  43.         }  
  44.     }  
  45.     if (use_mocap) {  
  46.         eph = fminf(eph, eph_mocap);  
  47.         inertial_filter_correct(corr_mocap[0][0], dt, x_est, 0, w_mocap_p);  
  48.         inertial_filter_correct(corr_mocap[1][0], dt, y_est, 0, w_mocap_p);  
  49.     }  
  50. }  
  51. /* run terrain estimator */  
  52. terrain_estimator.predict(dt, &att, &sensor, &lidar);  
  1. 函数解析  
  2. e是修正系数;dt周期时间;x[2]是2个float型成员的数组,x[0]是位置,x[1]是速度;  
  3. i表示修正是位置还是速度,0是修正位置,1是修正速度;w是权重系数  
  4. 这里x_est、y_est、z_est通过float x[2]传进来来后,经过函数处理直接传回来给x_est、y_est、z_est(这里和C语法有点不同,但是不这么解释就说不过去了)  
  1. void inertial_filter_correct(float e, float dt, float x[2], int i, float w)  
  2. {  
  3.     if (isfinite(e) && isfinite(w) && isfinite(dt)) {  
  4.         float ewdt = e * w * dt;  
  5.         x[i] += ewdt;  
  6.   
  7.         if (i == 0) {  
  8.             x[1] += w * ewdt;  
  9.         }  
  10.     }  
  11. }  

10.发布

  1. /* publish local position */  
  2. local_pos.xy_valid = can_estimate_xy;  
  3. local_pos.v_xy_valid = can_estimate_xy;  
  4. local_pos.xy_global = local_pos.xy_valid && use_gps_xy;  
  5. local_pos.z_global = local_pos.z_valid && use_gps_z;  
  6. local_pos.x = x_est[0];  
  7. local_pos.vx = x_est[1];  
  8. local_pos.y = y_est[0];  
  9. local_pos.vy = y_est[1];  
  10. local_pos.z = z_est[0];  
  11. local_pos.vz = z_est[1];  
  12. local_pos.yaw = att.yaw;  
  13. local_pos.dist_bottom_valid = dist_bottom_valid;  
  14. local_pos.eph = eph;  
  15. local_pos.epv = epv;  
  16.   
  17. if (local_pos.dist_bottom_valid) {  
  18.     local_pos.dist_bottom = dist_ground;  
  19.     local_pos.dist_bottom_rate = - z_est[1];  
  20. }  
  21.   
  22. local_pos.timestamp = t;  
  23.   
  24. orb_publish(ORB_ID(vehicle_local_position), vehicle_local_position_pub, &local_pos);  
  25.   
  26. if (local_pos.xy_global && local_pos.z_global) {  
  27.     /* publish global position */  
  28.     global_pos.timestamp = t;  
  29.     global_pos.time_utc_usec = gps.time_utc_usec;  
  30.   
  31.     double est_lat, est_lon;  
  32.     map_projection_reproject(&ref, local_pos.x, local_pos.y, &est_lat, &est_lon);  
  33.   
  34.     global_pos.lat = est_lat;  
  35.     global_pos.lon = est_lon;  
  36.     global_pos.alt = local_pos.ref_alt - local_pos.z;  
  37.   
  38.     global_pos.vel_n = local_pos.vx;  
  39.     global_pos.vel_e = local_pos.vy;  
  40.     global_pos.vel_d = local_pos.vz;  
  41.   
  42.     global_pos.yaw = local_pos.yaw;  
  43.   
  44.     global_pos.eph = eph;  
  45.     global_pos.epv = epv;  
  46.   
  47.     if (terrain_estimator.is_valid()) {  
  48.         global_pos.terrain_alt = global_pos.alt - terrain_estimator.get_distance_to_ground();  
  49.         global_pos.terrain_alt_valid = true;  
  50.   
  51.     } else {  
  52.         global_pos.terrain_alt_valid = false;  
  53.     }  
  54.   
  55.     global_pos.pressure_alt = sensor.baro_alt_meter[0];  
  56.   
  57.     if (vehicle_global_position_pub == NULL) {  
  58.         vehicle_global_position_pub = orb_advertise(ORB_ID(vehicle_global_position), &global_pos);  
  59.   
  60.     } else {  
  61.         orb_publish(ORB_ID(vehicle_global_position), vehicle_global_position_pub, &global_pos);  
  62.     }  
  63. }  

常用传感器

气压+加速度=高度(此部分摘自http://blog.sina.com.cn/s/blog_8fe4f2f40102wo50.html)

1. 变量初始化。

  1. float z_est[2] = { 0.0f, 0.0f }; // z轴的高度、速度  
  2. float acc[] = { 0.0f, 0.0f, 0.0f }; //地理坐标系(NED)的加速度数据  
  3. float acc_bias[] = { 0.0f, 0.0f, 0.0f }; //机体坐标系下的加速度偏移量  
  4. float corr_baro = 0.0f; // 气压计校正系数  

2. 计算气压计高度的零点偏移,主要是取200个数据求平均。

  1. baro_offset += sensor.baro_alt_meter;  
  2. baro_offset /= (float) baro_init_cnt;  

3. 将传感器获取的机体加速度数据转换到地理坐标系下。

加速度数据要先去除偏移量;

  1. sensor.accelerometer_m_s2[0] -=acc_bias[0];  
  2. sensor.accelerometer_m_s2[1] -= acc_bias[1];  
  3. sensor.accelerometer_m_s2[2] -=acc_bias[2];  

然后转换坐标系;

  1. acc[i] += PX4_R(att.R, i, j) *sensor.accelerometer_m_s2[j];  

地理坐标系下的z轴加速度是有重力加速度的,因此补偿上去。

  1. acc[2] += CONSTANTS_ONE_G;  

4. 计算气压计的校正系数

corr_baro = baro_offset -sensor.baro_alt_meter - z_est[0];

5. 加速度偏移向量校正

accel_bias_corr[2] -= corr_baro *params.w_z_baro * params.w_z_baro;

6. 将偏移向量转换到机体坐标系

c += PX4_R(att.R, j, i) *accel_bias_corr[j];

acc_bias[i] += c * params.w_acc_bias * dt;

7. 加速度推算高度

inertial_filter_predict(dt, z_est, acc[2]);

8. 气压计校正系数进行校正

inertial_filter_correct(corr_baro, dt,z_est, 0, params.w_z_baro);

光流

  1. orb_copy(ORB_ID(optical_flow), optical_flow_sub, &flow);  
  2. if (fabs(rates_setpoint.pitch) < rate_threshold) {  
  3.     //warnx("[inav] test ohne comp");  
  4.     flow_ang[0] = (flow.pixel_flow_x_integral / (float)flow.integration_timespan * 1000000.0f) * params.flow_k;//for now the flow has to be scaled (to small)  
  5. }  
  6. else {  
  7.     //warnx("[inav] test mit comp");  
  8.     //calculate flow [rad/s] and compensate for rotations (and offset of flow-gyro)  
  9.     flow_ang[0] = ((flow.pixel_flow_x_integral - flow.gyro_x_rate_integral) / (float)flow.integration_timespan * 1000000.0f  
  10.                + gyro_offset_filtered[0]) * params.flow_k;//for now the flow has to be scaled (to small)  
  11. }  
  12. if (fabs(rates_setpoint.roll) < rate_threshold) {  
  13.     flow_ang[1] = (flow.pixel_flow_y_integral / (float)flow.integration_timespan * 1000000.0f) * params.flow_k;//for now the flow has to be scaled (to small)  
  14. }  
  15. else {  
  16.     //calculate flow [rad/s] and compensate for rotations (and offset of flow-gyro)  
  17.     flow_ang[1] = ((flow.pixel_flow_y_integral - flow.gyro_y_rate_integral) / (float)flow.integration_timespan * 1000000.0f  
  18.                + gyro_offset_filtered[1]) * params.flow_k;//for now the flow has to be scaled (to small)  
  19. }  

得出flow_ang[]


  1. float dist_bottom = lidar.current_distance;   
  2. float flow_dist = dist_bottom;   
所以说光流的距离来自lidar,也就是超声波
  1. gyro_offset_filtered[0] = flow_gyrospeed_filtered[0] - att_gyrospeed_filtered[0];  
  2. gyro_offset_filtered[1] = flow_gyrospeed_filtered[1] - att_gyrospeed_filtered[1];  
  3. gyro_offset_filtered[2] = flow_gyrospeed_filtered[2] - att_gyrospeed_filtered[2];  
  4. flow_gyrospeed[0] = flow.gyro_x_rate_integral / (float)flow.integration_timespan * 1000000.0f;  
  5. flow_gyrospeed[1] = flow.gyro_y_rate_integral / (float)flow.integration_timespan * 1000000.0f;  
  6. flow_gyrospeed[2] = flow.gyro_z_rate_integral / (float)flow.integration_timespan * 1000000.0f;  
  7. yaw_comp[0] = - params.flow_module_offset_y * (flow_gyrospeed[2] - gyro_offset_filtered[2]);  
  8. yaw_comp[1] = params.flow_module_offset_x * (flow_gyrospeed[2] - gyro_offset_filtered[2]);  

PX4_R(att.R, i, j)的意思是(att.R[i* 3 + j])

  1. if (fabs(rates_setpoint.yaw) < rate_threshold) {  
  2.     flow_m[0] = -flow_ang[0] * flow_dist;  
  3.     flow_m[1] = -flow_ang[1] * flow_dist;  
  4. else {  
  5.     flow_m[0] = -flow_ang[0] * flow_dist - yaw_comp[0] * params.flow_k;  
  6.     flow_m[1] = -flow_ang[1] * flow_dist - yaw_comp[1] * params.flow_k;  
  7. }  

得出flow_m[]光流测量向量

  1. flow_m[2] = z_est[1];  
  2. for (int i = 0; i < 2; i++) {  
  3.     for (int j = 0; j < 3; j++) {  
  4.         flow_v[i] += PX4_R(att.R, i, j) * flow_m[j];  
  5.     }  
  6. }  
  7. corr_flow[0] = flow_v[0] - x_est[1];  
  8. corr_flow[1] = flow_v[1] - y_est[1];  

得出corr_flow[]


  1. accel_bias_corr[0] -= corr_flow[0] * params.w_xy_flow;  
  2. accel_bias_corr[1] -= corr_flow[1] * params.w_xy_flow;  

得出accel_bias_corr[]


PX4_R(att.R, i, j)的意思是(att.R[i* 3 + j])

  1. /* transform error vector from NED frame to body frame */  
  2. for (int i = 0; i < 3; i++) {  
  3.     float c = 0.0f;  
  4.     for (int j = 0; j < 3; j++) {  
  5.         c += PX4_R(att.R, j, i) * accel_bias_corr[j];  
  6.     }  
  7.     if (PX4_ISFINITE(c)) {  
  8.         acc_bias[i] += c * params.w_acc_bias * dt;  
  9.     }  
  10. }  

得出acc_bias[]

  1. inertial_filter_predict(dt, x_est, acc[0]);  
  2. inertial_filter_predict(dt, y_est, acc[1]);  

得出x_est、y_est

  1. inertial_filter_correct(corr_flow[0], dt, x_est, 1, params.w_xy_flow * w_flow);  
  2. inertial_filter_correct(corr_flow[1], dt, y_est, 1, params.w_xy_flow * w_flow);  

得出修正后的x_est、y_est

GPS

  1. orb_copy(ORB_ID(vehicle_gps_position), vehicle_gps_position_sub, &gps);  
  2. float alt = gps.alt * 1e-3;  
  3. local_pos.ref_alt = alt + z_est[0];  
  4. est_buf[buf_ptr][0][0] = x_est[0];  
  5. est_buf[buf_ptr][0][1] = x_est[1];  
  6. est_buf[buf_ptr][1][0] = y_est[0];  
  7. est_buf[buf_ptr][1][1] = y_est[1];  
  8. est_buf[buf_ptr][2][0] = z_est[0];  
  9. est_buf[buf_ptr][2][1] = z_est[1];  
  10. map_projection_project(&ref, lat, lon, &(gps_proj[0]), &(gps_proj[1]));  
  11. corr_gps[0][0] = gps_proj[0] - est_buf[est_i][0][0];  
  12. corr_gps[1][0] = gps_proj[1] - est_buf[est_i][1][0];  
  13. corr_gps[2][0] = local_pos.ref_alt - alt - est_buf[est_i][2][0];  
  14. corr_gps[0][1] = gps.vel_n_m_s - est_buf[est_i][0][1];  
  15. corr_gps[1][1] = gps.vel_e_m_s - est_buf[est_i][1][1];  
  16. corr_gps[2][1] = gps.vel_d_m_s - est_buf[est_i][2][1];  

得出corr_gps[][]

  1. bool use_gps_xy = ref_inited && gps_valid && params.w_xy_gps_p > MIN_VALID_W;  
  2. accel_bias_corr[0] -= corr_gps[0][0] * w_xy_gps_p * w_xy_gps_p;  
  3. accel_bias_corr[0] -= corr_gps[0][1] * w_xy_gps_v;  
  4. accel_bias_corr[1] -= corr_gps[1][0] * w_xy_gps_p * w_xy_gps_p;  
  5. accel_bias_corr[1] -= corr_gps[1][1] * w_xy_gps_v;  
  6. accel_bias_corr[2] -= corr_gps[2][0] * w_z_gps_p * w_z_gps_p;  
  7. accel_bias_corr[2] -= corr_gps[2][1] * w_z_gps_v;  

得出accel_bias_corr[]


  1. /* push current rotation matrix to buffer */  
  2. memcpy(R_buf[buf_ptr], att.R, sizeof(att.R));  
  3. /* save rotation matrix at this moment */  
  4. memcpy(R_gps, R_buf[est_i], sizeof(R_gps));  
  5. /* transform error vector from NED frame to body frame */  
  6. for (int i = 0; i < 3; i++) {  
  7.     float c = 0.0f;  
  8.     for (int j = 0; j < 3; j++) {  
  9.         c += R_gps[j][i] * accel_bias_corr[j];  
  10.     }  
  11.     if (PX4_ISFINITE(c)) {  
  12.         acc_bias[i] += c * params.w_acc_bias * dt;  
  13.     }  
  14. }   

得出acc_bias[]

  1. // gps[a][b],a=0则为x方向,a=1则为y方向,a=2则为z方向  
  2. //b=0则为位置,b=1则为速度  
  3. inertial_filter_predict(dt, z_est, acc[2]);  

得出z_est

  1. inertial_filter_correct(corr_gps[2][0], dt, z_est, 0, w_z_gps_p);   
  2. inertial_filter_correct(corr_gps[2][1], dt, z_est, 1, w_z_gps_v);  

得出修正后的z_est

  1. inertial_filter_predict(dt, x_est, acc[0]);  
  2. inertial_filter_predict(dt, y_est, acc[1]);  
  3. inertial_filter_correct(corr_gps[0][0], dt, x_est, 0, w_xy_gps_p);  
  4. inertial_filter_correct(corr_gps[1][0], dt, y_est, 0, w_xy_gps_p);  
  5. inertial_filter_correct(corr_gps[0][1], dt, x_est, 1, w_xy_gps_v);  
  6. inertial_filter_correct(corr_gps[1][1], dt, y_est, 1, w_xy_gps_v);  
  1.   


  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
使用 JavaScript 编写的记忆游戏(附源代码)   项目:JavaScript 记忆游戏(附源代码) 记忆检查游戏是一个使用 HTML5、CSS 和 JavaScript 开发的简单项目。这个游戏是关于测试你的短期 记忆技能。玩这个游戏 时,一系列图像会出现在一个盒子形状的区域中 。玩家必须找到两个相同的图像并单击它们以使它们消失。 如何运行游戏? 记忆游戏项目仅包含 HTML、CSS 和 JavaScript。谈到此游戏的功能,用户必须单击两个相同的图像才能使它们消失。 点击卡片或按下键盘键,通过 2 乘 2 旋转来重建鸟儿对,并发现隐藏在下面的图像! 如果翻开的牌面相同(一对),您就赢了,并且该对牌将从游戏中消失! 否则,卡片会自动翻面朝下,您需要重新尝试! 该游戏包含大量的 javascript 以确保游戏正常运行。 如何运行该项目? 要运行此游戏,您不需要任何类型的本地服务器,但需要浏览器。我们建议您使用现代浏览器,如 Google Chrome 和 Mozilla Firefox, 以获得更好、更优化的游戏体验。要玩游戏,首先,通过单击 memorygame-index.html 文件在浏览器中打开游戏。 演示: 该项目为国外大神项目,可以作为毕业设计的项目,也可以作为大作业项目,不用担心代码重复,设计重复等,如果需要对项目进行修改,需要具备一定基础知识。 注意:如果装有360等杀毒软件,可能会出现误报的情况,源码本身并无病毒,使用源码时可以关闭360,或者添加信任。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值