Apollo 2.0/2.5 規劃子產品代碼層次結構說明
本文檔将從代碼層面講解Apollo Planning規劃子產品的工作,規劃子產品是一個相對比較複雜的子產品,他可以接受來自定位Localization、高精地圖HD Map、交通燈子產品Traffic Light,路由子產品Routing以及預測子產品Prediction的資訊,并且綜合上述資訊,給出無人駕駛汽車在目前環境下短期内的路徑規劃。注意這個規劃僅僅是短期的。
Apollo針對路徑規劃的思想是,利用Routing子產品産生一條目前位置到終點的路徑,這條路徑是很理想的,不會考慮實際的路況與環境資訊。Planning子產品就是利用Routing産生的理想軌迹,結合目前路況下信号燈(Traffic Light子產品得到),障礙物短期内的運動軌迹(Prediction子產品得到的LaneSequence及其機率),來修正短期内無人駕駛汽車的路徑(也就是決策),通過Planning得到的一個修正的路徑以後行駛到新的位置,可以根據這個新的位置再次去查詢Routing子產品,得到新的路由軌迹,以此往複,直到到達終點。
這一節将從代碼入手,詳細講解Planning子產品的各個細節,小結與Prediction子產品類似,首先介紹Planning子產品中的各個元件,分析每個元件的功能和算法,最後整體分析Planning子產品的工作流程。
Planning子產品元件分為以下部分:
1.車輛狀态提供器: VehicleStateProvider
這是最簡單的元件,他負責将定位Localization與底盤Chassis資訊進行融合,得到目前車輛的狀态
2. 規劃與控制地圖: Planning and Control Map, pnc map
pnc map其實和高精地圖hd map沒有關系,後者是專門為規劃與控制子產品設計的庫函數,在hd map層次之上,負責一些地圖相關資訊的處理。例如查詢車輛可能的形式路徑(list)
3. 指引線提供器: Reference Line Provider
指引線提供器其實就是路徑的生成,對于一系列的RouteSegments進行平滑與拼接,最終得到無人車行駛的指引線,也就是行駛路徑。
額外補充
最後我們額外補充一下,Planning和Routing子產品的核心資料結構。其中包括路由查詢RoutingRequest與路由響應RoutingResponse。
/// file in apollo/modules/routing/proto/routing.proto
message LaneWaypoint {
optional string id = 1;
optional double s = 2;
optional apollo.common.PointENU pose = 3;
}
message LaneSegment {
optional string id = 1;
optional double start_s = 2;
optional double end_s = 3;
}
message RoutingRequest {
optional apollo.common.Header header = 1;
// at least two points. The first is start point, the end is final point.
// The routing must go through each point in waypoint.
repeated LaneWaypoint waypoint = 2;
repeated LaneSegment blacklisted_lane = 3;
repeated string blacklisted_road = 4;
optional bool broadcast = 5 [default = true];
}
從上述的protobuf定義内容可以看到:
- RoutingRequest裡面的waypoint(LaneWaypoint類型)是路徑查詢的核心,例如我要查詢公交站A到學校B的一條路徑,那麼waypoint就是兩個;如果我要查詢公交站A到學校B的一條路徑,并且我還要經過早餐店C,那麼最終的waypoint就是三個。
- LaneSegment和Prediction中的LaneSegment一樣,定義了一條車道的[start_s, end_s]路段區間,使用repeated形式可以完整的離散化定義一條車道。
- LaneWaypoint可以定義車道上的任意一點,包括所在車道id,所在車道的累計距離s,以及世界坐标系下的坐标pose。
message Measurement {
optional double distance = 1;
}
enum ChangeLaneType {
FORWARD = 0;
LEFT = 1;
RIGHT = 2;
};
message Passage {
repeated LaneSegment segment = 1;
optional bool can_exit = 2;
optional ChangeLaneType change_lane_type = 3 [default = FORWARD];
}
message RoadSegment {
optional string id = 1;
repeated Passage passage = 2;
}
message RoutingResponse {
optional apollo.common.Header header = 1;
repeated RoadSegment road = 2;
optional Measurement measurement = 3;
optional RoutingRequest routing_request = 4;
// the map version which is used to build road graph
optional bytes map_version = 5;
optional apollo.common.StatusPb status = 6;
}
以上是路徑查詢的傳回/響應結果RoutingResponse,其中routing_request是對應發出的查詢,measurement是行駛距離,最核心的内容就是road(repeated RoadSegment),這是一條從起點公交站A到重點學校B,并且經過中間早餐店C的完整路徑,由一段段離散化的RoadSegment組成。
RoadSegment類型包含了repeated Passage,這意味着,一個RoadSegment中包含了多個通道,每個通道可以了解為一條車道,一個道路段RoadSegment可以有多條并行向前行駛的車道。而Passage中每條車道可以有多個LaneSegment組成,意味着進一步劃分成小的區間段,便于精細化排程。
最終的可視化結果如下圖所示
如有侵權,請聯系本人删除!
參考資料:
https://github.com/YannZyl/Apollo-Note/blob/master/docs/planning/planning_arch.md