|
from time import sleep |
|
import turtle |
|
import serial |
|
import random |
|
import math |
|
|
|
ArduinoData = serial.Serial('/dev/cu.usbserial-1420', 9600) |
|
|
|
sleep(5) |
|
|
|
RANGE_OF_MOTION = 2 |
|
DISTANCE_PER_SECOND = 35 |
|
|
|
BICEP = 192 |
|
FOREARM = 146 |
|
|
|
WRIST_90 = 80 |
|
|
|
hypotenuse = 0 |
|
servo_angle = 0 |
|
|
|
|
|
def find_height(hypotenuse, angle): |
|
height = math.sin(math.radians(angle))*hypotenuse |
|
return height |
|
|
|
|
|
def distance(): |
|
global hypotenuse, servo_angle |
|
ArduinoData.write(b"distang") |
|
|
|
while hypotenuse == 0: |
|
try: |
|
hypotenuse = int(ArduinoData.readline()) |
|
except ValueError: |
|
hypotenuse = 0 |
|
|
|
servo_angle = int(ArduinoData.readline())-WRIST_90 |
|
hypotenuse = hypotenuse |
|
|
|
print("Servo angled at:", servo_angle, "Distance to Object:", hypotenuse) |
|
|
|
distance = round(math.cos(math.radians(servo_angle))*hypotenuse) |
|
print("Lateral Distance:", distance) |
|
return distance |
|
|
|
|
|
def grab_components(): |
|
ArduinoData.write(b"grabComponents") |
|
elbow_angle = 0 |
|
hypotenuse = 0 |
|
servo_angle = 0 |
|
|
|
while hypotenuse == 0: |
|
try: |
|
hypotenuse = int(ArduinoData.readline())*10 |
|
except ValueError: |
|
hypotenuse = 0 |
|
|
|
while servo_angle == 0: |
|
try: |
|
servo_angle = int(ArduinoData.readline()) |
|
except ValueError: |
|
servo_angle = 0 |
|
|
|
while elbow_angle == 0: |
|
try: |
|
elbow_angle = int(ArduinoData.readline()) |
|
except ValueError: |
|
elbow_angle = 0 |
|
|
|
original_shoulder = int(ArduinoData.readline()) |
|
|
|
return hypotenuse+80, servo_angle, elbow_angle, original_shoulder |
|
|
|
|
|
def wrist_angle(distance, height): |
|
return math.degrees(math.atan(height/distance)) |
|
|
|
|
|
def absolute(num): |
|
return ((num)**2)**0.5 |
|
|
|
|
|
def convert_to_3_digits(value): |
|
value = str(round(value)) |
|
if len(value) == 1: |
|
value = '00' + value |
|
elif len(value) == 2: |
|
value = '0' + value |
|
|
|
return value |
|
|
|
|
|
def target(coordinates): |
|
pass |
|
|
|
|
|
def find(object): |
|
pass |
|
|
|
|
|
def draw_quadrilateral(AB, BC, CD, AD, angle_A, angle_B, angle_C, angle_D): |
|
t = turtle.Turtle() |
|
turtle.Screen().bgcolor("black") |
|
t.hideturtle() |
|
turtle.colormode(255) |
|
t.pencolor((32, 161, 236)) |
|
t.clear() |
|
t.pensize(2) |
|
shoulder_displacement = 90-(180-angle_D-(90-(angle_C-WRIST_90))) |
|
t.left(shoulder_displacement+angle_A) |
|
|
|
t.penup() |
|
t.goto(-100, -100) |
|
t.pendown() |
|
|
|
t.forward(AB) |
|
t.left(180-angle_B) |
|
t.forward(BC) |
|
t.left(180-angle_C) |
|
t.forward(CD) |
|
t.left(180-angle_D) |
|
t.forward(AD) |
|
|
|
t.penup() |
|
t.goto(-100, -100) |
|
t.pendown() |
|
|
|
|
|
def grab(): |
|
elbow_origin = 110 |
|
shoulder_origin = 10 |
|
|
|
AB = BICEP |
|
BC = FOREARM |
|
CD, angle_C, angle_B, original_shoulder = grab_components() |
|
original_elbow = angle_B |
|
print(CD, angle_C, angle_B, original_shoulder) |
|
|
|
angle_B_full = (0.511*angle_B)+75 |
|
print(angle_B_full) |
|
angle_C_full = 80+angle_C |
|
|
|
angle_C = math.radians(angle_C_full) |
|
|
|
BD = math.sqrt(BC**2 + CD**2 - 2 * BC * CD * math.cos(angle_C)) |
|
|
|
cos_C = (BC**2 + CD**2 - BD**2) / (2 * BC * CD) |
|
angle_C = math.degrees(math.acos(cos_C)) |
|
|
|
sin_B = (BC * math.sin(math.radians(angle_C))) / BD |
|
angle_BDC = math.degrees(math.asin(sin_B)) |
|
|
|
sin_D = (CD * math.sin(math.radians(angle_C))) / BD |
|
angle_CBD = math.degrees(math.asin(sin_D)) |
|
|
|
angle_B = angle_B_full-angle_CBD |
|
|
|
AD = math.sqrt(AB**2 + BD**2 - 2 * AB * BD * |
|
math.cos(math.radians(angle_B))) |
|
|
|
cos_D = (AD ** 2 + BD ** 2 - AB ** 2) / (2 * AD * BD) |
|
angle_D = math.degrees(math.acos(cos_D)) |
|
|
|
angle_A = 180 - angle_B - angle_D |
|
|
|
angle_D = angle_D+angle_BDC |
|
|
|
AD = AD |
|
|
|
original_A = angle_A |
|
|
|
print("-"*100) |
|
print(f"Angle A = {angle_A:.2f} degrees") |
|
print(f"Angle B = {angle_B_full:.2f} degrees") |
|
print(f"Angle C = {angle_C_full:.2f} degrees") |
|
print(f"Angle D = {angle_D:.2f} degrees") |
|
|
|
print(f"The length of side AB is {AB:.2f}") |
|
print(f"The length of side BC is {BC:.2f}") |
|
print(f"The length of side CD is {CD:.2f}") |
|
print(f"The length of side AD is {AD:.2f}") |
|
print("-"*100) |
|
|
|
draw_quadrilateral(AB, BC, CD, AD, angle_A, angle_B, angle_C, angle_D) |
|
|
|
CD = 90 |
|
|
|
|
|
AC = math.sqrt(CD**2 + AD**2 - 2 * CD * AD * |
|
math.cos(math.radians(angle_D))) |
|
cos_ACD = (AD**2 + AC**2 - CD**2) / (2 * AD * AC) |
|
angle_CAD = math.degrees(math.acos(cos_ACD)) |
|
angle_ACD = 180 - angle_CAD - angle_D |
|
|
|
cos_B = (AB ** 2 + BC ** 2 - AC ** 2) / (2 * AB * BC) |
|
angle_B = math.degrees(math.acos(cos_B)) |
|
|
|
cos_C = (BC ** 2 + AC ** 2 - AB ** 2) / (2 * BC * AC) |
|
angle_C = math.degrees(math.acos(cos_C)) + angle_ACD |
|
angle_A = (180 - angle_B - angle_C) |
|
cos_A = (AB ** 2 + AC ** 2 - BC ** 2) / (2 * AB * AC) |
|
angle_A = math.degrees(math.acos(cos_A)) + angle_CAD |
|
|
|
shoulder_displacement = -1*(90-(180-angle_D-(90-(angle_C-WRIST_90)))) |
|
|
|
print("-"*100) |
|
print(f"Angle A = {angle_A:.2f} degrees") |
|
print(f"Angle B = {angle_B:.2f} degrees") |
|
print(f"Angle C = {angle_C:.2f} degrees") |
|
print(f"Angle D = {angle_D:.2f} degrees") |
|
print(f"Shoulder Displacement = {shoulder_displacement:.2f} degrees") |
|
print(f"Shoulder from 90 = {shoulder_displacement+angle_A:.2f} degrees") |
|
|
|
print(f"The length of side AB is {AB:.2f}") |
|
print(f"The length of side BC is {BC:.2f}") |
|
print(f"The length of side CD is {CD:.2f}") |
|
print(f"The length of side AD is {AD:.2f}") |
|
print("-"*100) |
|
draw_quadrilateral(AB, BC, CD, AD, (180-angle_A), |
|
angle_B, angle_C, angle_D) |
|
|
|
|
|
|
|
|
|
elbow = 1.9*angle_B-140 |
|
wrist = angle_C - 80 |
|
|
|
|
|
shoulder = -0.4484848484848485 * (angle_A+shoulder_displacement) + 97.0 |
|
|
|
ArduinoData.write(bytes( |
|
f"grab {convert_to_3_digits(shoulder)} {convert_to_3_digits(elbow)} {convert_to_3_digits(wrist)}", "utf-8")) |
|
|
|
|
|
def go(direction, distance): |
|
global servo_angle, hypotenuse |
|
if direction == "forward": |
|
print("Going forward") |
|
height = find_height(hypotenuse, servo_angle) |
|
|
|
if distance > RANGE_OF_MOTION: |
|
send_distance = distance - RANGE_OF_MOTION |
|
send_time = send_distance/DISTANCE_PER_SECOND |
|
remaining_distance = distance-send_distance |
|
send_angle = wrist_angle(remaining_distance, height)+50 |
|
print("Moving:", send_distance, |
|
"\t\tDistance to Object:", remaining_distance) |
|
|
|
ArduinoData.write(bytes(f"forward {int(send_time*1000)}", 'utf-8')) |
|
sleep(1.5) |
|
ArduinoData.write(bytes(f"wrist_track {int(send_angle)}", "utf-8")) |
|
|
|
if direction == "backward": |
|
send_distance = distance - RANGE_OF_MOTION |
|
send_time = send_distance/DISTANCE_PER_SECOND |
|
ArduinoData.write(bytes(f"backward {int(send_time*1000)}", 'utf-8')) |
|
|
|
|
|
|
|
|
|
grab() |
|
turtle.done() |
|
|