研:6-DOF抓取位姿估計與機器人視覺抓取實戰(zhàn))
項目標題: anygrasp算法調(diào)研 項目正文: 無 關鍵詞: anygrasp, 抓取位姿估計, 6-DOF抓取, 視覺抓取, 機器人操作, RGB-D, GraspNet最近一個月我一直在做機器人視覺抓取方向的方案預研把主流抓取姿態(tài)估計模型挨個過了個遍其中ANYGRASP是我花時間最多、也最有話想說的一個。如果你想做的項目是“讓機械臂從雜亂料筐里把零件一個一個揀出來”或者你正在為移動機械臂選一個能用的抓取感知方案那這篇調(diào)研記錄應該能幫你少走不少彎路。ANYGRASP是一個從單幀RGB-D圖像直接輸出6自由度抓取位姿的開源算法。和很多學術項目不同它的模型權重、推理腳本、甚至數(shù)據(jù)的組織方式都是可以實際落地的不需要你自己從零訓練。它的核心價值在于給定一幀深度圖或者其他方式得到的點云模型在一兩百毫秒內(nèi)給出若干個可行的抓取姿態(tài)每個姿態(tài)按置信度排序機械臂直接挑最高分那個去執(zhí)行就行。這篇文章我分五塊聊先講清楚它到底解決什么問題再拆原理然后說部署和調(diào)用細節(jié)接著是實測中會踩的坑最后聊一聊我能想到的擴展方向。整個過程會保持“調(diào)研筆記”的口吻盡可能把為什么這么做也交代清楚。1. 先搞清楚它在解決什么1.1 抓取姿態(tài)為什么是個難題在聊算法之前得先給沒怎么接觸過抓取規(guī)劃的朋友補個背景。機械臂要抓起一個物體本質(zhì)上需要回答兩個問題抓哪里以及怎么把夾爪送過去。夾爪接近物件的方向、夾爪開合的方向、以及夾爪最終停留的位置這九個自由度3個位置3個旋轉(zhuǎn)加上開口寬度組合起來就是一個抓取位姿。傳統(tǒng)的做法是手寫規(guī)則。比如圓柱體就從側(cè)面夾長方體就夾重心。這種思路在物流行業(yè)的分揀場景里用了很多年前提是物品種類固定、擺放姿態(tài)可控。一旦落到工業(yè)現(xiàn)場的料筐、家里的雜物箱或者餐盤上沒擺好的碗碟規(guī)則就開始失靈了。物體的形狀、遮擋、堆疊讓同一個物體在不同時刻呈現(xiàn)出完全不同的外觀手寫規(guī)則根本無法覆蓋這種組合爆炸。所以業(yè)界轉(zhuǎn)向了數(shù)據(jù)驅(qū)動。給模型看成千上萬張帶有標注的抓取位姿的圖讓它自己學習“什么樣的位置、什么樣的姿態(tài)夾爪閉合后能抓住物體”。這個思路本身不復雜真正的門檻在于兩個一是訓練數(shù)據(jù)從哪里來二是用什么樣的網(wǎng)絡結(jié)構去表達一個完整的6自由度抓取姿態(tài)。1.2 ANYGRASP的定位與適用邊界ANYGRASP正是沖著“雜亂場景中的單視圖6-DOF抓取”這個具體問題去的。它的前身是GraspNet-1B項目熟悉抓取感知的朋友可能知道GraspNet-1B提出了一個基于能量圖energy map的抓取質(zhì)量評估方法但只能輸出自上而下方向的抓取——也就是4自由度抓取。而ANYGRASP把這個問題推廣到了完整的6-DOF空間夾爪可以從任意方向接近物體這在真實場景中意義很大。我個人的理解是ANYGRASP最適合這類任務把一堆混雜的、無規(guī)律堆疊的工業(yè)零件從一個容器里取出。它不依賴于物體三維模型不需要事先建模也不要求物體處于孤立、無遮擋狀態(tài)。它能處理的物體尺寸范圍大概在幾厘米到幾十厘米之間這個范圍覆蓋了大多數(shù)小零件分揀、上料、以及一部分家庭服務場景。它的邊界也很清晰。如果你面對的是完全透明的玻璃杯、強反射的金屬件或者需要亞毫米級精度的精密裝配那它就不合適了。深度相機的精度局限會讓這類物體的點云直接失真模型再強也是無米之炊。還有一個點它做的是單幀靜態(tài)抓取不追蹤、不預測物體在成像之后被碰歪了它就管不著了。2. 算法原理與網(wǎng)絡拆解2.1 輸入輸出與整體流程ANYGRASP的輸入是一幀對齊好的RGB-D圖像經(jīng)過相機內(nèi)參轉(zhuǎn)換得到點云送到網(wǎng)絡里。輸出是N個抓取假設grasp proposals每個假設包含抓取位置夾爪中心的三維坐標單位是米抓取旋轉(zhuǎn)一個3x3的旋轉(zhuǎn)矩陣定義了夾爪從哪個方向接近物體、夾爪平面怎么旋轉(zhuǎn)夾爪寬度用于夾取時預張開置信度分數(shù)0到1之間越高表示模型越認為這是個能抓穩(wěn)的位姿。整個流程看下來模型內(nèi)部是單次前向推理不會先做目標檢測、不會先分割物體、也不會先做位姿估計而是直接從像素到抓取假設。這種端到端的路線減少了誤差累積也簡化了工程集成。用一個生活化的類比來說你閉上一只眼用一只眼掃一眼桌上的雜物然后直接伸手去拿某個東西。你不會先精確識別“這是一個馬克杯它當前朝向是30度”而是憑整體視覺直接估計出“往那邊伸手、這樣張開手指”就夠了。ANYGRASP就是把這種本能式的操作變成一個參數(shù)化的網(wǎng)絡。2.2 網(wǎng)絡核心近似可分抓取表示ANYGRASP在原理上最值得關注的設計我稱之為“近似可分抓取表示”。它把全6-DOF抓取分解成幾個子問題由網(wǎng)絡的不同分支同時預測抓取置信度分支對每個采樣點評估“從這里抓有多大可能性成功”接觸點分支預測夾爪與物體接觸的兩個點或區(qū)域用于約束抓取位置在物體表面附近接近向量分支預測夾爪從什么方向接近物體即抓取方向與物體表面法線的關系夾爪旋轉(zhuǎn)分支在接近向量確定后再預測夾爪圍繞接近軸的旋轉(zhuǎn)角寬度分支預測夾爪需要張開多大才能包住目標。核心思路是6-DOF空間太大、太稠密直接回歸旋轉(zhuǎn)矩陣或四元數(shù)很難訓練收斂。而把它分解成“位置方向接近向量繞向旋轉(zhuǎn)寬度”之后每個分支的任務都變得可學習、可監(jiān)督。這種分解不是ANYGRASP首創(chuàng)的但它在“如何把多個分支結(jié)果組合成物理可行的抓取假設”上做得比較扎實。舉一個通俗的解釋如果你要判斷“能不能從這個角度握住一個杯子”直接搜索6D空間就是100萬種嘗試而分解之后網(wǎng)絡先猜出手該落在哪個區(qū)域位置再猜出手指的朝向接近方向再想想手腕要不要轉(zhuǎn)一下繞向旋轉(zhuǎn)最后估計手指張多大。每一步都是一個簡單得多的二分類或回歸任務。2.3 訓練數(shù)據(jù)與生成策略我翻了它的技術報告和開源倉庫訓練數(shù)據(jù)使用的是基于物理仿真生成的大規(guī)模抓取標注。具體做法是在一個物理引擎里放置大量虛擬物體用采樣策略生成大量候選抓取位姿通過模擬夾取測試判斷是否成功把成功/失敗的結(jié)果作為監(jiān)督信號。這里有一個容易忽略的點模型學到的抓取偏好直接由仿真數(shù)據(jù)的質(zhì)量決定。如果仿真里物體的材質(zhì)、摩擦系數(shù)設置得和現(xiàn)實差異很大模型在現(xiàn)實中的成功率就會打折。所以那些在仿真里效果很好、一上真機就不行的案例多半不是網(wǎng)絡結(jié)構的問題而是數(shù)據(jù)分布與真實場景偏差太大。ANYGRASP團隊后來推出的新版本ANYGRASP-Anything也是為了緩解這個問題通過在更多物體類型、更多場景布局上擴充訓練數(shù)據(jù)來提升跨場景泛化能力。這提醒我們搞抓取算法不能只看網(wǎng)絡結(jié)構數(shù)據(jù)從哪里來、怎么組織的往往才是決定上限的因素。2.4 與同類方案的橫向?qū)Ρ仍谡{(diào)研時我把常見開源方案放在一張表里比較過方案自由度輸入是否需要物體模型推理速度參考適用場景定位傳統(tǒng)幾何方法表面法線力閉合6-DOF點云否數(shù)秒到數(shù)十秒簡單場景單物體GraspNet-1B4-DOFRGB-D否百毫秒級平面堆疊、料筐揀選6-DOF GraspNet6-DOF點云否秒級較復雜但工程化不足ANYGRASP6-DOFRGB-D否兩百毫秒級雜亂堆疊、工業(yè)分揀基于大模型的方法如GraspGPT等6-DOFRGB-D/語言否秒級語義抓取、開放詞匯倒不是說ANYGRASP在所有維度都最優(yōu)。它的不足主要在兩點一是對透明、高反光物體幾乎無解這其實是整個深度視覺領域的通病二是網(wǎng)絡本身沒有語義理解能力它不知道“這是個杯子”還是“這是個螺絲”它只知道“這里有一個形狀適合抓”。如果你的需求是“只抓紅色的零件、不抓黑色的零件”ANYGRASP本身做不到需要在上游加一個語義分割或目標檢測模塊來篩選抓取區(qū)域。3. 部署與調(diào)用從倉庫到第一組抓取3.1 環(huán)境準備與依賴項ANYGRASP開源倉庫的部署難度屬于中等不需要從零訓練但依賴項還是不少。我部署時用的環(huán)境是Ubuntu 20.04 Python 3.8 PyTorch 1.11CUDA 11.3GPU是基礎級的工控顯卡算力8.6的即可具體型號不一定非得旗艦。倉庫里要求的核心依賴包括PyTorch及相關CUDA庫點云庫open3d用于點云處理與可視化抓取采樣庫倉庫會捆綁用于生成候選抓取也包含抓取質(zhì)量評估模塊視覺推理的一些輔助庫比如cv2、numpy等基礎棧可選的ROS接口如果你要在機器人系統(tǒng)里用需要安裝對應版本。這個環(huán)境如果從零配起大概需要小半天時間。第一次跑的時候建議直接用倉庫自帶的demo腳本它會加載一個預先訓練好的模型權重輸入一幀測試圖輸出可視化的抓取假設。能跑通demo再往自己的相機數(shù)據(jù)上遷移。有一個容易卡住的細節(jié)模型權重文件需要單獨下載數(shù)量不小GB級別倉庫不會自動幫你拉下來。而且有些權重版本和倉庫代碼版本是對不上的建議先看release頁面的說明找一個測試過的組合。我踩過這個坑當時下載了最新權重復古用老代碼報了一堆維度不匹配的錯誤排查了半天才發(fā)現(xiàn)是權重版本不匹配。3.2 推理流程的關鍵代碼路徑我整理了一份自己的調(diào)用模板核心流程簡化為三步# 1. 讀取一幀RGB-D用相機內(nèi)參構造點云 rgb cv2.imread(scene_rgb.png) depth cv2.imread(scene_depth.png, cv2.IMREAD_UNCHANGED) points, colors, _ create_point_cloud_from_depth(depth, intrinsic) # 2. 構建模型輸入前向推理 grasp_proposals, _ graspnetAPI.inference(points, colors, intrinsic) # 3. 按置信度排序取最高分位姿執(zhí)行 grasp_proposals.sort_by_score() best_grasp grasp_proposals[0]從代碼層面看create_point_cloud_from_depth負責把深度圖轉(zhuǎn)成點云這里必須保證深度圖的單位是毫米還是米在前后是一致的。模型內(nèi)部對輸入點云有體素下采樣的預處理所以你輸入的原始點云分辨率不需要特別高能覆蓋物體就行。推理速度方面我在單張顯卡上測過512x512分辨率的輸入大概130到220毫秒視GPU而定。這個速度對于“慢速揀選”“半自主抓取”是夠的。如果你的產(chǎn)線節(jié)拍要求每秒一次抓取那可能需要TensorRT加速或者把輸入分辨率降下來。3.3 從單幀到機器人執(zhí)行任何一個抓取算法只輸出位姿是不夠的最終要把位姿轉(zhuǎn)成機械臂的運動指令。這一步看似簡單實際上有很多細節(jié)決定成功率。首先要把相機坐標系下的抓取位姿變換到機器人基座坐標系下。這需要相機與機器人之間的手眼標定。標定的精度直接決定了抓取位置是否偏。其次機械臂運動到抓取位姿時需要注意接近方向不能和物體周圍的其他障礙物碰撞簡單做法是讓機械臂先運動到抓取點后方的一個預備位置再沿接近方向直線插入。還有一個看似微小但很影響成功率的點夾爪閉合的力度和速度。ANYGRASP輸出的寬度是模型估計的“需要張開多大”但不代表夾爪真能張開這么多。我建議在代碼里加一個夾爪寬度上下限的裁剪同時根據(jù)目標物體的尺寸估算合理的夾取力擋位。這些參數(shù)沒有統(tǒng)一答案跟夾爪型號和被抓物體材質(zhì)有關需要在現(xiàn)場試。3.4 低成本部署的可行性判斷如果你預算有限不打算上昂貴的工業(yè)相機和機械臂ANYGRASP是否還能用我的判斷是可以做初步驗證但要提前管理預期。先看傳感器。任何能輸出對齊的RGB-D的相機都可以比如入門級的深度相機。問題在于深度質(zhì)量近距離幾十厘米到一米內(nèi)、光照適中、無強反射的條件下入門級相機的點云質(zhì)量夠用。一旦物體是深色、反光或者處于強烈環(huán)境光下深度圖會出現(xiàn)大塊空洞直接導致抓取位姿不可用。再看算力。ANYGRASP官方demo在消費級中端顯卡上就能跑到實時或準實時。我用過不帶獨立顯卡的迷你主機CPU推理大概需要兩三秒一幀也能出結(jié)果只是節(jié)拍很慢。因此前期算法驗證階段不需要特別貴的算力等確認可行再考慮上專用設備。4. 實測記錄成功案例與避坑指南4.1 場景一小型金屬零件的料筐分揀我搭了一套實驗系統(tǒng)場景是一個40cm見方的料筐里面混著十幾種尺寸從2cm到8cm不等的金屬零件包括螺釘、螺母、墊片、彈簧、異形支架等。相機裝在料筐斜上方約70cm處ANYGRASP模型每次輸出5到10個候選抓取按置信度取最高的執(zhí)行。剛開始的成功率并不高大概只有五成左右。分析失敗案例后發(fā)現(xiàn)問題大多不是模型判斷錯了而是點云本身太稀疏細小的螺釘、彈簧在70cm距離下深度點數(shù)量很少模型難以給出穩(wěn)定的抓取建議。把相機降低到45cm左右之后點云密度明顯提升成功率升到七成以上。這個場景給我的經(jīng)驗是對小型零件成像距離和相機分辨率比算法調(diào)參重要得多。如果條件允許盡量讓目標物體在畫面中占據(jù)足夠大的像素面積而不是為了讓相機視角更廣把距離拉遠。4.2 場景二透明玻璃杯與高反光金屬這個測試是為了驗證邊界。我把一個透明玻璃杯和一塊鏡面不銹鋼塊放進場景想看看模型的失敗模式。結(jié)果符合預期透明玻璃在深度圖上基本呈空洞模型輸出的位姿完全不可用鏡面不銹鋼塊的深度值在邊緣處出現(xiàn)跳變抓取位置與真實表面偏差很大。做這個測試不是為了證明ANYGRASP不行而是為了提醒自己真實工業(yè)現(xiàn)場有很多深度相機無法可靠成像的物體。遇到這類物料需要額外方案比如給物體表面噴涂層、開結(jié)構光或者干脆改用雙目視覺中的紋理特征。4.3 高頻問題排查速查表我在不同環(huán)境里測了幾十輪把最常見的問題整理成了下表現(xiàn)象可能原因排查方向模型輸出的位姿指向空中點云里有大量離群噪聲檢查深度圖是否有大范圍空洞檢查點云裁剪半徑夾爪總是從側(cè)面而不是頂部接近抓取方向不包含重力約束模型純幾何判斷如果需要“只能從上方抓”后處理中篩選接近向量與重力方向的夾角同一物體連續(xù)兩次抓取結(jié)果變化大深度噪聲、下采樣令牌不同嘗試固定隨機種子對深度圖做時間平滑推理特別慢GPU利用不足、輸入點云太大降低輸入分辨率啟用批處理檢查是否在CPU上跑意外分支抓取成功但夾持后掉落寬度估計偏大夾爪未真正夾緊后處理裁剪寬度上限調(diào)整夾爪力度考慮加指尖傳感器反饋4.4 幾個我認為值得注意的細節(jié)第一任何公開抓取模型的置信度分數(shù)都不能直接當成功率用。ANYGRASP輸出0.9分不意味著實際抓取成功率是90%。這個分數(shù)只用于排序“相對更好”的候選實際的“絕對成功率”取決于你的物體、相機、機器人系統(tǒng)。所以不要一上來就把閾值設得特別高容易一個抓取都出不來。建議先在現(xiàn)場統(tǒng)計出自己的“置信度-成功率”曲線再定閾值。第二抓取位姿的執(zhí)行順序也有講究。如果模型一次輸出多個候選不要每次都只取最高分那個。最高分那個如果因為某些原因失敗了再試同一個位置的“第二名”往往也不行——因為模型認為那兩個位置其實很近。更好的做法是在下一次嘗試時把上一次失敗位置周圍的候選全部過濾掉讓機械臂換個區(qū)域去試。這雖然不是算法的一部分但在工程中非常管用。第三備注一下軟件層面的坑。倉庫代碼更新不算快但issue區(qū)很活躍。如果你在編譯過程中碰到與CUDA版本相關的報錯優(yōu)先去issue里搜基本都能找到解決方案。不要自己盲目升版本很可能升完之后其它依賴又崩了。5. 從調(diào)研到選型的幾點判斷5.1 方案選型建議如果你是做技術方案選型我按場景給幾點建議場景是“規(guī)則擺放的少量物體”且可以提前建模傳統(tǒng)幾何方法或者基于模板匹配的方案就夠不必上深度學習場景是“平面堆疊、只需要從上方抓取”GraspNet-1B這類4-DOF方案可能就夠模型更簡單部署更容易場景是“無規(guī)則堆疊、需要從側(cè)面或任意方向抓取”ANYGRASP這類6-DOF方案是更合理的選擇場景是“需要語義理解比如只拿紅色的杯子”那單做抓取位姿估計不夠要在前面加一個語義分割模塊ANYGRASP負責位姿語義模塊負責篩選。5.2 ANYGRASP在實際工程里的兩種撘法第一種是直接使用官方模型推理。適合前期驗證、樣機demo、中小批量的非標自動化項目。優(yōu)點是很省事缺點是泛化性受限于訓練數(shù)據(jù)分布遇到特別異形的物體可能給出較差的抓取建議。第二種是在自己的數(shù)據(jù)上微調(diào)。如果你的物體品類獨特、形狀高度一致比如專門抓某一種異形零件那么在官方預訓練權重的基礎上用仿真生成一批該物體的抓取數(shù)據(jù)做小規(guī)模微調(diào)通常能獲得比直接使用更好的效果。微調(diào)比重訓容易得多數(shù)據(jù)集規(guī)模幾百到幾千張就夠。微調(diào)有一點要提醒需要保證新數(shù)據(jù)與原始數(shù)據(jù)的“分布”不要差太遠比如原來訓練數(shù)據(jù)主要覆蓋室內(nèi)雜物你的新數(shù)據(jù)全部是室外強光下的物體那模型很可能會出現(xiàn)災難性遺忘。遇到這種情況建議保留一部分原始數(shù)據(jù)參與微調(diào)避免模型忘掉基本能力。5.3 從靜態(tài)抓取走向閉環(huán)單幀抓取是ANYGRASP的能力邊界但實際工程里很少是“看一眼抓一次”這么簡單。更常見的情況是抓取位姿執(zhí)行后夾爪帶上零件放到目標位置再回來抓下一個。這要求系統(tǒng)具備簡單的狀態(tài)判斷能力比如用夾爪的閉合量來判斷“是否真的夾到了東西”。我在實際測試中發(fā)現(xiàn)把“抓取置信度”和“夾爪閉合結(jié)果”組合起來做一個簡單的反饋閉環(huán)可以顯著提高揀選成功率。如果發(fā)現(xiàn)夾爪閉合距離明顯小于模型預測的寬度大概率是空抓或夾偏了這時系統(tǒng)可以自動放棄重新規(guī)劃而不是傻乎乎地繼續(xù)走回放流程。這種樸素的反饋機制比任何算法優(yōu)化都見效快。6. 后續(xù)計劃與生態(tài)觀察6.1 與語言模型的結(jié)合最近“大語言模型機器人操作”的思路很熱ANYGRASP這類位姿估計模型很適合作為“視覺底層”。大致管線是語言模型理解用戶指令“把紅色螺絲放進藍色盒子”視覺模型負責檢測紅色螺絲在圖像中的位置區(qū)域然后把區(qū)域掩碼疊加到點云上把范圍限制后交給ANYGRASP生成在該區(qū)域內(nèi)的高質(zhì)量抓取位姿。這樣就把“任意抓”變成了“按指令抓”。這個方向我個人非??春玫惨嵝熏F(xiàn)在很多論文把這條管線說得過于順滑實際上中間每個環(huán)節(jié)都有失敗率整體成功率是各環(huán)節(jié)成功率的乘積。哪怕每步都做到90%三步下來也只有73%。真正要落地需要每一環(huán)都做兜底和異?;謴?。6.2 動態(tài)場景的潛力ANYGRASP本質(zhì)是單幀靜態(tài)模型但如果我們用高幀率相機連續(xù)運行每一幀重新推理其實也能覆蓋一部分動態(tài)場景前提是物體移動速度不快。有人做過實驗把抓取頻率提到5到10Hz對緩慢移動的傳送帶物體也有效果。這不會替代專門的動態(tài)抓取方法但作為低成本方案值得一試。6.3 一個容易忽略的調(diào)研結(jié)論最后說一個我這次調(diào)研里感觸最深的一點算法本身只占項目難度的一半甚至不到一半。真正的復雜度來自數(shù)據(jù)、相機、標定、機器人運動規(guī)劃、異常處理這些“臟活”。很多人第一次接觸ANYGRASP看demo跑通了會很興奮然后興沖沖接上真機結(jié)果發(fā)現(xiàn)成功率不如預期于是懷疑算法不行。實際上多數(shù)失敗案例的原因都在相機參數(shù)、點云裁剪范圍、夾爪硬件適配這些看似不起眼的環(huán)節(jié)上。我的建議是做抓取項目時先把“測試條件固定住”。用一個簡單的、形狀規(guī)則的物體在一個光照穩(wěn)定、背景干凈的小場景里把全鏈路跑通記錄成功率。然后逐步增加物體種類、增加堆疊、增加干擾每改一個變量就重新統(tǒng)計一次成功率。這種增量式的測試方式能幫你快速定位問題出在哪個模塊——是感知、是規(guī)劃還是執(zhí)行。如果還沒有這么做的朋友建議參考這個思路重新搭一個項目文件夾按場景版本管理測試結(jié)果后續(xù)做優(yōu)化會高效很多。這套調(diào)研做完我對ANYGRASP的判斷是它不是一個完美的抓取算法但它是目前開源方案里綜合完成度最高的一個——有清晰的論文、可用的代碼、合理的文檔還有一批真實用戶踩坑記錄。對中小團隊來說與其自己從頭搞抓取位姿估計不如先把它用起來在它的基礎上疊加自己場景的數(shù)據(jù)和業(yè)務邏輯。畢竟算法的終點不是跑通一個demo而是讓機器人真正完成那些“重復、繁瑣、且不得不做”的操作。