Upload program object_sorter
This commit is contained in:
parent
384adae17c
commit
5dec438d78
232
Color_Sorting/Program/Object_sorter.py
Normal file
232
Color_Sorting/Program/Object_sorter.py
Normal file
@ -0,0 +1,232 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
from time import sleep
|
||||||
|
from ev3dev2.motor import Motor, MoveTank, SpeedPercent, OUTPUT_A, OUTPUT_B, OUTPUT_C, OUTPUT_D
|
||||||
|
from ev3dev2.sensor import INPUT_2,INPUT_3,INPUT_4
|
||||||
|
from ev3dev2.sensor.lego import ColorSensor, UltrasonicSensor, GyroSensor
|
||||||
|
from ev3dev2.led import Leds
|
||||||
|
from pixycamev3.pixy2 import Pixy2
|
||||||
|
|
||||||
|
class Object_Sorter():
|
||||||
|
# Define type of global variables
|
||||||
|
state: str
|
||||||
|
last_state: str
|
||||||
|
us: UltrasonicSensor
|
||||||
|
cs: ColorSensor
|
||||||
|
gyro: GyroSensor
|
||||||
|
m_left: Motor
|
||||||
|
m_right: Motor
|
||||||
|
tank: MoveTank
|
||||||
|
leds: Leds
|
||||||
|
pixy2: Pixy2
|
||||||
|
params: dict
|
||||||
|
states: dict
|
||||||
|
cylces: int
|
||||||
|
|
||||||
|
# Define all inputs, outputs of the Robot and initialize
|
||||||
|
def __init__(self, **args):
|
||||||
|
# Camera and sensors are inputs
|
||||||
|
self.us = UltrasonicSensor(args.get("ultrasonic_input",INPUT_2))
|
||||||
|
self.cs = ColorSensor(args.get("color_input",INPUT_3))
|
||||||
|
self.gyro = GyroSensor(args.get("gyro_input",INPUT_4))
|
||||||
|
self.pixy2 = Pixy2(port=args.get("camera_port",1), i2c_address=0x54)
|
||||||
|
# Motors are outputs
|
||||||
|
self.m_left = Motor(args.get("leftmotor_output",OUTPUT_A))
|
||||||
|
self.m_right = Motor(args.get("rightmotor_output",OUTPUT_D))
|
||||||
|
# Also define drive tank to move syncronized
|
||||||
|
self.tank = MoveTank(args.get("leftmotor_output",OUTPUT_A), args.get("rightmotor_output",OUTPUT_D))
|
||||||
|
self.leds = Leds()
|
||||||
|
|
||||||
|
# The motor is initialized to run counter-clockwise (gegen den Uhrzeigersinn)
|
||||||
|
# use 'normal' to initialize it to run clockwise (im Uhrzeigersinn)
|
||||||
|
self.m_left.polarity = args.get("leftmotor_polarity",'inversed')
|
||||||
|
self.m_right.polarity = args.get("rightmotor_polarity",'inversed')
|
||||||
|
|
||||||
|
# Read inputs for the given experiment / enviroment
|
||||||
|
params["sig_let"] = args.get("signature_dice_remains",1) # Signatur of orange dice
|
||||||
|
params["sig_sort"] = args.get("signature_dice_sorted",2)# Signatur of green dice
|
||||||
|
params["fast"] = args.get("speed_drive", 30) # driving speed
|
||||||
|
params["slow"] = args.get("speed_search", 10) # searching speed
|
||||||
|
params["dist_us"] = args.get("distance_us",12) # detection range ultrasonic sensor
|
||||||
|
params["line"] = args.get("max_reflection_outline", 10) # max. reflection of outline
|
||||||
|
|
||||||
|
# Safe Parameters for later, can be changed
|
||||||
|
self.params = params
|
||||||
|
|
||||||
|
# initalization state defined
|
||||||
|
self.state = "search" # Initiate search state for beginning
|
||||||
|
self.last_state = "search" # Variable for saving last state
|
||||||
|
self.cycles = 0 # control variable
|
||||||
|
self.gyro.reset() # reset gyro sensor
|
||||||
|
|
||||||
|
self.states = { # dictionary of the states/classes
|
||||||
|
"search": self.search,
|
||||||
|
"get": self.get,
|
||||||
|
"sort": self.sort,
|
||||||
|
"avoid": self.avoid,
|
||||||
|
"edge": self.edge
|
||||||
|
}
|
||||||
|
|
||||||
|
# Define method/state search
|
||||||
|
def search (self):
|
||||||
|
# turn slowly aroud on place and search for blocks,
|
||||||
|
# if nothing is found change searchplace
|
||||||
|
self.leds.set_color("LEFT", "BLACK")
|
||||||
|
self.leds.set_color("RIGHT", "BLACK")
|
||||||
|
# turn on place to the right
|
||||||
|
self.m_right.on(SpeedPercent(-1*self.params["slow"]))
|
||||||
|
self.m_left.on(SpeedPercent(self.params["slow"]))
|
||||||
|
# search for blocks
|
||||||
|
nr_sort, sort_block = self.pixy2.get_blocks(self.params["sig_sort"], 2)
|
||||||
|
nr_let, let_block = self.pixy2.get_blocks(self.params["sig_let"], 2)
|
||||||
|
if self.cs.reflected_light_intensity < self.params["line"]: # if outline is reached change state to edge
|
||||||
|
self.tank.stop()
|
||||||
|
self.last_state = self.state
|
||||||
|
self.state = "edge"
|
||||||
|
elif self.us.distance_centimeters < self.params["dist_us"]: # if a block is currently in the arms change to sort
|
||||||
|
self.last_state = state
|
||||||
|
self.state = "sort"
|
||||||
|
elif nr_sort > 0: # when block to sort is found then change to get
|
||||||
|
self.tank.stop()
|
||||||
|
self.last_state = self.state
|
||||||
|
self.state = "get"
|
||||||
|
elif nr_let > 0: # when block that remains is found then change to avoid
|
||||||
|
self.last_state = self.state
|
||||||
|
self.state = "avoid"
|
||||||
|
elif self.gyro.angle > 720: # when the robot does not find a block drive a little bit forward
|
||||||
|
rounds=0 # rounds of driving forward
|
||||||
|
while self.cs.reflected_light_intensity > self.params["line"] and rounds <= 5:
|
||||||
|
self.tank.on(self.params["fast"],self.params["fast"])
|
||||||
|
sleep(0.2)
|
||||||
|
rounds+=1
|
||||||
|
if self.cs.reflected_light_intensity <= self.params["line"] :
|
||||||
|
self.tank.stop()
|
||||||
|
self.last_state = self.state
|
||||||
|
self.state = "edge"
|
||||||
|
self.gyro.reset()
|
||||||
|
rounds=0 # Reset control variable
|
||||||
|
|
||||||
|
# Define method/state get
|
||||||
|
def get (self):
|
||||||
|
# drive twoards block and get it into arms
|
||||||
|
self.leds.set_color("LEFT", "GREEN")
|
||||||
|
self.leds.set_color("RIGHT", "BLACK")
|
||||||
|
# drive straight ahead
|
||||||
|
self.tank.on(self.params["fast"],self.params["fast"])
|
||||||
|
# find the block for sorting again
|
||||||
|
nr_sort, sort_block = self.pixy2.get_blocks(self.params["sig_sort"], 2)
|
||||||
|
if nr_sort > 0: # if block is found again get position
|
||||||
|
x = sort_block[0].x_center #get where in the field of vision the block lays
|
||||||
|
self.cylces = 0
|
||||||
|
else: # when block is not found, virtually place the robot in the middle of the vision
|
||||||
|
x = 130
|
||||||
|
self.cylces +=1
|
||||||
|
if 4 <= self.cylces < 6: # camera has not found block for 4 cycles
|
||||||
|
self.tank.on_for_seconds(-1*self.params["fast"],-1*self.params["fast"],0.4) # drive backwards max. 2 times
|
||||||
|
elif 6 == self.cylces: # if block is not found drive a little bit to left
|
||||||
|
self.m_right.on(SpeedPercent(self.params["slow"]))
|
||||||
|
self.m_left.on(SpeedPercent(-1*self.params["slow"]))
|
||||||
|
sleep(0.2)
|
||||||
|
elif self.cylces > 6: # when block is still not found go back to search
|
||||||
|
self.cylces = 0
|
||||||
|
self.state = "search"
|
||||||
|
self.gyro.reset()
|
||||||
|
# Decide what robot should do with the gathered information
|
||||||
|
if self.us.distance_centimeters <= self.params["dist_us"]: # block is in the arms of robot change to sort
|
||||||
|
self.last_state = self.state
|
||||||
|
self.state = "sort" # when block distance is small switch state
|
||||||
|
else: # correct drive direction to get block into arms
|
||||||
|
# when block on left side drive more left
|
||||||
|
if x < 110: # turn left
|
||||||
|
self.m_right.on(SpeedPercent(self.params["slow"]))
|
||||||
|
self.m_left.on(SpeedPercent(-1*self.params["slow"]))
|
||||||
|
# when block on right side drive more right
|
||||||
|
elif x > 150: # turn right
|
||||||
|
self.m_right.on(SpeedPercent(-1*self.params["slow"]))
|
||||||
|
self.m_left.on(SpeedPercent(self.params["slow"]))
|
||||||
|
if self.cs.reflected_light_intensity < self.params["line"]: # robot detected line change to edge
|
||||||
|
self.tank.stop()
|
||||||
|
self.last_state = self.state
|
||||||
|
self.state = "edge" # When colorsensor detects line then switch state
|
||||||
|
|
||||||
|
# Define method/state sort
|
||||||
|
def sort (self):
|
||||||
|
# block is caught, drive to the edge
|
||||||
|
self.leds.set_color("LEFT", "GREEN")
|
||||||
|
self.leds.set_color("RIGHT", "GREEN")
|
||||||
|
# drive straight ahead
|
||||||
|
self.tank.on(self.params["fast"],self.params["fast"])
|
||||||
|
# search for block to let be in area
|
||||||
|
nr_let, let_block = self.pixy2.get_blocks(sig_let, 2)
|
||||||
|
if self.cs.reflected_light_intensity < self.params["line"]: # when reached line change to edge
|
||||||
|
self.tank.stop()
|
||||||
|
self.last_state = self.state
|
||||||
|
self.state = "edge"
|
||||||
|
elif nr_let > 0:
|
||||||
|
self.last_state = self.state
|
||||||
|
self.state = "avoid"
|
||||||
|
|
||||||
|
# Define method/state avoid
|
||||||
|
def avoid (self):
|
||||||
|
# found green block, do not want to kick it out
|
||||||
|
self.leds.set_color("LEFT", "ORANGE")
|
||||||
|
self.leds.set_color("RIGHT", "ORANGE")
|
||||||
|
# search for green block again
|
||||||
|
nr_let, let_block = self.pixy2.get_blocks(sig_let, 2)
|
||||||
|
if nr_let > 0: # if block is found again get position
|
||||||
|
x = let_block[0].x_center # get where in the field of vision the block lays
|
||||||
|
else: # when block is not found, virtually place the robot in the middle of the vision
|
||||||
|
x = 130
|
||||||
|
# When block lays in middle of the vision drive around it
|
||||||
|
if 100 < x < 150:
|
||||||
|
self.m_right.on(SpeedPercent(-1*self.params["fast"]))
|
||||||
|
self.m_left.on(SpeedPercent(self.params["fast"]))
|
||||||
|
sleep(0.2)
|
||||||
|
self.state = self.last_state
|
||||||
|
self.last_state = "avoid"
|
||||||
|
|
||||||
|
# Define method/state edge
|
||||||
|
def edge (self):
|
||||||
|
# robot reached outerline and should turn around
|
||||||
|
self.leds.set_color("LEFT", "BLACK")
|
||||||
|
self.leds.set_color("RIGHT", "RED")
|
||||||
|
self.gyro.reset() # reset gyro sensor
|
||||||
|
# drive straight backwards
|
||||||
|
self.tank.on_for_rotations(-1*self.params["fast"],-1*self.params["fast"],2)
|
||||||
|
while self.gyro.angle < 100: #turn around for 100 degrees
|
||||||
|
self.m_right.on(SpeedPercent(-1*self.params["fast"]))
|
||||||
|
self.m_left.on(SpeedPercent(self.params["fast"]))
|
||||||
|
self.state = "search"
|
||||||
|
self.gyro.reset() # reset gyro sensor again
|
||||||
|
|
||||||
|
def get_params(self):
|
||||||
|
return self.params
|
||||||
|
|
||||||
|
def run(self):
|
||||||
|
print('start')
|
||||||
|
while True: # endless-loop for switching states
|
||||||
|
func = self.states.get(self.state) # function that gets state
|
||||||
|
func() # activate current state
|
||||||
|
sleep(0.3) # wait for 0.3 seconds between the different states
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
# All arguments that can be changed are given here
|
||||||
|
arguments = dict(
|
||||||
|
#ultrasonic_input = INPUT_2,
|
||||||
|
#color_input = INPUT_3,
|
||||||
|
#gyro_input = INPUT_4,
|
||||||
|
#camera_port = 1,
|
||||||
|
#leftmotor_output = OUTPUT_A,
|
||||||
|
#rightmotor_output = OUTPUT_D,
|
||||||
|
#signature_dice_remains = 1,
|
||||||
|
#signature_dice_sorted = 2,
|
||||||
|
#speed_drive = 30,
|
||||||
|
#speed_search = 10,
|
||||||
|
#distance_us =10,
|
||||||
|
max_reflection_outline = 10
|
||||||
|
|
||||||
|
)
|
||||||
|
|
||||||
|
os = Object_Sorter(arguments)
|
||||||
|
os.run()
|
||||||
|
|
Loading…
Reference in New Issue
Block a user