实现过程主要包含三个部分:
1.怎么初始化避障模块?
2.怎么获取避障距离数据?
3.怎么实现避障控制
1.如何初始化
(1)主函数中调用过这个函数:
void Rover::init_ardupilot()
{
…………
init_proximity();//避障函数初始化
}
在/APMrover2/sensors里有:
void Rover::init_proximity(void)
{
#if PROXIMITY_ENABLED == ENABLED
g2.proximity.init();//测距传感器初始化
g2.proximity.set_rangefinder(&rangefinder);//设置近距传感器
#endif
}
(2)避障初始化函数执行顺序
首先看 g2.proximity.init()函数;
void AP_Proximity::init(void)
{
if (num_instances != 0) //没有传感器就直接返回
return;
for (uint8_t i=0; i<PROXIMITY_MAX_INSTANCES; i++)
{
detect_instance(i); //传感器识别
if (drivers[i] != nullptr) //我们为这个实例加载了一个驱动程序,所以它必须存在(尽管它可能不健康)
{
// we loaded a driver for this instance, so it must be present (although it may not be healthy)
num_instances = i+1;
}
//初始化状态标志-----initialise status
state[i].status = Proximity_NotConnected;
}
}
------------------------------------------------------------
下面代码是识别我们用的哪种传感器 detect_instance(i);
------------------------------------------------------------
void AP_Proximity::detect_instance(uint8_t instance)
{
uint8_t type = _type[instance];
if (type == Proximity_Type_SF40C) //激光测距模块
{
if (AP_Proximity_LightWareSF40C::detect(serial_manager))
{
state[instance].instance = instance;
//使用哪种传感器就创建哪种对象:
drivers[instance] = new AP_Proximity_LightWareSF40C(*this, state[instance], serial_manager);
return;
}
}
if (type == Proximity_Type_MAV)
{
state[instance].instance = instance;
drivers[instance] = new AP_Proximity_MAV(*this, state[instance]);
return;
}
if (type == Proximity_Type_TRTOWER)
{
if (AP_Proximity_TeraRangerTower::detect(serial_manager))
{
state[instance].instance = instance;
drivers[instance] = new AP_Proximity_TeraRangerTower(*this, state[instance], serial_manager);
return;
}
}
if (type == Proximity_Type_RangeFinder) //测距仪器
{
state[instance].instance = instance;
drivers[instance] = new AP_Proximity_RangeFinder(*this, state[instance]);
return;
}
#if CONFIG_HAL_BOARD == HAL_BOARD_SITL
if (type == Proximity_Type_SITL)
{
state[instance].instance = instance;
drivers[instance] = new AP_Proximity_SITL(*this, state[instance]); //创建实例
return;
}
#endif
}
这是APM支持的驱动类型:
在const AP_Param::GroupInfo AP_Proximity::var_info[]中有我们用到的参数**
2.更新避障数据
SCHEDTASK(update_proximity, 100, 50), //更新近距离传感器,避障使用
//更新数据的函数:
void Rover::update_proximity(void)
{
#if PROXIMITY_ENABLED == ENABLED
g2.proximity.update();
#endif
}
在update()中有这一行:drivers[i]->update(); //更新数据
//这里由于 virtual void update() = 0;是纯虚函数,我们以AP_Proximity_RangeFinder为例分析
void AP_Proximity_RangeFinder::update(void)
{
//如果没有测距仪目标立即退出
const RangeFinder *rngfnd = frontend.get_rangefinder();
if (rngfnd == nullptr)
{
set_status(AP_Proximity::Proximity_NoData);
return;
}
//查看所有测距仪
for (uint8_t i=0; i<rngfnd->num_sensors(); i++)
{
if (rngfnd->has_data(i))
{
//检查水平测距仪
if (rngfnd->get_orientation(i) <= ROTATION_YAW_315)
{
uint8_t sector = (uint8_t)rngfnd->get_orientation(i); //获取方向
_angle[sector] = sector * 45; //获取角度
_distance[sector] = rngfnd->distance_cm(i) / 100.0f; //获取距离
_distance_min = rngfnd->min_distance_cm(i) / 100.0f; //最小距离
_distance_max = rngfnd->max_distance_cm(i) / 100.0f; //最大距离
_distance_valid[sector] = (_distance[sector] >= _distance_min) && (_distance[sector] <= _distance_max); //是否在限制的范围
_last_update_ms = AP_HAL::millis(); //获取上次时间
update_boundary_for_sector(sector);//这里是更新扇区的介绍,重要函数
}
//检查向上测距仪----------check upward facing range finder
if (rngfnd->get_orientation(i) == ROTATION_PITCH_90)
{
_distance_upward = rngfnd->distance_cm(i) / 100.0f;
_last_upward_update_ms = AP_HAL::millis();
}
}
}
//检查超时并设置健康状态--------- check for timeout and set health status
if ((_last_update_ms == 0) || (AP_HAL::millis() - _last_update_ms > PROXIMITY_RANGEFIDER_TIMEOUT_MS))
{
set_status(AP_Proximity::Proximity_NoData);
} else
{
set_status(AP_Proximity::Proximity_Good);
}
}
获取到的这些值应该传到避障控制函数中,
怎么传过去的,要看这个函数:update_boundary_for_sector(sector)//更新边界区域
这个函数最终会计算得到避障边界点数据:_boundary_point[]
3.避障控制实现
下面这个函数是控制航行器速度的:
_avoid->adjust_velocity(_pos_control.get_pos_xy_kP(),_loiter_accel_cmss, desired_vel);
具体实现:
void AC_Avoid::adjust_velocity(float kP, float accel_cmss, Vector2f &desired_vel)
{
//没有使能立即退出---exit immediately if disabled
if (_enabled == AC_AVOID_DISABLED)
{
return;
}
//限制加速度------limit acceleration
float accel_cmss_limited = MIN(accel_cmss, AC_AVOID_ACCEL_CMSS_MAX);
if ((_enabled & AC_AVOID_STOP_AT_FENCE) > 0) //这个是围栏设置,可以先不看
{
adjust_velocity_circle_fence(kP, accel_cmss_limited, desired_vel);
adjust_velocity_polygon_fence(kP, accel_cmss_limited, desired_vel);
}
if ((_enabled & AC_AVOID_USE_PROXIMITY_SENSOR) > 0 && _proximity_enabled) //采用近距传感器,重点看这里
{
adjust_velocity_proximity(kP, accel_cmss_limited, desired_vel); //根据近距离传感器调节速度
}
}
在这个函数adjust_velocity_proximity(kP, accel_cmss_limited, desired_vel) 中有如下代码:
……………………………………………………
//从近距传感器获取边界-----------get boundary from proximity sensor
uint16_t num_points;
const Vector2f *boundary = _proximity.get_boundary_points(num_points);//计算边界点
adjust_velocity_polygon(kP, accel_cmss, desired_vel, boundary, num_points, false, _margin); //通过避障点计算所需要的目标速度。