【Apollo源码分析】系列的第二部分【perception】
【Apollo源码分析】系列的第二部分【perception】
perception
perception:感知模块 仍然是 处于待完善的状态。只有200行代码左右。
下面简单介绍一下。
perception模块的主要作用是根据激光雷达Lidar, 摄像机camera等传感器 sensors接收的数据来感知周围环境。
主要任务是对物体进行检测,对行人进行识别,对交通信号灯进行判断,对道路车辆进行感知判断。
感知模块与其他模块一样是一个独立的进程。与其他模块通过tcp/共享内存进行通信。
perception/perception.h
class Perception : public apollo::common::ApolloApp {
public:
std::string Name() const override;//模块名
apollo::common::Status Init() override;//初始化步骤
apollo::common::Status Start() override;//模块工作内容:主要是检测交通信号灯和障碍物等。
void Stop() override; //清理函数
};
using apollo::common::adapter::AdapterManager;
using apollo::common::Status;
std::string Perception::Name() const { return "perception"; }//模块名称
Status Perception::Init() { //模块启动初始化
AdapterManager::Init();
return Status::OK();
}
目前整个模块的核心:
Status Perception::Start() {
ros::AsyncSpinner spinner(1);
spinner.start();
ros::waitForShutdown();
spinner.stop();
ros::Rate loop_rate(FLAGS_perception_loop_rate);//感知频率,默认是10hz
while (ros::ok()) {
AdapterManager::Observe();///进行一次感知测量/检测
PerceptionObstacles perceptionObstacles;///检测障碍物实例对象
AdapterManager::FillPerceptionObstaclesHeader(
Name(), perceptionObstacles.mutable_header());
AdapterManager::PublishPerceptionObstacles(perceptionObstacles);///向ROS发布检测到的障碍物对象
TrafficLightDetection trafficLightDetection;///检测交通信号灯
AdapterManager::FillTrafficLightDetectionHeader(
Name(), trafficLightDetection.mutable_header());
///向ROS发布检测到的交通信号灯结果
AdapterManager::PublishTrafficLightDetection(trafficLightDetection);
}
return Status::OK();
}
好了,现在可以看出perception的核心了。虽然有检测障碍物和交通信号灯的代码,但是却没有任何意义。
因为这2者的构造函数都执行默认构造函数,也就是说目前perception模块只是搭建了这样一个感知检测模块流程。但是如何检测障碍物和如何探知交通信号灯却没有任何实现。所以说Apollo 1.0 只能在封闭道路行驶。要是放到大马路上去,是100%要【撞行人+闯红灯】的。
perception/common/perception_gflags.*
DEFINE_int32(perception_loop_rate, 10, "Loop rate for perception node, in Hz.");//感知频率,10hz
DEFINE_string(node_name, "perception", "The perception module name in proto");//模块名称
下面是障碍物的描述信息proto文件内容:
syntax = "proto2";
package apollo.perception;
import "modules/common/proto/error_code.proto";
import "modules/common/proto/header.proto";
//point是感知的三维点。三维坐标xyz单位是m。
//如何感知Point?APollo没有给出。个人估计是激光雷达+VIO视觉算法(单目.双目.深度相机)
message Point {
optional double x = 1; // in meters.
optional double y = 2;
optional double z = 3;
}
//障碍物描述信息。
//
message PerceptionObstacle {
optional int32 id = 1; // obstacle ID.障碍物标识id
optional Point position = 2; // obstacle position in the world coordinate
// system.障碍物坐标
optional double theta = 3; // 障碍物head角,heading in the world coordinate system.
optional Point velocity = 4; // 障碍物移动速度。obstacle velocity.
// Size of obstacle bounding box.
//障碍物的AABB描述子
optional double length = 5; // obstacle length.
optional double width = 6; // obstacle width.
optional double height = 7; // obstacle height.
//障碍物的角点
repeated Point polygon_point = 8; // obstacle corner points.
//持续时间
// duration of an obstacle since detection in s.
optional double tracking_time = 9;
//障碍物类型
enum Type {
UNKNOWN = 0;
UNKNOWN_MOVABLE = 1;
UNKNOWN_UNMOVABLE = 2;
PEDESTRIAN = 3; // Pedestrian, usually determined by moving behaviour.
BICYCLE = 4; // bike, motor bike
VEHICLE = 5; // Passenger car or truck.
};
optional Type type = 10; // obstacle type
//测量时间
optional double timestamp = 11; // GPS time in seconds.
//debug使用的点云信息
// Format like : [x0, y0, z0, x1, y1, z1...]
repeated double point_cloud = 12 [packed = true];
}
//障碍物集合
message PerceptionObstacles {
repeated PerceptionObstacle perception_obstacle = 1; // An array of obstacles
optional apollo.common.Header header = 2; // Header
optional apollo.common.ErrorCode error_code = 3 [default = OK];
}
交通信号灯检测内容:
syntax = "proto2";
package apollo.perception;
import "modules/common/proto/header.proto";
//交通信号灯检测内容
message TrafficLight {
//交通信号状态,红绿蓝
enum Color {
UNKNOWN = 0;
RED = 1;
YELLOW = 2;
GREEN = 3;
};
optional Color color = 1;
//交通灯唯一标识符ID
optional string id = 2;
//检测结果置信概率
optional double confidence = 3 [default = 1.0];
//检测持续时间
optional double tracking_time = 4;
}
message TrafficLightDetection {
optional apollo.common.Header header = 2;//head信息
repeated TrafficLight traffic_light = 1;///检测对象内容
}
地图描述文件:
syntax = "proto2";
package apollo.perception;
import "modules/common/proto/header.proto";
import "modules/map/proto/map.proto";
//地图感知信息
message PerceptionMapROI {
optional apollo.common.Header header = 1; // Header.
optional apollo.hdmap.Header hdmap_header = 8; // HDMap header.
//地图xy方向最小值
optional double origin_x = 2;
optional double origin_y = 3;
//将地图均匀分割为小网格表示。
//网格大小是grid_size,以米为单位。
//num_rows是x方向网格数量。num_columns是y方向网格数量
optional double grid_size = 4;
optional int32 num_rows = 5;
optional int32 num_columns = 6;
// 网格中特定区域的位置描述.[x0,x1],[y0,y1]
message Region {
optional int32 start_x = 1;
optional int32 end_x = 2;
optional int32 start_y = 3;
optional int32 end_y = 4;
//路沿距离
optional int32 extension_distance = 5;
}
//多个区域。
repeated Region region = 7;
}
perception/main.cc
APOLLO_MAIN(apollo::perception::Perception);
注册一个模块并进行本模块的相关工作。
总结
目前来说,perception模块只是一个粗略的框架。 真正利用激光雷达Lidar, 摄像机camera来感知周围环境的算法仍然没有实现。目前只是对物体检测,通信号灯判断,道路行人感知进行了接口定义和属性描述。Apollo 1.0 只能说把框架搭好了,但是如何实现这个框架的内容目前仍然是一片空白。而这是无人驾驶的重中之重。缺少这个模块可以说距离无人车真正上路行驶还差的十分遥远。
我所知道的无人驾驶目前能做到的感知算法的能力:
图1:
图2:
图3:
图4:
图5:
可见无人车的感知模块真的是一个非常复杂的系统工程。感知能力的强弱直接决定了一个无人车系统的核心竞争力。
本文首发于微信公众号slamcode。
在blog.****.net/learnmoreonce亦有连载。
注释版源码:源码