據(jù)對齊與時間戳深度解析)
干過幾年VIO系統(tǒng)的人應(yīng)該都有這種體會跑通一個demo很容易真正把精度和穩(wěn)定性調(diào)上去你會發(fā)現(xiàn)最折磨人的不是狀態(tài)估計和優(yōu)化求解而是數(shù)據(jù)本身。圖像幀和IMU測量幀這兩個最基礎(chǔ)的東西往往藏著最大的坑。今天不聊那些高大上的優(yōu)化策略把這兩類幀數(shù)據(jù)從頭到尾掰開揉碎講清楚包括時間戳、同步、標定、預(yù)處理以及我在實際項目里踩過的一些坑。這內(nèi)容適合剛?cè)腴TVIO/SLAM的算法工程師也適合已經(jīng)在調(diào)系統(tǒng)、但老覺得“數(shù)據(jù)不對勁”的嵌入式或者機器人工程師??赐昴阒辽倌芑卮疬@幾個問題圖像幀的時間戳到底該打在哪個時刻IMU內(nèi)參為什么需要標定兩路傳感器的時間對齊方案怎么選以及當系統(tǒng)精度出問題時怎么快速判斷是數(shù)據(jù)壞了還是算法壞了。1. VIO中的數(shù)據(jù)流先搞清楚兩路傳感器在干什么1.1 圖像幀與IMU測量幀的角色分工VIO本質(zhì)上是把兩個互補性極強的傳感器數(shù)據(jù)融合起來。圖像幀這邊的特點是低頻、信息量大一幀圖里有大量特征點能提供豐富的幾何約束但圖像單獨用時有兩個致命問題一是尺度不可觀純視覺里程計拿不到真實的絕對尺度二是模糊和光照變化很容易讓特征跟丟。IMU測量幀這邊正好反過來頻率高、單幀信息量小每幀就一個三軸角速度加三軸加速度但它能提供幀間連續(xù)的運動估計尺度問題在加速度計參與后也變得可觀測了。打個比方圖像幀像你手里拿的地圖IMU幀像你腳下邁步時身體感受到的位移和旋轉(zhuǎn)。地圖能告訴你“這條路的大致走向”但沒法告訴你“這一步到底邁了多遠”身體感受告訴你每步的加速度和轉(zhuǎn)動但時間一長就會飄。VIO把這兩樣?xùn)|西捆起來用用視覺糾正IMU的漂移用IMU補全視覺在短時間內(nèi)的運動變化最終得到穩(wěn)定且具有真實尺度的位姿。這就是為什么VIO不能只靠其中一路數(shù)據(jù)。有些工程為了省事把IMU停掉視覺里程計短時間內(nèi)還能跑但一遇到純旋轉(zhuǎn)或者快速運動就會亂套反過來只靠IMU幾秒鐘內(nèi)積分出來的位置就沒法看了。所以理解VIO的核心先得理解這兩類幀數(shù)據(jù)在一個系統(tǒng)里是怎么分工、怎么交匯的。1.2 為什么IMU非得上這么高的頻率視覺通常也就15到30幀每秒而IMU一百赫茲到一千赫茲都很常見。有人會問30Hz的圖像幀已經(jīng)足夠感知環(huán)境了IMU搞那么高頻有意義嗎這里必須提采樣和運動頻率的關(guān)系。IMU測量的角速度和線加速度是連續(xù)的瞬時物理量要還原真實的運動軌跡采樣率必須遠高于運動本身的最高頻率。比如一個機器人快速抖動角速度可能在毫秒級別劇烈變化如果IMU只有50Hz兩個采樣點之間的運動完全丟失積分出來自然不對。更麻煩的是如果采樣率不夠高頻運動會混疊成低頻運動VIO前端看到的就是一堆錯誤的“假運動”。高頻帶來的數(shù)據(jù)量其實沒那么恐怖。算一筆賬一個200Hz的六軸IMU每幀假如用double存三軸角速度加三軸加速度24字節(jié)每秒也就4.8KB即便加上時間戳和一些頭信息也就幾十KB級別。而一路720p圖像用H.264壓到2Mbps即使壓縮后每秒都要250KB原始畫面更是上GB級別。所以IMU把頻率拉到200Hz甚至400Hz對帶寬和存儲壓力影響非常小但給算法帶來的運動信息密度卻高得多這筆賬怎么算都劃算。1.3 從傳感器到優(yōu)化兩路數(shù)據(jù)在算法里的流轉(zhuǎn)路徑在一個典型的VIO系統(tǒng)里數(shù)據(jù)流大概分四段前端、初始化、后端優(yōu)化、回環(huán)檢測可選。圖像幀會先到前端做特征提取和光流跟蹤形成2D-2D的特征對應(yīng)關(guān)系IMU測量幀則逐幀送入IMU預(yù)積分模塊把兩次圖像幀之間的IMU數(shù)據(jù)打包成一個相對運動約束。到了后端視覺重投影殘差和IMU預(yù)積分殘差一起進入滑窗優(yōu)化或者濾波器共同估計位姿、速度、以及IMU的零偏。這套流轉(zhuǎn)路線在VINS-Mono、ORB-SLAM3、MSCKF這些經(jīng)典框架里幾乎沒有本質(zhì)區(qū)別。MSCKF用圖像幀觸發(fā)EKF更新IMU只負責狀態(tài)預(yù)測VINS-Mono在每個關(guān)鍵幀做一次非線性最小二乘優(yōu)化ORB-SLAM3則是把IMU預(yù)積分和視覺因子圖融合在一起。無論用什么框架核心都是同一件事圖像幀和IMU測量幀必須在時間上對齊、在空間上通過外參關(guān)聯(lián)否則后端的殘差就是錯的優(yōu)化結(jié)果無從談起。2. 圖像幀的完整生命周期與采樣設(shè)計細節(jié)2.1 從CMOS曝光到時間戳圖像幀的第一道關(guān)卡很多做圖像處理的同學(xué)拿到一張圖就開始提特征從來沒想過這張圖到底是什么時刻“拍下來”的。在VIO里這恰恰是最關(guān)鍵的問題。先分清兩種快門模式。全局快門Global Shutter傳感器所有像素在同一時刻開始曝光并結(jié)束圖像對應(yīng)的姿態(tài)時刻非常明確卷簾快門Rolling Shutter則是逐行曝光每行之間的曝光時間有微小延遲。高速運動時卷簾快門會產(chǎn)生“果凍效應(yīng)”圖像里的特征點位置被拉伸時間戳概念也變得模糊。VIO對幾何精度要求極高能用全局快門就盡量用全局快門實在只能用卷簾至少要在相機內(nèi)參標定時加上rolling shutter參數(shù)算法層也要對特征點的行時間做補償。時間戳應(yīng)該打在哪個時刻業(yè)界公認比較合理的做法是打曝光的中間時刻。原因很簡單從曝光開始到曝光結(jié)束相機的位姿一直在變化假設(shè)這些時間內(nèi)的運動近似線性曝光中點對應(yīng)的姿態(tài)最接近圖像實際內(nèi)容的“平均姿態(tài)”。如果驅(qū)動直接把收到圖像數(shù)據(jù)的那一刻當成時間戳等于把曝光時長、傳輸延遲全部算進去了高動態(tài)場景下的誤差會非常明顯。比如曝光10ms的車載高速場景不補償曝光中點位姿誤差可能就是幾厘米甚至更多。2.2 圖像幀數(shù)據(jù)結(jié)構(gòu)里到底該放哪些東西有不少人在定義圖像幀結(jié)構(gòu)體時只放一個時間戳加一張圖等后期調(diào)試才發(fā)現(xiàn)信息完全不夠用。一個適合VIO使用的圖像幀結(jié)構(gòu)體至少應(yīng)該包含這些字段struct VisualFrame { uint64_t timestamp_ns; // 曝光中點時間戳單位納秒 uint64_t frame_id; // 幀序號用于丟幀檢測 cv::Mat image; // 原始圖像或去畸變圖像 double exposure_ns; // 曝光時長用于時間戳補償 double gain; // 增益輔助判斷圖像質(zhì)量 uint64_t imu_begin_idx; // 該幀對應(yīng)IMU緩沖起始索引 uint64_t imu_end_idx; // 該幀對應(yīng)IMU緩沖結(jié)束索引 };逐字段解釋一下為什么需要它們。frame_id很多人會省略但一旦驅(qū)動層出現(xiàn)重復(fù)幀或者漏幀沒有這個字段你只能靠時間戳去猜排查效率極低。exposure_ns和gain不是算法必需但在分析特征跟丟和圖像模糊時非常有用比如發(fā)現(xiàn)圖像突然變暗導(dǎo)致特征點數(shù)量驟減一看日志是自動曝光把增益拉低了問題定位就很快。imu_begin_idx和imu_end_idx是強烈建議加的它能告訴你這一幀圖像覆蓋的IMU數(shù)據(jù)范圍后續(xù)構(gòu)建預(yù)積分時不需要再去全局搜索性能和可讀性都更好。2.3 丟幀、重復(fù)幀與亂序幀的處理策略真實系統(tǒng)里圖像幀不會像理想中那樣按時按序到達。USB帶寬不足、驅(qū)動緩沖溢出、采集線程調(diào)度不及時都會導(dǎo)致丟幀驅(qū)動邏輯有bug時還會出現(xiàn)重復(fù)幀多線程競爭導(dǎo)致亂序也時有發(fā)生。處理策略分三層。第一層在驅(qū)動層做防護使用環(huán)形緩沖暫存最近N幀采集線程按順序?qū)懭胨惴ň€程按時間戳順序讀取從源頭減少亂序。第二層做質(zhì)量統(tǒng)計維護一個滑動窗口統(tǒng)計相鄰幀的間隔時間如果某一次間隔超過平均間隔的2倍以上就記一次丟幀連續(xù)丟幀超過閾值時直接告警。第三層才是算法層的補償重復(fù)幀按frame_id去重亂序幀在進入特征跟蹤前先按時間戳重排排完再送進跟蹤模塊。我一直強調(diào)一個原則數(shù)據(jù)層能解決的問題不要在算法層硬扛。特征跟蹤模塊本來負責的是像素匹配你讓它去猜上一幀是不是丟幀了邏輯混亂bug還難查。不如把幀數(shù)據(jù)質(zhì)量監(jiān)控放在數(shù)據(jù)入口處從驅(qū)動拿數(shù)據(jù)那一刻就保證“幀序正確、無重復(fù)、可統(tǒng)計丟失”后面所有模塊都會輕松很多。3. IMU測量幀的本質(zhì)與預(yù)處理細節(jié)3.1 IMU到底在測什么測量模型與內(nèi)參IMU測量幀在算法層面不是一個簡單的“六個數(shù)”它背后跟著一套測量模型加速度計測量值 載體真實加速度 - 重力加速度 零偏 高斯噪聲陀螺儀測量值 載體真實角速度 零偏 高斯噪聲之所以要搞明白這個模型是因為VIO后端優(yōu)化的狀態(tài)量里本來就包含加速度計和陀螺儀的零偏。零偏如果沒有在初始化階段估計準重力方向就會對不齊整個系統(tǒng)的俯仰和橫滾角從一開始就是歪的后面再怎么優(yōu)化也救不回來。這就是為什么IMU內(nèi)參標定不能省。很多IMU模塊的出廠手冊會給零偏參數(shù)但那是出廠測試條件下的值實際板子上的供電紋波、溫度、元器件個體差異都會改變零偏。更關(guān)鍵的是噪聲和零偏穩(wěn)定性這兩個參數(shù)會影響VIO初始化的收斂速度和最終精度。常用的標定工具是imu_utils它基于Allan方差分析需要將IMU固定在一個靜止平面上錄制約兩小時的靜止數(shù)據(jù)然后離線分析出零偏不穩(wěn)定性、角度隨機游走、速度隨機游走等參數(shù)。錄數(shù)據(jù)的時候板子要放在沒有振動和溫度突變的環(huán)境里最好提前上電預(yù)熱半小時否則零偏還會隨時間漂移。3.2 IMU幀的數(shù)據(jù)結(jié)構(gòu)與預(yù)積分的意義一個干凈的IMU測量幀結(jié)構(gòu)體大概是這樣的struct ImuFrame { uint64_t timestamp_ns; // IMU采樣時刻 double wx, wy, wz; // 三軸角速度 rad/s double ax, ay, az; // 三軸加速度 m/s^2 double temperature; // 傳感器溫度可選 uint8_t status; // 數(shù)據(jù)狀態(tài)位 };溫度字段很多人會忽略但對于要長期運行的設(shè)備它太有價值了。IMU零偏隨溫度變化是常態(tài)有了溫度信息可以對零偏做溫度補償或者至少在建圖和定位時監(jiān)控溫度是否發(fā)生了劇烈變化防止零偏跳變導(dǎo)致定位漂移。IMU數(shù)據(jù)在進入后端前通常要做預(yù)積分。預(yù)積分解決的問題很實際后端優(yōu)化時位姿一直在迭代更新如果每迭代一次都把兩幀圖像之間的IMU數(shù)據(jù)重新積分一遍計算量會隨窗口長度快速膨脹。預(yù)積分的思路是把兩幀之間的IMU測量“打包”成一個相對的旋轉(zhuǎn)量、速度變化量和位移量這些量只依賴IMU測量和零偏不直接依賴絕對位姿優(yōu)化迭代時可以反復(fù)復(fù)用。離散積分方式建議用中值積分而不是簡單的歐拉積分。歐拉積分直接用當前時刻的角速度推算旋轉(zhuǎn)粗暴但誤差大中值積分取相鄰兩幀IMU角速度的平均值作為該時間段內(nèi)的角速度精度高一個量級代碼實現(xiàn)只多一行沒有理由不用。3.3 驅(qū)動層的坑IMU中斷、緩沖與丟包處理IMU驅(qū)動這塊的坑比想象中多。第一是讀寫方式多數(shù)IMU通過SPI、UART或者USB接口輸出數(shù)據(jù)如果嵌入式側(cè)用了阻塞式讀取一個耗時操作就會把后續(xù)數(shù)據(jù)全部堵住。推薦的做法是讓IMU數(shù)據(jù)走DMA或獨立線程用環(huán)形緩沖區(qū)接收主流程只負責消費緩沖區(qū)的數(shù)據(jù)。第二是丟包檢測。IMU數(shù)據(jù)是連續(xù)流理論上相鄰兩幀時間戳間隔應(yīng)該恒定。驅(qū)動里應(yīng)該做一個連續(xù)性檢查當發(fā)現(xiàn)相鄰幀間隔超過設(shè)定閾值時記錄一次丟包事件。別小看這種統(tǒng)計我曾經(jīng)在一個項目里發(fā)現(xiàn)IMU驅(qū)動有5%的丟包系統(tǒng)初始化總是偶爾失敗查了半天才發(fā)現(xiàn)串口緩沖區(qū)開小了中斷頻繁喚醒反而丟數(shù)據(jù)把緩沖區(qū)翻倍后問題消失。第三是時間戳的注入位置。IMU時間戳應(yīng)該在數(shù)據(jù)讀取完成的那一刻立刻打上而不是在數(shù)據(jù)處理、濾波、協(xié)議解析之后。因為解析和濾波需要耗時等到處理完再打時間戳時間戳已經(jīng)偏了實際采樣時刻好幾毫秒這個誤差會直接污染預(yù)積分。4. 圖像幀與IMU測量幀的時間對齊VIO最容易翻車的環(huán)節(jié)4.1 時間戳源頭一個系統(tǒng)時鐘還是多個系統(tǒng)時鐘時間對齊的第一步是確認兩路傳感器的時間戳來自同一個時間基準。如果相機驅(qū)動和IMU驅(qū)動各跑一個進程各自調(diào)用本機的系統(tǒng)時鐘前提是這兩個進程在同一臺主機上并且系統(tǒng)時鐘沒有被NTP等機制頻繁調(diào)整。只要這兩點滿足兩個時間戳基準大體一致。更麻煩的是嵌入式場景。相機掛在一個MCU上IMU掛在另一個MCU上兩個MCU各自用自己的時鐘計數(shù)時間基準完全獨立哪怕上電時做了同步一段時間后也會因為晶振頻率差異產(chǎn)生漂移。這種場景必須引入統(tǒng)一的時間同步機制常見方案是讓主機通過PTP或者硬件脈沖周期性地對從設(shè)備校時確保所有傳感器的時間戳最終回溯到同一個主時鐘。時間戳基準統(tǒng)一后還應(yīng)該做一次質(zhì)量驗證。最簡單的辦法是統(tǒng)計相鄰幀間隔的抖動圖像幀間隔應(yīng)該基本穩(wěn)定在一個固定值比如33ms左右IMU間隔也應(yīng)該在設(shè)定周期附近小幅波動。如果間隔數(shù)據(jù)忽大忽小說明打時間戳的位置不對或者時鐘本身有問題這種問題先解決再談算法。4.2 硬觸發(fā)與軟觸發(fā)從毫秒到微秒的差距時間戳即使統(tǒng)一了也不代表圖像曝光時刻和IMU采樣時刻真的“同時發(fā)生”。這里就要區(qū)分軟觸發(fā)和硬觸發(fā)兩種方案。軟觸發(fā)就是把相機和IMU都設(shè)成自由運行模式相機按30FPS曝光IMU按200Hz采樣系統(tǒng)只在事后用時間戳去找對應(yīng)的數(shù)據(jù)。這種方案實現(xiàn)簡單數(shù)據(jù)不需要額外硬件支持但同步精度取決于時間戳精度和數(shù)據(jù)幀的到達時延通常能到幾毫秒到十幾毫秒的水平。低動態(tài)的室內(nèi)場景勉強夠用一旦速度快起來幾毫秒的錯位換算成IMU積分誤差就會非??捎^。硬觸發(fā)則是用一個硬件信號同時控制相機的曝光起始時刻和IMU的采樣時刻讓兩類數(shù)據(jù)的時刻偏差直接被物理信號限定在微秒量級。實現(xiàn)上通常用MCU或者FPGA產(chǎn)生一個多路同步脈沖一路送給相機的TRIGGER引腳一路送給IMU的同步采樣引腳。相機接收到脈沖后開始曝光IMU在同一個脈沖沿采集數(shù)據(jù)這樣圖像幀和IMU幀就有了硬件保證的時間對齊。這里順便說一句如果你在用FPGA做這套同步邏輯搜索資料時注意區(qū)分兩個“VIO”Vivado里那個用于在線調(diào)試的VIO核全稱是Virtual I/O是調(diào)試工具機器人領(lǐng)域常說的VIO是Visual-Inertial Odometry視覺慣性里程計。不少同學(xué)搜“VIO IP核”找了一堆FPGA調(diào)試文檔和本文講的是兩個方向別搞混了。4.3 時間偏移的數(shù)學(xué)補償與Kalibr聯(lián)合標定即便用了硬觸發(fā)圖像曝光中點和IMU真正采樣時刻之間還是可能存在一個固定的時間偏移td這個偏移來自曝光開啟延遲、傳感器響應(yīng)時間等。在VIO算法里td會以一個額外參數(shù)的形式被估計也可以離線通過標定工具確定。目前最主流的離線標定工具是Kalibr它能夠同時標定相機到IMU的外參旋轉(zhuǎn)和平移、時間偏移td以及IMU內(nèi)參。標定流程我非常建議按這套步驟來做先打印一張AprilGrid標定板貼在平整的板上保證紋理清晰、無反光。先用Kalibr的cam標定模塊單獨標定相機內(nèi)參或者直接使用廠家的內(nèi)參但需要確認參數(shù)質(zhì)量。用imu_utils對IMU做內(nèi)參標定得到噪聲密度和零偏參數(shù)。采集聯(lián)合標定數(shù)據(jù)手持設(shè)備在標定板前做緩慢到中速的各種旋轉(zhuǎn)和位移六個自由度都要充分激勵到標定板始終保持大部分在視野內(nèi)避免純勻速運動否則外參和時間偏移的可觀測性會變差。錄制2到3分鐘的bag包運行kalibr_calibrate_imucam命令rosrun kalibr kalibr_calibrate_imucam \ --target april_6x6_80x80cm.yaml \ --cam camchain-imucam.yaml \ --imu imu.yaml \ --bag dataset.bag \ --time-calibration運行完看結(jié)果時重點看幾個指標重投影誤差殘差、td的大小、旋轉(zhuǎn)矩陣和平移向量的合理性。td正常應(yīng)該在幾毫秒到幾十毫秒之間如果標定出幾百毫秒的偏移基本可以判定同步方案或者時間戳打點方式有問題先不要用這個結(jié)果。這套思路也適用于lidar-imu聯(lián)合標定只不過把圖像特征換成點云匹配或者手眼標定方法時間同步和對齊的核心邏輯完全一致。5. 實戰(zhàn)中的問題排查與調(diào)試技巧5.1 時間戳毛刺與跳變怎么快速定位系統(tǒng)跑起來后第一步永遠是檢查數(shù)據(jù)質(zhì)量而不是直接跑算法。我常用的方法很簡單把相鄰幀的時間戳差全部導(dǎo)出來畫折線圖正常情況是在均值附近的小幅波動突然出現(xiàn)一個尖峰比如圖像間隔從33ms跳到250ms基本可以斷定發(fā)生了丟幀或者驅(qū)動卡頓。用腳本快速檢測會更高效下面是一個處理CSV日志的小片段import csv ts_list [] with open(frame_timestamps.csv) as f: reader csv.DictReader(f) for row in reader: ts_list.append(int(row[timestamp_ns])) diffs [b - a for a, b in zip(ts_list[:-1], ts_list[1:])] avg sum(diffs) / len(diffs) for i, d in enumerate(diffs): if d avg * 2: print(f異常間隔: 幀 {i} - {i1}, 間隔 {d/1e6:.2f} ms)同樣的方法也應(yīng)該用在IMU時間戳上。IMU間隔異常通常表現(xiàn)為間隔成倍增大或者時間戳回退前者是丟包后者是時間戳注入位置不當。把這兩個檢查做成啟動腳本里的固定動作每次跑實驗前先跑一遍能省掉后面大量的排查時間。5.2 IMU數(shù)值突變、飽和與數(shù)據(jù)有效性檢測IMU數(shù)據(jù)里最隱蔽的坑是量程飽和。現(xiàn)在不少IMU標稱量程很大但在高沖擊或者劇烈振動場景下加速度計或陀螺儀輸出可能被限制在量程邊界。特征是什么數(shù)值連續(xù)多幀等于一個臨界值而且變化曲線被“切平”了。如果不做處理算法會把這種飽和輸出當成真實運動輕則軌跡失真重則濾波器發(fā)散。建議在預(yù)處理階段加一個數(shù)據(jù)有效性檢測模塊邏輯很簡單如果連續(xù)N幀的某一軸數(shù)值都在量程邊界附近就標記這段時間的數(shù)據(jù)為無效同時在VIO前端降低這部分數(shù)據(jù)在預(yù)積分中的權(quán)重。另外陀螺儀和加速度計也可以用多項式擬合或者滑動窗口做突變檢測單幀數(shù)值突然跳變超過閾值多半是硬件干擾或者數(shù)據(jù)解包錯誤直接丟棄比放進去讓算法硬扛更好。5.3 圖像模糊與自動曝光對特征跟蹤的影響圖像這塊除了丟幀最常見的問題是運動模糊和自動曝光導(dǎo)致的特征數(shù)量波動。車速快、曝光時間長圖像就會拖影特征點提取出來位置都不準光流跟蹤自然就漂。解決方向有兩個一是提高幀率、縮短單幀曝光時間代價是單幀圖像變暗可以用補光燈解決二是算法層增加圖像質(zhì)量評估模糊嚴重的幀不參與關(guān)鍵幀選擇。自動曝光則是另一個隱患。亮度變化劇烈的場景自動曝光會不斷調(diào)節(jié)增益和曝光時間導(dǎo)致圖像幀與幀之間的亮度、模糊程度頻繁跳變特征跟蹤很容易斷裂。在VIO設(shè)備上我強烈建議使用固定曝光和固定增益把圖像質(zhì)量調(diào)節(jié)交給物理光圈和補光設(shè)備而不是交給算法去試錯。自動曝光適合拍照不適合做幾何測量。5.4 標定結(jié)果質(zhì)量速查表最后給一個簡單的標定質(zhì)量檢查經(jīng)驗值表格方便大家標定后快速判斷結(jié)果是否合理檢查項合理范圍異常處理建議Kalibr重投影誤差0.5 ~ 1.5 像素殘差過大時檢查標定板是否平整、是否充分激勵運動相機-IMU時間偏移td幾毫秒 ~ 幾十毫秒結(jié)果幾百毫秒時檢查時間戳打點方式IMU零偏不穩(wěn)定性一般小于 0.01 deg/s過大時考慮溫度補償或更換IMU模塊相機-IMU外參重投影重投影誤差在閾值內(nèi)且多組數(shù)據(jù)一致不一致時重復(fù)采集多段數(shù)據(jù)對比標定不是一次搞完就萬事大吉。設(shè)備更換鏡頭、重新焊接、IMU模塊更換后外參都會變需要重新標定。我個人的習慣是固定一塊標定板放在測試環(huán)境里每隔一段時間做一次快速復(fù)標確保長期運行的設(shè)備參數(shù)沒有因為外力或溫度變化而悄悄偏移。這兩類幀數(shù)據(jù)的事說到底就是三條時間要準、空間要對、數(shù)據(jù)要干凈。時間問題上做硬觸發(fā)加時間偏移標定空間問題上做好相機和IMU的外參標定數(shù)據(jù)干凈則靠驅(qū)動層緩沖、丟幀檢測和IMU有效性判斷來保障。我把這些心思都花在數(shù)據(jù)入口后后端的調(diào)參壓力真的小了很多。很多VIO場景的“玄學(xué)報錯”最后查來查去都是時間戳或者幀數(shù)據(jù)在作妖。希望這篇能幫你少走點彎路把精力留給真正需要動腦子的優(yōu)化部分。