百度Apollo感知模块(perception)红绿灯检测代码解析
背景
最近在读apollo感知模块下的红绿灯检测,apollo框架思路清晰,风格规范,值得多读。直接上代码文件:trafficlights_perception_component.cc
trafficlights_perception_component.cc
整个trafficlights_perception_component.cc文件的函数主要分为三部分:以init开头的初始化部分,红绿灯模块的主函数OnReceiveImage,以及被主函数直接/间接调用的其他函数。
突然想写个记录,主函数已经扒得七七八八了,现在主要在抠细节,所以直接上细节函数的分析了,随写随更,部分简单的判断函数就不写了,懂的都懂。
ps:下面的函数顺序是按照函数的执行顺序写的,属于该文件的函数写在标题,不属于该文件的被调用的其他文件的函数挂在标题函数下面
pps: 目前自己c++技能还不太到位,有些描述不精准的自己看代码
UpdateLightsProjection()
- 接收参数
const CarPose &pose; // 保存汽车相关信息的变量
const TLPreprocessorOption &option; // 这个没看懂是干什么的
const std::string &camera_name; // 传来的相机名称,因为自动驾驶包括了多个摄像头,所以必须区分不同相机
std::vector<base::TrafficLightPtr> *lights; // 传来红绿灯信息指针,是个向量,向量每个元素就是一个红绿灯信息
清除变量,AINFO输出信息到日志:
lights_on_image_.clear();
lights_outside_image_.clear();
AINFO << "clear lights_outside_image_ " << lights_outside_image_.size();
判断lights
指针是否为空。空则不需要做映射,因为红绿灯的检测是阶段性地启动,在汽车进入红绿检测范围才会执行红绿灯检测;非空则说明已经通过汽车的坐标获取到了红绿灯在三维世界的坐标。判断代码很简单,如下:
if (lights->empty()) {
AINFO << "No lights to be projected";
return true;
}
lights
非空后执行映射函数ProjectLights(),该函数返回布尔值,以判断映射是否成功执行,映射失败则AERROR到监控器和日志中:
if (!ProjectLights(pose, camera_name, lights, &lights_on_image_, &lights_outside_image_)) {
AERROR << "update_lights_projection project lights on " << camera_name << " image failed";
return false;
}
判断映射后的图像坐标是否超出视频图像帧的范围:
if (lights_outside_image_.size() > 0) {
AERROR << "update_lights_projection failed," << "lights_outside_image->size() " << lights_outside_image_.size() << " ts: " << pose.getTimestamp();
return false;
}
后面的代码还没看,暂时不写了:
auto min_focal_len_working_camera = GetMinFocalLenWorkingCameraName();
if (camera_name == min_focal_len_working_camera) {
return lights_on_image_.size() > 0;
}
for (const base::TrafficLightPtr &light : lights_on_image_) {
if (OutOfValidRegion(light->region.projection_roi,
projection_.getImageWidth(camera_name),
projection_.getImageHeight(camera_name),
option.image_borders_size->at(camera_name))) {
AINFO << "update_lights_projection light project out of image region. "
<< "camera_name: " << camera_name;
return false;
}
}
AINFO << "UpdateLightsProjection success";
return true;
ProjectLights()
- 接收参数
const CarPose &pose; // 保存汽车相关信息的变量
const std::string &camera_name; // 传来的相机名称,因为自动驾驶包括了多个摄像头,所以必须区分不同相机
std::vector<base::TrafficLightPtr> *lights; // 传来红绿灯信息指针,是个向量,向量每个元素就是一个红绿灯信息
base::TrafficLightPtrs *lights_on_image; // 指向一个向量的指针,向量的每个元素都是一个红绿灯指针,每个红绿灯指针指向一个红绿灯信息
base::TrafficLightPtrs *lights_outside_image; // 同上 ,只是上面保存的是映射在图片中的红绿灯信息,这个保存了映射在图片外的红绿灯信息
读到第一部分发现和上个函数同样的指针判空,太好了可以抄自己作业:
判断lights
指针是否为空。空则不需要做映射,因为红绿灯的检测是阶段性地启动,在汽车进入红绿检测范围才会执行红绿灯检测;非空则说明已经通过汽车的坐标获取到了红绿灯在三维世界的坐标。判断代码很简单,如下:
if (lights->empty()) {
AINFO << "No lights to be projected";
return true;
}
判断相机是否正确,相应模块是否启动。HasCamera判断相机相机名是否在相机名列表中,且相应的模块是否启动,返回布尔值:
if (!projection_.HasCamera(camera_name)) {
AERROR << "project_lights get invalid camera_name: " << camera_name;
return false;
}
相机没问题继续执行下面代码。初始化布尔变量is_working
,调用**GetCameraWorkingFlag()**函数执行。注意,调用该函数时,传进的参数is_working
是使用了引用&
,也就意味着该函数执行会改变is_working
的值,然后根据返回的布尔结果判断是否AWARN到日志中:
// camera is not working
bool is_working = false;
if (!GetCameraWorkingFlag(camera_name, &is_working) || !is_working) {
AWARN << "TLPreprocessor::project_lights not project lights, " << "camera is not working, camera_name: " << camera_name;
return true;
}
is_working
在上面的代码执行后会从false变为true,表示相机正常工作,继续执行下面的代码:
for (size_t i = 0; i < lights->size(); ++i) {
base::TrafficLightPtr light_proj(new base::TrafficLight); // 申请一个新的TrafficLightPtr指针
auto light = lights->at(i);
if (!projection_.Project(pose, ProjectOption(camera_name), light.get())) { // 利用if判断被调函数Project结果,正常流程应该走else,进if则说明映射到帧上的坐标超出了图像大小
light->region.outside_image = true;
*light_proj = *light;
lights_outside_image->push_back(light_proj);
} else {
light->region.outside_image = false; // 如果Project成功执行,则将light指针下的region下的outside_image设为false,表示没有超出图片
*light_proj = *light; // 传递正确映射的指针
lights_on_image->push_back(light_proj); // 将指针推入lights_on_image向量中保存
}
}
return true; // 返回ProjectLights函数执行的结果,即正确执行
MultiCamerasProjection::Project()
- 接收参数
const Eigen::Vector3f& point3d; //
上一篇: centos安装python3.6.5
下一篇: 两种方法求x的n次幂