調(diào)優(yōu)指南)
MATLAB 里的駕駛場景設計器Driving Scenario Designer下文簡稱 DSD是我這幾年做自動駕駛彎道仿真的默認起點。它不神秘本質上就是一個帶道路編輯器的場景裝配臺你畫出中心線、拉出車道、擺上幾臺車、配好速度軌跡按下運行就能看到車沿著你畫的線跑起來。真正卡住人的從來不是“按鈕在哪”而是“為什么這么點”——為什么中心點要多密、為什么速度剖面必須跟路徑點一一對應、為什么仿真步長稍大一點車就切出車道。下面我把自己反復折騰出來的一整套流程攤開講從環(huán)境自查到代碼級拆解彎道怎么畫、速度怎么算、坑怎么填全部是可復制的東西。這篇內(nèi)容適合兩類人看剛接手駕駛仿真、需要在一小時內(nèi)跑出第一條彎道的新手已經(jīng)在用 DSD 但總被“車飛出去”“傳感器啥也測不到”“導出 Simulink 后場景不動”折磨的同行。全文以 MATLAB 腳本為主線圖形界面只作為校驗和兜底手段因為腳本可以版本管理、可以參數(shù)化、可以批量跑這三點在真實測試流程里比“點得爽”重要得多。1. 先把工具的能力邊界摸清楚1.1 彎道為什么是仿真里最“貴”的場景直線段仿真幾乎沒有技術含量車速恒定、航向恒定、車道邊界平行任何一套邏輯都能跑出漂亮結果。彎道就不一樣了它同時把四個維度的復雜度擰在一起幾何上曲率隨弧長變化車輛模型需要持續(xù)輸出橫向加速度感知上車道線從直線變成圓弧擬合算法要用二次或三次曲線去逼近控制上預瞄距離和前視點必須隨曲率調(diào)整否則純跟蹤算法會切內(nèi)道評價上橫向誤差、航向誤差、舒適性指標全都跟曲率強相關。這就是為什么很多人直線跑得挺順一進彎就原形畢露。DSD 在這方面提供的價值不是“畫個彎”而是把道路幾何、車輛運動學和傳感器模型綁在同一個時間軸上。你畫的中心線會被擬合成帶曲率連續(xù)性的道路車輛沿軌跡行駛時每一幀的位置、朝向、速度都是自洽的雷達和攝像頭模型拿到的也是同一套真值。這一點很關鍵——如果道路用一套坐標、車輛用另一套坐標、傳感器再用第三套你后面排查問題會瘋掉。另一個容易被忽略的點是彎道對時步的敏感性。直線上車輛朝某個方向勻速走步長 0.1 秒的影響無非是位置跳了一米彎道上同樣的步長會讓航向角每次跳好幾度視覺上就是車在一格一格地“拐硬彎”傳感器打出去的光束也會跟著抖動。所以彎道場景做得好不好很大程度取決于你對采樣率的把控而不是畫得多漂亮。1.2 圖形界面和腳本各自該干哪一半我見過不少人一上來就打開 App鼠標拖著中心點一個個點點完發(fā)現(xiàn)想改半徑只能全部推倒重來。這屬于用錯了工具的分工。我的習慣是探索性設計用界面可復現(xiàn)場景用腳本。第一次試某個彎道形態(tài)、想快速看看車道寬度和轉彎半徑比例是否合理打開drivingScenarioDesigner拖兩下確實快但一旦形態(tài)確定立刻把中心點坐標抄進腳本后面所有迭代都在代碼里做。界面的另一個正確用法是反向校驗。腳本跑出來的場景可以一鍵喂回 AppdrivingScenarioDesigner(scenario)把變量加載進去你就能在圖形界面里看到道路邊界、車道線、車輛軌跡、傳感器覆蓋范圍疊在一起的樣子。有些問題在命令行里看不出來比如兩條車道線在彎心處交叉、車輛軌跡貼著路緣擦過去圖形界面上一眼就能發(fā)現(xiàn)。這種“腳本生成 界面審查”的雙向流程比純界面或純腳本都高效。還有一個功能值得單獨提App 的 Tools 菜單里有一個針對道路和車輛時步的檢查項。它會把你的速度、采樣時間、道路曲率放在一起算一遍告訴你當前配置下車輛每步移動的距離是否超出了合理范圍。這個檢查我在項目里救過好幾次場——用高車速配 0.1 秒步長時它會直接標紅提示省得你后面花兩小時去查“為什么車會瞬移”。2. 動手前的環(huán)境自查與最小驗證2.1 工具箱、版本與常見依賴DSD 不是一個獨立產(chǎn)品它掛在自動駕駛工具箱體系下同時依賴場景建模的基礎設施。裝環(huán)境時至少確認這幾塊自動駕駛相關工具箱提供drivingScenario、vehicle、trajectory、各類傳感器生成器、導航與地圖相關工具箱部分道路擬合和曲線工具在這里、以及基礎的 MATLAB 本體。如果你的流程要接 Simulink 做閉環(huán)那 Simulink 和對應的場景讀取模塊也得在。版本差異是個真實的坑。同一個函數(shù)在不同年份的版本里參數(shù)名會變尤其是傳感器生成器那一塊屬性名和返回值順序調(diào)整過好幾次。我的經(jīng)驗是先鎖定一個版本再寫代碼把版本號寫在腳本頭部注釋里別今天用新版本跑通、明天換臺機器用舊版本報錯然后花半天懷疑人生。另外函數(shù)簽名不確定的時候別硬猜直接在命令行敲help 函數(shù)名看當前這個版本到底怎么寫的比在網(wǎng)上翻三年前的帖子靠譜得多。道路擬合部分需要說明一下它的原理。DSD 在根據(jù)你給的中心點生成道路時用的是回旋線clothoid擬合也就是曲率隨弧長線性變化的曲線。這個東西在公路設計里是標準做法——直線段曲率是 0圓曲線曲率是常數(shù) 1/R中間用回旋線過渡保證曲率連續(xù)。好處是車輛沿路行駛時方向盤轉角不會突變壞處是你給的中心點如果本身跳變很大擬合出來的道路可能偏離你預期的形狀。理解這一點你就知道為什么中心點不能隨手點了。2.2 三行代碼驗證環(huán)境是否真的可用在正式畫彎道之前我建議先跑一個最小閉環(huán)確認整條鏈路是通的。三行代碼就夠scenario drivingScenario(SampleTime, 0.05, StopTime, 5); road(scenario, [0 0 0; 50 0 0], Lanes, lanespec([1 1])); drivingScenarioDesigner(scenario);這三行的意思是建一個采樣時間 0.05 秒、總時長 5 秒的場景鋪一條從原點出發(fā)、沿 x 軸方向長 50 米的直路中心線左右各一條車道然后把它丟進圖形界面里看一眼。如果界面正常打開、道路顯示為兩條平行車道線說明基礎環(huán)境沒問題。這一步的價值在于把所有環(huán)境問題前置。我見過太多次興沖沖寫了兩百行彎道代碼一運行報“函數(shù)不存在”才開始排查是哪個工具箱沒裝。用最小用例先探路成本三十秒收益是后面省掉半小時。如果這三行都跑不通那問題一定在環(huán)境層面跟你的彎道邏輯毫無關系方向很明確。順手再驗證一下推演機制while advance(scenario) p pose(scenario.Actors(1)); fprintf(t%.2f x%.2f y%.2f\n, scenario.CurrentTime, p(1), p(2)); end這段用來說明advance是怎么推進時間的——每次調(diào)用把場景往前推一個采樣步長返回 false 表示到StopTime了。后面所有的仿真循環(huán)都是這個骨架。3. 彎道場景的三層建模道路、車輛、傳感器3.1 道路層中心點密度決定了一切道路是場景的地基彎道尤其如此。核心接口是road(scenario, roadCenters, Lanes, lanespec([...]))其中roadCenters是一個 N×3 的矩陣每行是一個中心點的 [x, y, z] 坐標z 用來表達高程和橫坡。DSD 會按順序把這些點連成一條帶曲率連續(xù)性的中心線再按lanespec往兩側鋪車道。中心點密度這里有兩條經(jīng)驗值。第一彎道上相鄰中心點的間距控制在曲率半徑的 1/10 到 1/5 之間。半徑 60 米的彎點間距 6 到 12 米比較合適。間距太大回旋線擬合出來的形狀跟你腦子里想的不一樣間距太小擬合會放大數(shù)值噪聲道路出現(xiàn)細微抖動車輛的航向角跟著抖。第二直線段不需要這么密30 米一個點完全夠用因為直線曲率恒為零擬合結果沒有任何自由度。lanespec的參數(shù)形式是lanespec([左車道數(shù), 右車道數(shù)])。lanespec([1 1])是雙向兩車道lanespec([0 1])是只有右側一條車道。這里有個容易搞混的地方車道的左右是相對于中心線的前進方向定義的右車道的中心線在中心線右側偏移半個車道寬默認車道寬 3.6 米所以偏移是 1.8 米。如果你的車要跑在右車道正中間初始位置就不能放在中心線上。高程那一列別隨便填。很多人圖省事全部寫 0平面場景下沒問題但如果你想驗證車輛在帶橫坡的彎道上是否會有姿態(tài)變化第三列就要按橫向坡率填。常規(guī)公路彎道超高在 2% 到 6% 之間半徑 60 米這種中速彎取 4% 比較常見。具體做法是讓外彎側比內(nèi)彎側高高差 車道寬 × 坡率。3.2 車輛層位置、朝向與速度剖面車輛用vehicle(scenario, Position, [x y z])創(chuàng)建能配置的包括尺寸、類別、初始朝向。位置坐標是世界坐標系下的米朝向是相對 x 軸逆時針的角度弧度。初始位姿的坑在于它必須跟軌跡的第一個點一致。trajectory的行為是讓車輛從當前位姿出發(fā)去追擊你給的路徑點如果第一個路徑點跟初始位置差了五米車輛會在第一步就瞬移到那個點上后續(xù)的軌跡全部錯位。我踩過這個坑現(xiàn)象是車輛在起點閃一下然后整條軌跡看起來像整體平移了一段。真正決定彎道表現(xiàn)的是速度剖面。trajectory(actor, waypoints, speed)的第三個參數(shù)可以是標量全程勻速也可以是與waypoints行數(shù)相同的向量每點一個速度。用向量的時候必須嚴格對齊行數(shù)多一個少一個都會報錯這個報錯信息還挺模糊的容易讓人卡住。速度剖面的設計原則是從橫向加速度約束倒推。車輛過彎時受到的橫向加速度近似為 a v2/R這個值直接決定乘客的舒適感。工程上取 1.5 到 2.5 m/s2 作為舒適上限超過 3 m/s2 就明顯不適了。所以給定半徑 R彎中允許的最大車速是 v √(a·R)。這個公式是整個速度設計的錨點后面具體算的時候會用到。3.3 傳感器層裝在哪、看多遠傳感器模型不是必須的但彎道場景不加傳感器價值至少少一半。常用的兩個是雷達數(shù)據(jù)生成器和視覺檢測生成器。雷達的參數(shù)重點是安裝位置、視場角和量程。安裝位置用MountingLocation單位是米坐標是相對車身、以車輛中心為原點的車身坐標系x 向前、y 向左、z 向上。量產(chǎn)車的毫米波雷達一般裝在前保險杠縱向 3 到 4 米、橫向 0、高度 0.4 到 0.8 米。視場角用FieldOfView格式是 [水平角, 俯仰角]角雷達通常水平 90 度、俯仰 10 到 20 度。視覺檢測器的關鍵參數(shù)是量程、檢測概率和誤檢率。量程要跟你的場景尺度匹配彎道半徑 60 米、總長一百多米的話量程 60 米是個合理起點。檢測概率默認 0.9 左右意味著每幀有 10% 概率漏檢如果你想驗證跟蹤算法的魯棒性可以調(diào)到 0.7 制造壓力。彎道下傳感器有個特有現(xiàn)象內(nèi)彎側目標被遮擋外彎側目標提前暴露。這是幾何決定的雷達和攝像頭都一樣。如果你的場景里放了多輛車做評估時要意識到這個不對稱性——同一輛目標車在彎道入口和彎道出口的檢測穩(wěn)定性可能完全不同別把它當成算法的穩(wěn)定性問題。4. 完整實操五分鐘搭出一條 90 度彎道4.1 第一步 用腳本生成中心線先定義基本幾何參數(shù)。我要的是一條從原點出發(fā)、走 30 米直線、然后左轉 90 度的彎彎道半徑 60 米。這幾個數(shù)字決定了整條路的位置。R 60; % 彎道半徑單位 m lineLen 30; % 入彎前直線長度單位 m nLine 7; % 直線段中心點數(shù)量 nArc 10; % 彎道段中心點數(shù)量 % 直線段沿 x 方向y 恒為 0 sLine linspace(0, lineLen, nLine); ptsLine [sLine, zeros(nLine, 1), zeros(nLine, 1)]; % 彎道段圓心位于 (lineLen, R)從 θ0 轉到 θπ/2 theta linspace(0, pi/2, nArc); ptsArc [lineLen R*sin(theta), R - R*cos(theta), zeros(nArc, 1)]; % 拼接時去掉重復的接縫點 roadCenters [ptsLine; ptsArc(2:end, :)];這段代碼的幾何關系值得說清楚。圓心選在 (30, 60)起點是 (30, 60-60) (30, 0)正好接上直線段的終點終點是 (3060, 60) (90, 60)。參數(shù)方程用 sin 和 (1-cos) 的組合起點處切線方向是 x終點處切線方向是 y也就是標準的左轉 90 度。拼接時去掉ptsArc的第一個點因為那一點和直線段最后一點完全重合重復的中心點會讓后續(xù)的弧長計算出現(xiàn)零長度段某些函數(shù)會直接報錯。如果換成右轉、或者轉 45 度只需要改theta的范圍比如linspace(0, -pi/2, nArc)就是右轉。半徑和直線長度改了圓心位置要跟著改這個是唯一的聯(lián)動關系。4.2 第二步 鋪車道與擺車scenario drivingScenario(SampleTime, 0.02, StopTime, 25); road(scenario, roadCenters, Lanes, lanespec([1 1]));采樣時間我選了 0.02 秒比默認的 0.05 更細。原因后面第 5 節(jié)會展開簡單說就是彎道上每步位移要控制住不然航向角跳變明顯。lanespec([1 1])是雙向兩車道視覺上完整一些。接著擺車。為了讓車跑在右車道中心而不是壓著中心線先用中心點的法向量往外偏 1.8 米dx gradient(roadCenters(:,1)); dy gradient(roadCenters(:,2)); nor [-dy, dx] ./ vecnorm([-dy dx], 2, 2); % 單位法向量指向左側 laneCenters roadCenters(:,1:2) - 1.8 * nor; % 右車道中心 laneCenters(:,3) 0;gradient算的是每個點處切線的差分近似[-dy, dx]旋轉 90 度得到法向。注意方向這個法向指向左側所以減去 1.8 才是右側車道中心。這個偏移用在整個路徑上而不是只偏起點——彎道里法向是連續(xù)變化的只偏起點會讓車輛越跑越往外。然后創(chuàng)建車輛并把初始位置設到路徑第一個點ego vehicle(scenario, ... ClassID, 1, ... Position, laneCenters(1,:), ... Length, 4.6, Width, 1.9, Height, 1.5);4.3 第三步 配軌跡與速度速度剖面按前面說的橫向加速度倒推。我取舒適上限 1.5 m/s2半徑 60 米aLatMax 1.5; vCorner sqrt(aLatMax * R); % 約 9.49 m/s折合 34 km/h vEnter 14; % 入彎前車速m/s sDecelFrom 10; % 從弧長 10 m 處開始減速vCorner sqrt(1.5 × 60) 9.49米每秒大概 34 公里每小時。入彎前 14 米每秒50 公里每小時所以需要在直線段內(nèi)減速。按弧長重采樣路徑點再逐點填速度s [0; cumsum(vecnorm(diff(roadCenters), 2, 2))]; sUniform linspace(0, s(end), 240); waypoints [interp1(s, laneCenters(:,1), sUniform), ... interp1(s, laneCenters(:,2), sUniform), ... zeros(numel(sUniform),1)]; speedProfile vCorner * ones(size(sUniform)); idx1 sUniform sDecelFrom; speedProfile(idx1) vEnter; idx2 sUniform sDecelFrom sUniform lineLen; speedProfile(idx2) vEnter (vCorner - vEnter) * ... (sUniform(idx2) - sDecelFrom) / (lineLen - sDecelFrom); trajectory(ego, waypoints, speedProfile);這里有兩個關鍵動作。一是按弧長等間距重采樣把原來疏密不均的中心點變成間隔均勻的點總長約 124 米240 個點間距約 0.52 米這樣速度剖面在空間上的分布才是均勻的。二是速度向量長度必須等于路徑點行數(shù)代碼里都用sUniform驅動天然對齊。入彎的減速段是線性的實際車上會做成加加速度受限的 S 形曲線但用于仿真驗證橫向控制線性減速已經(jīng)夠用而且更容易分析。4.4 第四步 運行與可視化bep birdsEyePlot(XLimits, [-20 130], YLimits, [-40 100]); lp laneBoundaryPlotter(bep, DisplayName, 車道邊界); tp trackPlotter(bep, DisplayName, 自車, MarkerFaceColor, red); plotLaneBoundary(lp, scenario.LaneBoundaries); while advance(scenario) p pose(ego); tp(p(1), p(2), p(3)); drawnow limitrate end跑起來之后你應該能看到車從原點出發(fā)沿直線跑 30 米在彎道入口減速然后貼著彎道內(nèi)側平穩(wěn)轉過 90 度。如果車輛在中途跳出車道或者航向角劇烈擺動直接跳到第 6 節(jié)找對應癥狀。5. 代碼逐段拆解與參數(shù)怎么算5.1 圓弧參數(shù)化與切線方向圓弧參數(shù)方程用的是(圓心 R·sinθ, 圓心_y - R·cosθ)這種組合而不是常見的(R·cosθ, R·sinθ)。這個選擇不是隨意的是因為后者在 θ0 處的切線方向是 y起點朝向不對你還得額外加一個旋轉矩陣。用 sin 和 (1-cos) 的形式天然滿足“起點在原點方向、切線沿 x”的需求省去一堆坐標變換。對于任意起始朝向的彎道更通用的做法是先算一個旋轉矩陣再作用到點上heading0 pi/6; % 起始朝向30 度 Rmat [cos(heading0) -sin(heading0); sin(heading0) cos(heading0)]; ptsArcRotated (Rmat * ptsArc(:,1:2));不過實際項目里我一般不用這套通用解因為場景都是圍繞自車坐標系搭建的讓自車從原點沿 x 出發(fā)后面所有幾何都能用最簡單的表達式寫。保持這個約定能省掉大量調(diào)試坐標系的時間。還有一個細節(jié)trajectory計算車輛朝向是靠前后路徑點的差分所以路徑點的順序必須是從起點到終點單調(diào)推進。如果你不小心把點排反了車輛會試圖倒著走或者干脆原地打轉。中心點拼接順序錯了是新手常見的失誤癥狀是車輛在起點來回抽搐。5.2 弧長重采樣為什么必須做不重采樣會發(fā)生什么你給的中心點可能是 7 個直線點加 10 個彎道點間距分別是 5 米和 10.5 米而速度向量如果按點數(shù)配每個點之間代表的空間距離完全不同。線性插值速度的話減速的“陡峭程度”就會隨點間距變化彎道入口那一段的減速度可能比你設計的大兩三倍。重采樣的本質是把時間維度的設計轉換到空間維度。速度剖面本質上是 s弧長的函數(shù)只有等間距采樣速度曲線在空間上的斜率才有物理意義。cumsum(vecnorm(diff(...)))這段就是算累積弧長然后interp1在弧長域上做線性插值把原來不均勻的點映射到均勻網(wǎng)格上。采樣密度怎么定我給的經(jīng)驗值是空間分辨率 0.5 米左右對應總長 124 米就是 240 個點。這個密度下60 米半徑的彎道每兩點之間的轉角約 0.5 度視覺上足夠平滑。密度再高收益不大反而增加計算量低于 0.3 米的間距就要注意數(shù)值噪聲了。5.3 橫向加速度反推限速這張表是我常用的速查取橫向加速度上限 1.5 m/s2彎道半徑 R (m)彎中限速 v (m/s)換算 (km/h)典型場景205.519.7停車場掉頭306.724.1城市小半徑路口508.731.2城市主干道轉彎609.534.2郊區(qū)匝道8011.039.4快速路匝道10012.244.1高速互通如果你的場景是驗證緊急工況可以把上限提到 2.5 m/s2車速相應提高約 29%因為 √(2.5/1.5) ≈ 1.29。但要注意此時車輛模型的輪胎側偏特性可能進入非線性區(qū)仿真結果的參考價值會下降。反過來用也很有價值給定你希望跑的車速反推需要多大的半徑。比如驗證某個彎道 60 km/h 的通過性v 16.7 m/s在 1.5 m/s2 約束下需要 R v2/a 278 米。這個數(shù)字一算出來你就知道60 km/h 過 60 米半徑的彎橫向加速度會到 4.6 m/s2屬于相當激進的工況。5.4 仿真主循環(huán)的時序控制采樣時間選 0.02 秒不是拍腦袋。判斷標準是單步位移量與彎道曲率的關系每步車輛前進的距離 Δs v·Δt如果 Δs 大到讓離散化后的軌跡明顯偏離圓弧航向角就會出現(xiàn)階躍。拿彎中 9.5 m/s 算0.02 秒步長對應 Δs 0.19 米圓弧上對應的圓心角是 0.19/60 ≈ 0.18 度完全可以忽略。如果用 0.05 秒Δs 0.475 米轉角 0.45 度還湊合用 0.1 秒Δs 0.95 米轉角接近 1 度視覺上就能看出車輛“一格一格拐”。高速工況下這個差異更明顯——30 m/s 配 0.1 秒步長單步走了 3 米彎道上基本沒法看。代價是計算量。0.02 秒步長、25 秒場景就是 1250 步比 0.05 秒多了 2.5 倍。如果場景里有多個傳感器、每幀都要做檢測跑一次可能要幾十秒。我的折中方案是調(diào)試階段用 0.02批量回歸用 0.05前者保證可視化正確后者保證吞吐量。真要卡精度可以在彎道段動態(tài)調(diào)整步長但這就復雜了一般場景用不上。另外StopTime要留余量。按 124 米總長、平均速度 10 m/s 估大約 12.4 秒能跑完我給 25 秒是有富裕的。如果StopTime設小了車輛跑到一半仿真就結束你可能誤以為是軌跡斷了。6. 踩坑實錄彎道仿真最常見的六類問題6.1 車切出車道或“飛出去”這是最高頻的問題原因通常有三個按出現(xiàn)頻率排序。第一路徑點順序錯亂或存在重復點。拼接中心線時如果接縫點沒去重cumsum里會出現(xiàn)零長度段interp1在這一點上會產(chǎn)生 NaN軌跡就斷了。表現(xiàn)是車輛在某個位置突然消失或跳到遠處。檢查方法很簡單跑之前打一行any(diff(s) 0)返回 true 就說明有非遞增的弧長。第二速度剖面長度與路徑點數(shù)不匹配。這個報錯通常直接報“向量長度不一致”但如果你用了廣播機制不小心讓它跑通了速度就會錯位到別的點上車輛會在彎心附近莫名其妙加速。第三車輛初始位姿與路徑首點偏離。前面提過偏離超過一兩米車輛就會瞬移。檢查方法是打印ego.Position和waypoints(1,:)對比差的應該是零。還有一種“飛出去”是真的物理原因——速度太快軌跡函數(shù)算出來的轉向角跟不上。這時候車輛不是瞬移而是沿著切線方向沖出去路徑變成一條直線。看到這個現(xiàn)象先降速再談別的。6.2 傳感器檢測不到目標傳感器返回空結果排查順序建議這樣走。先確認調(diào)用時機傳感器生成器需要在advance之后、用當前時刻的scenario.Actors調(diào)用如果你在循環(huán)外面調(diào)那永遠拿到的是初始狀態(tài)。再確認坐標系MountingLocation用的是車身坐標系不是世界坐標系寫錯了傳感器就裝到車頂上或者車尾去了。然后是視場角。彎道場景里如果你的傳感器水平視場只有 30 度那內(nèi)彎側的目標在很長一段距離里都進不了視野這是幾何決定的不是 bug。想驗證這一點把視場角調(diào)到 120 度再跑一遍如果檢測突然出現(xiàn)了說明就是視野問題。最后是版本的返回值順序。不同年份的版本里視覺檢測器的返回值可能是[detections, numDetections, image]也可能是別的排列用之前help一下確認別照著舊帖子抄。6.3 導出 Simulink 之后的斷層場景在腳本里跑得好好的導出成模型之后車不動或者場景不變問題通常出在這幾處。場景數(shù)據(jù)沒跟著模型走。導出時場景是保存成一個數(shù)據(jù)文件或工作區(qū)變量的Simulink 里的場景讀取模塊需要指向這個變量。如果你換了機器或者清了工作區(qū)模型找不到數(shù)據(jù)就會用默認空場景表現(xiàn)就是路沒畫出來、車也不動。采樣時間不匹配。模型里的求解步長跟場景的SampleTime如果不是整數(shù)倍關系車輛位置會出現(xiàn)插值誤差彎道上表現(xiàn)為軌跡抖動。建議把模型的固定步長設成與場景采樣時間一致或者成整數(shù)倍。道路參數(shù)沒有同步。有些導出方式只把車輛軌跡帶過去道路幾何要單獨配置。這時候模型里車輛是沿著一條不存在的路在跑視覺上就是懸浮。檢查方法是在模型里把道路預覽打開看邊界線是否顯示?,F(xiàn)象最可能原因快速驗證車輛起點閃爍后整體偏移初始位姿與首路徑點不一致打印兩者差值彎道中車輛沿切線沖出速度超過曲率允許上限按 √(aR) 重算限速軌跡在某個位置斷裂路徑點重復導致弧長非遞增any(diff(s)0)傳感器全程無檢測調(diào)用時機在循環(huán)外或視場過窄加大視場角重跑導出后場景空白場景數(shù)據(jù)未隨模型加載檢查模塊指向的變量彎道上航向角一跳一跳采樣步長過大步長減半觀察7. 從單車彎道走向多車交互與批量測試7.1 編排一輛對向車單車跑通之后加一輛對向車是驗證感知和決策邏輯的下一步。做法是復制路徑生成邏輯把車道偏移反過來oppLane roadCenters(:,1:2) 1.8 * nor; % 左側車道 oppLane(:,3) 0; % 對向車從彎道出口往入口跑路徑需要反轉 oppWaypoints flipud(oppLane); oppSpeed 8 * ones(size(oppWaypoints,1), 1); opp vehicle(scenario, ClassID, 1, Position, oppWaypoints(1,:)); trajectory(opp, oppWaypoints, oppSpeed);關鍵點是路徑必須反轉。對向車的行駛方向跟自車相反如果不翻轉它會從彎道出口倒著開回入口雖然位置對但朝向完全錯看起來像在倒車。翻轉之后還要檢查速度向量的長度也跟著變這一點容易漏。時間上的編排更有講究。你想讓兩車在彎心交會還是錯開交會時機取決于兩車進入場景的時間差。trajectory支持延遲啟動可以在路徑前面補一段靜止點或者干脆調(diào)整初始位置。我一般用初始位置控制直觀一些把對向車的起點往遠處挪讓它晚一點進入交互區(qū)域。7.2 把場景參數(shù)化以便批量跑單次仿真說明不了什么真正的價值在于跑一批參數(shù)組合。把整個搭場景過程包成函數(shù)是最省事的做法function scenario buildCurveScenario(R, vEnter, aLatMax, dt) if nargin 4, dt 0.02; end vCorner sqrt(aLatMax * R); ... % 內(nèi)部按前面的邏輯生成道路、車輛、軌跡 end這樣外層就能用嵌套循環(huán)掃參數(shù)results []; for R [40 60 80 100] for v0 [10 12 14 16] sc buildCurveScenario(R, v0, 1.5, 0.05); metric runAndEvaluate(sc); % 自己寫的評估函數(shù) results [results; R, v0, metric]; end end評估函數(shù)里我通常記三個指標最大橫向誤差車輛實際位置到車道中心線的距離峰值、最大橫向加速度從速度平方除以曲率算、航向誤差收斂時間從入彎到誤差穩(wěn)定在設計值以內(nèi)的時間。這三個放在一起基本能判斷某個控制參數(shù)在彎道上的適應性。批量跑有個坑drivingScenario對象是有狀態(tài)的跑完之后不能直接復用必須重新創(chuàng)建。循環(huán)里每次都調(diào)buildCurveScenario就是因為這個別圖省事在循環(huán)外建一次然后反復advance。另外每次創(chuàng)建場景的隨機種子要固定傳感器模型里有隨機成分種子不固定的話同一組參數(shù)跑兩次結果不一樣你會誤以為算法不穩(wěn)定。我個人在實際操作中的體會是彎道仿真這件事八成的時間花在“把幾何和速度對上”兩成花在“看結果”。第一版場景能跑起來之后別急著加傳感器、加多車先把單車軌跡跑順、把橫向誤差曲線畫出來確認車輛確實貼著車道中心走。這個基線穩(wěn)了后面加什么都是增量驗證基線不穩(wěn)后面每加一個元素你都要重新懷疑一遍到底是誰的問題。