def __init__(self, rawbus, buswindex, moduleid): self.chess_engine = Stockfisher() self.moduleid = moduleid self.bus = CyclicBus(rawbus, buswindex, moduleid) regs_strings = ["player_colour", "difficulty"] self.regs = {} for str in regs_strings: self.regs[str] = None self.previous_num_of_white_pieces = 0 self.previous_num_of_black_pieces = 0 self.previous_num_of_pieces = [0] * 2 self.previous_num_of_pieces[0] = lambda: self.previous_num_of_white_pieces self.previous_num_of_pieces[1] = lambda: self.previous_num_of_black_pieces self.possible_capture = False self.first_pass = True self.last_error = "" self.moves = [] self.board = self.initChessboard(startpos=" ")
def __init__(self, rawbus, buswindex, moduleid): self.devaddr = "20:17:01:10:26:87" self.devpath = "/dev/myrfcomm0" self.moduleid = moduleid self.bus = CyclicBus(rawbus, buswindex, moduleid) self.dev = None self.stop_threads = False self.connector = None
class RoboChessCore(): def __init__(self): # init bus rawbus, buswindex = busCreate() self.moduleid = "cr" # init gui self.gui = self.startProcess(ChessGUI_launcher, rawbus, buswindex, "ui") # init chess cv self.cv = self.startProcess(ChessCV_launcher, rawbus, buswindex, "cv") # init bt reader self.bt = self.startThread(ChessBT_launcher, False, rawbus, buswindex, "bt") self.bus = CyclicBus(rawbus, buswindex, self.moduleid) def commWorker(self): while True: msg = self.bus.get() if msg: print("Chess_Core got: ", msg) msg = msg.split(";") if msg[CyclicBus.ACTION_INDX] == "terminate": self.bus.put("cv", "terminate") self.bus.put("bt", "terminate") self.cv.join() self.bt.join() break time.sleep(0.01) def startProcess(self, function, *arguments): arg_tuple = () for i in range(len(arguments)): arg_tuple += (arguments[i],) process = multiprocessing.Process(target=function, args=arg_tuple) process.start() return process def startThread(self, function, ifdaemon, *arguments): arg_tuple = () for i in range(len(arguments)): arg_tuple += (arguments[i],) thread = threading.Thread(target=function, args=arg_tuple) thread.setDaemon(ifdaemon) thread.start() return thread
def __init__(self): # init bus rawbus, buswindex = busCreate() self.moduleid = "cr" # init gui self.gui = self.startProcess(ChessGUI_launcher, rawbus, buswindex, "ui") # init chess cv self.cv = self.startProcess(ChessCV_launcher, rawbus, buswindex, "cv") # init bt reader self.bt = self.startThread(ChessBT_launcher, False, rawbus, buswindex, "bt") self.bus = CyclicBus(rawbus, buswindex, self.moduleid)
class ChessBT(): def __init__(self, rawbus, buswindex, moduleid): self.devaddr = "20:17:01:10:26:87" self.devpath = "/dev/myrfcomm0" self.moduleid = moduleid self.bus = CyclicBus(rawbus, buswindex, moduleid) self.dev = None self.stop_threads = False self.connector = None #self.dev_mutex = threading.Lock() def connectToDongle(self, devpath, devaddr): while not self.stop_threads: btsock = bluetooth.BluetoothSocket(bluetooth.RFCOMM) try: btsock.connect((devaddr, 1)) btsock.setblocking(False) self.bus.put("ui", "changeStatus;Connected to bluetooth device") self.dev = btsock self.connector = None break except: self.bus.put( "ui", "changeStatus;Could not connect to Bluetooth device") def connectToDongle_OLD(self, devpath, devaddr): while True: #self.bus.put(("ui", "changeStatus", "Trying to connect to Bluetooth device")) # "Trying to connect to Bluetooth device" connecter = subprocess.Popen( ["rfcomm", "-r", "connect", "hci0", devaddr, "1"], stdout=subprocess.PIPE, stderr=subprocess.STDOUT, bufsize=0) time1 = gettime() timeout = 7000 timed_out = False while not os.path.exists(devpath): if gettime() - time1 > timeout: print("Chess_BT: timed out waiting for connection") self.bus.put(("ui", "changeStatus", "Could not connect to Bluetooth device")) connecter.terminate() timed_out = True #time.sleep(1) break if not timed_out: #self.dev_mutex.acquire() btdev = os.open(devpath, os.O_RDWR) flags = fcntl.fcntl( btdev, fcntl.F_GETFL) # get current p.stdout flags fcntl.fcntl(btdev, fcntl.F_SETFL, flags | os.O_NONBLOCK) self.dev = btdev self.bus.put( ("ui", "changeStatus", "Connected to bluetooth device")) break #return btdev # def bluetoothReader(self): # while True: # self.dev_mutex.acquire() # self.dev = self.connectToDongle(self.devpath, self.devaddr) # self.dev_mutex.release() # self.bus.put(("ui","Connected to bluetooth device")) # # while True: def commWorker(self): #bt_connecting = False line = b'' while not self.stop_threads: msg = self.bus.get() if msg: print("Chess_BT got: ", msg) msg = msg.split(";") action = msg[CyclicBus.ACTION_INDX] if self.dev is not None: if action == "movePieceFromTo": pass elif action == "moveTo": id = msg[CyclicBus.ARG1_INDX] values = msg[CyclicBus.ARG2_INDX] cmd = "mov{}=".format(id) + ",".join(values) self.dev.send((cmd + "\n").encode()) #os.write(self.dev, (cmd+"\n").encode()) elif action == "gripperToggle": self.dev.send(("gripper\n").encode()) #os.write(self.dev, ("gripper\n").encode()) if action == "terminate": self.stop_threads = True if self.connector: self.connector.join() break if self.dev is None: if self.connector is None: #bt_connecting = True self.connector = self.startThread(self.connectToDongle, False, self.devpath, self.devaddr) else: try: char = self.dev.recv(1) if char != b'\n': line += char else: print("Chess_BT received from Bluetooth: ", line.decode()) line = b'' except: pass time.sleep(0.02) def startThread(self, function, ifdaemon, *arguments): arg_tuple = () for i in range(len(arguments)): arg_tuple += (arguments[i], ) thread = threading.Thread(target=function, args=arg_tuple) thread.setDaemon(ifdaemon) thread.start() return thread
class ChessCV(): def __init__(self, rawbus, buswindex, moduleid): self.chess_engine = Stockfisher() self.moduleid = moduleid self.bus = CyclicBus(rawbus, buswindex, moduleid) regs_strings = ["player_colour", "difficulty"] self.regs = {} for str in regs_strings: self.regs[str] = None self.previous_num_of_white_pieces = 0 self.previous_num_of_black_pieces = 0 self.previous_num_of_pieces = [0] * 2 self.previous_num_of_pieces[0] = lambda: self.previous_num_of_white_pieces self.previous_num_of_pieces[1] = lambda: self.previous_num_of_black_pieces self.possible_capture = False self.first_pass = True self.last_error = "" self.moves = [] self.board = self.initChessboard(startpos=" ") #self.commWorker = self.startThread(self.commWorkerLoop, read_queue) def startThread(self, function, *arguments): arg_tuple = () for i in range(len(arguments)): arg_tuple += (arguments[i],) thread = threading.Thread(target=function, args=arg_tuple) thread.setDaemon(True) thread.start() return thread def commWorkerLoop(self): while True: msg = self.bus.get() if msg: print("Chess_CV got: ", msg) msg = msg.split(";") if msg[CyclicBus.ACTION_INDX] == "makeTurn": self.makeTurn() elif msg[CyclicBus.ACTION_INDX] == "startNG": self.chess_engine.setDifficulty(self.regs["difficulty"]) self.chess_engine.resetGame() self.board = self.initChessboard(msg[CyclicBus.ARG1_INDX]) self.makeTurn() elif msg[CyclicBus.ACTION_INDX] == "player_colour": self.regs["player_colour"] = msg[CyclicBus.ARG1_INDX] elif msg[CyclicBus.ACTION_INDX] == "difficulty": self.regs["difficulty"] = msg[CyclicBus.ARG1_INDX] elif msg[CyclicBus.ACTION_INDX] == "terminate": self.chess_engine.terminate() break else: print("Chess_CV: no such action: ", msg[CyclicBus.ACTION_INDX]) time.sleep(0.01) def makeTurn(self, *args): #print(self.regs) #while True: #print(self.first_pass) self.bus.put("ui","changeStatus;Taking photo...") img = self.takePhoto() if not self.first_pass: self.bus.put("ui", "changeStatus;Recognizing player move...") else: self.bus.put("ui", "changeStatus;Checking starting position...") status, mask, tile_positions = self.recognizeCurrentChessboard(img) print("This mask:\n", np.matrix(mask), "\n") if DEBUG == 1: imS = cv2.resize(img, (640,480)) cv2.imshow('points', imS) cv2.waitKey(0) cv2.destroyAllWindows() #break if status != SUCCESS: #continue self.bus.put("ui", "changeStatus;ERROR: " + self.last_error) return this_img = img if not self.first_pass: tmp_board = np.copy(self.board) status, tmp_board, player_move = self.parsePlayerMove(tmp_board, mask) if status != SUCCESS: #continue self.bus.put("ui","changeStatus;ERROR: " + self.last_error) return self.bus.put("ui", "changeStatus;Player moved " + player_move) self.visualiseMove(player_move) self.moves.append(player_move) self.board = np.copy(tmp_board) computer_move = self.chess_engine.takeMove(self.moves) status, self.board = self.parseComputerMove(self.board, computer_move) if status != SUCCESS: self.bus.put("ui", "changeStatus;ERROR: " + self.last_error) self.visualiseMove(self.reverseMove(player_move)) del self.moves[-1] return self.moveArm(tile_positions, computer_move) self.bus.put("ui", "changeStatus;Computer moved " + computer_move) self.visualiseMove(computer_move) self.moves.append(computer_move) #print("This move:\n", np.matrix(this_array), "\n") #print("Previous move:\n", np.matrix(previous_array), "\n") #if DEBUG == 1: # cv2.imshow("this", this_img) # cv2.imshow("previous", previous_img) # cv2.waitKey(0) #for i in range(0, 8): # for j in range(0, 8): # previous_array[i][j] = this_array[i][j] else: # check if starting position is correct #self.bus.put(("ui", "changeStatus", "Checking ")) self.first_pass = False for i in range(0, 8): for j in range(0, 8): if (mask[i][j] != 0 and self.board[i][j] == 0) or (mask[i][j] == 0 and self.board[i][j] != 0): self.last_error = "Wrong starting position" print(self.last_error) self.bus.put("ui", "changeStatus;ERROR: " + self.last_error) self.first_pass = True return #if chess engine is playing white let it make first move if self.regs["player_colour"] == "black": #chess_engine.colour == "white": computer_move = self.chess_engine.takeMove(self.moves) self.visualiseMove(computer_move) self.moves.append(computer_move) status, self.board = self.parseComputerMove(self.board, computer_move) self.moveArm(tile_positions, computer_move) #for i in range(0, 8): # for j in range(0, 8): # previous_array[i][j] = this_array[i][j] previous_img = this_img # cv2.imshow('original', img) # cv2.imshow('warped', img2) # cv2.waitKey(0) # cv2.destroyAllWindows() print("Turn complete\n") self.bus.put("ui", "changeStatus;Turn complete") #break def visualiseMove(self, move): self.bus.put("ui","movePiece;" + move) def moveArm(self,tile_positions, move): moved_from, moved_to, tile_pos_index = [0] * 2, [0] * 2, [0] * 2 moved_from[0] = 7 - int(ord(move[1]) - ord('1')) moved_from[1] = int(ord(move[0]) - ord('a')) moved_to[0] = 7 - int(ord(move[3]) - ord('1')) moved_to[1] = int(ord(move[2]) - ord('a')) tile_pos_index[0] = moved_from[0] * 8 + moved_from[1] tile_pos_index[1] = moved_to[0] * 8 + moved_to[1] self.bus.put("bt", "movePieceFromTo;{},{};{},{}".format( str(tile_positions[0][tile_pos_index[0]]), str(tile_positions[1][tile_pos_index[0]]), str(tile_positions[0][tile_pos_index[1]]), str(tile_positions[1][tile_pos_index[1]]))) def initChessboard(self, startpos): # moves format: "a2a4 d7d5 g8f6" etc.. self.previous_num_of_white_pieces = 16 self.previous_num_of_black_pieces = 16 self.moves = [] self.first_pass = True self.possible_capture = False board = np.zeros(shape=(8, 8), dtype=int) board[0] = [bR, bN, bB, bQ, bK, bB, bN, bR] board[1] = [bP, bP, bP, bP, bP, bP, bP, bP] board[6] = [wP, wP, wP, wP, wP, wP, wP, wP] board[7] = [wR, wN, wB, wQ, wK, wB, wN, wR] if startpos != " ": individual_moves = startpos.split(" ") for i in range(0, len(individual_moves)): board = self.parseComputerMove(board, individual_moves[i]) # WONT WORK NOW DUE TO PIECE CHECKING INCLUDED print("Initiated starting position. Current board:\n", np.matrix(board), "\n") return board def parsePlayerMove(self, previous_board, current_board_mask): #global previous_num_of_black_pieces #global previous_num_of_white_pieces #global possible_capture moved_to = None moved_from = None capture_confirmed = False this_board = np.zeros(shape=(8, 8), dtype=int) for i in range(0, 8): for j in range(0, 8): if current_board_mask[i][j]: # if there is a piece on i, j field if previous_board[i][j] != 0: # there was something here - now check if it was capture piece_to_check = previous_board[i][j] if (piece_to_check > 10 and current_board_mask[i][j] == 1) or \ (piece_to_check < 10 and current_board_mask[i][j] == 11): # was A colour move but previously there was B colour piece - it is capture if self.possible_capture: # make sure camera found out that too self.possible_capture = False else: print("Error recognizing move: Camera did not found possible capture") if self.regs["player_colour"] == "white": # if player is white then black piece was captured... self.previous_num_of_black_pieces -= 1 else: # else a white piece was captured self.previous_num_of_white_pieces -= 1 print("Capture occured!") if moved_to is None: moved_to = [i, j] else: print("Error recognizing move: 'Moved to' found second time in capture recogition!") return MOVE_RECOG_ERR, None, None #else: # print("Error recognizing move: Camera did not found possible capture") else: this_board[i][j] = previous_board[i][j] else: if moved_to is None: moved_to = [i, j] else: print("Error recognizing move: 'Moved to' found second time!") return MOVE_RECOG_ERR, None, None else: # if no piece on i,j field this_board[i][j] = 0 if previous_board[i][j] != 0: if moved_from is None: moved_from = [i, j] else: print("Error recognizing move: 'Moved from' found second time!") return MOVE_RECOG_ERR, None, None if moved_to is None and moved_from is None: self.last_error = "Player move not found. Did you move any piece?" print("Player move not found. Did you move any piece?") return PLAYER_MOVE_ERR, None, None else: try: this_board[moved_to[0]][moved_to[1]] = previous_board[moved_from[0]][moved_from[1]] player_move = "{}{}{}{}".format(chr((moved_from[1]) + ord('a')), chr((7 - moved_from[0]) + ord('1')), chr((moved_to[1]) + ord('a')), chr((7 - moved_to[0]) + ord('1'))) print("Player move: ", player_move) print("Previous board:\n", np.matrix(previous_board), "\n") print("This board:\n", np.matrix(this_board), "\n") return SUCCESS ,this_board, player_move except: self.last_error = "Could not recognise move" print("Error recognizing move") return MOVE_RECOG_ERR, None, None def parseComputerMove(self, previous_board, computer_move): # first check if computer has played his piece. If he has chosen player piece to play it means # that player move was not recognized -> it is not compilant with rules of chess game. It has to be undone. moved_from, moved_to = [0] * 2, [0] * 2 moved_from[0] = 7 - int(ord(computer_move[1]) - ord('1')) moved_from[1] = int(ord(computer_move[0]) - ord('a')) # if self.regs["player_colour"] == "white" and previous_board[moved_from[0]][moved_from[1]] < 10 or \ # self.regs["player_colour"] == "black" and previous_board[moved_from[0]][moved_from[1]] > 10: # self.last_error = "Player move is illegal" # return PLAYER_MOVE_ERR, None print(">"+computer_move+"<") current_board = np.zeros(shape=(8,8)) for i in range(0, 8): for j in range(0, 8): current_board[i][j] = previous_board[i][j] if len(computer_move) == 4: # standard move #moved_from, moved_to = [0]*2, [0]*2 #moved_from[0] = 7-int( ord(computer_move[1]) - ord('1')) #moved_from[1] = int( ord(computer_move[0]) - ord('a')) moved_to[0] = 7-int(ord(computer_move[3]) - ord('1')) moved_to[1] = int(ord(computer_move[2]) - ord('a')) # check if it capture: current_board[moved_to[0]][moved_to[1]] = previous_board[moved_from[0]][moved_from[1]] if previous_board[moved_to[0]][moved_to[1]]: # did that field contained piece? print("Computer captures!") if previous_board[moved_to[0]][moved_to[1]] < 10 and self.regs["player_colour"] == "white": # means chess_engine_colour == "black": #global previous_num_of_white_pieces self.previous_num_of_white_pieces -= 1 elif previous_board[moved_to[0]][moved_to[1]] > 10 and self.regs["player_colour"] == "black":#chess_engine_colour == "white": #global previous_num_of_black_pieces self.previous_num_of_black_pieces -= 1 else: print("Not supported capture move") current_board[moved_from[0]][moved_from[1]] = 0 else: print("Error parsing computer move: Not yet supported") print("Previous board:\n", np.matrix(previous_board), "\n") print("This board:\n", np.matrix(current_board), "\n") return SUCCESS, current_board def findPointDuplicates(self, array): array.sort() duplicates = [] i = 0 while i < len(array) - 1: j = i area = array[j][3] while j<len(array)-1 and abs(array[j][0] - array[j + 1][0]) < DUPLICATES_ERROR and \ abs(array[j][1] - array[j + 1][1]) < DUPLICATES_ERROR: #print([array[i][0], array[i][1]]) area += array[j+1][3] j += 1 if j != i: if CONTOUR_MAX_AREA > area > CONTOUR_MIN_AREA: duplicates.append([array[i][0], array[i][1], array[j][2]]) if DEBUG == 1: color = (255 * (array[j][2] - 3)) ^ 255 #cv2.drawMarker(img, (array[i][0], array[i][1]), (color, color, color), cv2.MARKER_CROSS, 60, 20) #cv2.circle(img, (array[i][0], array[i][1]), 20, (color, color, color), -1) #cv2.circle(image, (array[i][0], array[i][1]), 2, (0, 0, 255), -1) i = j i+=1 return duplicates def detectMarkers(self, contours, contour_len, polygons_to_find): markers = [] for c in contours: peri = cv2.arcLength(c, True) if peri > contour_len: approx = cv2.approxPolyDP(c, CONTOUR_EPSILON * peri, True) num_of_corners = len(approx) for i in range(0, len(polygons_to_find)): if num_of_corners == polygons_to_find[i]: M = cv2.moments(c) try: cX = int(M["m10"] / M["m00"]) except: cX = 0 try: cY = int(M["m01"] / M["m00"]) except: cY = 0 area = cv2.contourArea(c, False) #cv2.drawContours(image, [approx], -1, (0, 255, 0), 2) if area > 0: markers.append([cX, cY, num_of_corners, area]) #cv2.drawContours(image2, [approx], -1, (0, 255, 0), 1) return markers def recognizeCurrentChessboard(self, image): gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) edges = cv2.adaptiveThreshold(gray, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY, THRESH1, THRESH2) im2, contours, hierarchy = cv2.findContours(edges, cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE) markers = self.detectMarkers(contours, CONTOUR_MIN_LEN, [3, 4]) if DEBUG == 1: imS = cv2.resize(edges, (640,480)) cv2.imshow('threshold', imS) possible_corners = self.findPointDuplicates(markers) # look for boundary markers corners = [0]*4 distance_sum = [] [distance_sum.append(possible_corners[i][0] + possible_corners[i][1]) for i in range(0, len(possible_corners))] min_index = distance_sum.index(min(distance_sum)) min_x = possible_corners[min_index][0] min_y = possible_corners[min_index][1] corners[0] = ([min_x, min_y, possible_corners[min_index][2]]) max_index = distance_sum.index(max(distance_sum)) max_x = possible_corners[max_index][0] max_y = possible_corners[max_index][1] corners[2] = ([max_x, max_y, possible_corners[max_index][2]]) center = [int((max_x + min_x) / 2), int((max_y + min_y) / 2)] left_index, right_index = 0, 0 last_left_sum, last_right_sum = 0, 0 for i in range(0, len(possible_corners)): this_x = possible_corners[i][0] this_y = possible_corners[i][1] if (this_x != max_x or this_y != max_y) and (this_x != min_x or this_y != min_y): summ = (this_x - center[0]) + (center[1] - this_y) if summ < 0 and summ < last_left_sum: last_left_sum = summ left_index = i elif summ > 0 and summ > last_right_sum: last_right_sum = summ right_index = i corners[3] = ([possible_corners[left_index][0], possible_corners[left_index][1], possible_corners[left_index][2]]) corners[1] = ([possible_corners[right_index][0], possible_corners[right_index][1], possible_corners[right_index][2]]) print("Chessboard corners: ", corners) num_of_rectangles = 0 num_of_triangles = 0 for i in range(0, 4): if corners[i][2] == 4: num_of_rectangles += 1 elif corners[i][2] == 3: num_of_triangles += 1 main_index = i if num_of_rectangles != 3 or num_of_triangles != 1: self.last_error = ("Corner detection error. Found {} rectangles and {} triangles". format(str(num_of_rectangles),str(num_of_triangles))) print(self.last_error) return CHESSB_NOT_FOUND, None, None rect = np.zeros((4, 2), dtype="float32") rect[0][0] = corners[main_index][0] rect[0][1] = corners[main_index][1] index = main_index for i in range(1, 4): index += 1 if index == 4: # wrap quadrant value index = 0 rect[i][0] = corners[index][0] rect[i][1] = corners[index][1] # check rectangility of figure constisted of corners: x1 = rect[0][0] y1 = rect[0][1] v1 = [ rect[0][0]-rect[1][0], rect[0][1]-rect[1][1] ] for i in range(0, 4): v2 = [ rect[(i+2)%4][0] - rect[(i+1)%4][0], rect[(i+2)%4][1] - rect[(i+1)%4][1]] angle = np.rad2deg(np.arccos( np.vdot(v1,v2) / (np.linalg.norm(v1) * np.linalg.norm(v2)))) if not (90 - RECTANGILITY_ERROR < angle < 90 + RECTANGILITY_ERROR): self.last_error = "Found corners do not form chessboard shape" print(self.last_error) return CHESSB_NOT_FOUND, None, None v1 = v2 corner1x=rect[0][0] corner1y=rect[0][1] corner2x=rect[1][0] corner2y=rect[1][1] border_len = np.sqrt( (corner2y-corner1y)**2 + (corner2x-corner1x)**2 ) tile_len = (border_len / 8 )- 1 dst = np.array([ [0, 0], [border_len - 1, 0], [border_len - 1, border_len - 1], [0, border_len - 1]], dtype="float32") # compute the perspective transform matrix and then apply it markers2wrap = np.array([possible_corners], dtype='float32') markers2wrap = markers2wrap[:,:,:-1] #markers = np.array([markers]) M = cv2.getPerspectiveTransform(rect, dst) warped_markers = cv2.perspectiveTransform(markers2wrap, M) warped_markers=warped_markers[0] pieces = [0]*2 mask = np.zeros((8, 8)) for i in range(0, len(warped_markers)): x = warped_markers[i][0] - 1 y = warped_markers[i][1] - 1 piece = possible_corners[i][2]-3 #cv2.circle(img, (int(x), int(y)), 20, (0, 255, 0), -1) if x > 0 and y > 0: x_tile = int(x / tile_len) y_tile = int(y / tile_len) try: mask[y_tile][x_tile] = 1 + 10 * (piece) if possible_corners[i][2] == 3: pieces[0] += 1 else: pieces[1] += 1 except: pass #global possible_capture for i in range(0 ,2): if pieces[i] == self.previous_num_of_pieces[i](): # found previous number of pieces? - just simple move self.possible_capture = False elif pieces[i] == self.previous_num_of_pieces[i]() - 1: # found previous number of pieces - 1? possibly capture occured self.possible_capture = True else: self.last_error ="Error finding {}-colour pieces. Found: {}. Expected: {}".\ format(str(chr( ord("W") - i*21)), str(pieces[i]), str(self.previous_num_of_pieces[i]())) print(self.last_error) return PIECES_NOT_FOUND, mask, None # calculate pieces real position pxtomm_scale = 230 / border_len # http://mathforum.org/mathimages/index.php/Transformation_Matrix v1 = [(rect[1][0] - rect[0][0]), (rect[1][1] - rect[0][1])] v2 = [(rect[2][0] - rect[3][0]), (rect[2][1] - rect[3][1])] angle1 = (np.arctan2(-v1[1], v1[0]) + np.arctan2(-v2[1], v2[0])) / 2 v1 = [(rect[2][0] - rect[1][0]), (rect[2][1] - rect[1][1])] v2 = [(rect[3][0] - rect[0][0]), (rect[3][1] - rect[0][1])] angle2 = (np.arctan2(-v1[1], v1[0]) + np.arctan2(-v2[1], v2[0])) / 2 angle = (angle1 + angle2) / 2 + (3.14 / 4) # rotmat = np.array([ # [np.cos(angle), -np.sin(angle)], # [np.sin(angle), np.cos(angle)]]) rotmat = np.array([ [np.cos(angle), -np.sin(angle)], [np.sin(angle), np.cos(angle)]]) a1 = (rect[2][1] - rect[0][1]) / (rect[2][0] - rect[0][0]) b1 = rect[0][1] - rect[0][0] * a1 a2 = (rect[3][1] - rect[1][1]) / (rect[3][0] - rect[1][0]) b2 = rect[1][1] - rect[1][0] * a2 chessb_center_x = (b2 - b1) / (a1 - a2) chessb_center_y = a1 * chessb_center_x + b1 print("Chessb center: ", chessb_center_x, chessb_center_y) campos_x = 0 campos_y = 250 photo_center_x = WIDTH / 2 photo_center_y = HEIGHT / 2 vx = (chessb_center_x - photo_center_x) * pxtomm_scale vy = (chessb_center_y - photo_center_y) * pxtomm_scale tile_real = 25 tile_pos = np.zeros(shape=(2, 64)) for i in range(8): for j in range(8): tile_pos[0][i * 8 + j] = tile_real / 2 + j * tile_real - 100 tile_pos[1][i * 8 + j] = tile_real / 2 + (7 - i) * tile_real - 100 #for i in range(64): # tile_pos[1][i] = (tile_real / 2 + int(i / 8) * tile_real) - 100 # j==0 => x, j==1 -> y # tile_pos[0][i] = (tile_real / 2 + i % 8 * tile_real) - 100 # angle1 = (angles[0]+(angles[2]-3.14))/2 # angle2 = (angles[1] + (angles[3] - 3.14)) / 2 # print(np.rad2deg(angles)) print(np.rad2deg(angle)) tile_pos = np.dot(rotmat, tile_pos) tile_pos[0] += campos_x + vx tile_pos[1] += campos_y + vy # for i in range(len(tile_pos[0])): # x = tile_pos[0][i] # y = tile_pos[1][i] # if i == 63: # cv2.drawMarker(img, (int(x), int(y)), (0, 0, 255), cv2.MARKER_DIAMOND, 5, 5) # else: # cv2.drawMarker(img, (int(x), int(y)), (255, 0, 0), cv2.MARKER_DIAMOND, 5, 5) return SUCCESS, mask, tile_pos def takePhoto(self): #photographer = subprocess.Popen(["raspistill", "-t", "1000","-co", "100", "-o", "img.jpg"]) #photographer.wait() image_taken = cv2.imread("img4.jpg") return image_taken def reverseMove(self, move): return move[2:4] + move[0:2]
def __init__(self, rawbus, buswindex, moduleid): self.app = QtGui.QApplication(sys.argv) super(ChessGUI, self).__init__() # store bus reference here self.moduleid = moduleid self.bus = CyclicBus(rawbus, buswindex, moduleid) # store reg values here regs_strings = ["player_colour", "difficulty"] self.regs = {} for str in regs_strings: self.regs[str] = None # prepare popup self.popup = None # initiate Qt app self.setWindowTitle('RoboChess') # self.main_window = QtGui.QWidget() # self.main_window.resize(250, 150) # self.main_window.move(300, 300) self.setWindowIcon(QtGui.QIcon('icons/chess.ico')) # create statusbar self.statbar = QtGui.QLabel("") self.statbar_lines = [" "] * 3 self.statbar_index = 0 self.statusbar = self.statusBar() self.statusbar.addWidget(self.statbar) #self.statusbar.showMessage('Ready') # set tooltip formatting QtGui.QToolTip.setFont(QtGui.QFont('SansSerif', 10)) # create Qtabwidget self.tabwidget = QtGui.QTabWidget() #self.tabwidget.setTabShape(QtGui.QTabWidget.Triangular) #self.tabwidget.Triangular # set Qtabwidget as central widget self.setCentralWidget(self.tabwidget) # create 3 tabs self.tab1 = ChessboardTab(self) #QtGui.QWidget() self.tab2 = SettingsTab(self) #QtGui.QWidget() self.tab3 = ManualSteeringTab(self) # add tabs to tabwidget self.tabwidget.addTab(self.tab1, "Chessboard") self.tabwidget.addTab(self.tab2, "Settings") self.tabwidget.addTab(self.tab3, "Manual arm control") # self.ChessboardFrame = ChessboardTab(self.tab1, self) # self.setChessboardTab(self.tab1) # self.setSettingsTab(self.tab2) # start bus reader thread self.startThread(self.commWorkerLoop) # exit handler self.app.aboutToQuit.connect(self.exitHandler) # statusbar connect signal #self.changeStatusBar.connect(lambda string: self.statusbar.showMessage(string)) self.changeStatusBar.connect( lambda string: self.addStatusMessage(string)) self.show()
class ChessGUI(QtGui.QMainWindow): # signals notifyCaller = QtCore.pyqtSignal(int, int) startMovingIcon = QtCore.pyqtSignal(str) moveIcon = QtCore.pyqtSignal(int, int) finishMovingIcon = QtCore.pyqtSignal(int, int) openPopup = QtCore.pyqtSignal(str) changePopup = QtCore.pyqtSignal(str) stopPopup = QtCore.pyqtSignal() changeStatusBar = QtCore.pyqtSignal(str) def __init__(self, rawbus, buswindex, moduleid): self.app = QtGui.QApplication(sys.argv) super(ChessGUI, self).__init__() # store bus reference here self.moduleid = moduleid self.bus = CyclicBus(rawbus, buswindex, moduleid) # store reg values here regs_strings = ["player_colour", "difficulty"] self.regs = {} for str in regs_strings: self.regs[str] = None # prepare popup self.popup = None # initiate Qt app self.setWindowTitle('RoboChess') # self.main_window = QtGui.QWidget() # self.main_window.resize(250, 150) # self.main_window.move(300, 300) self.setWindowIcon(QtGui.QIcon('icons/chess.ico')) # create statusbar self.statbar = QtGui.QLabel("") self.statbar_lines = [" "] * 3 self.statbar_index = 0 self.statusbar = self.statusBar() self.statusbar.addWidget(self.statbar) #self.statusbar.showMessage('Ready') # set tooltip formatting QtGui.QToolTip.setFont(QtGui.QFont('SansSerif', 10)) # create Qtabwidget self.tabwidget = QtGui.QTabWidget() #self.tabwidget.setTabShape(QtGui.QTabWidget.Triangular) #self.tabwidget.Triangular # set Qtabwidget as central widget self.setCentralWidget(self.tabwidget) # create 3 tabs self.tab1 = ChessboardTab(self) #QtGui.QWidget() self.tab2 = SettingsTab(self) #QtGui.QWidget() self.tab3 = ManualSteeringTab(self) # add tabs to tabwidget self.tabwidget.addTab(self.tab1, "Chessboard") self.tabwidget.addTab(self.tab2, "Settings") self.tabwidget.addTab(self.tab3, "Manual arm control") # self.ChessboardFrame = ChessboardTab(self.tab1, self) # self.setChessboardTab(self.tab1) # self.setSettingsTab(self.tab2) # start bus reader thread self.startThread(self.commWorkerLoop) # exit handler self.app.aboutToQuit.connect(self.exitHandler) # statusbar connect signal #self.changeStatusBar.connect(lambda string: self.statusbar.showMessage(string)) self.changeStatusBar.connect( lambda string: self.addStatusMessage(string)) self.show() #self.bus.put(("core", "guiReady")) #self.popup = Popup(self) def addStatusMessage(self, new_line): self.statbar_lines[2] = self.statbar_lines[1] self.statbar_lines[1] = self.statbar_lines[0] self.statbar_lines[0] = time.strftime("[%H:%M:%S] ") + new_line self.statbar.setText("\n".join(self.statbar_lines)) def resizeEvent(self, QResizeEvent): if self.popup: self.popup.followParent() def moveEvent(self, QMoveEvent): if self.popup: self.popup.followParent() def commWorkerLoop(self): while True: msg = self.bus.get() if msg: print("Chess_GUI got: ", msg) msg = msg.split(";") action = msg[CyclicBus.ACTION_INDX] if action == "movePiece": self.startMovingIcon.emit(msg[CyclicBus.ARG1_INDX]) elif action == "startPopup": pass elif action == "changeStatus": self.changeStatusBar.emit(msg[CyclicBus.ARG1_INDX]) elif action == "changePopup": pass elif action == "stopPopup": pass else: print("Chess_GUI: no such action: ", msg[CyclicBus.ACTION_INDX]) time.sleep(0.01) def exitHandler(self): self.bus.put("cr", "terminate") if self.popup: self.popup.close() #time.sleep(0.01) def startThread(self, function, *arguments): arg_tuple = () for i in range(len(arguments)): arg_tuple += (arguments[i], ) thread = threading.Thread(target=function, args=arg_tuple) thread.setDaemon(True) thread.start() return thread def start(self): # launch Qt app sys.exit(self.app.exec_())