前言
在上篇文章中,我們探討了如何創(chuàng)造一個能夠進(jìn)行Connect4的對弈大腦。簡單的介紹了幾種對弈算法,例如極小化極大算法,Alpha-Beta剪枝算法等,最關(guān)鍵的是目前最流行的神經(jīng)網(wǎng)絡(luò)算法和深度學(xué)習(xí)。神經(jīng)網(wǎng)絡(luò)算法,讓計算機(jī)也有一個想人類一樣能夠思考的大腦,設(shè)置獨(dú)特的場景來進(jìn)行學(xué)習(xí)下棋。在本篇文章中,我們將進(jìn)一步探討如何讓機(jī)械臂來實現(xiàn)下棋動作,將想法給實現(xiàn)出來。(換句話說就是,AI機(jī)械臂下棋)
如果感興趣歡迎觀看上篇文章。
Introduction
下面的內(nèi)容主要分為四個部分來進(jìn)行介紹。
● 獲取信息:用攝像頭獲取到棋盤上的信息,進(jìn)行對弈
● 處理信息:處理獲取到的信息識別出棋子的位置,通過對弈算法,計算出下一步棋子應(yīng)該在哪里下
● 機(jī)械臂的軌跡:設(shè)計機(jī)械臂如何抓取棋子,設(shè)計放置棋子的路徑
● 功能的整合:將上面三個功能結(jié)合在一起,實現(xiàn)AI機(jī)械臂下棋。
讓我們一起來看看吧~
項目
獲取信息
環(huán)境:python,最新版的opencv,numpy
首先需要獲取棋盤的信息,信息包括棋盤,棋盤上的棋子。我們用到的是OpenCV當(dāng)中cv2.aruco.ArucoDetector(dictionary, parameters)
該方法用來檢測Aruco二維碼,從圖片當(dāng)中標(biāo)記出Aruco的位置,并且計算出標(biāo)記的位置和姿態(tài)信息。這樣就能夠確定整個棋盤的位置了,確定四個角的位置。
Code:代碼是用cv2.aruco.ArucoDetector(dictionary, parameters)方法來確定我們棋盤的位置。
dictionary = cv2.aruco.getPredefinedDictionary(cv2.aruco.DICT_6X6_250)
parameters = cv2.aruco.DetectorParameters()
detector = cv2.aruco.ArucoDetector(dictionary, parameters)
corners, ids, rejectedCandidates = detector.detectMarkers(bgr_data)
rvec, tvec, _ = cv2.aruco.estimatePoseSingleMarkers(corners, 0.05, self.mtx, self.dist)
if rvec is None or len(corners) != 4:
return None
# debug
if DEBUG:
debug_img = bgr_data.copy()
for i in range(rvec.shape[0]):
cv2.drawFrameAxes(debug_img, self.mtx, self.dist, rvec[i, :, :, ], tvec[i, :, :, ],
0.03)
# Draw a square around the marker.
cv2.aruco.drawDetectedMarkers(debug_img, corners)
cv2.imshow("debug1", debug_img)
# Sort the detected QR code corner points in the following order: top left, top right, bottom left, bottom right.
corners = np.mean(corners, axis=2)
corners = (np.ceil(corners)).astype(int)
corners = corners.reshape((4, 2))
cx, cy = (np.mean(corners[:, 0]), np.mean(corners[:, 1]))
res: list = [None for _ in range(4)]
for x, y in corners:
if x < cx and y < cy:
res[0] = (x, y)
elif x > cx and y < cy:
res[1] = (x, y)
elif x < cx and y > cy:
res[2] = (x, y)
else:
res[3] = (x, y)
res = np.array(res)
## debug code
if DEBUG:
debug_img = bgr_data.copy()
for p in res:
cv2.circle(debug_img, p, 3, BGR_GREEN, -1)
cv2.imshow("aruco", debug_img)
return res
確定完棋盤之后,我們用不同的顏色來當(dāng)棋子,這里就用兩種區(qū)分度比較大的顏色,紅色和黃色,并且標(biāo)注出來。
設(shè)置一個邏輯,當(dāng)棋面每多一枚棋子的時候,將當(dāng)前棋盤的數(shù)據(jù)返回給到對弈算法,進(jìn)行判斷下一步棋應(yīng)該如何走。
處理信息
接下來需要處理棋盤的信息。
從上邊可以看到我們獲取到了棋盤的數(shù)據(jù),接下來我們需要把數(shù)據(jù),傳遞給對弈算法,讓對弈算法將下一步棋子的位置預(yù)測出來。
下面是處理的偽代碼:
functionmodel_predict(state, available_actions):
# 將available_actions轉(zhuǎn)換為numpy數(shù)組
available_actions = np.array(available_actions)
# 對state進(jìn)行擴(kuò)展,以適應(yīng)ONNX模型的輸入要求
state = np.expand_dims(np.expand_dims(np.array(state, dtype=np.float32), axis=0), axis=0)
# 構(gòu)建ONNX模型的輸入
ort_inputs ={self.policy_net.get_inputs()[0].name: state}
# 進(jìn)行模型預(yù)測,獲取每個可用位置的預(yù)測值
r_actions =self.policy_net.run(None, ort_inputs)[0][0,:]
# 根據(jù)預(yù)測值選擇最優(yōu)的落子位置
state_action_values = np.array(
[r_actions[action]for action in available_actions])
argmax_action = np.argmax(state_action_values)
greedy_action = available_actions[argmax_action]
return greedy_action
該方法中的主要邏輯是使用ONNX模型來進(jìn)行模型預(yù)測,并根據(jù)預(yù)測結(jié)果選擇最優(yōu)的落子位置。首先,將可用位置available_actions轉(zhuǎn)換為numpy數(shù)組,并將當(dāng)前游戲狀態(tài)state進(jìn)行擴(kuò)展,以適應(yīng)ONNX模型的輸入要求。然后,將擴(kuò)展后的state傳遞給ONNX模型進(jìn)行預(yù)測,并將預(yù)測結(jié)果保存在r_actions變量中。接著,根據(jù)預(yù)測結(jié)果以及可用的落子位置,計算出每個可用位置的預(yù)測值,選取其中最大的一個對應(yīng)的落子位置作為最優(yōu)的落子位置,并將其返回。
機(jī)械臂的軌跡
大腦(對弈算法),眼睛(識別算法)都有了,現(xiàn)在就差一個手去執(zhí)行動作。我們使用python庫pymycobot來對機(jī)械臂進(jìn)行控制。因為棋盤的原因,棋子只能從棋盤的上方投下,我們給每一條數(shù)列的棋個上設(shè)置一個坐標(biāo)點(diǎn)位,就可以完成機(jī)械臂的路徑規(guī)劃了。因為棋面比較干凈沒有遮擋物,所以不用考慮過多的路徑因素。
下面是機(jī)械臂運(yùn)行軌跡位置的偽代碼:
# 初始化定義幾個坐標(biāo)點(diǎn)
# 設(shè)定一個長度為7的列表
self.chess_table = [None for _ in range(7)]
self.chess_table[0]-[6] = [J1,J2,J3,J4,J5,J6] # 七個棋格的位置
self.angle_table = {
"recovery": [0, 0, 0, 0, 0, 0], #初始位置
"observe": [-2.54, 135.0, -122.95, -32.34, 2.46, -90.35],#觀察位置
"stack-hover-1": [-47.19, -37.96, -58.53, 1.05, -1.93, -1.84],#吸取棋子的位置
}
接下來介紹一下pymycobot當(dāng)中控制機(jī)械臂的一些方法:
#Sending the angle to the robotic arm.
self.send_angles(self.chess_table[n], ARM_SPEED)
#Sending the Cartesian coordinates to the robotic arm.
self.send_coords(coord_list,ARM_SPEED)
功能的整合
將功能點(diǎn)整合之前我們得整理它們之間的邏輯。
下棋的流程圖有了接下來就是,將功能點(diǎn)結(jié)合在一起.
這是程序的結(jié)構(gòu)文件。
├── Agent.py The logic of the robotic arm's gameplay.
├── ArmCamera.pyCamera control.
├── ArmInterface.py Robotics Arm control
├── Board.py Data structure of the chessboard and related judgments.
├── CameraDemo.py Small program for testing camera performance.
├── config.pyUtilized to define specific configuration details.
├── Detection.py Machine vision recognition.
├── dqn.ptNeural network model file, used to implement gameplay logic.
├── main.pymain program.
├── StateMachine.pyA state machine.
總結(jié)
從理論上來說的話,幾乎沒有人能夠在贏得勝利。因為機(jī)器的算法可以預(yù)測到后面將要下在幾步棋甚至更多,而對于普通人來說,一般能夠預(yù)測的也就兩三步棋。但是從視頻上來看,AI只贏了一場比賽,輸?shù)舻哪且粓鍪且驗榻Y(jié)構(gòu)因素的影響,本來該下的棋盤的位置,被迫換了一個地方。
你覺得這個項目有意思嗎?我們會在后續(xù)將Connect4 這個套裝進(jìn)行完善后,上架在我們的網(wǎng)站,有興趣的朋友可以關(guān)注我們,后續(xù)會進(jìn)行更新。
你是否會嘗試用機(jī)械臂來實現(xiàn)其他的棋藝呢?例如國際象棋,中國象棋等,不同的棋藝所使用的算法也會大大不同,歡迎大家在地下跟我們留言進(jìn)行分享你們的想法。
審核編輯 黃宇
-
機(jī)器人
+關(guān)注
關(guān)注
211文章
28575瀏覽量
207745 -
算法
+關(guān)注
關(guān)注
23文章
4625瀏覽量
93124 -
人工智能
+關(guān)注
關(guān)注
1793文章
47532瀏覽量
239295 -
機(jī)械臂
+關(guān)注
關(guān)注
12文章
518瀏覽量
24656
發(fā)布評論請先 登錄
相關(guān)推薦
評論