Figure 1: Quanser Interactive Labs simulation of Q-Arm and autoclaves

import random
import sys
sys.path.append('../')
from Common.simulation_project_library import *

hardware = False
QLabs = configure_environment(project_identifier, ip_address, hardware).QLabs
arm = qarm(project_identifier,ip_address,QLabs,hardware)
potentiometer = potentiometer_interface()

# small note when running code - sometimes some of the autoclaves cannot be reached using potentiometer control
# in this case, move the potentiometer to the other extreme (ie. if value is ~100 set to 0) very quickly 
# this will trigger the "cannot rotate past +/- 175 degree" error, which will stop the rotation and allow the potentiometer control to move base again  

# different location coordinates - pickup, dropoff, and home locations respectively
p_loc = [0.60,0.050,0.04]
d_loc = [[0.0, -0.63, 0.30],[0.0, 0.63, 0.30],[-0.63, 0.235, 0.30],[0.0, -0.42, 0.17], [0.0, 0.42, 0.17], [-0.41, 0.17, 0.17]]
h_loc = [0.406, 0, 0.483]

# picks up container from pickup location and returns arm to home position
def pick_up_container(p_loc: list, home_loc: list):
    # small delay to wait for everything to load
    time.sleep(1)
    # sets the location of pickup location of the box
    box_x = p_loc[0]
    box_y = p_loc[1]
    box_z = p_loc[2]
    # sets the coordinates of home
    home_x = home_loc[0]
    home_y = home_loc[1]
    home_z = home_loc[2]
    # move arm just above box to prevent hitting box
    arm.move_arm(box_x, box_y, box_z + 0.5)
    time.sleep(2)
    arm.move_arm(box_x, box_y, box_z)
    time.sleep(2)
    arm.control_gripper(35)
    time.sleep(2)
    arm.move_arm(home_x, home_y, home_z)

# allows user control of how much the Q-Arm base should be rotated by
def rotate_base(item_val: int):
    # get initial potentiometer reading
    reading_a = potentiometer.right()
    check_color = int(item_val)
    # uses item_val to check color of the box and make sure it is in front of correct autoclave
    if item_val == 1 or item_val == 4:
        color = 'red'
    elif item_val == 2 or item_val == 5:
        color = 'green'
    elif item_val == 3 or item_val == 6:
        color = 'blue'
    # allows user to continue to rotate the base until both potentiometer readings are correct
    while not (arm.check_autoclave(color) and ((potentiometer.left()==1.0 and item_val >= 4) or (0.5<potentiometer.left()<1.0 and item_val <= 3))):
        # gets the difference between the readings to find how much to rotate the base by
        reading_b = potentiometer.right()
        delta = reading_b - reading_a
        arm.rotate_base(350*delta)
        reading_a = reading_b

# drops off the container - Joon
def drop_off(locations: list, item_val: int):
    time.sleep(1)
    # check color of box and its respective location
    loc = locations[item_val - 1]
    # uses item_val to check color of the box and make sure it is in front of correct autoclave
    if item_val == 1 or item_val == 4:
        color = 'red'
    elif item_val == 2 or item_val == 5:
        color = 'green'
    elif item_val == 3 or item_val == 6:
        color = 'blue'
    arm.activate_autoclaves()
    # get potentiometer reading then checks where the box should go
    reading = potentiometer.left()
    # if reading is 100, opens drawer and drops box off then closes drawer again
    if reading == 1.0:
        arm.open_autoclave(color)
        time.sleep(2)
        # moves arm just above the dropoff location to prevent the arm from hitting anything as it approaches
        arm.move_arm(loc[0], loc[1], loc[2] + 0.1)
        time.sleep(2)
        arm.move_arm(loc[0], loc[1], loc[2])
        time.sleep(1)
        arm.control_gripper(-35)
        time.sleep(1)
        arm.home()
        time.sleep(1)
        arm.open_autoclave(color, False)
        time.sleep(4)
        # sometimes the drawer won't close so as a backup, attempt to close one more time
        arm.open_autoclave(color, False)
        time.sleep(2)
    # if reading is 50<reading<100, drops box off on top of autoclave
    elif 1.0 > reading > 0.5:
        time.sleep(1)
        # moves arm just above the dropoff location to prevent the arm from hitting anything as it approaches
        arm.move_arm(loc[0], loc[1], loc[2] + 0.1)
        time.sleep(2)
        arm.move_arm(loc[0], loc[1], loc[2])
        time.sleep(1)
        arm.control_gripper(-35)
        time.sleep(1)
        arm.home()
    # deactivates autoclaves and return arm to home position
    arm.deactivate_autoclaves()
    time.sleep(1)
    arm.home()
    time.sleep(2)

# funcion to check whether to continue or not
def continue_or_not(box_num: int):
    # remove box that has already been used
    box_num_list.pop(box_num)
    # if box_num_list is empty, stop program
    if not box_num_list:
        arm.home()
        time.sleep(1)
        arm.terminate_arm()
    else:
        main()

box_num_list = [1,2,3,4,5,6]

def main():
    # generate new box number and generate in simulation - this is the index of the item
    box_num = random.randint(0, len(box_num_list) - 1)
    # move container to desired location then repeat 6 times
    arm.spawn_cage(box_num_list[box_num])
    pick_up_container(p_loc, h_loc)
    rotate_base(box_num_list[box_num])
    drop_off(d_loc, box_num_list[box_num])
    continue_or_not(box_num)
                    

Figure 2: Final working computer program

Project overview

The Goal: Create a system to transport surgical tools for sterilization

The Task: Write a program that sorts autoclave containers by color and size

The Constraints: Two potentiometer controls need to be implemented for specific tasks

The Solution: Efficiently sort containers using a Q-Arm

Skills Used

Soft Skills: Collaboration, Engineering Report Writing, Time Management

Technical Skills: Python, Quanser Interactive Labs, Q-Arm, ANSYS-GRANTA EduPack, Microsoft Office

Design Process

Problem Framing: The team met to accuratly define the problem and came up with the objective, function, and constraint for our computer program

Ideas Brainstorming: The team came up with various ideas on feature implementation

Planning: The team came up with a flowchart for the entire program and wrote some pseudocode for each required function

Development: The team split up the work into equal parts and each member wrote a different function of the program

Code Review: The team put all completed code together and checked over each other's work to ensure that the code would run without issues

Testing: I tested the code to make sure the small details were correct, such as the exact pick-up and drop-off location coordinates

Administrative Role

Role: I was the Administrator for the computing sub-team

Responsibilities: I created and shared the collaborative working document for the team and submitted all deliverables on behalf of the computing sub-team. I also created the Final Gantt Chart to document the project's actual progress vs. the planned progress.

Expectations: Ensured that the team worked on the Project Report in a collaborative manner and that the tean was aware of all expectations

What I learned

Engineering Interviews: I learned how to prepare well for technical interviews and how to answer technical questions on the spot

Project Management: As the administrator for the computing sub-team, I learned how to evenly split up tasks for all sub-team members and keep them all on track to meet deadlines.

Final Thoughts

While my teammates were all very friendly and easy-to-approach, not all of them had up-to-par technical abilities, often leading to me having to take on more responsibilities and initially agreed-upon. There were many bumps along the way, which took a long time to solve because of the lack of communications. I definitely learned that good communications is the key to sucess and I hope everyone learnd that as well.