國外大型網(wǎng)站曹操seo博客
1. abstract
本文主要講解routing和planning模塊中的reference line,我之前一直搞不明白這個(gè)reference line是如何生成的,有什么作用,和routing以及planning的關(guān)系。現(xiàn)在有了一些心得打算梳理一下:
決策規(guī)劃模塊負(fù)責(zé)生成車輛的行駛軌跡。要做到這一點(diǎn),決策規(guī)劃模塊需要從宏觀到局部經(jīng)過三個(gè)層次來進(jìn)行決策。
- 第一個(gè)層次是Routing的搜索結(jié)果。Routing模塊的輸入是若干個(gè)按順序需要達(dá)到的途徑點(diǎn)(也可能只有一個(gè)起點(diǎn)和終點(diǎn))。Routing模塊根據(jù)地圖的拓?fù)浣Y(jié)構(gòu)搜索出可達(dá)的完整路線來,這個(gè)路線的長度可能是幾公里甚至幾百公里。因此這個(gè)是最為宏觀的數(shù)據(jù)。另外,Routing的搜索結(jié)果是相對(duì)固定的。在沒有障礙物的情況下,車輛會(huì)一直沿著原先獲取到的Routing路線行駛。只有當(dāng)車輛駛出了原先規(guī)劃的路線之外(例如:為了避障),才會(huì)重新發(fā)送請(qǐng)求給Routing模塊,以重新計(jì)算路線。
- 第二個(gè)層次就是reference line。決策規(guī)劃模塊會(huì)實(shí)時(shí)的根據(jù)車輛的具體位置來計(jì)算reference line。reference line的計(jì)算會(huì)以Routing的路線為基礎(chǔ)。但同時(shí),reference line會(huì)考慮車輛周邊的動(dòng)態(tài)信息,例如:障礙物,交通規(guī)則等。reference line是包含車輛所在位置周邊一定的范圍,通常是幾百米的長度。相較于Routing結(jié)果,它是較為局部的數(shù)據(jù)。
- 第三個(gè)層次是Trajectory。Trajectory是決策規(guī)劃模塊的最終輸出結(jié)果。它的依據(jù)是reference line。在同一時(shí)刻,reference line可能會(huì)有多條,例如:在變道的時(shí)候,自車所在車道和目標(biāo)車道都會(huì)有一條reference line。而Trajectory,是在所有可能的結(jié)果中,綜合決策和優(yōu)化的結(jié)果,最終的唯一結(jié)果。因此它是更為具體和局部的數(shù)據(jù)。軌跡不僅僅包含了車輛的路線,還包含了車輛行駛這條路線時(shí)的詳細(xì)狀態(tài),例如:車輛的方向,速度,加速度等等。
參考線是整個(gè)決策規(guī)劃算法的基礎(chǔ)。在Planning模塊的每個(gè)計(jì)算循環(huán)中,都會(huì)先生成參考線,然后在這個(gè)基礎(chǔ)上進(jìn)行后面的處理,例如:交通規(guī)則邏輯,障礙物投影,路徑優(yōu)化,速度決策等等。可以說,參考線貫穿了整個(gè)Planning模塊的實(shí)現(xiàn)。下面就看下reference line如何在routing和plannin中承前啟后的:
從這幅圖中可以看出,這里涉及到三個(gè)模塊,下面會(huì)挨個(gè)梳理:
- routing模塊,這部分內(nèi)容追在Routing模塊一文中講解,本文不再贅述。
- **pnc_map模塊:負(fù)責(zé)讀取和處理Routing搜索結(jié)果。**是planning的子模塊,因?yàn)橹匾桶阉麊为?dú)拎出來了。
- planning模塊:根據(jù)Routing結(jié)果和車輛的實(shí)時(shí)狀態(tài)(包括周邊環(huán)境)生成reference line和trajectory。
2. routing
Routing模塊正如其名稱所示,其主要作用就是根據(jù)請(qǐng)求生成路由信息。
模塊輸入:
- 地圖數(shù)據(jù)
- 請(qǐng)求,包括:
- 開始和結(jié)束位置
模塊輸出:
- 路由導(dǎo)航信息
2.1 Topo地圖
為了計(jì)算路由路徑,在Routing模塊中包含一系列的類用來描述Topo地圖的詳細(xì)結(jié)構(gòu)。這些類的定義位于modules/routing/graph/
目錄下。它們的說明如下:
簡(jiǎn)單來說,Topo地圖中最重要的就是節(jié)點(diǎn)和邊,本質(zhì)上是一系列的Topo節(jié)點(diǎn)以及它們的連接關(guān)系,節(jié)點(diǎn)對(duì)應(yīng)了道路,邊對(duì)應(yīng)了道路的連接關(guān)系,這個(gè)在Apollo開發(fā)者社區(qū)的技術(shù)文章中著重講過。如下圖所示:
Routing模塊需要的地圖結(jié)構(gòu)通過TopoGraph來描述,而TopoGraph的初始化需要一個(gè)地圖文件。但該地圖文件與其他模塊需要的地圖文件并不一樣,這里的地圖文件是Proto結(jié)構(gòu)導(dǎo)出的數(shù)據(jù)。之所以這樣做是因?yàn)?#xff1a;Routing模塊不僅需要地圖的Topo結(jié)構(gòu),還需要知道每條路線的行駛代價(jià)。在Proto結(jié)構(gòu)中包含了這些信息。在下面的內(nèi)容中,我們將看到這個(gè)行駛代價(jià)是從哪里來的。
很顯然,兩個(gè)地點(diǎn)的導(dǎo)航路徑結(jié)果通常會(huì)有多個(gè)。而計(jì)算導(dǎo)航路徑的時(shí)候需要有一定的傾向,這個(gè)傾向就是行駛的代價(jià)越小越好。我們很自然的想到,影響行駛代價(jià)最大的因素就是行駛的距離。
但實(shí)際上,影響行駛代價(jià)的因素遠(yuǎn)不止距離這一個(gè)因素。距離只是宏觀上的考慮,而從微觀的角度來看,行駛過程中,需要進(jìn)行多少次轉(zhuǎn)彎,多少次掉頭,多少變道,這些都是影響行駛代價(jià)的因素。所以,在計(jì)算行駛代價(jià)的時(shí)候,需要綜合考慮這些因素。
再從另外一個(gè)角度來看,(在路線已經(jīng)確定的情況下)行駛的距離是一個(gè)物理世界客觀存在的結(jié)果,這是我們無法改變的。不過,對(duì)于行駛過程中,有多在意轉(zhuǎn)彎,掉頭和變道,每個(gè)人或者每個(gè)場(chǎng)景下的偏好就不一樣了。而這,就是配置文件“/apollo/modules/routing/conf/routing/config.pb.txt“存在的意義了。這里面配置了上面提到的這些動(dòng)作的懲罰基數(shù),而這些基數(shù)會(huì)影響路線時(shí)的計(jì)算代價(jià)。
routing的請(qǐng)求接口是下面這個(gè):
bool Routing::Process(const std::shared_ptr<RoutingRequest> &routing_request, RoutingResponse* const routing_response);
這個(gè)接口只有很簡(jiǎn)潔的兩個(gè)參數(shù):一個(gè)是描述請(qǐng)求的輸入?yún)?shù)routing_request
,一個(gè)是包含結(jié)果的輸出參數(shù)routing_response
。它們都是在proto文件中定義的。
2.2 RoutingRequest
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;repeated LaneWaypoint waypoint = 2;repeated LaneSegment blacklisted_lane = 3;repeated string blacklisted_road = 4;optional bool broadcast = 5 [default = true];optional apollo.hdmap.ParkingSpace parking_space = 6;
}
2.3 RoutingResponse:
message RoutingResponse {optional apollo.common.Header header = 1;repeated RoadSegment road = 2;optional Measurement measurement = 3;optional RoutingRequest routing_request = 4;optional bytes map_version = 5;optional apollo.common.StatusPb status = 6;
}message RoadSegment {optional string id = 1;repeated Passage passage = 2;
}message Passage {repeated LaneSegment segment = 1;optional bool can_exit = 2;optional ChangeLaneType change_lane_type = 3 [default = FORWARD];
}message LaneSegment {optional string id = 1;optional double start_s = 2;optional double end_s = 3;
}enum ChangeLaneType {FORWARD = 0;LEFT = 1;RIGHT = 2;
};message Measurement {optional double distance = 1;
}
RoutingResponse中的屬性說明如下:
這里的RoadSegment road
是最重要的數(shù)據(jù)。這個(gè)數(shù)據(jù)其實(shí)是一個(gè)三層的結(jié)構(gòu)體嵌套,它們的說明如下:
RoadSegment road
:描述道路,一條道路可能包含了并行的幾條通路(Passage)。Passage
:描述通路,通路是直連不含變道的可行駛區(qū)域。一個(gè)通路可能包含了前后連接的多個(gè)車道。(對(duì)應(yīng)了pac_map中的RouteSegments
)LaneSegment
:描述車道,車道是道路中的一段,自動(dòng)駕駛車輛會(huì)盡可能沿著車道的中心線行駛。
3. pnc_map
pnc全稱是Planning And Control,是Planning用來對(duì)接Routing搜索結(jié)果的子模塊,但他比較重要,這里我把它單獨(dú)拎出來梳理下。
PncMap
類負(fù)責(zé)對(duì)接Routing搜索結(jié)果的更新:會(huì)根據(jù)車輛當(dāng)前位置,提供車輛周邊的RouteSegments
信息供ReferenceLineProvider
生成ReferenceLine
。而這里的RouteSegments
對(duì)應(yīng)了routing模塊里RoutingResponse
里的Passage
結(jié)構(gòu),它其中會(huì)包含若干個(gè)車道信息。這個(gè)RouteSegments類繼承自std::vector。RouteSegments中有如下一些方法值得關(guān)注:
- NextAction():車輛接下來要采取的動(dòng)作??赡苁侵毙?#xff0c;左變道,或者右變道。
- CanExit():當(dāng)前通路是否可以接續(xù)到Routing結(jié)果的另外一個(gè)通路上。
- GetProjection():將一個(gè)點(diǎn)投影到當(dāng)前通路上。返回SLPoint和LaneWaypoint。
- Stitch():縫合另外一個(gè)RouteSegments。即:去除兩個(gè)RouteSegments間重合的多余部分,然后連接起來。
- Shrink():縮短到指定范圍。
- IsOnSegment():車輛是否在當(dāng)前RouteSegments上。
- IsNeighborSegment():當(dāng)前RouteSegments是否是車輛的臨近RouteSegments。
4. planning
在Planning模塊中有以下三個(gè)數(shù)據(jù)結(jié)構(gòu)將是本文關(guān)注的重點(diǎn):
ReferenceLine
:原始參考線,源碼位于planning/reference_line/
目錄下。根據(jù)Routing的搜索結(jié)果生成。ReferenceLineInfo
:源碼位于planning/reference_line/
目錄下。Planning實(shí)現(xiàn)中,邏輯計(jì)算的基礎(chǔ)數(shù)據(jù)結(jié)構(gòu),很多操作都會(huì)在這個(gè)數(shù)據(jù)結(jié)構(gòu)上進(jìn)行(例如:交通規(guī)則邏輯,障礙物投影,路徑優(yōu)化,速度決策等)。本文中的“參考線”一詞將不區(qū)分ReferenceLine
和ReferenceLineInfo
兩個(gè)結(jié)構(gòu)。Trajectory
:下文中我們將看到,有好幾個(gè)結(jié)構(gòu)用來描述軌跡。它們?cè)诓煌膱?chǎng)合下使用。這其中,ADCTrajectory
是Planning模塊的輸出。它是Planning模塊一次計(jì)算循環(huán)中,處理了所有邏輯的最終結(jié)果,包含了車輛行駛需要的所有信息。因此,這個(gè)數(shù)據(jù)將直接影響到自動(dòng)駕駛車輛的行車行為。
5. reference
解析百度Apollo之Routing模塊
解析百度Apollo之參考線與軌跡
開發(fā)者說丨離散點(diǎn)曲線平滑原理
直播回顧丨Apollo自動(dòng)駕駛論壇①規(guī)劃模塊算法解析
Apollo Planning Frame
Apollo ReferenceLineProvider
Apollo EMPlanner(v 3.0)
Apollo 6.0 規(guī)劃算法解析
Apollo 6.0 規(guī)劃模塊算法解析2