Annalisa DeBari and Raven Fournier
Our robot consists of two motors and beams of length 14 cm and 11 cm (first and second beam respectively).
Challenge 1: Build the arm and demonstrate the range of motion:
Maximum X position: 25 cm
Maximum Y position: 25 cm
Minimum X position: -11.3 cm
Minimum Y position: -25 cm
Challenge 2: Calculate end effector position based on manual movement of arm.
Challenge 2 was done to ensure that position of the end effector is being properly tracked by the computer. The video demonstrates the motion and then shows the position of the end effector, denoted x_b & y_b.
Challenge 3: Create program that records positions and “plays” back.
As the first half of Challenge 3, we wanted to demonstrate that our robotic arm moves rigidly to specific points to be played back. It can be noted that the sampling and playback rates can be altered for a more accurate playback, but this video demonstrates that the robot successfully moves to the predetermined positions.
For the second half, we wanted to demonstrate that our robotic arm can move and follow fluid motions. This was done by altering the code slightly. Depending on the desired application, we know what alterations to make in our code.
#!/usr/bin/env python3 ev3 = Device("this") def manageRange(n): return max(min(n,1050),-1050) def main(): import math # initialize variables position_1 = None length1 = None length2 = None theta1 = None theta2 = None i = 0 # x_a is the x-coordinate of the end of the beam connected to motor 1, and x_b is the x-coordinate of the end effector x_a = None x_b = None y_a = None y_b = None # create vectors to hold the motor location data theta1_array = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] theta2_array = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] while True: # set theta1 to the position of the motor in port b (motor 1) theta1 = ev3.LargeMotor('outB').position theta1 = -1 * theta1 # had to multiply by -1 for the math to work out # store that value into the current location of an array theta1_array[i] = theta1 theta2 = ev3.LargeMotor('outD').position theta2 = -1 * theta2 theta2_array[i] = theta2 length1 = 14 # length of first beam length2 = 11 # length of 2nd beam # from class we calculated these formulas x_a = length1 * math.cos(theta1 / 180.0 * math.pi) y_a = length1 * math.sin(theta1 / 180.0 * math.pi) print('x_a:' + str(x_a)) print('y_a:' + str(y_a)) print('motor1 position:' + str(theta1)) x_b = x_a + length2 * math.cos((theta1+theta2) / 180.0 * math.pi) y_b = y_a + length2 * math.sin((theta1+theta2) / 180.0 * math.pi) print('x_b:' + str(x_b)) print('y_b:' + str(y_b)) print('motor2 position:' + str(theta2)) sleep(1) i = i+1 # increase the counter variable # once the code has recorded location 14 times, enter this next portion where it “plays back” if i >=14: print('entered if statement') print('theta1_array:') print(theta1_array) print('theta2_array:') print(theta2_array) # need another counter variable to access the stored values j=0 for count in range(14): print('ENTERED FOR LOOP') print('j is:' + str(j)) print('motor1 position:') print(theta1_array[j]) print('motor2 position:') print(theta2_array[j]) current_posA = theta1_array[j] * -1 current_posB = theta2_array[j] * -1 # needed to keep track of the previous position in order to move to the correct location relative to the original zero location instead of moving relative to its current position prev_posA = 0 prev_posB = 0 if j >= 1: prev_posA = theta1_array[j-1] * -1 prev_posB = theta2_array[j-1] * -1 outB = ev3.LargeMotor('outB') outB.run_to_rel_pos(speed_sp=manageRange(15 * 10.50),position_sp=current_posA - prev_posA, stop_action="hold") outD = ev3.LargeMotor('outD') outD.run_to_rel_pos(speed_sp=manageRange(15 * 10.50),position_sp=current_posB - prev_posB, stop_action="hold") j=j+1 sleep(1) pass print('done') break if __name__ == '__main__': main()
Disclaimer: Our code logic is correct, but since the EV3 motors are not very precise the locations are not always precise either. The mechanical components have weight to them, and the motors can become misaligned with zero fairly easily. There is also a decent amount of “wiggle room” with the motors where you can mechanically move back and forth a couple of millimeters and the motor reads the same position throughout.
Changing the sleep times also changes the rate of collection. So, to collect more fluidly, changing the sleep time to .5 or less allows the code to store the data more rapidly and collect more fluid motion. We also changed the motor command stop_action set to “coast” instead of “hold” to make the motion even more fluid as seen in the second video of challenge 3.