The primary function of the mechanism was to safely and efficiently collect and deposit containers when needed. We had to design our mechanism with a set of constraints prescribed to this project: the full mechanism must weigh less than 90 grams, must be attached in 2 locations to the base plate, it must have input connections within 127 mm and 97.71 mm rectangle and have output connections on the pivot legs. Keeping these constraints in mind we maximized the attributes of our design coinciding with the objectives of our mechanism. The objectives for our mechanism consisted of the mechanism being easy to use and assemble, lightweight, durable for repeated use, cost effective, fast & efficient, simple yet creative and be material efficient. Our mechanism consists of a rack and pinion design. The pinion is driven by the rotary actuator, and the rack is a ¼ circular gear design which when driven tilts the hopper into a deposit position and returns similarly.

Untitled

Untitled

Untitled

Untitled

           Our computer program had two main tasks including dispensing a random container and loading it to the Q-bot as well as using the Q-bot to transfer the container to its respective destination. To tackle each of the two mentioned tasks, we broke our code into 6 main functions, this also decreased the probability of getting errors and made the code easier to read and troubleshoot. These 6 functions include a dispense function for dispensing a random container, a load container function which would load the dispensed container onto the Q-bot to help us achieve the first task, for the second task we created a follow line function, which uses the IR sensors present in the Q-bot to follow the yellow line, a reached bin function which would help us determine if we have reached the destination bin of our container, a deposit container function that activates the actuators on the Q-bot to deposit the containers to the bin, and lastly a return home function which would allow the Q-bot to return to its home position. As mentioned, by breaking down our code into distinct functions we were able to design a program that if was ever publicly used, can be easily updated, upgraded, and modified in the future by people who might have never seen the code before.
import sys
sys.path.append('../')
from Common.project_library import *

# Modify the information below according to you setup and uncomment the entire section

# 1. Interface Configuration
project_identifier = 'P3B' # enter a string corresponding to P0, P2A, P2A, P3A, or P3B
ip_address = '169.254.174.112' # enter your computer's IP address
hardware = False # True when working with hardware. False when working in the simulation

# 2. Servo Table configuration
short_tower_angle = 315 # enter the value in degrees for the identification tower 
tall_tower_angle = 90 # enter the value in degrees for the classification tower
drop_tube_angle = 180#270# enter the value in degrees for the drop tube. clockwise rotation from zero degrees

# 3. Qbot Configuration
bot_camera_angle = 0 # angle in degrees between -21.5 and 0

# 4. Bin Configuration
# Configuration for the colors for the bins and the lines leading to those bins.
# Note: The line leading up to the bin will be the same color as the bin 

bin1_offset = 0.17 # offset in meters
bin1_color = [1,0,0] # e.g. [1,0,0] for red
bin2_offset = 0.17
bin2_color = [0,1,0]
bin3_offset = 0.17
bin3_color = [0,0,1]
bin4_offset = 0.17
bin4_color = [1,0,1]

#--------------- DO NOT modify the information below -----------------------------

if project_identifier == 'P0':
    QLabs = configure_environment(project_identifier, ip_address, hardware).QLabs
    bot = qbot(0.1,ip_address,QLabs,None,hardware)
    
elif project_identifier in ["P2A","P2B"]:
    QLabs = configure_environment(project_identifier, ip_address, hardware).QLabs
    arm = qarm(project_identifier,ip_address,QLabs,hardware)

elif project_identifier == 'P3A':
    table_configuration = [short_tower_angle,tall_tower_angle,drop_tube_angle]
    configuration_information = [table_configuration,None, None] # Configuring just the table
    QLabs = configure_environment(project_identifier, ip_address, hardware,configuration_information).QLabs
    table = servo_table(ip_address,QLabs,table_configuration,hardware)
    arm = qarm(project_identifier,ip_address,QLabs,hardware)
    
elif project_identifier == 'P3B':
    table_configuration = [short_tower_angle,tall_tower_angle,drop_tube_angle]
    qbot_configuration = [bot_camera_angle]
    bin_configuration = [[bin1_offset,bin2_offset,bin3_offset,bin4_offset],[bin1_color,bin2_color,bin3_color,bin4_color]]
    configuration_information = [table_configuration,qbot_configuration, bin_configuration]
    QLabs = configure_environment(project_identifier, ip_address, hardware,configuration_information).QLabs
    table = servo_table(ip_address,QLabs,table_configuration,hardware)
    arm = qarm(project_identifier,ip_address,QLabs,hardware)
    bins = bins(bin_configuration)
    bot = qbot(0.1,ip_address,QLabs,bins,hardware)
    

#---------------------------------------------------------------------------------
# MAIN CODE BEGINS
#---------------------------------------------------------------------------------

# Here the IR and COlOR sensor are activated 
bot.activate_ir_sensor()
bot.activate_color_sensor()

# This function loads the containers to the Qbot by getting the properties of each container as input
def load_container(container_properties):
    # Here we set the initial mass and number of containers loaded to 0
    total_mass = 0 
    total_containers = 0
    # here the current container properties is set to the input recieved from the load_container function and the destination bin is set to the destination
    # of the deposit bin
    current_container_properties = container_properties
    destination_bin = current_container_properties[2]

    # This while loop will make sure that we will only keep loading more containers to the Qbot if the total
    # loaded mass is less than 90g and the total number of loaded containers is less than 3
    while total_mass < 90 and total_containers < 3:
        
        if destination_bin == "Bin01" :  # This if statement is to check wether our container is a metal can or not
                                         # since the metal can has a smaller size so the pickup coordinates must be different
                                         

            # The following lines of code are the coordinates of the metal can for the arm to grab 
            arm.move_arm(0.633, 0.0, 0.27)
            time.sleep(1)                   # the sleep functions stops the program for 1 second so the movement can be more stable
            arm.control_gripper(45)
            time.sleep(1)
            arm.move_arm(0.597, -0.217, 0.5)
            time.sleep(1)
            arm.move_arm(0.015, -0.414, 0.55)
            time.sleep(1)
            arm.move_arm(0.015, -0.500, 0.55)
            arm.rotate_elbow(10)
            time.sleep(1)
            arm.control_gripper(-20)
            time.sleep(1)
            arm.move_arm(0.018, -0.500, 0.54)
            time.sleep(1)
            arm.move_arm(0.011, -0.303, 0.783)
            time.sleep(2)
            arm.home() # The arm.home method moves the arm to it's home position

                
        else:       # The else statement is when our container is made from plastic or paper and has a higher
                    # hight which requires a different pickup location than the metal cans

            # The following lines of code are the coordinates of paper or plastic container for the arm to grab 
            arm.move_arm(0.633, 0.0, 0.364)
            time.sleep(1)
            arm.control_gripper(45)
            time.sleep(1)                   # the sleep functions stops the program for 1 second so the movement can be more stable
            arm.move_arm(0.597, -0.217, 0.399)
            time.sleep(1)
            arm.move_arm(0.015, -0.414, 0.68)
            arm.move_arm(0.015, -0.414, 0.63)
            time.sleep(1)
            arm.control_gripper(-20)
            arm.move_arm(0.018, -0.500, 0.54)
            time.sleep(1)
            arm.move_arm(0.011, -0.303, 0.783)
            time.sleep(2)
            arm.home() # The arm.home method moves the arm to it's home position

        # Here we add the mass of the container that was just loaded to the total mass of containers that are loaded
        # and the number of total containers is incremented by 1
        total_mass += container_properties[1]
        total_containers += 1
        # Here a new container is dispensed using the dispense_container function and the value of current container properties is
        # updated with the properties of the new dispensed container, this is followed by updating the destination bin variable with the destination of the new bin
        current_container_properties = dispense_container()
        current_destination_bin = current_container_properties[2]

        # Here we check if the destination bin of the new dispensed container is the same as the destination bin of the previouse container 
        if current_destination_bin == destination_bin:
            continue # if they are the same, the loop will run again
        else:
            break # if not the loop will stop
        
    return current_container_properties # lastly the function returns the properties of the last container that was dispensed

# This function makes the Qbot follow the yellow tape on the ground using the IR sensor
def follow_line():
    
    if bot.line_following_sensors() == [1, 1]:  # If both the left and right IR sensors detect the tape, the qbot will move forward
        bot.set_wheel_speed([0.07, 0.07])
        time.sleep(0.01)
    elif bot.line_following_sensors() == [1, 0]:# If only the left IR sensor is detecting the tape, the left wheel will spin faster resulting the in qbot turning to the right
        bot.set_wheel_speed([0.06, 0.095])
        time.sleep(0.01)
    elif bot.line_following_sensors() == [0, 1]:# If only the right IR sensor is detecting the tape, the right wheel will spin faster resulting the in qbot turning to the left
        bot.set_wheel_speed([0.09, 0.06])
        time.sleep(0.01)

# This function uses the color sensor and the qbots position to check if the qbot has reached the correct destination bin
def reached_bin(destination_bin):
    
    if destination_bin == "Bin01": 
        return bot.read_color_sensor()[0] == [1, 0, 0] and bot.position()[0] < 1.03 # if the destination is the red bin and the bot reached the red bin True will be returned
    elif destination_bin == "Bin02":
        return bot.read_color_sensor()[0] == [0, 1, 0] and bot.position()[0] < 0    # if the destination is the green bin and the bot reached the green bin True will be returned
    elif destination_bin == "Bin03":
        return bot.read_color_sensor()[0] == [0, 0, 1] and bot.position()[0] > 0    # if the destination is the blue bin and the bot reached the blue bin True will be returned
    elif destination_bin == "Bin04":
        return bot.read_color_sensor()[0] == [1, 0, 1] and bot.position()[0] > 1.03 # if the destination is the pink bin and the bot reached the pink bin True will be returned

# This function will transfer the container by having the destination bin as input
def transfer_container(destination_bin):
    while True:
        follow_line() # the qbot will follow the line 
        if reached_bin(destination_bin):# if it reaches its destination bin the function completely stops and the bot stops moving
            bot.stop()
            return        

# This function will deposit the container by using the built-in dump method
def deposit_container():
    bot.activate_linear_actuator()
    time.sleep(1)
    bot.dump()
    time.sleep(1)
    bot.deactivate_linear_actuator()
    time.sleep(1)

# This function will return the qbot to the home position 
def return_home():
    while bot.position()[0] < 1.4 or bot.position()[1] < 0: # the bot will follow the line until it reaches the specific coordinates of the home position 
        follow_line()
    bot.stop()

# The dispense container will dispense a random container and return its properties 
def dispense_container():
    container_ID = random.randint(1,6) # container id is set to a random number from 1 to 6 
    container_properties = table.dispense_container(container_ID, True)
    return container_properties

# The main function will run the program "iteration" many times where iteration is a number specified by the user 
def main(iterations):

    # The program will start by dispensing the first container and setting its properties to container properties
    container_properties = dispense_container()
    
    for i in range(iterations):
        # here destination bin is set to the destination of the last dispensed container
        destination_bin = container_properties[2]
        container_properties = load_container(container_properties) # here the last dispensed container will be loaded to the qbot
        transfer_container(destination_bin) # after the qbot is loaded to its maximum capacity, the qbot will move to the respectible bin
        deposit_container() # the qbot deposits the container into the bin
        return_home() # lastly the qbot returns home and the loop runs again
    

main(20)
         The final mechanism and the computer program can work together allowing for an effective sorting and recycling process. This design has the potential to be used within different recycling facilities to provide a good sorting system for containers and be efficient.