实现过程主要包含三个部分:
1.怎么初始化避障模块?
2.怎么获取避障距离数据?
3.怎么实现避障控制

1.如何初始化

(1)主函数中调用过这个函数:

  1. void Rover::init_ardupilot()
  2. {
  3. …………
  4. init_proximity();//避障函数初始化
  5. }

在/APMrover2/sensors里有:

  1. void Rover::init_proximity(void)
  2. {
  3. #if PROXIMITY_ENABLED == ENABLED
  4. g2.proximity.init();//测距传感器初始化
  5. g2.proximity.set_rangefinder(&rangefinder);//设置近距传感器
  6. #endif
  7. }

(2)避障初始化函数执行顺序
首先看 g2.proximity.init()函数;

  1. void AP_Proximity::init(void)
  2. {
  3. if (num_instances != 0) //没有传感器就直接返回
  4. return;
  5. for (uint8_t i=0; i<PROXIMITY_MAX_INSTANCES; i++)
  6. {
  7. detect_instance(i); //传感器识别
  8. if (drivers[i] != nullptr) //我们为这个实例加载了一个驱动程序,所以它必须存在(尽管它可能不健康)
  9. {
  10. // we loaded a driver for this instance, so it must be present (although it may not be healthy)
  11. num_instances = i+1;
  12. }
  13. //初始化状态标志-----initialise status
  14. state[i].status = Proximity_NotConnected;
  15. }
  16. }
  17. ------------------------------------------------------------
  18. 下面代码是识别我们用的哪种传感器 detect_instance(i);
  19. ------------------------------------------------------------
  20. void AP_Proximity::detect_instance(uint8_t instance)
  21. {
  22. uint8_t type = _type[instance];
  23. if (type == Proximity_Type_SF40C) //激光测距模块
  24. {
  25. if (AP_Proximity_LightWareSF40C::detect(serial_manager))
  26. {
  27. state[instance].instance = instance;
  28. //使用哪种传感器就创建哪种对象:
  29. drivers[instance] = new AP_Proximity_LightWareSF40C(*this, state[instance], serial_manager);
  30. return;
  31. }
  32. }
  33. if (type == Proximity_Type_MAV)
  34. {
  35. state[instance].instance = instance;
  36. drivers[instance] = new AP_Proximity_MAV(*this, state[instance]);
  37. return;
  38. }
  39. if (type == Proximity_Type_TRTOWER)
  40. {
  41. if (AP_Proximity_TeraRangerTower::detect(serial_manager))
  42. {
  43. state[instance].instance = instance;
  44. drivers[instance] = new AP_Proximity_TeraRangerTower(*this, state[instance], serial_manager);
  45. return;
  46. }
  47. }
  48. if (type == Proximity_Type_RangeFinder) //测距仪器
  49. {
  50. state[instance].instance = instance;
  51. drivers[instance] = new AP_Proximity_RangeFinder(*this, state[instance]);
  52. return;
  53. }
  54. #if CONFIG_HAL_BOARD == HAL_BOARD_SITL
  55. if (type == Proximity_Type_SITL)
  56. {
  57. state[instance].instance = instance;
  58. drivers[instance] = new AP_Proximity_SITL(*this, state[instance]); //创建实例
  59. return;
  60. }
  61. #endif
  62. }

这是APM支持的驱动类型:
Ardupilot 避障代码 - 图1


在const AP_Param::GroupInfo AP_Proximity::var_info[]中有我们用到的参数**

2.更新避障数据

SCHEDTASK(update_proximity, 100, 50), //更新近距离传感器,避障使用

//更新数据的函数:

  1. void Rover::update_proximity(void)
  2. {
  3. #if PROXIMITY_ENABLED == ENABLED
  4. g2.proximity.update();
  5. #endif
  6. }

在update()中有这一行:drivers[i]->update(); //更新数据

  1. //这里由于 virtual void update() = 0;是纯虚函数,我们以AP_Proximity_RangeFinder为例分析
  2. void AP_Proximity_RangeFinder::update(void)
  3. {
  4. //如果没有测距仪目标立即退出
  5. const RangeFinder *rngfnd = frontend.get_rangefinder();
  6. if (rngfnd == nullptr)
  7. {
  8. set_status(AP_Proximity::Proximity_NoData);
  9. return;
  10. }
  11. //查看所有测距仪
  12. for (uint8_t i=0; i<rngfnd->num_sensors(); i++)
  13. {
  14. if (rngfnd->has_data(i))
  15. {
  16. //检查水平测距仪
  17. if (rngfnd->get_orientation(i) <= ROTATION_YAW_315)
  18. {
  19. uint8_t sector = (uint8_t)rngfnd->get_orientation(i); //获取方向
  20. _angle[sector] = sector * 45; //获取角度
  21. _distance[sector] = rngfnd->distance_cm(i) / 100.0f; //获取距离
  22. _distance_min = rngfnd->min_distance_cm(i) / 100.0f; //最小距离
  23. _distance_max = rngfnd->max_distance_cm(i) / 100.0f; //最大距离
  24. _distance_valid[sector] = (_distance[sector] >= _distance_min) && (_distance[sector] <= _distance_max); //是否在限制的范围
  25. _last_update_ms = AP_HAL::millis(); //获取上次时间
  26. update_boundary_for_sector(sector);//这里是更新扇区的介绍,重要函数
  27. }
  28. //检查向上测距仪----------check upward facing range finder
  29. if (rngfnd->get_orientation(i) == ROTATION_PITCH_90)
  30. {
  31. _distance_upward = rngfnd->distance_cm(i) / 100.0f;
  32. _last_upward_update_ms = AP_HAL::millis();
  33. }
  34. }
  35. }
  36. //检查超时并设置健康状态--------- check for timeout and set health status
  37. if ((_last_update_ms == 0) || (AP_HAL::millis() - _last_update_ms > PROXIMITY_RANGEFIDER_TIMEOUT_MS))
  38. {
  39. set_status(AP_Proximity::Proximity_NoData);
  40. } else
  41. {
  42. set_status(AP_Proximity::Proximity_Good);
  43. }
  44. }

获取到的这些值应该传到避障控制函数中,
怎么传过去的,要看这个函数:update_boundary_for_sector(sector)//更新边界区域

这个函数最终会计算得到避障边界点数据:_boundary_point[]

3.避障控制实现

下面这个函数是控制航行器速度的:

  1. _avoid->adjust_velocity(_pos_control.get_pos_xy_kP(),_loiter_accel_cmss, desired_vel);

具体实现:

  1. void AC_Avoid::adjust_velocity(float kP, float accel_cmss, Vector2f &desired_vel)
  2. {
  3. //没有使能立即退出---exit immediately if disabled
  4. if (_enabled == AC_AVOID_DISABLED)
  5. {
  6. return;
  7. }
  8. //限制加速度------limit acceleration
  9. float accel_cmss_limited = MIN(accel_cmss, AC_AVOID_ACCEL_CMSS_MAX);
  10. if ((_enabled & AC_AVOID_STOP_AT_FENCE) > 0) //这个是围栏设置,可以先不看
  11. {
  12. adjust_velocity_circle_fence(kP, accel_cmss_limited, desired_vel);
  13. adjust_velocity_polygon_fence(kP, accel_cmss_limited, desired_vel);
  14. }
  15. if ((_enabled & AC_AVOID_USE_PROXIMITY_SENSOR) > 0 && _proximity_enabled) //采用近距传感器,重点看这里
  16. {
  17. adjust_velocity_proximity(kP, accel_cmss_limited, desired_vel); //根据近距离传感器调节速度
  18. }
  19. }

在这个函数adjust_velocity_proximity(kP, accel_cmss_limited, desired_vel) 中有如下代码:

  1. ……………………………………………………
  2. //从近距传感器获取边界-----------get boundary from proximity sensor
  3. uint16_t num_points;
  4. const Vector2f *boundary = _proximity.get_boundary_points(num_points);//计算边界点
  5. adjust_velocity_polygon(kP, accel_cmss, desired_vel, boundary, num_points, false, _margin); //通过避障点计算所需要的目标速度。