本案例展示了如何利用視覺系統提升機械臂的抓取精度,成功實現了人形機器人的雙臂抓取不在局限于單臂抓取。
引言
如今市面上已經有了許多不同類型的人形機器人,涵蓋了服務行業和醫療行業等各個領域。這些機器人以其智能化和自動化的特性逐漸融入我們的日常生活和工作中。然而,盡管現有的人形機器人在特定應用場景中展現出了巨大的潛力,如何進一步提升其操作精度、適應性和多功能性,仍然是機器人技術發展的關鍵挑戰。針對這一需求,本案例探討了通過整合視覺系統與機械臂技術,來提升人形機器人在復雜環境中的自主操作能力,特別是在精確抓取和操作任務中的應用。
目標:
通過結合openc算法&STag標記碼視覺系統和Mercury X1輪式人形機器人,實現對各種形狀和大小的物品進行精準抓取,提高分揀效率和準確度,實現雙手合作充分發揮人形機器人的作用。
產品
Mercury X1
Mercury X1是由Elephant Robotics開發的一款先進的人形機器人,特別設計用于應對各種自動化任務。它擁有19個自由度,(單臂7個自由度)使其在執行任務時具有極高的靈活性和適應性。Mercury X1配備了輪式移動底座,由高性能直驅電機驅動,能夠在復雜環境中穩定移動,并具備高達8小時的電池續航能力,適合個人和商業應用。
這款機器人采用高性能主控制器系統,配置了NVIDIA Jetson Xavier提供強大的計算支持,以處理視覺測距、傳感器融合、定位與地圖構建、障礙檢測和路徑規劃等復雜算法。此外,Mercury X1的移動基座裝備了LiDAR、超聲波傳感器和2D視覺系統,能夠實現高感知的環境交互。
myCobot Pro Adaptive Gripper
自適應夾爪,它可以拾起任何形狀的任何物體并且不會松開。使用它來完成一系列完整的應用,并快速投入生產 - 無需機器人專業知識。它是高度靈活和可靠的機器人單元的關鍵。
myCobot Pro Camera Flange
使用USB-B數據線能夠獲取到圖像的相機模組。
接下來,我們將探討這些技術在實際應用中是如何被集成到機器人中,并展示其在具體任務中的表現。
技術概覽
OpenCV
OpenCV是用于實現圖像處理和計算機視覺的開源庫,它在本次的案例中扮演了至關重要的角色,沒有它就不能完成這個項目。機器人的攝像頭通過OpenCV分析收集到的視覺數據,識別和定位物體。OpenCV的算法使機器人能夠識別物體形狀、大小和精確坐標,這些信息對于精確抓取和操作至關重要。
提供了物體的坐標給機器人,就可以實現精準的抓取。
S-Tag標記碼技術
S-Tag標記碼是一種高度可靠的標識系統,設計用于在視覺上挑戰的環境中提供準確的標記識別。這些標記被用于標識Mercury X1機器人操作環境中的物體和位置。即使在光線不足或視線受阻的情況下,S-Tag也能確保機器人通過其攝像頭系統準確識別目標物體。
https://youtu.be/vnHI3GzLVrY
通過這些技術的應用,Mercury X1大象人形機器人能夠執行復雜的任務,如自主導航、物體識別和精確操控,這些都是現代自動化和智能系統不可或缺的能力。
pymycobot
pymycobot是用于控制Mercury X1機器人機械臂和末端執行器(如夾爪)的Python庫。它允許開發者精確控制機械臂的角度、坐標以及運動模式,包括差補模式和刷新模式。此庫為機器人提供了高度的靈活性和可定制性,使得機器人能夠執行復雜的抓取和操控任務,并適應各種操作需求。
項目實現
使用前準備
首先的確保機械臂的零位正確,可以通過下述方法校準零位:
1)使用放松指令釋放關節電機(注意!放松后需要扶住關節防止機械臂下墜損壞!)
ml.release_all_servos() mr.release_all_servos()
2)拖動機械臂回到零位
可以通過以下細節確定零點的位置
3) 發送指令鎖閉電機
ml.focus_all_servos() mr.focus_all_servos()
4)檢查零點是否正確
輸入獲取關節角度指令查詢當前位置
ml.get_angles() mr.get_angles()
如果返回的關節角度逼近[0, 0, 0, 0, 90, 0],則視為零點正確
5)零點校準
如果在零位讀取到的關節角度與[0, 0, 0, 0, 90, 0]相差很大,則需要校準關節零位
for i in range(1,7): ml.set_servo_calibration(i) mr.set_servo_calibration(i)
校準完畢后讀取關節信息,返回為[0, 0, 0, 0, 90, 0]則表示校準成功
ml.get_angles() mr.get_angles()
這樣就準備ok了,接下來可以繼續我們的功能部分的實現了。
相機和夾爪的安裝
相機和夾爪的安裝方式與視覺識別的手眼矩陣相對應,已經提前做好了一個關于Mercury X1 相機夾爪的手眼標定的數值,如果更改的話需要重新進行手眼標定。
首先將機械臂移動回零點:
ml.over_limit_return_zero() mr.over_limit_return_zero()
安裝先裝攝像頭(注意方向)然后再安裝夾爪,也需要注意方向。
視覺算法模塊
然后我們會使用到camera_detect 這個功能包,封裝了一些關于相機使用的方法,接下來我會介紹一些接口,針對對STag碼的識別,使用起來非常的方便,不需要自己再次進行手眼標定的計算了。
obj = camera_detect(Camera_ID, mark_size, mtx, dist, direction) 參數: camera_ID: 相機ID mark_size: stag碼邊長mm direction: 0:左臂 1:右臂 功能: 相機和機械臂初始化 obj.camera_open_loop() 功能: 顯示相機畫面 obj.stag_identify_loop() 功能: 顯示相機畫面,識別并打印stag碼的相機坐標 coords = obj.stag_robot_identify(direction) 參數: direction: 0:左臂 1:右臂 return: stag碼的機械臂坐標 功能: 計算stag碼的機械臂坐標 obj.vision_trace(catch_mode, direction) 參數: catch_mode: 0:水平抓取,1:豎直抓取 direction: 0:左臂 1:右臂 功能: 顯示相機畫面,識別并打印stag碼的相機坐標
以下是調用camera_detect包的使用代碼,非常的干凈簡潔。
import numpy as np from pymycobot import Mercury # 導入視覺識別stag包 from camera_detect import camera_detect if __name__ == "__main__": camera_params = np.load("camera_params.npz") # 相機配置文件 mtx, dist = camera_params["mtx"], camera_params["dist"] ml = Mercury("/dev/left_arm") # 設置左臂端口 mr = Mercury("/dev/right_arm") # 設置右臂端口 arm = 0 # 0左臂,1右臂 catch_mode = 0 # 0水平抓取,1豎直抓取 # 攝像頭id需要根據實際更改 left_camera_id = 3 right_camera_id = 6 stag_size = 32 # 新建左右臂視覺識別對象 ml_obj = camera_detect(left_camera_id, stag_size, mtx, dist, arm) mr_obj = camera_detect(right_camera_id, stag_size, mtx, dist, arm) # 左右臂移動至水平觀察位,進行抓取 mr_obj.vision_trace(catch_mode, mr) ml_obj.vision_trace(catch_mode, ml)
正常的手眼標定的步驟如下:
1數據采集:采集若干組手眼數據,包括機器人末端執行器在不同位置的姿態(即位置和方向)和相機看到的特征點的位姿。
2 建立運動方程:為了確定相機坐標系與機器人末端執行器坐標系之間的變換關系
3 求解變換矩陣 :得到的是描述相機坐標系和機器人末端執行器(手)坐標系之間的空間變換關系的值。
下面的代碼是解變換矩陣的例子。
# 將旋轉矩陣轉為歐拉角 def CvtRotationMatrixToEulerAngle(pdtRotationMatrix): pdtEulerAngle = np.zeros(3) pdtEulerAngle[2] = np.arctan2(pdtRotationMatrix[1, 0], pdtRotationMatrix[0, 0]) fCosRoll = np.cos(pdtEulerAngle[2]) fSinRoll = np.sin(pdtEulerAngle[2]) pdtEulerAngle[1] = np.arctan2(-pdtRotationMatrix[2, 0], (fCosRoll * pdtRotationMatrix[0, 0]) + (fSinRoll * pdtRotationMatrix[1, 0])) pdtEulerAngle[0] = np.arctan2((fSinRoll * pdtRotationMatrix[0, 2]) - (fCosRoll * pdtRotationMatrix[1, 2]), (-fSinRoll * pdtRotationMatrix[0, 1]) + (fCosRoll * pdtRotationMatrix[1, 1])) return pdtEulerAngle # 將歐拉角轉為旋轉矩陣 def CvtEulerAngleToRotationMatrix(ptrEulerAngle): ptrSinAngle = np.sin(ptrEulerAngle) ptrCosAngle = np.cos(ptrEulerAngle) ptrRotationMatrix = np.zeros((3, 3)) ptrRotationMatrix[0, 0] = ptrCosAngle[2] * ptrCosAngle[1] ptrRotationMatrix[0, 1] = ptrCosAngle[2] * ptrSinAngle[1] * ptrSinAngle[0] - ptrSinAngle[2] * ptrCosAngle[0] ptrRotationMatrix[0, 2] = ptrCosAngle[2] * ptrSinAngle[1] * ptrCosAngle[0] + ptrSinAngle[2] * ptrSinAngle[0] ptrRotationMatrix[1, 0] = ptrSinAngle[2] * ptrCosAngle[1] ptrRotationMatrix[1, 1] = ptrSinAngle[2] * ptrSinAngle[1] * ptrSinAngle[0] + ptrCosAngle[2] * ptrCosAngle[0] ptrRotationMatrix[1, 2] = ptrSinAngle[2] * ptrSinAngle[1] * ptrCosAngle[0] - ptrCosAngle[2] * ptrSinAngle[0] ptrRotationMatrix[2, 0] = -ptrSinAngle[1] ptrRotationMatrix[2, 1] = ptrCosAngle[1] * ptrSinAngle[0] ptrRotationMatrix[2, 2] = ptrCosAngle[1] * ptrCosAngle[0] return ptrRotationMatrix # 坐標轉換為齊次變換矩陣,(x,y,z,rx,ry,rz)單位rad def Transformation_matrix(coord): position_robot = coord[:3] pose_robot = coord[3:] # 將歐拉角轉為旋轉矩陣 RBT = CvtEulerAngleToRotationMatrix(pose_robot) PBT = np.array([[position_robot[0]], [position_robot[1]], [position_robot[2]]]) temp = np.concatenate((RBT, PBT), axis=1) array_1x4 = np.array([[0, 0, 0, 1]]) # 將兩個數組按行拼接起來 matrix = np.concatenate((temp, array_1x4), axis=0) return matrix
機械臂抓取
我們來控制機械臂的雙臂,會使用到pymycobot庫當中的Mercury,我們為了能夠直觀明了,每一條手臂控制的時候都需要創建一個對象。
from pymycobot import Mercury ml = Mercury('/dev/left_arm') mr = Mercury('/dev/right_arm') 控制機械臂末端運動到coords的坐標。 send_base_coords(coords, speed) 功能::控制機械臂末端運動到指定坐標 參數: coords: : 坐標值列表 [x,y,z,rx,ry,rz],length6 速度(int): 1 ~ 100
下面是識別目標物體進行抓取的代碼。
if __name__ == "__main__": # 設置攝像頭id camera = UVCCamera(5, mtx, dist) # 打開攝像頭 camera.capture() # 設置左臂觀察點 origin_anglesL = [-44.24, 15.56, 0.0, -102.59, 65.28, 52.06, 23.49] # 設置夾爪運動模式 ml.set_gripper_mode(0) # 設置工具坐標系 ml.set_tool_reference([0, 0, Tool_LEN, 0, 0, 0]) # 將末端坐標系設置為工具 ml.set_end_type(1) # 設置移動速度 sp = 40 # 移動到觀測點 ml.send_angles(origin_anglesL, sp) # 等待機械臂運動結束 waitl() # 刷新相機界面 camera.update_frame() # 獲取當前幀 frame = camera.color_frame() # 獲取畫面中二維碼的角度和id (corners, ids, rejected_corners) = stag.detectMarkers(frame, 11) # 獲取物的坐標(相機系) marker_pos_pack = calc_markers_base_position(corners, ids, MARKER_SIZE, mtx, dist) # 獲取機械臂當前坐標 cur_coords = np.array(ml.get_base_coords()) # 將角度值轉為弧度值 cur_bcl = cur_coords.copy() cur_bcl[-3:] *= (np.pi / 180) # 通過矩陣變化將物體坐標(相機系)轉成(基坐標系) fact_bcl = Eyes_in_hand_left(cur_bcl, marker_pos_pack) target_coords = cur_coords.copy() target_coords[0] = fact_bcl[0] target_coords[1] = fact_bcl[1] target_coords[2] = fact_bcl[2] + 50 # 機械臂移動到二維碼上方 ml.send_base_coords(target_coords, 30) # 等待機械臂運動結束 waitl() # 打開夾爪 ml.set_gripper_value(100, 100) # 機械臂沿z軸向下移動 ml.send_base_coord(3, fact_bcl[2], 10) # 等待機械臂運動結束 waitl() # 閉合夾爪 ml.set_gripper_value(20, 100) # 等待夾爪閉合 time.sleep(2) # 抬起夾爪 ml.send_base_coord(3, fact_bcl[2] + 50, 10)
單獨啟動左手的demo
下面是單獨啟動右手的demo。
總結
如果擁有一臺Mercury X1你會用他來做些什么呢?發揮他人形機器人最關鍵的特性,如果你有什么好的想法,想要實現的歡迎在下方留言和我們溝通,你的點贊和留言是對我們最大的支持!
審核編輯 黃宇
-
機器人
+關注
關注
211文章
28557瀏覽量
207687 -
算法
+關注
關注
23文章
4623瀏覽量
93104 -
視覺系統
+關注
關注
3文章
336瀏覽量
30794 -
人形機器人
+關注
關注
2文章
474瀏覽量
16691
發布評論請先 登錄
相關推薦
評論