欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 财经 > 创投人物 > [星瞳科技]如何用OpenMV制造三子棋机器人?

[星瞳科技]如何用OpenMV制造三子棋机器人?

2024/10/25 6:32:19 来源:https://blog.csdn.net/SingTown_OpenMV/article/details/141159001  浏览:    关键词:[星瞳科技]如何用OpenMV制造三子棋机器人?

三子棋机器人,一共分三个步骤:

1,图像识别,获得棋子数组。

2,下棋策略算法。

3,机械臂控制抓取和落子。

硬件上我们使用了星瞳科技的OpenMV4 H7,所有的代码都是在OpenMV上运行的!包括机械臂控制,继电器控制,下棋策略算法,图像识别算法。

机械臂是直接3D打印的,使用了3个舵机,可以直接通过OpenMV的舵机扩展板控制。

棋子拾取是电磁铁来实现的,因为我顺手薅了10个纽扣电池当棋子。OpenMV可以通过继电器控制电磁铁。

1,图像识别很简单,先获取灰度图,然后在9个棋盘区域内,获取颜色信息,在OpenMV中使用statics完成。通过灰度信息,可以得到是黑子,还是白子,还是空子。 2,计算下一步棋应该怎么走,我的好朋友CHATGPT老师告诉我用minimax算法,并且给我写好了这部分的代码。 3,机械臂控制也比较简单,在等候取子区,以及每个9宫格落子区,都获取机械臂的位置,通常可以通过示教功能来完成,因为我的机械臂只用了一天时间做的很赶,所以是通过代码直接看位置。

# robot.pyimport time
from servo import Servos
from machine import SoftI2C, Pin
import math# 控制继电器,继电器控制电磁铁
pin1 = Pin('P1', Pin.OUT_PP, Pin.PULL_NONE)
pin1.value(0)# PCA9685 舵机扩展板
i2c = SoftI2C(sda=Pin('P5'), scl=Pin('P4'))
servo = Servos(i2c, address=0x40, freq=50, min_us=650, max_us=2800, degrees=180)# 三个舵机的初始位置
servo.position(0, 0)
servo.position(1, 90)
servo.position(2, 90)#全局变量,用于缓慢移动
servo_positions = [0,90,90]# 控制一个舵机移动
def move(index, angle):servo.position(index, angle)servo_positions[index] = angle# 控制三个舵机移动
def move_list(angle_list):print(angle_list)move(0, int(angle_list[0]))move(1, int(angle_list[1]))move(2, int(angle_list[2]))# 控制三个舵机慢速移动
def slow_move_to(angle_list):init_positions = servo_positions.copy()d0 = angle_list[0] - init_positions[0]d1 = angle_list[1] - init_positions[1]d2 = angle_list[2] - init_positions[2]dm = int(max(abs(d0), abs(d1), abs(d2)))if dm == 0:returnfor i in range(dm+1):move_list([init_positions[0]+i*d0/dm,init_positions[1]+i*d1/dm,init_positions[2]+i*d2/dm])time.sleep_ms(40)# 设置棋子拾取区的位置
PICK = [[74,128,19], [82,128,17], [90,125,14], [98,128,17], [106,128,19]]
# 拾取区机械臂提起来的位置
HIGH_PICK = [90,95,55]# 棋盘的放置位置
BOARD = [[[82,150,55], [82,140,40], [81,133,30]],[[90,150,55], [90,140,40], [90,133,30]],[[98,150,55], [98,140,40], [99,133,30]]
]# 棋盘落子上方的位置
HIGH_BOARD = [90,120,70]# 拾取棋子,并放置到 x,y
def pick_and_place(x,y):slow_move_to(HIGH_PICK)time.sleep_ms(500)slow_move_to(PICK[2])time.sleep_ms(500)slow_move_to(HIGH_PICK)time.sleep_ms(500)slow_move_to(HIGH_BOARD)time.sleep_ms(500)slow_move_to(BOARD[y][x])time.sleep_ms(500)pin1.value(1) # 继电器打开time.sleep_ms(500)slow_move_to(HIGH_PICK)pin1.value(0) # 继电器关闭time.sleep_ms(500)slow_move_to([0,90,90])if __name__ == "__main__":
# 校准测试用time.sleep_ms(1)for order in [BOARD[1][1], BOARD[0][0], BOARD[1][0],BOARD[2][0], BOARD[2][1], BOARD[2][2],BOARD[1][2], BOARD[0][2], BOARD[0][1],]:slow_move_to(HIGH_BOARD)time.sleep_ms(500)slow_move_to(order)time.sleep_ms(500)#slow_move_to(BOARD[0][2])#for x in PICK:#slow_move_to(HIGH_PICK)#time.sleep_ms(500)#slow_move_to(x)#time.sleep_ms(500)slow_move_to([0,90,90])
# chess.py
SIZE = 3# 检查赢了吗
def check_win(board, player):# Check rows and columnsfor i in range(SIZE):if all(board[i][j] == player for j in range(SIZE)) or \all(board[j][i] == player for j in range(SIZE)):return True# Check diagonalsif all(board[i][i] == player for i in range(SIZE)) or \all(board[i][SIZE - 1 - i] == player for i in range(SIZE)):return Truereturn False# 检查平局了吗
def check_draw(board):return all(board[i][j] != ' ' for i in range(SIZE) for j in range(SIZE))# 计算策略得分
def minimax(board, depth, is_maximizing):computer = 'X'player = 'O'if check_win(board, computer):return 10 - depthif check_win(board, player):return depth - 10if check_draw(board):return 0if is_maximizing:best_score = float('-inf')for i in range(SIZE):for j in range(SIZE):if board[i][j] == ' ':board[i][j] = computerscore = minimax(board, depth + 1, False)board[i][j] = ' 'best_score = max(score, best_score)return best_scoreelse:best_score = float('inf')for i in range(SIZE):for j in range(SIZE):if board[i][j] == ' ':board[i][j] = playerscore = minimax(board, depth + 1, True)board[i][j] = ' 'best_score = min(score, best_score)return best_score# 计算下一步位置
def computer_move(board):if board == [[" "," "," "],[" "," "," "],[" "," "," "]]:return 1,1best_score = float('-inf')move = (-1, -1)for i in range(SIZE):for j in range(SIZE):if board[i][j] == ' ':board[i][j] = 'X'score = minimax(board, 0, False)board[i][j] = ' 'if score > best_score:best_score = scoremove = (i, j)if move != (-1, -1):# board[move[0]][move[1]] = 'X'print(f"Computer places X at ({move[0]}, {move[1]})")return move[0], move[1]# 检查该谁走了
def check_turn(board):x_count = sum(row.count("X") for row in board)o_count = sum(row.count("O") for row in board)return "X" if x_count == o_count else "O"
# main.py
import sensor, image, time
from pyb import Pin
import robot
import chesssensor.reset()
sensor.set_pixformat(sensor.GRAYSCALE)
sensor.set_framesize(sensor.QVGA)
sensor.skip_frames(time = 2000)clock = time.clock()# 轻触开关
pin0 = Pin('P0', Pin.IN, Pin.PULL_UP)distance = 43
block = 10# 生成九宫格的区域位置
def generate_centered_rois(width, height, b, k):rois = []# 计算每个ROI中心的位置偏移offset = (b - k) // 2# 计算整个3x3矩阵的宽度和高度total_width = 3 * btotal_height = 3 * b# 计算左上角的起始点,使矩阵居中start_x = (width - total_width) // 2start_y = (height - total_height) // 2for i in range(3):row = []for j in range(3):x_center = start_x + j * b + b // 2y_center = start_y + i * b + b // 2x = x_center - k // 2y = y_center - k // 2row.append((x, y, k, k))rois.append(row)return rois# 九宫格的区域位置
rois = generate_centered_rois(sensor.width(), sensor.height(), distance, block)# 棋盘数组
# 黑子:X
# 白子:O
# 没有棋子:空字符串
board = [[" "," "," "],[" "," "," "],[" "," "," "],
]#等开关按下并松开
def wait_key():while pin0.value():img = sensor.snapshot().lens_corr(1.8)for y in range(len(rois)):for x in range(len(rois[y])):img.draw_rectangle(rois[y][x])while not pin0.value():time.sleep_ms(1)while(True):clock.tick()wait_key()img = sensor.snapshot().lens_corr(1.8)# 图像识别得到棋盘数组for y in range(len(rois)):for x in range(len(rois[y])):gray = img.get_statistics(roi=rois[y][x]).mean()if gray < 100:board[y][x] = "X"elif gray > 200:board[y][x] = "O"else:board[y][x] = " "# 打印当前棋盘数组for line in board:print(line)print()# 画棋盘数组for y in range(len(rois)):for x in range(len(rois[y])):if board[y][x] == "X":color = 255elif board[y][x] == "O":color = 0elif board[y][x] == " ":color = 127img.draw_rectangle(rois[y][x], color=color)# 下棋策略if chess.check_win(board, 'O'):print("你赢啦!")elif chess.check_win(board, 'X'):print("我赢啦!")elif chess.check_draw(board):print("平局啦!")elif chess.check_turn(board) == "X":# 计算下一步棋子放在哪里line,row = chess.computer_move(board)# 目标棋盘上画十字img.draw_cross(int(rois[line][row][0]+block/2), int(rois[line][row][1]+block/2), size=block, color=0)sensor.flush()# 机器人拾取并放置棋子robot.pick_and_place(row, line)sensor.flush()elif chess.check_turn(board) == "O":print("该你下了!")

 

星瞳科技OpenMV视频教程-三子棋

 

 

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com