From 50b33f4752da5545ab8cfa87bd453475c5af9d11 Mon Sep 17 00:00:00 2001 From: phebert5009 Date: Thu, 29 Nov 2018 10:15:36 -0700 Subject: [PATCH 01/12] transferred claw and robot to ev3dev2. Also improved claw a little --- Chess Robot/source/claw.py | 26 +++++++++++++++----------- Chess Robot/source/robot.py | 3 ++- 2 files changed, 17 insertions(+), 12 deletions(-) diff --git a/Chess Robot/source/claw.py b/Chess Robot/source/claw.py index 583a752..0edb039 100644 --- a/Chess Robot/source/claw.py +++ b/Chess Robot/source/claw.py @@ -1,35 +1,39 @@ -from ev3dev.ev3 import * +from ev3dev2.motor import * from time import sleep -class Claw: +class Claw(MediumMotor): def __init__(self, port = OUTPUT_B): - self.motor = MediumMotor(port) - self.motor.reset() + MediumMotor.__init__(self,port) + self.reset() #Close the gripper completely convergence_counter = 0 time_delta = 0.01 tachometer_reading = self.motor.position while convergence_counter < 3: - self.motor.run_forever(speed_sp=-360) + self.on(speed_sp=-24) sleep(time_delta) - if tachometer_reading == self.motor.position: + if tachometer_reading == self.position: convergence_counter = convergence_counter + 1 - tachometer_reading = self.motor.position - self.motor.stop() + tachometer_reading = self.position + self.stop() #Gripper is closed at this point - self.motor.run_to_rel_pos(position_sp=700, speed_sp = 360) + + #self.motor.run_to_rel_pos(position_sp=700, speed_sp = 360) + self.on_for_degrees(24,700); sleep(3) self.isOpen = True def open(self): if not self.isOpen: - self.motor.run_to_rel_pos(position_sp=700, speed_sp = 360) + #self.motor.run_to_rel_pos(position_sp=700, speed_sp = 360) + self.on_for_degrees(24,700); sleep(3) self.isOpen = True def close(self): if self.isOpen: - self.motor.run_to_rel_pos(position_sp=-700, speed_sp = 360) + #self.motor.run_to_rel_pos(position_sp=-700, speed_sp = 360) + self.on_for_degrees sleep(3) self.isOpen = False diff --git a/Chess Robot/source/robot.py b/Chess Robot/source/robot.py index b1a82c6..acfae80 100644 --- a/Chess Robot/source/robot.py +++ b/Chess Robot/source/robot.py @@ -1,4 +1,5 @@ -from ev3dev.ev3 import * +from ev3dev2.motor import * +from ev3dev2.sensor.lego import * from time import sleep from claw import * From 13d8d8194d3f61dcee0a6ea7e36fc8b78c4c7296 Mon Sep 17 00:00:00 2001 From: bbest31 Date: Thu, 29 Nov 2018 20:25:43 -0700 Subject: [PATCH 02/12] Robot pickup and place routine done --- Chess Robot/source/claw.py | 10 ++-- Chess Robot/source/client.py | 2 +- Chess Robot/source/move.py | 109 ++++++----------------------------- Chess Robot/source/robot.py | 52 +++++++++++------ Chess Robot/source/runner.py | 47 +++++++++------ Chess Robot/source/server.py | 21 +++++-- 6 files changed, 103 insertions(+), 138 deletions(-) diff --git a/Chess Robot/source/claw.py b/Chess Robot/source/claw.py index 0edb039..017f9ea 100644 --- a/Chess Robot/source/claw.py +++ b/Chess Robot/source/claw.py @@ -8,9 +8,9 @@ def __init__(self, port = OUTPUT_B): #Close the gripper completely convergence_counter = 0 time_delta = 0.01 - tachometer_reading = self.motor.position + tachometer_reading = self.position while convergence_counter < 3: - self.on(speed_sp=-24) + self.on(-24) sleep(time_delta) if tachometer_reading == self.position: convergence_counter = convergence_counter + 1 @@ -19,21 +19,21 @@ def __init__(self, port = OUTPUT_B): #Gripper is closed at this point #self.motor.run_to_rel_pos(position_sp=700, speed_sp = 360) - self.on_for_degrees(24,700); + self.on_for_degrees(24,700) sleep(3) self.isOpen = True def open(self): if not self.isOpen: #self.motor.run_to_rel_pos(position_sp=700, speed_sp = 360) - self.on_for_degrees(24,700); + self.on_for_degrees(24,700) sleep(3) self.isOpen = True def close(self): if self.isOpen: #self.motor.run_to_rel_pos(position_sp=-700, speed_sp = 360) - self.on_for_degrees + self.on_for_degrees(-24,700) sleep(3) self.isOpen = False diff --git a/Chess Robot/source/client.py b/Chess Robot/source/client.py index ac20808..e1c349a 100644 --- a/Chess Robot/source/client.py +++ b/Chess Robot/source/client.py @@ -12,7 +12,7 @@ def __init__(self,port): #We need to use the ipv4 address that shows up in ipconfig in the computer for the USB #Ethernet adapter handling the connection to the EV3 - host = "169.254.137.85" + host = "169.254.82.210" print("setting up client, address =", host, "port =", port) self.s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) self.s.connect((host, port)) diff --git a/Chess Robot/source/move.py b/Chess Robot/source/move.py index d6e6d4b..cd09145 100644 --- a/Chess Robot/source/move.py +++ b/Chess Robot/source/move.py @@ -1,97 +1,22 @@ +from queue import Queue +from server import * -from ev3dev.ev3 import * -import socket -from threading import Event, Thread -from time import sleep -from claw import * +#Thread-safe queue to get data from threads +queue = Queue() +server = Server(9999) -#yMotor = LargeMotor(OUTPUT_A) -#xMotor = LargeMotor(OUTPUT_C) -#zMotor = LargeMotor(OUTPUT_D) -#gripperMotor = MediumMotor(OUTPUT_B) - - -#Y -#yMotor.run_to_rel_pos(position_sp=720, speed_sp = 230) -#sleep(3) -#yMotor.stop() -#X -#xMotor.run_to_rel_pos(position_sp=960, speed_sp = 230) -#sleep(3) -#xMotor.stop() -#Gripper -#gripperMotor.run_to_rel_pos(position_sp=500, speed_sp = 360) -#sleep(3) -#gripperMotor.stop() - -#Gripper -#gripperMotor.run_to_rel_pos(position_sp=-500, speed_sp = 360) -#sleep(3) -#gripperMotor.stop() - -#Z -#Upwards -#zMotor.run_to_rel_pos(position_sp=-120, speed_sp = 100, stop_action="hold") -##sleep(3) -zMotor.stop() - - -#Downwards - - - - -#gripperMotor.run_to_rel_pos(position_sp=-2000, speed_sp = 360) -#sleep(6) -#gripperMotor.stop() - - -#zMotor.run_to_rel_pos(position_sp=-120, speed_sp = 100, stop_action="hold") -#sleep(3) -#zMotor.stop() +server.sendDistances(-76,-138, queue) +server.sendLowerClaw() +server.sendCloseClaw() +server.sendRaiseClaw() +server.sendDistances(0,-38,queue) +server.sendLowerClaw() +server.sendOpenClaw() +server.sendRaiseClaw() -#xMotor.run_to_rel_pos(position_sp=-960, speed_sp = 230) -#sleep(3) -#xMotor.stop() -#yMotor.run_to_rel_pos(position_sp=-420, speed_sp = 230) -#sleep(3) -#yMotor.stop() -#zMotor.run_to_rel_pos(position_sp=120, speed_sp = 100, stop_action="coast") -#sleep(3) -#zMotor.stop() - - -#gripperMotor.run_to_rel_pos(position_sp=700, speed_sp = 360) -#sleep(4) -#gripperMotor.stop() - -zMotor.run_to_rel_pos(position_sp=-120, speed_sp = 100, stop_action="hold") -sleep(3) -zMotor.stop() - - -claw = Claw(OUTPUT_B) - -zMotor.run_to_rel_pos(position_sp=120, speed_sp = 100, stop_action="coast") -sleep(3) -zMotor.stop() - -claw.close() - - -zMotor.run_to_rel_pos(position_sp=-120, speed_sp = 100, stop_action="hold") -sleep(3) -zMotor.stop() - -yMotor.run_to_rel_pos(position_sp=-420, speed_sp = 230) -sleep(3) -yMotor.stop() - -zMotor.run_to_rel_pos(position_sp=120, speed_sp = 100, stop_action="coast") -sleep(3) -zMotor.stop() - -claw.open() -#zMotor.reset() \ No newline at end of file +#yMotor = LargeMotor(OUTPUT_A) +#xMotor = LargeMotor(OUTPUT_C) +#zMotor = LargeMotor(OUTPUT_D) +#gripperMotor = MediumMotor(OUTPUT_B) \ No newline at end of file diff --git a/Chess Robot/source/robot.py b/Chess Robot/source/robot.py index acfae80..ba90d20 100644 --- a/Chess Robot/source/robot.py +++ b/Chess Robot/source/robot.py @@ -5,22 +5,26 @@ class Robot: def __init__(self): - self.yTouchSensor = TouchSensor(INPUT_1) - self.xTouchSensor = TouchSensor(INPUT_2) + self.millimetersPerTickY = 0.14444444 + self.millimetersPerTickX = 0.07222222 + self.yOffset = 100 self.yMotor = LargeMotor(OUTPUT_A) self.xMotor = LargeMotor(OUTPUT_C) self.zMotor = LargeMotor(OUTPUT_D) + self.currentY = 0 + self.currentX = 0 self.xMotor.reset() self.yMotor.reset() self.zMotor.reset() + #Lift the claw + self.clawUp() #Home the X axis self.homeX() #Home the Y axis self.homeY() - #Lift the claw - self.clawUp() + #After the claw has been lifted we initialze it self.claw = Claw() @@ -32,34 +36,44 @@ def closeClaw(self): self.claw.close() def homeX(self): - while not self.xTouchSensor.is_pressed: - self.xMotor.run_forever(speed_sp=230) + degrees = -(self.currentX/self.millimetersPerTickX) + self.xMotor.on_for_degrees(SpeedPercent(23),degrees) self.xMotor.stop() + self.currentX = 0 def homeY(self): - while not self.yTouchSensor.is_pressed: - self.yMotor.run_forever(speed_sp=230) + degrees = (self.currentY/self.millimetersPerTickY) + self.yMotor.on_for_degrees(SpeedPercent(23),degrees) self.yMotor.stop() + self.currentY = 0 - def moveX(self, degrees): - timer = abs(degrees)/230 + 0.1 - self.xMotor.run_to_rel_pos(position_sp=degrees, speed_sp = 230) - sleep(timer) + def moveX(self, milli): + degrees = abs(milli)/self.millimetersPerTickX + if(milli < 0): + self.xMotor.on_for_degrees(SpeedPercent(-23),degrees) + else: + self.xMotor.on_for_degrees(SpeedPercent(23),degrees) self.xMotor.stop() + self.currentX += milli + + def moveY(self, milli): + + degrees = abs(milli)/self.millimetersPerTickY + if(milli < 0): + self.yMotor.on_for_degrees(SpeedPercent(-23),degrees) + else: + self.yMotor.on_for_degrees(SpeedPercent(23),degrees) - def moveY(self, degrees): - timer = abs(degrees)/230 + 0.1 - self.yMotor.run_to_rel_pos(position_sp=degrees, speed_sp = 230) - sleep(timer) self.yMotor.stop() + self.currentY += milli def clawUp(self): - self.zMotor.run_to_rel_pos(position_sp=-120, speed_sp = 100, stop_action="hold") + self.zMotor.run_to_rel_pos(position_sp=-120, speed_sp = 50, stop_action="hold") sleep(1.8) self.zMotor.stop() def clawDown(self): - self.zMotor.run_to_rel_pos(position_sp=120, speed_sp = 100, stop_action="coast") - sleep(1.8) + self.zMotor.run_to_rel_pos(position_sp=120, speed_sp = 50, stop_action="coast") + sleep(3.5) self.zMotor.stop() diff --git a/Chess Robot/source/runner.py b/Chess Robot/source/runner.py index 5173527..14f94c7 100644 --- a/Chess Robot/source/runner.py +++ b/Chess Robot/source/runner.py @@ -11,6 +11,8 @@ robot = Robot() #Attempt to connect to server client = Client(9999) +robot.moveY(100) +robot.currentY = 0 while True: #Block until a command/message from the server is received @@ -21,22 +23,33 @@ break elif(data == "LOWER_CLAW"): robot.clawDown() + elif(data == "RAISE_CLAW"): + robot.clawUp() + elif(data == "OPEN_CLAW"): + robot.openClaw() + elif(data == "CLOSE_CLAW"): + robot.closeClaw() else: - #If the data we got from the server is not one of the predifined messages - #We assume (big assumption) that the message will contain the angles in the - #Agreed format: x_motor_angle,y_motor_angle - #We convert the angles to float after splitting the message on the tab - x_motor_angle, y_motor_angle = map(float,map(str,data.split(','))) - #This will make sure that both angles are at most 360 degrees. In addition, - #it will consider both, the clockwise and counterclockwise rotations to reach - #the desired position for each motor and will pick the smallest one. So that the chances of making - #very large rotations are lessened. - #x_motor_angle = int(x_motor_angle) % 360 - #x_motor_angle = min([x_motor_angle, x_motor_angle - 360], key=lambda x: abs(x)) - #y_motor_angle = int(y_motor_angle) % 360 - #y_motor_angle = min([y_motor_angle, y_motor_angle - 360], key=lambda x: abs(x)) - #After the proper rotation angle has been selected, we send the move command to the motors - print("Moving X: " + str(x_motor_angle)+ " Moving Y: " + str(y_motor_angle)) - robot.moveX(x_motor_angle) - robot.moveY(y_motor_angle) + # #If the data we got from the server is not one of the predifined messages + # #We assume (big assumption) that the message will contain the angles in the + # #Agreed format: x_motor_angle,y_motor_angle + # #We convert the angles to float after splitting the message on the tab + #for char in data: + # print(chr(char), end=', ') + #print() + x_distance, y_distance = map(float,map(str,data.split(','))) + # #This will make sure that both angles are at most 360 degrees. In addition, + # #it will consider both, the clockwise and counterclockwise rotations to reach + # #the desired position for each motor and will pick the smallest one. So that the chances of making + # #very large rotations are lessened. + # #x_motor_angle = int(x_motor_angle) % 360 + # #x_motor_angle = min([x_motor_angle, x_motor_angle - 360], key=lambda x: abs(x)) + # #y_motor_angle = int(y_motor_angle) % 360 + # #y_motor_angle = min([y_motor_angle, y_motor_angle - 360], key=lambda x: abs(x)) + # #After the proper rotation angle has been selected, we send the move command to the motors + # print("Moving X: " + str(x_motor_angle)+ " Moving Y: " + str(y_motor_angle)) + # robot.moveX(x_motor_angle) + # robot.homeY() + robot.moveX(x_distance) + robot.moveY(y_distance) client.sendDone() \ No newline at end of file diff --git a/Chess Robot/source/server.py b/Chess Robot/source/server.py index a2cdac7..ff9271f 100644 --- a/Chess Robot/source/server.py +++ b/Chess Robot/source/server.py @@ -13,7 +13,7 @@ def __init__(self,port): serversocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) #We need to use the ip address that shows up in ipconfig for the usb ethernet adapter #That handles the comunication between the PC and the crick - host = "169.254.137.85" + host = "169.254.82.210" print ("host: ", host) port = 9999 serversocket.bind((host, port)) @@ -29,11 +29,11 @@ def __init__(self,port): # joint_angle [Float]: The angle by which we want to joint to move # queue [Thread-safe Queue]: Mutable data structure to store (and return) # the messages received from the client - def sendAngles(self, x_motor_angle, y_motor_angle, queue): + def sendDistances(self, x_distance, y_distance, queue): #Format in which the client expects the data # angle1 angle2 - print(str(x_motor_angle) + " " + str(y_motor_angle)) - data = str(x_motor_angle)+","+str(y_motor_angle) + print(str(x_distance) + " " + str(y_distance)) + data = str(x_distance)+","+str(y_distance) print("Sending Data: (" + data + ") to robot.") self.cs.send(data.encode("UTF-8")) #Waiting for the client (ev3 brick) to let the server know @@ -48,6 +48,19 @@ def sendTermination(self): def sendLowerClaw(self): self.cs.send("LOWER_CLAW".encode("UTF-8")) + time.sleep(3.5) + + def sendRaiseClaw(self): + self.cs.send("RAISE_CLAW".encode("UTF-8")) + time.sleep(3.5) + + def sendOpenClaw(self): + self.cs.send("OPEN_CLAW".encode("UTF-8")) + time.sleep(3.5) + + def sendCloseClaw(self): + self.cs.send("CLOSE_CLAW".encode("UTF-8")) + time.sleep(3.5) From 4ae5c3fea59ca6bfc46dfd1f7e196d12ff721be4 Mon Sep 17 00:00:00 2001 From: Rafael Pineros Rhon Date: Fri, 30 Nov 2018 03:06:53 -0700 Subject: [PATCH 03/12] Calculate corners and proportion --- Chess Robot/source/board.jpg | Bin 0 -> 93830 bytes Chess Robot/source/distort.py | 74 ++++++++++++++++++++++++++++++++++ Chess Robot/source/webcam.py | 2 +- 3 files changed, 75 insertions(+), 1 deletion(-) create mode 100644 Chess Robot/source/board.jpg diff --git a/Chess Robot/source/board.jpg b/Chess Robot/source/board.jpg new file mode 100644 index 0000000000000000000000000000000000000000..0fde23de3998e9dc4e74f2c5c1012d44f206b01d GIT binary patch literal 93830 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 O+`o3*$4ag`)1#A;NgI0%Vz6!XXxcDYzz5XS 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 Date: Fri, 30 Nov 2018 16:24:02 -0700 Subject: [PATCH 04/12] Fixed bug with robot coordinates. --- .gitignore | 1 + .../source/{distort.py => coordinates.py} | 19 +++++++++++++++++-- Chess Robot/source/parallelogram.py | 13 +++++++++++++ 3 files changed, 31 insertions(+), 2 deletions(-) rename Chess Robot/source/{distort.py => coordinates.py} (63%) create mode 100644 Chess Robot/source/parallelogram.py diff --git a/.gitignore b/.gitignore index d9bde85..e549179 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ /.vscode/settings.json /Chess Robot/source/__pycache__/ /Chess Robot/source/.vscode/settings.json +/Chess Robot/.vscode/settings.json diff --git a/Chess Robot/source/distort.py b/Chess Robot/source/coordinates.py similarity index 63% rename from Chess Robot/source/distort.py rename to Chess Robot/source/coordinates.py index e0161f2..72a9e78 100644 --- a/Chess Robot/source/distort.py +++ b/Chess Robot/source/coordinates.py @@ -30,11 +30,26 @@ def closest_point(line_start, line_end, point): def calculate_coordinates(event, x,y, flags, params): if event == cv2.EVENT_LBUTTONDOWN: print("Distance to left corner") + closest_left = closest_point(corners[0],corners[1], (x,y)) + closest_bottom = closest_point(corners[0],corners[3], (x,y)) + closest_right = closest_point(corners[3],corners[2], (x,y)) + closest_top = closest_point(corners[1],corners[2], (x,y)) print(str(closest_point(corners[0],corners[1], (x,y)))) current_point = (x,y) - closest = closest_point(corners[0],corners[1], (x,y)) - print(str(np.subtract(current_point,closest))) + #Get Horizontal Length by Pythagoras Theorem + horizontal_length = ((closest_right[0] - closest_left[0])**2+(closest_right[1] - closest_left[1])**2)**(0.5) + #Get Vertical Length by Pythagoras Theorem + vertical_length = ((closest_top[0] - closest_bottom[0])**2+(closest_top[1] - closest_bottom[1])**2)**(0.5) + + #Horizontal length until the closest point (from left to right) + horizontal_distance_to_point = ((current_point[0] - closest_left[0])**2+(current_point[1] - closest_left[1])**2)**(0.5) + #Vertical length until the closest point (from bottom to top) + vertical_distance_to_point = ((current_point[0] - closest_bottom[0])**2+(current_point[1] - closest_bottom[1])**2)**(0.5) + + #In pixels + print("Current Point: " + str(current_point)) #Now we get the percentage eg (current position x)/total length of the x line )both in pixels. This will give us a percentage + print("Proportion in X: " + str(horizontal_distance_to_point/horizontal_length) + " Proportion in Y: " + str(vertical_distance_to_point/vertical_length)) #Then multiply that percentage by 307 to the the milimiter length #[lower_left, upper_left, upper_right, lower_right] diff --git a/Chess Robot/source/parallelogram.py b/Chess Robot/source/parallelogram.py new file mode 100644 index 0000000..7c07d92 --- /dev/null +++ b/Chess Robot/source/parallelogram.py @@ -0,0 +1,13 @@ +class Rectangle: + #Rectangle array is assumed to be in OpenCV standard representation of a rectange + # that is, an array of 4 elements: [x, y, width, height] where each quantity is given in pixels + # and x,y correspond to the coordinate of the top left corner of the rectangle. + def __init__(self,rectangle_array): + self.array_representation = rectangle_array + self.width = int(rectangle_array[2]) + self.height = int(rectangle_array[3]) + self.top_left = (int(rectangle_array[0]), int(rectangle_array[1])) + self.top_right = (int(rectangle_array[0]) + self.width , int(rectangle_array[1])) + self.bottom_left = (int(rectangle_array[0]) , int(rectangle_array[1]) + self.height) + self.bottom_right = (int(rectangle_array[0]) + self.width , int(rectangle_array[1]) + self.height) + self.centre = (self.top_left[0] + int(self.width/2), self.top_left[1] + int(self.height/2)) \ No newline at end of file From e551ee3351005d88fba5a7d55b854f3d31801754 Mon Sep 17 00:00:00 2001 From: Pineros Rhon Date: Fri, 30 Nov 2018 18:33:41 -0700 Subject: [PATCH 05/12] Code for robot movement --- Chess Robot/source/client.py | 2 +- Chess Robot/source/coordinates.py | 97 +++++++++++++++++++++---------- Chess Robot/source/move.py | 6 +- Chess Robot/source/robot.py | 6 +- Chess Robot/source/runner.py | 3 + Chess Robot/source/server.py | 7 ++- Chess Robot/source/webcam.py | 2 +- 7 files changed, 81 insertions(+), 42 deletions(-) diff --git a/Chess Robot/source/client.py b/Chess Robot/source/client.py index e1c349a..ac20808 100644 --- a/Chess Robot/source/client.py +++ b/Chess Robot/source/client.py @@ -12,7 +12,7 @@ def __init__(self,port): #We need to use the ipv4 address that shows up in ipconfig in the computer for the USB #Ethernet adapter handling the connection to the EV3 - host = "169.254.82.210" + host = "169.254.137.85" print("setting up client, address =", host, "port =", port) self.s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) self.s.connect((host, port)) diff --git a/Chess Robot/source/coordinates.py b/Chess Robot/source/coordinates.py index 72a9e78..f4d687c 100644 --- a/Chess Robot/source/coordinates.py +++ b/Chess Robot/source/coordinates.py @@ -4,10 +4,17 @@ from time import sleep import numpy as np -#webcam = Webcam() -#webcam.start() +from queue import Queue +from server import * -image = cv2.imread("board.jpg") +#Thread-safe queue to get data from threads +queue = Queue() +server = Server(9999) + +webcam = Webcam() +webcam.start() + +#image = cv2.imread("board.jpg") #in milimeters side_length = 307 @@ -17,6 +24,11 @@ def mouse_drawing(event, x, y, flags, params): print("Left click") corners.append((x, y)) +def add_target(event, x, y, flags, params): + if event == cv2.EVENT_LBUTTONDOWN: + print("Left click") + current_points.append((x, y)) + #As explained in http://paulbourke.net/geometry/pointlineplane/ def closest_point(line_start, line_end, point): #First element is delta x, second one is delta y @@ -27,30 +39,32 @@ def closest_point(line_start, line_end, point): return (x,y) -def calculate_coordinates(event, x,y, flags, params): - if event == cv2.EVENT_LBUTTONDOWN: - print("Distance to left corner") - closest_left = closest_point(corners[0],corners[1], (x,y)) - closest_bottom = closest_point(corners[0],corners[3], (x,y)) - closest_right = closest_point(corners[3],corners[2], (x,y)) - closest_top = closest_point(corners[1],corners[2], (x,y)) - print(str(closest_point(corners[0],corners[1], (x,y)))) - current_point = (x,y) - #Get Horizontal Length by Pythagoras Theorem - horizontal_length = ((closest_right[0] - closest_left[0])**2+(closest_right[1] - closest_left[1])**2)**(0.5) - #Get Vertical Length by Pythagoras Theorem - vertical_length = ((closest_top[0] - closest_bottom[0])**2+(closest_top[1] - closest_bottom[1])**2)**(0.5) - - #Horizontal length until the closest point (from left to right) - horizontal_distance_to_point = ((current_point[0] - closest_left[0])**2+(current_point[1] - closest_left[1])**2)**(0.5) - #Vertical length until the closest point (from bottom to top) - vertical_distance_to_point = ((current_point[0] - closest_bottom[0])**2+(current_point[1] - closest_bottom[1])**2)**(0.5) - - #In pixels - print("Current Point: " + str(current_point)) - #Now we get the percentage eg (current position x)/total length of the x line )both in pixels. This will give us a percentage - print("Proportion in X: " + str(horizontal_distance_to_point/horizontal_length) + " Proportion in Y: " + str(vertical_distance_to_point/vertical_length)) - #Then multiply that percentage by 307 to the the milimiter length +def calculate_coordinates(x,y): + print("Distance to left corner") + closest_left = closest_point(corners[0],corners[1], (x,y)) + closest_bottom = closest_point(corners[0],corners[3], (x,y)) + closest_right = closest_point(corners[3],corners[2], (x,y)) + closest_top = closest_point(corners[1],corners[2], (x,y)) + print(str(closest_point(corners[0],corners[1], (x,y)))) + current_point = (x,y) + #Get Horizontal Length by Pythagoras Theorem + horizontal_length = ((closest_right[0] - closest_left[0])**2+(closest_right[1] - closest_left[1])**2)**(0.5) + #Get Vertical Length by Pythagoras Theorem + vertical_length = ((closest_top[0] - closest_bottom[0])**2+(closest_top[1] - closest_bottom[1])**2)**(0.5) + + #Horizontal length until the closest point (from left to right) + horizontal_distance_to_point = ((current_point[0] - closest_left[0])**2+(current_point[1] - closest_left[1])**2)**(0.5) + #Vertical length until the closest point (from bottom to top) + vertical_distance_to_point = ((current_point[0] - closest_bottom[0])**2+(current_point[1] - closest_bottom[1])**2)**(0.5) + + #In pixels + print("Current Point: " + str(current_point)) + #Now we get the percentage eg (current position x)/total length of the x line )both in pixels. This will give us a percentage + print("Proportion in X: " + str(horizontal_distance_to_point/horizontal_length) + " Proportion in Y: " + str(vertical_distance_to_point/vertical_length)) + #Then multiply that percentage by 307 to the the milimiter length + proportionX = horizontal_distance_to_point/horizontal_length + propotionY = vertical_distance_to_point/vertical_length + return (side_length*proportionX, side_length*propotionY) #[lower_left, upper_left, upper_right, lower_right] corners = [] @@ -62,7 +76,7 @@ def calculate_coordinates(event, x,y, flags, params): while len(corners) < 4: # get image from webcam - #image = webcam.get_current_frame() + image = webcam.get_current_frame() for center_position in corners: cv2.circle(image, center_position, 5, (0, 0, 255), -1) # display image @@ -70,19 +84,38 @@ def calculate_coordinates(event, x,y, flags, params): key = cv2.waitKey(1) -cv2.setMouseCallback("Frame", calculate_coordinates) +cv2.setMouseCallback("Frame", add_target) -current_point = None +current_points = [] while True: # get image from webcam - #image = webcam.get_current_frame() + image = webcam.get_current_frame() for center_position in corners: cv2.circle(image, center_position, 5, (0, 0, 255), -1) # display image cv2.imshow('Frame', image) - if current_point is not None: + for current_point in current_points: cv2.circle(image, current_point, 5, (0, 0, 0), -1) + + if (len(current_points) == 2): + #First, take the initial and position end effector over it + #Make sure to account for the 100 mm in offset for the y axis and the 19mm for x and y + (x1,y1) = calculate_coordinates(current_points[0][0], current_points[0][1]) + server.sendDistances(-x1 + 19, -(100 + y1) + 19, queue) + server.sendLowerClaw() + server.sendCloseClaw() + server.sendRaiseClaw() + #After piece is grabbed, we move it to the desired position specified in the second point + (x2,y2) = calculate_coordinates(current_points[1][0], current_points[1][1]) + delta_x = x2 - x1 + delta_y = y2 - y1 + server.sendDistances(-delta_x, -delta_y, queue) + server.sendLowerClaw() + server.sendOpenClaw() + server.sendRaiseClaw() + server.sendHome() + break key = cv2.waitKey(1) diff --git a/Chess Robot/source/move.py b/Chess Robot/source/move.py index cd09145..2b9c1df 100644 --- a/Chess Robot/source/move.py +++ b/Chess Robot/source/move.py @@ -15,8 +15,6 @@ server.sendRaiseClaw() +# robot = Robot() -#yMotor = LargeMotor(OUTPUT_A) -#xMotor = LargeMotor(OUTPUT_C) -#zMotor = LargeMotor(OUTPUT_D) -#gripperMotor = MediumMotor(OUTPUT_B) \ No newline at end of file +# robot.xMotor.run_to_rel_pos(position_sp=-360,speed_sp=230) \ No newline at end of file diff --git a/Chess Robot/source/robot.py b/Chess Robot/source/robot.py index ba90d20..45d120f 100644 --- a/Chess Robot/source/robot.py +++ b/Chess Robot/source/robot.py @@ -6,7 +6,7 @@ class Robot: def __init__(self): self.millimetersPerTickY = 0.14444444 - self.millimetersPerTickX = 0.07222222 + self.millimetersPerTickX = 0.05833333 self.yOffset = 100 self.yMotor = LargeMotor(OUTPUT_A) self.xMotor = LargeMotor(OUTPUT_C) @@ -37,13 +37,13 @@ def closeClaw(self): def homeX(self): degrees = -(self.currentX/self.millimetersPerTickX) - self.xMotor.on_for_degrees(SpeedPercent(23),degrees) + self.xMotor.on_for_degrees(SpeedPercent(23), abs(degrees)) self.xMotor.stop() self.currentX = 0 def homeY(self): degrees = (self.currentY/self.millimetersPerTickY) - self.yMotor.on_for_degrees(SpeedPercent(23),degrees) + self.yMotor.on_for_degrees(SpeedPercent(23),abs(degrees)) self.yMotor.stop() self.currentY = 0 diff --git a/Chess Robot/source/runner.py b/Chess Robot/source/runner.py index 14f94c7..5210622 100644 --- a/Chess Robot/source/runner.py +++ b/Chess Robot/source/runner.py @@ -29,6 +29,9 @@ robot.openClaw() elif(data == "CLOSE_CLAW"): robot.closeClaw() + elif(data == "HOME"): + robot.homeX() + robot.homeY() else: # #If the data we got from the server is not one of the predifined messages # #We assume (big assumption) that the message will contain the angles in the diff --git a/Chess Robot/source/server.py b/Chess Robot/source/server.py index ff9271f..dd49838 100644 --- a/Chess Robot/source/server.py +++ b/Chess Robot/source/server.py @@ -13,7 +13,7 @@ def __init__(self,port): serversocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) #We need to use the ip address that shows up in ipconfig for the usb ethernet adapter #That handles the comunication between the PC and the crick - host = "169.254.82.210" + host = "169.254.137.85" print ("host: ", host) port = 9999 serversocket.bind((host, port)) @@ -62,5 +62,10 @@ def sendCloseClaw(self): self.cs.send("CLOSE_CLAW".encode("UTF-8")) time.sleep(3.5) + def sendHome(self): + self.cs.send("HOME".encode("UTF-8")) + time.sleep(100) + + diff --git a/Chess Robot/source/webcam.py b/Chess Robot/source/webcam.py index 0565a65..7ac0b45 100644 --- a/Chess Robot/source/webcam.py +++ b/Chess Robot/source/webcam.py @@ -4,7 +4,7 @@ class Webcam: def __init__(self): - self.video_capture = cv2.VideoCapture(0) + self.video_capture = cv2.VideoCapture(1) self.current_frame = self.video_capture.read()[1] # create thread for capturing images From b23b04739c01f7b6492d55d3d8e1fdba04cb8e0d Mon Sep 17 00:00:00 2001 From: Pineros Rhon Date: Fri, 30 Nov 2018 19:58:53 -0700 Subject: [PATCH 06/12] Robot can now do multiple moves. --- Chess Robot/source/claw.py | 3 +++ Chess Robot/source/coordinates.py | 12 ++++++++---- Chess Robot/source/robot.py | 9 ++++++++- Chess Robot/source/runner.py | 2 +- 4 files changed, 20 insertions(+), 6 deletions(-) diff --git a/Chess Robot/source/claw.py b/Chess Robot/source/claw.py index 017f9ea..b5d7fbf 100644 --- a/Chess Robot/source/claw.py +++ b/Chess Robot/source/claw.py @@ -37,4 +37,7 @@ def close(self): sleep(3) self.isOpen = False + def stop(self): + self.reset() + #if __name__ == "__main__": diff --git a/Chess Robot/source/coordinates.py b/Chess Robot/source/coordinates.py index f4d687c..98f61fc 100644 --- a/Chess Robot/source/coordinates.py +++ b/Chess Robot/source/coordinates.py @@ -90,14 +90,16 @@ def calculate_coordinates(x,y): while True: # get image from webcam + print("Get Frame") image = webcam.get_current_frame() for center_position in corners: cv2.circle(image, center_position, 5, (0, 0, 255), -1) # display image - cv2.imshow('Frame', image) for current_point in current_points: cv2.circle(image, current_point, 5, (0, 0, 0), -1) + cv2.imshow('Frame', image) + if (len(current_points) == 2): #First, take the initial and position end effector over it #Make sure to account for the 100 mm in offset for the y axis and the 19mm for x and y @@ -115,8 +117,10 @@ def calculate_coordinates(x,y): server.sendOpenClaw() server.sendRaiseClaw() server.sendHome() - break - + current_points.clear() key = cv2.waitKey(1) - + if 'q' == chr(key & 255): + break + +server.sendTermination() cv2.destroyAllWindows() \ No newline at end of file diff --git a/Chess Robot/source/robot.py b/Chess Robot/source/robot.py index 45d120f..0f0e9f6 100644 --- a/Chess Robot/source/robot.py +++ b/Chess Robot/source/robot.py @@ -6,7 +6,8 @@ class Robot: def __init__(self): self.millimetersPerTickY = 0.14444444 - self.millimetersPerTickX = 0.05833333 + #self.millimetersPerTickX = 0.05833333 + self.millimetersPerTickX = 0.0642 self.yOffset = 100 self.yMotor = LargeMotor(OUTPUT_A) self.xMotor = LargeMotor(OUTPUT_C) @@ -77,3 +78,9 @@ def clawDown(self): sleep(3.5) self.zMotor.stop() + def stop(self): + self.yMotor.reset() + self.xMotor.reset() + self.zMotor.reset() + self.claw.stop() + diff --git a/Chess Robot/source/runner.py b/Chess Robot/source/runner.py index 5210622..9b96f26 100644 --- a/Chess Robot/source/runner.py +++ b/Chess Robot/source/runner.py @@ -19,7 +19,7 @@ data = str(client.pollData()) if(data == 'EXIT'): #Terminate the routine on the client - #robot.stop() + robot.stop() break elif(data == "LOWER_CLAW"): robot.clawDown() From 7f398545a7635fb36f6456029ecb3e3e985257bc Mon Sep 17 00:00:00 2001 From: phebert5009 Date: Mon, 3 Dec 2018 16:28:15 -0700 Subject: [PATCH 07/12] attempt at preventing camera freeze --- Chess Robot/source/webcam.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Chess Robot/source/webcam.py b/Chess Robot/source/webcam.py index 7ac0b45..be7763c 100644 --- a/Chess Robot/source/webcam.py +++ b/Chess Robot/source/webcam.py @@ -9,7 +9,7 @@ def __init__(self): # create thread for capturing images def start(self): - Thread(target=self._update_frame, args=()).start() + self.thread = Thread(target=self._update_frame, args=()).start() def _update_frame(self): while(True): @@ -17,4 +17,4 @@ def _update_frame(self): # get the current frame def get_current_frame(self): - return self.current_frame \ No newline at end of file + return self.current_frame From 9b9c2e5308c56dc18f560d02d7af40d842403855 Mon Sep 17 00:00:00 2001 From: bbest31 Date: Mon, 3 Dec 2018 16:36:33 -0700 Subject: [PATCH 08/12] ip and video for testing --- Chess Robot/source/client.py | 2 +- Chess Robot/source/server.py | 2 +- Chess Robot/source/webcam.py | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Chess Robot/source/client.py b/Chess Robot/source/client.py index ac20808..e1c349a 100644 --- a/Chess Robot/source/client.py +++ b/Chess Robot/source/client.py @@ -12,7 +12,7 @@ def __init__(self,port): #We need to use the ipv4 address that shows up in ipconfig in the computer for the USB #Ethernet adapter handling the connection to the EV3 - host = "169.254.137.85" + host = "169.254.82.210" print("setting up client, address =", host, "port =", port) self.s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) self.s.connect((host, port)) diff --git a/Chess Robot/source/server.py b/Chess Robot/source/server.py index dd49838..be86551 100644 --- a/Chess Robot/source/server.py +++ b/Chess Robot/source/server.py @@ -13,7 +13,7 @@ def __init__(self,port): serversocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) #We need to use the ip address that shows up in ipconfig for the usb ethernet adapter #That handles the comunication between the PC and the crick - host = "169.254.137.85" + host = "169.254.82.210" print ("host: ", host) port = 9999 serversocket.bind((host, port)) diff --git a/Chess Robot/source/webcam.py b/Chess Robot/source/webcam.py index 7ac0b45..0565a65 100644 --- a/Chess Robot/source/webcam.py +++ b/Chess Robot/source/webcam.py @@ -4,7 +4,7 @@ class Webcam: def __init__(self): - self.video_capture = cv2.VideoCapture(1) + self.video_capture = cv2.VideoCapture(0) self.current_frame = self.video_capture.read()[1] # create thread for capturing images From 8d88a3ed27fbd32c1a4d9b858e8f8775c0734f6a Mon Sep 17 00:00:00 2001 From: phebert5009 Date: Mon, 3 Dec 2018 17:09:54 -0700 Subject: [PATCH 09/12] released motors for manual movement --- Chess Robot/source/robot.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Chess Robot/source/robot.py b/Chess Robot/source/robot.py index 0f0e9f6..d401144 100644 --- a/Chess Robot/source/robot.py +++ b/Chess Robot/source/robot.py @@ -10,6 +10,7 @@ def __init__(self): self.millimetersPerTickX = 0.0642 self.yOffset = 100 self.yMotor = LargeMotor(OUTPUT_A) + self.yMotor.stop_action = 'brake' self.xMotor = LargeMotor(OUTPUT_C) self.zMotor = LargeMotor(OUTPUT_D) self.currentY = 0 @@ -29,6 +30,9 @@ def __init__(self): #After the claw has been lifted we initialze it self.claw = Claw() + + def __del__(self): + self.zMotor.stop(strop_action='coast') def openClaw(self): self.claw.open() From b572331f7ff76fbc1feb7118e8ae1e24cb92d747 Mon Sep 17 00:00:00 2001 From: phebert5009 Date: Mon, 3 Dec 2018 17:22:52 -0700 Subject: [PATCH 10/12] self stopping thread --- Chess Robot/source/webcam.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/Chess Robot/source/webcam.py b/Chess Robot/source/webcam.py index 783da3e..9c07b33 100644 --- a/Chess Robot/source/webcam.py +++ b/Chess Robot/source/webcam.py @@ -6,13 +6,17 @@ class Webcam: def __init__(self): self.video_capture = cv2.VideoCapture(0) self.current_frame = self.video_capture.read()[1] + self.__continue = True + + def __del__(self): + self.__continue = False # create thread for capturing images def start(self): self.thread = Thread(target=self._update_frame, args=()).start() def _update_frame(self): - while(True): + while(self.__continue): self.current_frame = self.video_capture.read()[1] # get the current frame From 54f96fcc5b77bf361537a47f8e7324a8ac724481 Mon Sep 17 00:00:00 2001 From: phebert5009 Date: Mon, 3 Dec 2018 19:48:08 -0700 Subject: [PATCH 11/12] waiting for everything with recv --- Chess Robot/source/runner.py | 2 +- Chess Robot/source/server.py | 15 ++++++++++----- 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/Chess Robot/source/runner.py b/Chess Robot/source/runner.py index 9b96f26..0ab9823 100644 --- a/Chess Robot/source/runner.py +++ b/Chess Robot/source/runner.py @@ -55,4 +55,4 @@ # robot.homeY() robot.moveX(x_distance) robot.moveY(y_distance) - client.sendDone() \ No newline at end of file + client.sendDone() diff --git a/Chess Robot/source/server.py b/Chess Robot/source/server.py index be86551..ebab0de 100644 --- a/Chess Robot/source/server.py +++ b/Chess Robot/source/server.py @@ -48,23 +48,28 @@ def sendTermination(self): def sendLowerClaw(self): self.cs.send("LOWER_CLAW".encode("UTF-8")) - time.sleep(3.5) + reply = self.cs.recv(128).decode("UTF-8") + queue.put(reply) def sendRaiseClaw(self): self.cs.send("RAISE_CLAW".encode("UTF-8")) - time.sleep(3.5) + reply = self.cs.recv(128).decode("UTF-8") + queue.put(reply) def sendOpenClaw(self): self.cs.send("OPEN_CLAW".encode("UTF-8")) - time.sleep(3.5) + reply = self.cs.recv(128).decode("UTF-8") + queue.put(reply) def sendCloseClaw(self): self.cs.send("CLOSE_CLAW".encode("UTF-8")) - time.sleep(3.5) + reply = self.cs.recv(128).decode("UTF-8") + queue.put(reply) def sendHome(self): self.cs.send("HOME".encode("UTF-8")) - time.sleep(100) + reply = self.cs.recv(128).decode("UTF-8") + queue.put(reply) From 554b4da25c65fe3577c04b0b11b9a9949fce5dc7 Mon Sep 17 00:00:00 2001 From: bbest31 Date: Mon, 3 Dec 2018 19:58:24 -0700 Subject: [PATCH 12/12] move time delay fix --- Chess Robot/source/coordinates.py | 1 - Chess Robot/source/robot.py | 4 ++-- Chess Robot/source/server.py | 5 ----- 3 files changed, 2 insertions(+), 8 deletions(-) diff --git a/Chess Robot/source/coordinates.py b/Chess Robot/source/coordinates.py index 98f61fc..9b72956 100644 --- a/Chess Robot/source/coordinates.py +++ b/Chess Robot/source/coordinates.py @@ -90,7 +90,6 @@ def calculate_coordinates(x,y): while True: # get image from webcam - print("Get Frame") image = webcam.get_current_frame() for center_position in corners: cv2.circle(image, center_position, 5, (0, 0, 255), -1) diff --git a/Chess Robot/source/robot.py b/Chess Robot/source/robot.py index d401144..0ec782e 100644 --- a/Chess Robot/source/robot.py +++ b/Chess Robot/source/robot.py @@ -32,8 +32,8 @@ def __init__(self): self.claw = Claw() def __del__(self): - self.zMotor.stop(strop_action='coast') - + self.stop() + def openClaw(self): self.claw.open() diff --git a/Chess Robot/source/server.py b/Chess Robot/source/server.py index ebab0de..e8ead8d 100644 --- a/Chess Robot/source/server.py +++ b/Chess Robot/source/server.py @@ -49,27 +49,22 @@ def sendTermination(self): def sendLowerClaw(self): self.cs.send("LOWER_CLAW".encode("UTF-8")) reply = self.cs.recv(128).decode("UTF-8") - queue.put(reply) def sendRaiseClaw(self): self.cs.send("RAISE_CLAW".encode("UTF-8")) reply = self.cs.recv(128).decode("UTF-8") - queue.put(reply) def sendOpenClaw(self): self.cs.send("OPEN_CLAW".encode("UTF-8")) reply = self.cs.recv(128).decode("UTF-8") - queue.put(reply) def sendCloseClaw(self): self.cs.send("CLOSE_CLAW".encode("UTF-8")) reply = self.cs.recv(128).decode("UTF-8") - queue.put(reply) def sendHome(self): self.cs.send("HOME".encode("UTF-8")) reply = self.cs.recv(128).decode("UTF-8") - queue.put(reply)