对弈人工智能!大象机器人myCobot 280开源六轴机械臂Connect 4 四子棋对弈下篇

前言

在上篇文章中,我们探讨了如何创造一个能够进行Connect4的对弈大脑。简单的介绍了几种对弈算法,例如极小化极大算法,Alpha-Beta剪枝算法等,最关键的是目前最流行的神经网络算法和深度学习。神经网络算法,让计算机也有一个想人类一样能够思考的大脑,设置独特的场景来进行学习下棋。

在本篇文章中,我们将进一步探讨如何让机械臂来实现下棋动作,将想法给实现出来。(换句话说就是,AI机械臂下棋),如果感兴趣欢迎观看上篇文章。

Introduction

下面的内容主要分为四个部分来进行介绍。

● 获取信息:用摄像头获取到棋盘上的信息,进行对弈


            ● 处理信息:处理获取到的信息识别出棋子的位置,通过对弈算法,计算出下一步棋子应该在哪里下


            ● 机械臂的轨迹:设计机械臂如何抓取棋子,设计放置棋子的路径


            ● 功能的整合:将上面三个功能结合在一起,实现AI机械臂下棋。

复制

让我们一起来看看吧~

项目

获取信息

环境:python最新版的opencv,numpy

首先需要获取棋盘的信息,信息包括棋盘,棋盘上的棋子。我们用到的是OpenCV当中cv2.aruco.ArucoDetector(dictionary, parameters)

该方法用来检测Aruco二维码,从图片当中标记出Aruco的位置,并且计算出标记的位置和姿态信息。这样就能够确定整个棋盘的位置了,确定四个角的位置。

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

复制

确定完棋盘之后,我们用不同的颜色来当棋子,这里就用两种区分度比较大的颜色,红色和黄色,并且标注出来。

设置一个逻辑,当棋面每多一枚棋子的时候,将当前棋盘的数据返回给到对弈算法,进行判断下一步棋应该如何走。

处理信息

接下来需要处理棋盘的信息。

从上边可以看到我们获取到了棋盘的数据,接下来我们需要把数据,传递给对弈算法,让对弈算法将下一步棋子的位置预测出来。

下面是处理的伪代码:

functionmodel_predict(state, available_actions):
# 将available_actions转换为numpy数组
    available_actions = np.array(available_actions)
# 对state进行扩展,以适应ONNX模型的输入要求
    state = np.expand_dims(np.expand_dims(np.array(state, dtype=np.float32), axis=0), axis=0)
# 构建ONNX模型的输入
    ort_inputs ={self.policy_net.get_inputs()[0].name: state}
# 进行模型预测,获取每个可用位置的预测值
    r_actions =self.policy_net.run(None, ort_inputs)[0][0,:]
# 根据预测值选择最优的落子位置
    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模型来进行模型预测,并根据预测结果选择最优的落子位置。首先,将可用位置available_actions转换为numpy数组,并将当前游戏状态state进行扩展,以适应ONNX模型的输入要求。

然后,将扩展后的state传递给ONNX模型进行预测,并将预测结果保存在r_actions变量中。接着,根据预测结果以及可用的落子位置,计算出每个可用位置的预测值,选取其中最大的一个对应的落子位置作为最优的落子位置,并将其返回。

机械臂的轨迹

大脑(对弈算法),眼睛(识别算法)都有了,现在就差一个手去执行动作。我们使用python库pymycobot来对机械臂进行控制。因为棋盘的原因,棋子只能从棋盘的上方投下,我们给每一条数列的棋个上设置一个坐标点位,就可以完成机械臂的路径规划了。因为棋面比较干净没有遮挡物,所以不用考虑过多的路径因素。

下面是机械臂运行轨迹位置的伪代码:

# 初始化定义几个坐标点
# 设定一个长度为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当中控制机械臂的一些方法:

#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)

复制

功能的整合

将功能点整合之前我们得整理它们之间的逻辑。

下棋的流程图有了接下来就是,将功能点结合在一起.

这是程序的结构文件。

├── 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.

总结

从理论上来说的话,几乎没有人能够在赢得胜利。因为机器的算法可以预测到后面将要下在几步棋甚至更多,而对于普通人来说,一般能够预测的也就两三步棋。但是从视频上来看,AI只赢了一场比赛,输掉的那一场是因为结构因素的影响,本来该下的棋盘的位置,被迫换了一个地方。

你觉得这个项目有意思吗?我们会在后续将Connect4 这个套装进行完善后,上架在我们的网站,有兴趣的朋友可以关注我们,后续会进行更新。

你是否会尝试用机械臂来实现其他的棋艺呢?例如国际象棋,中国象棋等,不同的棋艺所使用的算法也会大大不同,欢迎大家在地下跟我们留言进行分享你们的想法。

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 六子是一种双人对战的类游戏,通过在盘上落子,以先连成六个子为胜利条件。下面是一个简单的六子对弈程序的编写思路: 1. 初始化盘:创建一个6x6的二维数组,表示盘,初始值为0,表示空位。 2. 编写落子函数:通过输入玩家的坐标,将对应位置的值设置为1(玩家1)或2(玩家2)。 3. 编写判断胜利函数:在落子后,判断当前落子的玩家是否胜利。可以通过遍历盘的每个位置,查找横向、纵向、左上至右下和右上至左下四个方向上是否有连续的六个子。 4. 编写主函数:在主函数中,通过轮流输入两个玩家的坐标,并调用落子函数和判断胜利函数,直到有一方获胜或盘下满。 5. 输出结果:根据最终胜利的玩家,输出对应的胜利信息。 以上为六子对弈程序的简单实现思路,可以根据具体要求进行完善和扩展。在编写程序时,需要注意边界条件的处理,例如输入的坐标是否合法、盘已满无法落子等情况的处理。同时,可以考虑增加人机对战功能、计算机自动下子等扩展功能,提升游戏的趣味性和智能性。 ### 回答2: 六子是一种类游戏,在一个6×6的盘上,双方轮流下子,先将6个自己的子连成一条线的一方获胜。下面是一个简单的六子对弈程序。 首先,我们需要定义一个6×6的盘,可以用一个二维数组来表示。其中,空格用0表示,玩家1下的子用1表示,玩家2下的子用2表示。 接下来,我们需要编写一个函数来打印当前盘的状态,方便玩家观察。我们可以使用循环来遍历整个盘数组,根据不同的数字来显示相应的符号。 然后,我们需要编写一个函数来判断是否出现获胜的情况。对于每个下子的位置,我们可以分别检查水平、垂直和两个对角线方向上是否存在连续的6个相同的数字,如果有则表示获胜。 接着,我们需要编写一个函数来允许玩家进行下。我们可以使用循环来不断接受玩家的输入,并将对应的数字填入盘数组中的相应位置。 最后,我们需要编写一个主函数,用于控制整个对弈的流程。在主函数中,我们可以交替调用玩家下和判断获胜的函数,直到出现获胜的情况为止。 需要注意的是,对于每一步输入的位置,我们需要检查该位置是否为空,如果不为空则需要重新输入。 以上是一个简单的六子对弈程序的实现方法,只是一个基础的框架,具体的细节还可以根据需要进行进一步的优化和完善。 ### 回答3: 六子是一种双人对弈类游戏,玩家通过轮流落子,在盘上尝试连接六个子来获胜。编写六子对弈程序的主要思路如下。 首先,需要创建一个6x6的盘作为游戏的背景。可以使用二维数组来表示盘,每个元素表示一个位置,初始值为空。 接下来,需要实现玩家可以通过输入坐标来落子的功能。可以通过交替输入两个玩家的坐标来完成轮流落子。同时,需要判断输入的坐标是否合法,即是否在盘范围内以及该位置是否已经被占据。 落子完成后,程序需要判断是否有玩家获胜。可以创建一个函数来判断当前落子是否导致了连续六个相同颜色的子,如果是,则该玩家获胜。可以通过遍历盘的每个位置,判断该位置上、右上、右侧、右下四个方向上的连续子数量来实现。 最后,需要循环执行落子和判断胜负的过程,直到有玩家获胜或者盘被下满而无法继续落子。在游戏结束后,可以输出胜利的玩家或者平局的提示信息,然后询问是否继续游戏。 总结起来,编写六子对弈程序的关键是实现盘的表示、落子和判断胜负的功能。通过循环执行这些操作,可以实现一个基本的六子对战游戏。当然,还可以进一步优化程序,加入更多的功能,如人机对弈、保存和读取游戏进度等。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值