基于深度学习的自动识别夹取机械臂
實現功能
可以實現對指定目標的自動搜索夾取工作具體效果
https://www.bilibili.com/video/BV1h64y1h7Yj/
優勢和不足
在目標檢測中使用的是基于深度學習的yolov4網絡訓練出來的模型,可以根據要識別的物體訓練相應的模型適用范圍更廣。不足之處是該機械臂 并沒有實現對物體角度的檢測和調整,以及 6自由度的控制仍然需要進一步完善。同時在夾取過程中沒有對夾取力的反饋是個開環控制仍需要改進。
基本結構與硬件選擇
機械臂的結構
機械臂的設計選取參考來了淘寶上賣的成品機械臂,購買了舵機支架和串口舵機進行了機械臂的組裝。最終成品采用了6個串口舵機組裝出了機械臂,淘寶商家都說這是6自由度的機械臂,其實完全不能達到6自由度機械臂的效果但是對于夾取來說完全足夠。
主控的選取
由于我使用的目標檢測是使用的yolov4的神經網絡模型進行檢測物體因此對主控的算力要求較高,開始選擇了樹莓派作為主控,結果發現在進行識別時識別速度太慢,延遲過高。因此選取了算力更加強大的nvidia nx作為主控。在攝像頭上選取了普通的720p無畸變的攝像頭。
具體實現過程
夾取部分實現
控制基本運動
控制串口舵機來控制機械臂的行動,選取串口舵機的原因是串口舵機占用主控資源較少同時該機械臂為實驗機器并不需要夾取太重物體,綜合考慮串口舵機較為適合。結合數字舵機的控制設置了串口舵機的串口參數并實現了對單個舵機的控制,為了實時檢測舵機的狀態,同時給出了可以讀取舵機位置的接口。具體程序如下
import serial import time class MOVE:def __init__(self,name,rate): self.command = {"MOVE_WRITE":1, "POS_READ":28, "LOAD_UNLOAD_WRITE": 31} self.ser = serial.Serial(name,rate)def servoWriteCmd(self,id, cmd, par1 = None, par2 = None):buf = bytearray(b'\x55\x55')try:len = 3 buf1 = bytearray(b'')if par1 is not None:len += 2 buf1.extend([(0xff & par1), (0xff & (par1 >> 8))]) if par2 is not None:len += 2buf1.extend([(0xff & par2), (0xff & (par2 >> 8))]) buf.extend([(0xff & id), (0xff & len), (0xff & cmd)])buf.extend(buf1) sum = 0x00for b in buf: sum += bsum = sum - 0x55 - 0x55 sum = ~sum buf.append(0xff & sum) self.ser.write(buf) except Exception as e:print(e)def readPosition(self,id):self.ser.flushInput() self.servoWriteCmd(id, self.command["POS_READ"]) time.sleep(0.00034) time.sleep(0.005) count = self.ser.inWaiting() pos = Noneif count != 0:recv_data = self.ser.read(count) if count == 8: if recv_data[0] == 0x55 :if recv_data[1] == 0x55 :if recv_data[4] == 0x1c:pos= 0xffff &(recv_data[5]|(0xff00 & recv_data[6] << 8)) return pos if __name__ =='__main__':move = MOVE(name="/dev/ttyUSB0",rate=115200)while(True):move.servoWriteCmd(2,1,500,0)pos=move.readPosition(1)time.sleep(1)print(pos)在實現對單個舵機的控制之后發現控制舵機轉動不能精確到固定角度,因此寫了角度轉換的的接口。
def runchange_angel (move,ang,times):for i in range(6):ang[i] = ang[i]*3.7 pos[i] = start[i]+int(ang[i])move.servoWriteCmd(5, 1, pos[4], times)move.servoWriteCmd(3, 1, pos[2], times)move.servoWriteCmd(4, 1, pos[3], times)move.servoWriteCmd(2, 1, pos[1], times)move.servoWriteCmd(1, 1, pos[0], times)move.servoWriteCmd(6, 1, pos[5], times)在實現對舵機的簡單控制之后考慮實現機械臂的基本運動,由于在檢測目標時僅僅識別到 二維平面的信息因此只需考慮機械臂在平面上的運動即可,采用極坐標系對夾爪的點進行定位,首先水平轉動平臺上的舵機來控制角度。該控制直接調用demo即可。對于長度方向上的控制,進行了簡單的運動學分析,得出在機械臂伸長時1和2舵機應向相反方向轉動相同角度的關系。具體控制代碼如下
def extend(move,pos,number,times):pos[1]+=numberpos[2]+=numberif pos[1]>=1000:print("伸長超出范圍")pos[1]=1000if pos[2]>=1000:print("伸長超出范圍")pos[2]=1000if pos[1]<=0:print("伸長超出范圍")pos[1]=0if pos[2]<=0:print("伸長超出范圍")pos[2]=0action.run(move,pos,times)return pos由于高度固定因此在機械臂的下降過程中直接通過實驗直接固定了角度調整的參數。
def decline_catch(move,pos,times):pos[2]=pos[2]-360pos[3]=pos[3]-310 #下降action.run(move,pos,times)pos[5]=pos[5]+250 #夾取action.run(move,pos,times)pos[2]=pos[2]+360pos[3]=pos[3]+310 #抬升 action.run(move,pos,times)return pos視覺識別
識別過程共采取兩種方案一是通過opencv第三方庫進行識別但是對比來看該方法的不足是識別不同物體時需要重新對程序進行大量修改,有時受光線的影響較大。但是該方法對主控的算力要求較低。而采用神經網絡的方法適用范圍廣,對主控算力要求高,綜合考慮選取了神經網絡的方式進行識別,在識別過程中選取了yolov4模型進行視覺的識別,首先收集到大量的目標物體圖片(由于實驗夾取的物體特征簡單因此只標記了200張圖片)進行訓練并調用攝像頭獲得圖像進行檢測最終將識別到的物體中心坐標以參數的形式返回
if __name__ =="__main__":move = mv.MOVE(name="/dev/ttyUSB0",rate=115200)# pos=[500, 511, 484, 800, 390, 276]# action.run(move,pos,1000)# decline_catch(move,pos,1000)# go_home(move,pos,1000)cap = cv2.VideoCapture(0) #讀取攝像頭cap.set(cv2.CAP_PROP_FRAME_WIDTH, 640);cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 480);ret, frame = cap.read()cx=320cy=240+100pos,dets=search(move,[200,800],cap)print(pos,dets)while ret:ret, frame = cap.read()dets,frame = tracking.detector.detect_image(frame,classes=['fy']) if len(dets) > 0:name,score,bbox = dets[0]x = (bbox[0] + bbox[2]) / 2y = (bbox[1] + bbox[3]) / 2pos,pan_error,tai_error=tracking.pid_move(move,x,y,cx,cy,pos)print(pos)if pan_error==0 and tai_error==0:pos=decline_catch(move,pos,1000)go_home(move,pos,1000)breakcv2.imshow('frame', frame)cv2.waitKey(1)目標尋找以及PID控制
尋找物體時采用的方式是使機械臂遍歷整個區域從而檢測目標物,當檢測到目標物時在進入PID調節從而快速確定夾爪應在位置。為了快速將夾爪定位到準確位置使用了PID算法進行了控制優化。
import time from math import pi, isnanclass PID:_kp = _ki = _kd = _integrator = _imax = 0_last_error = _last_derivative = _last_t = 0_RC = 1/(2 * pi * 20)def __init__(self, p=0, i=0, d=0, imax=0):self._kp = float(p)self._ki = float(i)self._kd = float(d)self._imax = abs(imax)self._last_derivative = float('nan')def get_pid(self, error, scaler):tnow = time.clock()dt = tnow - self._last_toutput = 0if self._last_t == 0 or dt > 1000:dt = 0self.reset_I()self._last_t = tnowdelta_time = float(dt) / float(1000)output += error * self._kpif abs(self._kd) > 0 and dt > 0:if isnan(self._last_derivative):derivative = 0self._last_derivative = 0else:derivative = (error - self._last_error) / delta_timederivative = self._last_derivative + \((delta_time / (self._RC + delta_time)) * \(derivative - self._last_derivative))self._last_error = errorself._last_derivative = derivativeoutput += self._kd * derivativeoutput *= scalerif abs(self._ki) > 0 and dt > 0:self._integrator += (error * self._ki) * scaler * delta_timeif self._integrator < -self._imax: self._integrator = -self._imaxelif self._integrator > self._imax: self._integrator = self._imaxoutput += self._integratorreturn outputdef reset_I(self):self._integrator = 0self._last_derivative = float('nan')得出PID優化后的偏差后不斷進行反復調整最終實現了夾爪的快速定位
def pid_move(move,x,y,cx,cy,pos):pan_error = cx-x #左邊為負tai_error = cy-y #上邊為負print(pan_error,tai_error)if abs(pan_error) < 40:pan_error = 0 if abs(tai_error) < 40:tai_error = 0pan_out=pan_pid.get_pid(pan_error,1)tai_out=tai_pid.get_pid(tai_error,1)pos=catch.turn(move,pos,int(pan_out),15)pos=catch.extend(move,pos,int(tai_out),15)for number in pos:if number<=0:number=0if number>=1000:number=1000return(pos,pan_error,tai_error)該機械臂是仍是一個十分不成熟的產品,存在諸多問題。若文中出現錯誤,懇請大佬批評指正!
總結
以上是生活随笔為你收集整理的基于深度学习的自动识别夹取机械臂的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 计算机在化学中的应用免费论文,计算机在化
- 下一篇: LTC6911 采用 MSOP 封装并具