def test_left_key_returns_none(self): num_elements = 3 contents = [["A" + str(i), "a" + str(i)] for i in range(num_elements)] cb = Checkbox(contents, get_mock_input(), get_mock_output(), name=cb_name) cb.refresh = lambda *args, **kwargs: None #Checking at the start of the list def scenario(): cb.deactivate() #KEY_LEFT assert not cb.in_foreground with patch.object(cb, 'idle_loop', side_effect=scenario) as p: return_value = cb.activate() assert return_value is None #Checking at the end of the list def scenario(): for i in range(num_elements): cb.move_down() #KEY_DOWN x3 cb.deactivate() #KEY_LEFT assert not cb.in_foreground with patch.object(cb, 'idle_loop', side_effect=scenario) as p: return_value = cb.activate() assert return_value is None
def test_enter_on_last_returns_right(self): num_elements = 3 contents = [["A" + str(i), "a" + str(i)] for i in range(num_elements)] cb = Checkbox(contents, get_mock_input(), get_mock_output(), name=cb_name) cb.refresh = lambda *args, **kwargs: None #Checking at other elements - shouldn't return def scenario(): cb.select_entry() #KEY_ENTER assert cb.in_foreground #Should still be active cb.deactivate( ) #because is not deactivated yet and would idle loop otherwise with patch.object(cb, 'idle_loop', side_effect=scenario) as p: return_value = cb.activate() assert return_value is None #Scrolling to the end of the list and pressing Enter - should return a correct dict def scenario(): for i in range(num_elements): cb.move_down() #KEY_DOWN x3 cb.select_entry() #KEY_ENTER assert not cb.in_foreground with patch.object(cb, 'idle_loop', side_effect=scenario) as p: return_value = cb.activate() assert isinstance(return_value, dict) assert all( [isinstance(key, basestring) for key in return_value.keys()]) assert all( [isinstance(value, bool) for value in return_value.values()])
def test_constructor(self): """tests constructor""" checkbox = Checkbox([["Option", "option"]], get_mock_input(), get_mock_output(), name=cb_name) self.assertIsNotNone(checkbox)
def design(self): panel_1 = Panel(position_constraint("relative", .2), position_constraint("centered"), size_constraint("relative", .7), size_constraint("relative", .7), "Main", max_w=50, title="Main") self.add_element(panel_1) panel_2 = Panel(position_constraint("absolute", 0), position_constraint("relative", .05), size_constraint("relative", .45), size_constraint("relative", .45), "RadioPan", max_w=40, title="Radio Buttons") panel_1.add_child(panel_2) radio_1 = RadioButton(position_constraint("absolute", 1), position_constraint("absolute", 0), "rad1", "Radio 1") panel_2.add_child(radio_1) radio_2 = RadioButton(position_constraint("absolute", 3), position_constraint("absolute", 0), "rad2", "Radio 2") panel_2.add_child(radio_2) panel_3 = Panel(position_constraint("absolute", 0), position_constraint("relative", .5), size_constraint("relative", .45), size_constraint("relative", .45), "Check Pan", max_w=40, title="Check Boxes") panel_1.add_child(panel_3) check_1 = Checkbox(position_constraint("absolute", 1), position_constraint("absolute", 0), "chk1", "Check 1") panel_3.add_child(check_1) check_2 = Checkbox(position_constraint("absolute", 3), position_constraint("absolute", 0), "chk2", "Check 2") panel_3.add_child(check_2)
def test_exit_label_leakage(self): """tests whether the exit label of one Checkbox leaks into another""" i = get_mock_input() o = get_mock_output() c1 = Checkbox([["a", "1"]], i, o, name=cb_name + "1", final_button_name="Name1") c2 = Checkbox([["b", "2"]], i, o, name=cb_name + "2", final_button_name="Name2") c3 = Checkbox([["c", "3"]], i, o, name=cb_name + "3") assert (c1.exit_entry != c2.exit_entry) assert (c2.exit_entry != c3.exit_entry) assert (c1.exit_entry != c3.exit_entry)
def test_keymap(self): """tests keymap""" checkbox = Checkbox([["Option", "option"]], get_mock_input(), get_mock_output(), name=cb_name) self.assertIsNotNone(checkbox.keymap) for key_name, callback in checkbox.keymap.iteritems(): self.assertIsNotNone(callback)
def generate_checkbox(self): posx = self.posx + self.s_left + self.items_sizex + self.s_between return Checkbox(posx, self.items_pos_y, self.items_sizex, self.items_sizey, text="Auto-scroll", color=(120, 50, 40), font_size=self.font_size)
def __init__(self): self.running = True self.numLoops = 300 # the number of times to loop around the circle self.step = 0.05 # take little steps self.spinAngle = 0.0 self.controls: Dict[str, Control] = { "lblNumerator": Label((10, 14), "Numerator:"), "Numerator": Slider((150, 20), 1, 10, 4.3, 0.1), "lblDenominator": Label((10, 44), "Denominator:"), "Denominator": Slider((150, 50), 1, 10, 7.6, 0.1), "lblSpinning": Label((10, 80), "Spin?"), "Spinning": Checkbox((150, 80), True), "lblSpeed": Label((10, 104), "Spin speed:"), "Speed": Slider((150, 110), 1, 50, 3, 1), "lblScale": Label((10, 144), "Scale:"), "Scale": Slider((150, 150), 50, 380, 200, 10), "Color": Button((150, 200), "Change Color", Program.ChangeColor), }
def __init__(self): pygame.init() pygame.display.set_caption("GridSim") self.current_dir = os.path.dirname(os.path.abspath(__file__)) self.screen_width = config.screen_width self.screen_height = config.screen_height self.screen = pygame.display.set_mode((self.screen_width, self.screen_height)) self.screen.fill([255, 255, 255]) self.exit = False self.manual_driving_button = Button("manual driving", (500, 150), (350, 50), config.inactive_color, config.active_color) self.ga_button = Button("neuro-evolutionary", (500, 200), (350, 50), config.inactive_color, config.active_color) self.ga_train_button = Button("→ train", (500, 250), (350, 50), config.inactive_color, config.active_color) self.ga_predict_button = Button("→ predict", (500, 300), (350, 50), config.inactive_color, config.active_color) self.drl_button = Button("deep reinf. learning", (500, 250), (350, 50), config.inactive_color, config.active_color) # DQN self.drl_train_button = Button("→ train", (500, 300), (350, 50), config.inactive_color, config.active_color) self.drl_predict_button = Button("→ predict", (500, 350), (350, 50), config.inactive_color, config.active_color) self.record_button = Button("record data", (500, 300), (350, 50), config.inactive_color, config.active_color) self.replay_button = Button("replay", (500, 350), (350, 50), config.inactive_color, config.active_color) self.back_button = Button("back", (500, 400), (350, 50), config.inactive_color, (200, 0, 0)) self.exit_button = Button("exit", (500, 450), (350, 50), config.inactive_color, (200, 0, 0)) self.activation_cbox = Checkbox(1000, 50, "Print activations", True) self.sensors_cbox = Checkbox(1000, 70, "Enable visual sensors", True) self.distance_sensor_cbox = Checkbox(1000, 90, "Enable distance sensor", False) self.traffic_cbox = Checkbox(1000, 110, "Enable traffic", True) self.ga_buttons_interactions = False self.drl_buttons_interactions = False self.background_vid = cv2.VideoCapture("resources/backgrounds/zoomed-background-video.mp4") if self.background_vid.isOpened() is False: raise OSError("Error opening video stream or file") self.current_background_frame = None self.pause_background_video = False pygame.display.update()
def create_checkbox_lambda( *, manager=None, register=True, id=None, x=0, y=0 ): """ Create the checkbox at given x, y. If register then register to manager with either passed id or generated. """ if (id is None): id = "checkbox_" + str(random.randint(0, sys.maxsize)) checkbox = Checkbox( manager.get_image_info(), enabled_rect=Rect(16, 0, 16, 16), disabled_rect=Rect(0, 0, 16, 16), x=x, y=y ) if (manager is not None and register): manager.register_widget(id, checkbox) return (id, checkbox)
def run(self): # place car on road car = Car(5, 27) # initialize traffic self.init_traffic_cars() # sensor checkboxes on top right corner cbox_front_sensor = Checkbox(self.screen_width - 200, 10, 'Enable front sensor', True) cbox_rear_sensor = Checkbox(self.screen_width - 200, 35, 'Enable rear sensor', True) # reset position list -> to be updated rs_pos_list = [[650, 258, 90.0], [650, 258, 270.0], [0, 0, 180.0], [0, 0, 0.0], [302, 200, 45.0], [40, 997, 0.0], [40, 997, 180.0], [100, 997, 0.0], [100, 997, 180.0], [400, 998, 0.0], [400, 998, 180.0], [385, 315, 135.0]] # boolean variable needed to check for single-click press mouse_button_pressed = False # initialize object mask object_mask = pygame.Surface((self.screen_width, self.screen_height)) if self.record_data is True: index_image = 0 while not self.exit: # VARIABLE_UPDATE if self.traffic is True: collision_list = [False] * len(self.traffic_list) dt = self.clock.get_time() / 1000 self.event_handler(cbox_front_sensor, cbox_rear_sensor, mouse_button_pressed) # LOGIC self.key_handler(car, dt, rs_pos_list) car.acceleration = max(-car.max_acceleration, min(car.acceleration, car.max_acceleration)) car.steering = max(-car.max_steering, min(car.steering, car.max_steering)) # DRAWING stagePos = self.draw_sim_environment(car, object_mask, cbox_front_sensor, cbox_rear_sensor, print_coords=True) relPos = (stagePos[2], stagePos[3]) stagePos = (stagePos[0], stagePos[1]) # UPDATE # ------------------------ traffic car ----------------------------------------------- if self.traffic is True: self.check_collisions(collision_list) self.traffic_movement(collision_list, object_mask, stagePos) # ------------------------------------------------------------------------------------------- car.update(dt) act_mask = pygame.Surface((self.screen_width, self.screen_height)) if cbox_front_sensor.isChecked(): self.optimized_front_sensor(car, object_mask, act_mask, display_obstacle_on_sensor=True) if cbox_rear_sensor.isChecked(): self.optimized_rear_sensor(car, object_mask, act_mask, display_obstacle_on_sensor=True) if self.record_data is True: image_name = 'image_' + str(index_image) + '.png' print(index_image) index_image += 1 if self.record_data is True: # RECORD TAB # Save replay # Write reference trajectory write_data( os.path.join(os.path.dirname(__file__), "recorded_data", "reference.csv"), car.position, car.angle) write_data( os.path.join(os.path.dirname(__file__), "recorded_data", "obstacles.csv"), self.traffic_obstacle_points) # reset obstacle point list self.traffic_obstacle_points = list() pygame.display.update() self.clock.tick(self.ticks) pygame.quit()
def run(self, record_data_path=None, replay_data_path=None, save_image=False, save_minimap=False, minimap_name=None): """ :param record_data_path: only path, replay.txt and state.txt generated automatically :param replay_data_path: replay path, replay and state are found automatically :param save_image: if you want in replay to save the display :param save_minimap: if you want to save the minimap :param minimap_name: name of the minimap you want to save :return: """ if record_data_path is not None: if os.path.exists(record_data_path) is False: raise OSError(record_data_path + ' does not exists.') if replay_data_path is not None: if os.path.exists(replay_data_path) is False: raise OSError(replay_data_path + ' does not exists.') else: car_replay_coords = read_replay_coords(replay_data_path + '/replay_data.txt') index_replay = 0 replay = True else: replay = False if self.show_activ is True or save_image is True: cbox_front_sensor = Checkbox(self.screen_width - 200, 10, 'Enable front sensor', True) cbox_rear_sensor = Checkbox(self.screen_width - 200, 35, 'Enable rear sensor', True) else: cbox_front_sensor = Checkbox(self.screen_width - 200, 10, 'Enable front sensor', False) cbox_rear_sensor = Checkbox(self.screen_width - 200, 35, 'Enable rear sensor', False) mouse_button_pressed = False # to be updated rs_pos_list = [] sensor_mask = pygame.Surface((self.screen_width, self.screen_height)) if self.show_activ is True: layer_names, image_buf, state_buf, activation_model = self.initialize_activation_model( 'convolution0') index_image = 0 while not self.exit: dt = self.clock.get_time() / 1000 self.event_handler(cbox_front_sensor, cbox_rear_sensor, mouse_button_pressed) if replay is True: if index_replay > len(car_replay_coords) - 1: break self.car.position.x = car_replay_coords[index_replay][0] self.car.position.y = car_replay_coords[index_replay][1] self.car.angle = car_replay_coords[index_replay][2] index_replay += 1 else: action = self.key_handler(dt, rs_pos_list) self.action_handler(dt) sensor_mask.fill((0, 0, 0)) self.draw_sim_environment(sensor_mask, cbox_front_sensor, cbox_rear_sensor, save_minimap=save_minimap, minimap_name=minimap_name) self.car.update(dt) if replay is True and save_image is True: image_name = 'image_' + str(index_replay) + '.png' save_frame(self.screen, image_name, replay_data_path + '/images') if self.show_activ is True: self.show_activations(layer_names, image_buf, state_buf, activation_model, sensor_mask) if record_data_path is not None: image_name = 'image_' + str(index_image) + '.png' index_image += 1 actions = [ self.car.position.x, self.car.position.y, float(round(self.car.angle, 3)), float(round(self.car.acceleration, 3)), float(round(self.car.velocity.x, 3)), action, image_name ] write_replay_data(record_data_path + '/replay_data.txt', self.car.position, self.car.angle) write_state_buf(record_data_path + '/state_buf.txt', actions) pygame.display.update() self.clock.tick(self.ticks) pygame.quit()
def __init__( self, screen, screen_width, screen_height, car_x=5, car_y=27, sensor_size=50, rays_nr=8, activations=False, record_data=False, replay_data_path=None, state_buf_path=None, sensors=False, distance_sensor=False, enabled_menu=False, # relative paths to the current folder object_map_path=None, background_path=None, car_image_path=None, traffic_car_image_path=None, object_car_image_path=None): pygame.init() self.screen_width = screen_width self.screen_height = screen_height self.screen = screen # The color of the object mask # Yellow self.bkd_color = [255, 255, 0, 255] self.current_dir = os.path.dirname(os.path.abspath(__file__)) self.car = Car(car_x, car_y) if car_image_path is not None: self.car_image_path = os.path.join(self.current_dir, car_image_path) self.car_image = pygame.image.load( self.car_image_path).convert_alpha() else: self.car_image = None if traffic_car_image_path is not None: self.traffic_image_path = os.path.join(self.current_dir, traffic_car_image_path) self.traffic_car_image = pygame.image.load( self.traffic_image_path).convert_alpha() else: self.traffic_car_image = None if object_car_image_path is not None: self.object_car_image_path = os.path.join(self.current_dir, object_car_image_path) self.object_car_image = pygame.image.load( self.object_car_image_path).convert_alpha() else: self.object_car_image = None if object_map_path is not None: self.object_map_path = os.path.join(self.current_dir, object_map_path) self.object_map = pygame.image.load( self.object_map_path).convert_alpha() else: self.object_map = None self.print_activations = activations self.model_path = os.path.join(self.current_dir, 'used_models/activations_model.h5') if os.path.exists(self.model_path) is False: raise OSError("model to path doesn't exists") self.background_path = os.path.join(self.current_dir, background_path) self.background = pygame.image.load(self.background_path).convert() self.bgWidth, self.bgHeight = self.background.get_rect().size pygame.font.init() self.used_font = pygame.font.SysFont('Comic Sans MS', 30) self.input_image = pygame.surfarray.array3d(self.screen) self.sensors = sensors self.distance_sensor = distance_sensor self.sensor_size = sensor_size self.rays_nr = rays_nr self.rays_sensor_distances = None self.sensor_mask = pygame.Surface( (self.screen_width, self.screen_height)) self.object_mask = pygame.Surface( (self.screen_width, self.screen_height)) self.record_data = record_data self.enabled_menu = enabled_menu self.replay_data_path = replay_data_path self.state_buf_path = state_buf_path self.ppu = 16 self.exit = False self.clock = pygame.time.Clock() self.ticks = 60 self.dt = None self.cbox_front_sensor = Checkbox(self.screen_width - 200, 10, 'Enable front sensor', self.sensors) self.cbox_rear_sensor = Checkbox(self.screen_width - 200, 35, 'Enable rear sensor', self.sensors) self.cbox_distance_sensor = Checkbox(self.screen_width - 200, 60, 'Enable distance sensor', self.distance_sensor)
# ############################################################ import sys sys.path.append("libs") import http.server import urllib.parse, json from myglobals import MyGlobals from checkbox import Checkbox from scatter import Scatter from radio import Radio from chart import Chart from excel import Excel from table import Table checkbox = Checkbox() scatter = Scatter() radio = Radio() chart = Chart() xl = Excel() table = Table() class Handler(http.server.BaseHTTPRequestHandler): def do_POST(self): jsonResponse = self.rfile.read(int(self.headers['Content-Length'])) self.send_response(200) self.end_headers() jsonAsString = jsonResponse.decode("UTF-8")
def main(): pygame.init() screen = pygame.display.set_mode((640, 480),pygame.SWSURFACE) pygame.key.set_repeat(100, 100) '''TEST''' g=Gui() #g.enableDirtyRect() g.optimizeDraw() i=PygameInput() Image.mImageLoader=PygameImageLoader() gr=PygameGraphics() gr.setTarget(screen) f=ImageFont("C:\Python25\Projects\Guichan\consolefont.bmp") #f=ImageFont("consolefont.bmp") f.setColorkey( Color(255,0,255) ) f.setGlyphSpacing(2) f2=PygameFont("C:\Python25\Projects\Guichan\LiberationMono-Regular.ttf",14,Color(0,0,0,255)) #f2=PygameFont("C:\Python25\Projects\Guichan\Caracteres L1.ttf",13,Color(0,0,0,255)) f2.setGlyphSpacing(1) Widget.setGlobalFont(f2) c=Container() c.setOpaque(False) c.setPosition(0,0) c.setSize(640,480) c.setBaseColor( Color(255,0,0,255) ) a=ActionListener() a.action=action b, b2=Button("YEY!"), Button("WHa?") b.setPosition(0,50) b.setActionEventId("Button 1") b.addActionListener(a) b2.setPosition(100,100) b2.setActionEventId("Button 2") b2.addActionListener(a) b2.setBaseColor( Color(200,200,200) ) b2.setCaption("ABCDEFGHIJKLMNOPQRSTUVWXYZ!@#$%^&*()") w,w2=Window("Hey over here!"), Window("Trapped in a window!") wColor=w.getBaseColor() wColor.a=200 w.setBaseColor(wColor) w.setTextColor(Color(255,0,255)) xyz=Button("XYZ") xyz.setTextColor(Color(0,255,255)) pb=ProgressBar(100.0) pb.setBaseColor( Color(255,255,0) ) pb.setForegroundColor( Color(0,255,255) ) pb.setSize(100, 20) pb.setPosition(300, 300) pb.setValue(50.0) c.add(w,0,100) c.add(b) c.add(b2) c.add(xyz,10,10) c.add(pb) check=Checkbox("Ye what? GET BACK HERE BOY!") check.setActionEventId("Checkbox") check.addActionListener(a) text=TextField("Hey Hey Hey Hey Hey Hey Hey Hey") text.setBackgroundColor( Color(255,255,255,255) ) text.setMaxSize(150) text2=TextBox("Hey, HeyTrapped in a window!\nWhat's goin' onTrapped in a window!\ntodays???Trapped in a window!") text2.setTabSize(10) sc=ScrollArea(text2) sc.setSize(200,100) rBox=Container() r1=RadioButton("1984","Dystopia") r2=RadioButton("Fahrenheit 451","Dystopia") r3=RadioButton("Brave New World","Dystopia") rBox.add(r1,0,0) rBox.add(r2,0,r1.getY()+r1.getHeight()) rBox.add(r3,0,r2.getY()+r2.getHeight()) label=Label("WE AIN'T GOT IT") ico_image=Image.load("C:\Python25\Projects\Guichan\May.bmp") ico=Icon(ico_image) lb=ListBox( List_ListModel(["Bollocks!","Never!","Cuppa tea, mate?","Hello!","Goodbye!","OK Computer!","Oh Inverted World!","How To Disappear Completely!","Hold Still!","It Takes A Train To Cry!","A","B","C","D","E","F","G","H","I",]) ) sc2=ScrollArea(lb) sc2.setSize(125,100) lb.setWidth(110) slider=Slider(0,100) slider.setOrientation(Slider.Orientation.VERTICAL) slider.setSize(15,100) slider.setActionEventId("Slider") #slider.addActionListener(a) ib=ImageButton(ico_image) ta=TabbedArea() c.add(w2) ta.addTab("Text",[ (text,0,0), (sc,0,50) ]) ta.addTab("Check",check) ta.addTab("Radio",rBox) ta.addTab("List",[ (sc2,0,0) ]) ta.addTab("Label",label) ta.addTab("Icon",[ (ico,0,0), (ib,100,0) ]) ta.addTab("Slider",slider) ta.setSize(300,300) w2.add(ta,0,0) g.setGraphics(gr) w2.resizeToContent() w.setSize(300,300) g.setInput(i) g.setTop(c) clock=pygame.time.Clock() g.mDirtyRect.addRect( Rectangle(0,0,640,480) ) done=False while done == False: clock.tick(0) for event in pygame.event.get(): if event.type==KEYDOWN: if event.key == K_ESCAPE: c.remove(b) c.remove(b2) done=True elif event.key == K_RETURN: w=Window("It'a window!") w.add(Checkbox("Kool thing")) w.resizeToContent() c.add(w, 10, 10) elif event.key == K_LEFT: pb.setValue( pb.getValue()-1.0 ) elif event.key == K_RIGHT: pb.setValue( pb.getValue()+1.0 ) if event.type == ACTIVEEVENT: if event.gain == 1: g.mDirtyRect.addRect( Rectangle(0,0,640,480) ) i.pushInput(event) g.logic() b2.setCaption( str( int(clock.get_fps()) ) ) fRect=GuichanToPygameDirtyRect(g.mDirtyRect.getList()) #for ix in fRect: screen.fill((255,0,0),ix) screen.fill((255,0,0)) g.draw() #pygame.display.update( GuichanToPygameDirtyRect(g.mDirtyRect.getList()) ) pygame.display.update() g.mDirtyRect.clearList()
def __init__(self, positions_list, screen_w=1280, screen_h=720, cars_nr=4, sensor_size=50, rays_nr=8, record_data=False, replay_data_path=None, state_buf_path=None, sensors=False, distance_sensor=False, all_cars_visual_sensors=False, # relative paths to the current folder object_map_path=None, background_path=None, traffic_car_image_path=None, object_car_image_path=None): pygame.init() self.screen_width = screen_w self.screen_height = screen_h self.screen = pygame.display.set_mode((screen_w, screen_h)) self.bkd_color = [255, 255, 0, 255] self.current_dir = os.path.dirname(os.path.abspath(__file__)) self.positions_list = positions_list self.cars_nr = cars_nr self.kinematic_cars = {} if traffic_car_image_path is not None: self.traffic_image_path = os.path.join(self.current_dir, traffic_car_image_path) self.traffic_car_image = pygame.image.load(self.traffic_image_path).convert_alpha() else: self.traffic_car_image = None if object_car_image_path is not None: self.object_car_image_path = os.path.join(self.current_dir, object_car_image_path) self.object_car_image = pygame.image.load(self.object_car_image_path).convert_alpha() else: self.object_car_image = None if object_map_path is not None: self.object_map_path = os.path.join(self.current_dir, object_map_path) self.object_map = pygame.image.load(self.object_map_path).convert_alpha() else: self.object_map = None self.background_path = os.path.join(self.current_dir, background_path) self.background = pygame.image.load(self.background_path).convert() self.bgWidth, self.bgHeight = self.background.get_rect().size pygame.font.init() self.used_font = pygame.font.SysFont('Arial', 30) # start automatically with car_1 self.current_car = "car_1" self.global_cars_positions = {} self.sensors = sensors self.distance_sensor = distance_sensor self.all_cars_visual_sensors = all_cars_visual_sensors self.sensor_size = sensor_size self.rays_nr = rays_nr self.rays_sensor_distances = None self.sensor_mask = pygame.Surface((screen_w, screen_h)) self.object_mask = pygame.Surface((screen_w, screen_h)) self.sensor_masks = {} self.record_data = record_data self.replay_data_path = replay_data_path self.state_buf_path = state_buf_path self.ppu = 16 self.exit = False self.clock = pygame.time.Clock() self.ticks = 60 self.dt = None self.cbox_front_sensor = Checkbox(screen_w - 200, 10, 'Enable front sensor', self.sensors, (0, 255, 75)) self.cbox_rear_sensor = Checkbox(screen_w - 200, 35, 'Enable rear sensor', self.sensors, (0, 255, 75)) self.cbox_distance_sensor = Checkbox(screen_w - 200, 60, 'Enable distance sensor', self.distance_sensor, (0, 255, 75)) self.cbox_all_cars_visual_sensors = Checkbox(screen_w - 200, 85, 'Enable all cars sensors', self.all_cars_visual_sensors, (0, 255, 75)) self.car1_checkbox = Checkbox(10, 180, "Car1", True, (0, 255, 75)) if self.cars_nr >= 2: self.car2_checkbox = Checkbox(10, 210, "Car2", False, (0, 255, 75)) else: self.car2_checkbox = None if self.cars_nr >= 3: self.car3_checkbox = Checkbox(10, 240, "Car3", False, (0, 255, 75)) else: self.car3_checkbox = None if self.cars_nr == 4: self.car4_checkbox = Checkbox(10, 270, "Car4", False, (0, 255, 75)) else: self.car4_checkbox = None # MPC VARIABLES # currently implemented only for 2 cars self.mpc_input_data_car1 = None self.mpc_trajectory_points_car1 = [] self.mpc_delta_car1 = 0 self.mpc_acc_car1 = 0 self.mpc_angle_car1 = 0 self.mpc_coords_car1 = [0, 0] self.mpc_input_data_car2 = None self.mpc_trajectory_points_car2 = [] self.mpc_delta_car2 = 0 self.mpc_acc_car2 = 0 self.mpc_angle_car2 = 0 self.mpc_coords_car2 = [0, 0] self.prev_ref_index_car1 = 40 self.prev_ref_index_car2 = 40
class MultipleCarsSimulator: def __init__(self, positions_list, screen_w=1280, screen_h=720, cars_nr=4, sensor_size=50, rays_nr=8, record_data=False, replay_data_path=None, state_buf_path=None, sensors=False, distance_sensor=False, all_cars_visual_sensors=False, # relative paths to the current folder object_map_path=None, background_path=None, traffic_car_image_path=None, object_car_image_path=None): pygame.init() self.screen_width = screen_w self.screen_height = screen_h self.screen = pygame.display.set_mode((screen_w, screen_h)) self.bkd_color = [255, 255, 0, 255] self.current_dir = os.path.dirname(os.path.abspath(__file__)) self.positions_list = positions_list self.cars_nr = cars_nr self.kinematic_cars = {} if traffic_car_image_path is not None: self.traffic_image_path = os.path.join(self.current_dir, traffic_car_image_path) self.traffic_car_image = pygame.image.load(self.traffic_image_path).convert_alpha() else: self.traffic_car_image = None if object_car_image_path is not None: self.object_car_image_path = os.path.join(self.current_dir, object_car_image_path) self.object_car_image = pygame.image.load(self.object_car_image_path).convert_alpha() else: self.object_car_image = None if object_map_path is not None: self.object_map_path = os.path.join(self.current_dir, object_map_path) self.object_map = pygame.image.load(self.object_map_path).convert_alpha() else: self.object_map = None self.background_path = os.path.join(self.current_dir, background_path) self.background = pygame.image.load(self.background_path).convert() self.bgWidth, self.bgHeight = self.background.get_rect().size pygame.font.init() self.used_font = pygame.font.SysFont('Arial', 30) # start automatically with car_1 self.current_car = "car_1" self.global_cars_positions = {} self.sensors = sensors self.distance_sensor = distance_sensor self.all_cars_visual_sensors = all_cars_visual_sensors self.sensor_size = sensor_size self.rays_nr = rays_nr self.rays_sensor_distances = None self.sensor_mask = pygame.Surface((screen_w, screen_h)) self.object_mask = pygame.Surface((screen_w, screen_h)) self.sensor_masks = {} self.record_data = record_data self.replay_data_path = replay_data_path self.state_buf_path = state_buf_path self.ppu = 16 self.exit = False self.clock = pygame.time.Clock() self.ticks = 60 self.dt = None self.cbox_front_sensor = Checkbox(screen_w - 200, 10, 'Enable front sensor', self.sensors, (0, 255, 75)) self.cbox_rear_sensor = Checkbox(screen_w - 200, 35, 'Enable rear sensor', self.sensors, (0, 255, 75)) self.cbox_distance_sensor = Checkbox(screen_w - 200, 60, 'Enable distance sensor', self.distance_sensor, (0, 255, 75)) self.cbox_all_cars_visual_sensors = Checkbox(screen_w - 200, 85, 'Enable all cars sensors', self.all_cars_visual_sensors, (0, 255, 75)) self.car1_checkbox = Checkbox(10, 180, "Car1", True, (0, 255, 75)) if self.cars_nr >= 2: self.car2_checkbox = Checkbox(10, 210, "Car2", False, (0, 255, 75)) else: self.car2_checkbox = None if self.cars_nr >= 3: self.car3_checkbox = Checkbox(10, 240, "Car3", False, (0, 255, 75)) else: self.car3_checkbox = None if self.cars_nr == 4: self.car4_checkbox = Checkbox(10, 270, "Car4", False, (0, 255, 75)) else: self.car4_checkbox = None # MPC VARIABLES # currently implemented only for 2 cars self.mpc_input_data_car1 = None self.mpc_trajectory_points_car1 = [] self.mpc_delta_car1 = 0 self.mpc_acc_car1 = 0 self.mpc_angle_car1 = 0 self.mpc_coords_car1 = [0, 0] self.mpc_input_data_car2 = None self.mpc_trajectory_points_car2 = [] self.mpc_delta_car2 = 0 self.mpc_acc_car2 = 0 self.mpc_angle_car2 = 0 self.mpc_coords_car2 = [0, 0] self.prev_ref_index_car1 = 40 self.prev_ref_index_car2 = 40 def init_kinematic_cars(self): for position, car_index in zip(self.positions_list, range(1, self.cars_nr + 1)): car_tag = "car_" + str(car_index) car_image_path = self.current_dir + '/resources/cars/' + car_tag + '.png' car_image = pygame.image.load(car_image_path).convert_alpha() car_image = pygame.transform.scale(car_image, (42, 20)) car = Car(position[0], position[1], car_tag=car_tag, car_image=car_image) car.max_velocity = 10 if len(position) == 3: car.angle = position[2] self.kinematic_cars[car_tag] = car def on_road(self, car, screen): Ox = 32 Oy = 16 center_world_x = int(self.screen_width / 2) center_world_y = int(self.screen_height / 2) bot_right_x = center_world_x + int(Ox * cos(radians(-car.angle))) - int(Oy * sin(radians(-car.angle))) bot_right_y = center_world_y + int(Ox * sin(radians(-car.angle))) + int(Oy * cos(radians(-car.angle))) bot_left_x = center_world_x - int(Ox * cos(radians(-car.angle))) - int(Oy * sin(radians(-car.angle))) bot_left_y = center_world_y - int(Ox * sin(radians(-car.angle))) + int(Oy * cos(radians(-car.angle))) top_left_x = center_world_x - int(Ox * cos(radians(-car.angle))) + int(Oy * sin(radians(-car.angle))) top_left_y = center_world_y - int(Ox * sin(radians(-car.angle))) - int(Oy * cos(radians(-car.angle))) top_right_x = center_world_x + int(Ox * cos(radians(-car.angle))) + int(Oy * sin(radians(-car.angle))) top_right_y = center_world_y + int(Ox * sin(radians(-car.angle))) - int(Oy * cos(radians(-car.angle))) if (np.array_equal(screen.get_at((bot_right_x, bot_right_y)), self.bkd_color) or np.array_equal (screen.get_at((bot_left_x, bot_left_y)), self.bkd_color) or np.array_equal(screen.get_at((top_left_x, top_left_y)), self.bkd_color) or np.array_equal(screen.get_at((top_right_x, top_right_y)), self.bkd_color)): Collision.offroad(car) return False else: return True @staticmethod def compute_end_point(side, base_point, sensor_length, sensor_angle, car_angle): if side is 'front': end_point_x = base_point[0] + sensor_length * cos(radians(sensor_angle - car_angle)) end_point_y = base_point[1] + sensor_length * sin(radians(sensor_angle - car_angle)) elif side is 'rear': end_point_x = base_point[0] - sensor_length * cos(radians(sensor_angle - car_angle)) end_point_y = base_point[1] - sensor_length * sin(radians(sensor_angle - car_angle)) else: raise ValueError("Side not defined.") return end_point_x, end_point_y def compute_collision_point(self, side, base_point, sensor_length, sensor_angle, car_angle, data_screen, draw_screen, end_point): if side is 'front': for index in range(0, sensor_length): coll_point_x = base_point[0] + index * cos(radians(sensor_angle - car_angle)) coll_point_y = base_point[1] + index * sin(radians(sensor_angle - car_angle)) try: if np.array_equal(data_screen.get_at((int(coll_point_x), int(coll_point_y))), self.bkd_color): break except: pass pygame.draw.line(draw_screen, (0, 255, 0), base_point, (coll_point_x, coll_point_y), True) pygame.draw.line(draw_screen, (255, 0, 0), (coll_point_x, coll_point_y), (end_point[0], end_point[1]), True) elif side is 'rear': for index in range(0, sensor_length): coll_point_x = base_point[0] - index * cos(radians(sensor_angle - car_angle)) coll_point_y = base_point[1] - index * sin(radians(sensor_angle - car_angle)) try: if np.array_equal(data_screen.get_at((int(coll_point_x), int(coll_point_y))), self.bkd_color): break except: pass pygame.draw.line(draw_screen, (0, 255, 0), base_point, (coll_point_x, coll_point_y), True) pygame.draw.line(draw_screen, (255, 0, 0), (coll_point_x, coll_point_y), (end_point[0], end_point[1]), True) else: raise ValueError("Side not defined.") return coll_point_x, coll_point_y def compute_sensor_distance(self, car, base_point, sensor_length, sensor_angle, data_screen, draw_screen, side=None): end_point = self.compute_end_point(side, base_point, sensor_length, sensor_angle, car.angle) coll_point = self.compute_collision_point(side, base_point, sensor_length, sensor_angle, car.angle, data_screen, draw_screen, end_point) distance = euclidean_norm(base_point, coll_point) # print(distance) return distance def enable_front_sensor(self, car, draw_screen, rays_nr): """ front distance sensor :param car: :param data_screen: :param draw_screen: :param rays_nr: :return: """ position = self.global_cars_positions[car.car_tag] center = Collision.calculate_center_for_car(car, position) if car.car_tag == self.current_car: center = Collision.center_rect(self.screen_width, self.screen_height) mid_of_front_axle = Collision.point_rotation(car, 0, 16, center) distance = np.array([]) for angle_index in range(120, 240, int(round(120/rays_nr))): distance = np.append(distance, self.compute_sensor_distance(car, mid_of_front_axle, 200, angle_index, self.object_mask, draw_screen, side='front')) return distance def enable_rear_sensor(self, car, draw_screen, rays_nr): """ rear distance sensor :param car: :param data_screen: :param draw_screen: :param rays_nr: :return: """ position = self.global_cars_positions[car.car_tag] center = Collision.calculate_center_for_car(car, position) if car.car_tag == self.current_car: center = Collision.center_rect(self.screen_width, self.screen_height) mid_of_rear_axle = Collision.point_rotation(car, 65, 16, center) distance = np.array([]) for angle_index in range(120, 240, int(round(120/rays_nr))): distance = np.append(distance, self.compute_sensor_distance(car, mid_of_rear_axle, 200, angle_index, self.object_mask, draw_screen, side='rear')) return distance def optimized_front_sensor(self, car, act_mask, display_obstacle_on_sensor=False): """ front visual sensor :param act_mask: :param display_obstacle_on_sensor: :return: """ # act_mask is a separate image where you can only see what the sensor sees position = self.global_cars_positions[car.car_tag] center = Collision.calculate_center_for_car(car, position) if car.car_tag == self.current_car: center = Collision.center_rect(self.screen_width, self.screen_height) mid_of_front_axle = Collision.point_rotation(car, -1, 16, center) arc_points = get_arc_points(mid_of_front_axle, 150, radians(90 + car.angle), radians(270 + car.angle), self.sensor_size) draw_center = Collision.center_rect(self.screen_width, self.screen_height) draw_mid_front_axle = Collision.point_rotation(car, -1, 16, draw_center) draw_arc_points = get_arc_points(draw_mid_front_axle, 150, radians(90 + car.angle), radians(270 + car.angle), self.sensor_size) offroad_edge_points = [] draw_offroad_edge_points = [] for end_point, draw_end_point in zip(arc_points, draw_arc_points): points_to_be_checked = list(get_equidistant_points(mid_of_front_axle, end_point, 25)) draw_points_to_be_checked = list(get_equidistant_points(draw_mid_front_axle, draw_end_point, 25)) check = False for line_point, draw_line_point in zip(points_to_be_checked, draw_points_to_be_checked): try: if np.array_equal(self.object_mask.get_at((int(line_point[0]), int(line_point[1]))), self.bkd_color): check = True break except: check = True break if check is False: offroad_edge_points.append(end_point) draw_offroad_edge_points.append(draw_end_point) else: offroad_edge_points.append(line_point) draw_offroad_edge_points.append(draw_line_point) for index in range(0, len(arc_points)): if offroad_edge_points[index] == arc_points[index]: pygame.draw.line(self.screen, (0, 255, 0), mid_of_front_axle, arc_points[index], True) pygame.draw.line(act_mask, (0, 255, 0), draw_mid_front_axle, draw_arc_points[index], True) else: pygame.draw.line(self.screen, (0, 255, 0), mid_of_front_axle, offroad_edge_points[index], True) pygame.draw.line(act_mask, (0, 255, 0), draw_mid_front_axle, draw_offroad_edge_points[index], True) if display_obstacle_on_sensor is True: pygame.draw.line(self.screen, (255, 0, 0), offroad_edge_points[index], arc_points[index], True) pygame.draw.line(act_mask, (255, 0, 0), draw_offroad_edge_points[index], draw_arc_points[index], True) def optimized_rear_sensor(self, car, act_mask, display_obstacle_on_sensor=False): """ rear visual sensor :param car: :param object_mask: :param act_mask: :param display_obstacle_on_sensor: :return: """ # act_mask is a separate image where you can only see what the sensor sees position = self.global_cars_positions[car.car_tag] center = Collision.calculate_center_for_car(car, position) if car.car_tag == self.current_car: center = Collision.center_rect(self.screen_width, self.screen_height) mid_of_rear_axle = Collision.point_rotation(car, 65, 16, center) arc_points = get_arc_points(mid_of_rear_axle, 150, radians(-90 + car.angle), radians(90 + car.angle), self.sensor_size) draw_center = Collision.center_rect(self.screen_width, self.screen_height) draw_mid_rear_axle = Collision.point_rotation(car, 65, 16, draw_center) draw_arc_points = get_arc_points(draw_mid_rear_axle, 150, radians(-90 + car.angle), radians(90 + car.angle), self.sensor_size) offroad_edge_points = [] draw_offroad_edge_points = [] for end_point, draw_end_point in zip(arc_points, draw_arc_points): points_to_be_checked = list(get_equidistant_points(mid_of_rear_axle, end_point, 25)) draw_points_to_be_checked = list(get_equidistant_points(draw_mid_rear_axle, draw_end_point, 25)) check = False for line_point, draw_line_point in zip(points_to_be_checked, draw_points_to_be_checked): try: if np.array_equal(self.object_mask.get_at((int(line_point[0]), int(line_point[1]))), self.bkd_color): check = True break except: check = True break if check is False: offroad_edge_points.append(end_point) draw_offroad_edge_points.append(draw_end_point) else: offroad_edge_points.append(line_point) draw_offroad_edge_points.append(draw_line_point) for index in range(0, len(arc_points)): if offroad_edge_points[index] == arc_points[index]: pygame.draw.line(self.screen, (0, 255, 0), mid_of_rear_axle, arc_points[index], True) pygame.draw.line(act_mask, (0, 255, 0), draw_mid_rear_axle, draw_arc_points[index], True) else: pygame.draw.line(self.screen, (0, 255, 0), mid_of_rear_axle, offroad_edge_points[index], True) pygame.draw.line(act_mask, (0, 255, 0), draw_mid_rear_axle, draw_offroad_edge_points[index], True) if display_obstacle_on_sensor is True: pygame.draw.line(self.screen, (255, 0, 0), offroad_edge_points[index], arc_points[index], True) pygame.draw.line(act_mask, (255, 0, 0), draw_offroad_edge_points[index], draw_arc_points[index], True) def custom_drawing(self, *args): """ custom drawing function add drawings to simulator :param args: arguments :return: """ pass def draw_other_kinematic_cars(self, stagePosX, stagePosY, debug=False): current_car = self.kinematic_cars[self.current_car] self.global_cars_positions[self.current_car] = (stagePosX, stagePosY) current_position = current_car.position if debug is True: pos_list = [] for car in self.kinematic_cars: car_to_draw = self.kinematic_cars[car] if car_to_draw.car_tag != self.current_car: draw_pos_x = (car_to_draw.position.x * self.ppu - stagePosX) + car_to_draw.car_image.get_height()/2 draw_pos_y = (car_to_draw.position.y * self.ppu - stagePosY) + car_to_draw.car_image.get_width()/2 x = self.screen_width / 2 - draw_pos_x y = self.screen_height / 2 - draw_pos_y self.global_cars_positions[car_to_draw.car_tag] = (x, y) if debug is True: pos_list.append((car_to_draw.car_tag, car_to_draw.position, x, y)) rotated = pygame.transform.rotate(car_to_draw.car_image, car_to_draw.angle) obj_rotated = pygame.transform.rotate(self.object_car_image, car_to_draw.angle) self.screen.blit(rotated, (x, y)) self.object_mask.blit(obj_rotated, (x, y)) if debug is True: text0 = self.used_font.render('current_car_pos ' + str(current_position), True, (250, 0, 0)) text1 = self.used_font.render(str(pos_list[0]), True, (250, 0, 0)) text2 = self.used_font.render(str(pos_list[1]), True, (250, 0, 0)) text3 = self.used_font.render(str(pos_list[2]), True, (250, 0, 0)) self.screen.blit(text0, (200, 170)) self.screen.blit(text1, (200, 200)) self.screen.blit(text2, (200, 230)) self.screen.blit(text3, (200, 260)) def draw_sim_environment(self, car, print_coords=False, print_other_cars_coords=False): # Drawing """ principal draw function that builds the simulator environment :param print_coords: print_coors on screen bool :param print_other_cars_coords=False :return: """ stagePosX = car.position[0] * self.ppu stagePosY = car.position[1] * self.ppu rel_x = stagePosX % self.bgWidth rel_y = stagePosY % self.bgHeight self.object_mask.blit(self.object_map, (rel_x - self.bgWidth, rel_y - self.bgHeight)) self.object_mask.blit(self.object_map, (rel_x, rel_y)) self.object_mask.blit(self.object_map, (rel_x - self.bgWidth, rel_y)) self.object_mask.blit(self.object_map, (rel_x, rel_y - self.bgHeight)) self.screen.blit(self.background, (rel_x - self.bgWidth, rel_y - self.bgHeight)) self.screen.blit(self.background, (rel_x, rel_y)) self.screen.blit(self.background, (rel_x - self.bgWidth, rel_y)) self.screen.blit(self.background, (rel_x, rel_y - self.bgHeight)) self.draw_other_kinematic_cars(stagePosX, stagePosY, debug=print_other_cars_coords) if self.car1_checkbox is not None: self.car1_checkbox.update() if self.car2_checkbox is not None: self.car2_checkbox.update() if self.car3_checkbox is not None: self.car3_checkbox.update() if self.car4_checkbox is not None: self.car4_checkbox.update() if self.cbox_front_sensor is not None: self.cbox_front_sensor.update() if self.cbox_rear_sensor is not None: self.cbox_rear_sensor.update() if self.cbox_distance_sensor is not None: self.cbox_distance_sensor.update() if self.cbox_all_cars_visual_sensors is not None: self.cbox_all_cars_visual_sensors.update() if self.cbox_all_cars_visual_sensors.isChecked() is True: self.all_cars_visual_sensors = True else: self.all_cars_visual_sensors = False if self.cbox_front_sensor.isChecked() is True or self.cbox_rear_sensor.isChecked() is True: self.sensors = True else: self.sensors = False if self.cbox_distance_sensor.isChecked() is True: self.distance_sensor = True else: self.distance_sensor = False rotated = pygame.transform.rotate(car.car_image, car.angle) rotated_obj = pygame.transform.rotate(self.object_car_image, car.angle) rot_rect = rotated.get_rect() center_x = int(self.screen_width / 2) - int(rot_rect.width / 2) center_y = int(self.screen_height / 2) - int(rot_rect.height / 2) # draw the ego car self.screen.blit(rotated, (center_x, center_y)) self.object_mask.blit(rotated_obj, (center_x, center_y)) self.custom_drawing() if print_coords is True: text1 = self.used_font.render('Car pos x: ' + str(round(stagePosX, 2)), True, (250, 0, 0)) text2 = self.used_font.render('Car pos y: ' + str(round(stagePosY, 2)), True, (250, 0, 0)) text3 = self.used_font.render('rel x: ' + str(round(rel_x, 2)), True, (250, 0, 0)) text4 = self.used_font.render('rel y: ' + str(round(rel_y, 2)), True, (250, 0, 0)) text5 = self.used_font.render('velocity: ' + str(round(car.velocity.x, 2) * self.ppu/4) + ' km/h', True, (250, 0, 0)) self.screen.blit(text1, (20, 20)) self.screen.blit(text2, (20, 50)) self.screen.blit(text3, (20, 80)) self.screen.blit(text4, (20, 110)) self.screen.blit(text5, (20, 140)) return stagePosX, stagePosY, rel_x, rel_y def key_handler(self, car, dt, rs_pos_list): # User input """ key handler that coordinates the car movement with user keyboard input :param car: :param dt: :param rs_pos_list: :return: """ pressed = pygame.key.get_pressed() if pressed[pygame.K_ESCAPE]: quit() if pressed[pygame.K_r]: car.reset_car(rs_pos_list) if pressed[pygame.K_UP]: car.accelerate(dt) elif pressed[pygame.K_DOWN]: car.brake(dt) elif pressed[pygame.K_SPACE]: car.handbrake(dt) else: car.cruise(dt) if pressed[pygame.K_RIGHT]: car.steer_right(dt) elif pressed[pygame.K_LEFT]: car.steer_left(dt) else: car.no_steering() @staticmethod def change_state_for_other_checkboxes(checkbox_list): for checkbox in checkbox_list: if checkbox is not None and checkbox.isChecked(): checkbox.changeState() def change_car(self, mouse_button_pressed, mouse_pos): if self.car1_checkbox.onCheckbox(mouse_pos) and mouse_button_pressed is False: self.car1_checkbox.changeState() checkbox_list = [self.car2_checkbox, self.car3_checkbox, self.car4_checkbox] self.change_state_for_other_checkboxes(checkbox_list) if self.cars_nr >= 2: if self.car2_checkbox.onCheckbox(mouse_pos) and mouse_button_pressed is False: self.car2_checkbox.changeState() checkbox_list = [self.car1_checkbox, self.car3_checkbox, self.car4_checkbox] self.change_state_for_other_checkboxes(checkbox_list) if self.cars_nr >= 3: if self.car3_checkbox.onCheckbox(mouse_pos) and mouse_button_pressed is False: self.car3_checkbox.changeState() checkbox_list = [self.car1_checkbox, self.car2_checkbox, self.car4_checkbox] self.change_state_for_other_checkboxes(checkbox_list) if self.cars_nr == 4: if self.car4_checkbox.onCheckbox(mouse_pos) and mouse_button_pressed is False: self.car4_checkbox.changeState() checkbox_list = [self.car1_checkbox, self.car2_checkbox, self.car3_checkbox] self.change_state_for_other_checkboxes(checkbox_list) def event_handler(self, mouse_button_pressed): # Event queue """ event handler for sensors check_boxes, exit event or mouse pressing events :param mouse_button_pressed: :return: """ for event in pygame.event.get(): if event.type == pygame.QUIT: self.exit = True if event.type == pygame.MOUSEBUTTONDOWN: mouse_pos = pygame.mouse.get_pos() self.change_car(mouse_button_pressed, mouse_pos) if self.cbox_front_sensor.onCheckbox(mouse_pos) and mouse_button_pressed is False: self.cbox_front_sensor.changeState() if self.cbox_rear_sensor.onCheckbox(mouse_pos) and mouse_button_pressed is False: self.cbox_rear_sensor.changeState() if self.cbox_distance_sensor.onCheckbox(mouse_pos) and mouse_button_pressed is False: self.cbox_distance_sensor.changeState() if self.cbox_all_cars_visual_sensors.onCheckbox(mouse_pos) and mouse_button_pressed is False: self.cbox_all_cars_visual_sensors.changeState() mouse_button_pressed = True if event.type == pygame.MOUSEBUTTONUP: mouse_button_pressed = False def access_simulator_data(self, car_tags, car_data_bool=False, visual_sensor_data_bool=False, distance_sensor_data_bool=False): """ car_data: acceleration -> car_data[0] ; steering -> car_data[1] ; angle -> car_data[2] ; velocity -> car_data[3] sensor_data: subsurface with sensor image :param car_tags: tags of cars :param car_data_bool: if you want to access car_data set to true :param visual_sensor_data_bool: if you want to access sensor_data set to true :param distance_sensor_data_bool: if you want to access rays_sensor_data set to true and check the cbox in the simulator for rays_sensor. :return: """ _car_data = [] if self.sensors is True: _visual_data = None elif self.all_cars_visual_sensors is True: _visual_data = [] else: _visual_data = [] _distance_data = [] for tag in car_tags: if tag in self.kinematic_cars: car = self.kinematic_cars[tag] if car_data_bool is True: car_acc = car.acceleration car_steering = car.steering car_angle = car.angle car_velocity = car.velocity.x car_data = [car_acc, car_steering, car_velocity, car_angle] _car_data.append(car_data) if visual_sensor_data_bool is True: if self.sensors is True: image_rect = pygame.Rect((390, 110), (500, 500)) sub = self.sensor_mask.subsurface(image_rect) _visual_data = sub if self.all_cars_visual_sensors is True: sub = self.sensor_masks[tag] _visual_data.append(sub) if distance_sensor_data_bool is True: if self.distance_sensor is True: if self.rays_sensor_distances is not None: _distance_data.append(self.rays_sensor_distances) else: raise ValueError('car_tag not found, please specify a valid car tag') return _car_data, _visual_data, _distance_data def update_cars(self): for car in self.kinematic_cars: if self.kinematic_cars[car].car_tag != self.current_car: self.kinematic_cars[car].update(self.dt) def determine_current_car(self): if self.car1_checkbox.isChecked(): self.current_car = "car_1" elif self.cars_nr >= 2 and self.car2_checkbox.isChecked(): self.current_car = "car_2" elif self.cars_nr >= 3 and self.car3_checkbox.isChecked(): self.current_car = "car_3" elif self.cars_nr == 4 and self.car4_checkbox.isChecked(): self.current_car = "car_4" else: self.current_car = "car_1" def get_sensor_mask_for_car(self, car): """ Access a specific sensor mask when all the sensors are active. all_cars_sensors has to be True. :param car: :return: """ if car.car_tag in self.sensor_masks: return self.sensor_masks[car.car_tag] def activate_sensors_for_all_cars(self): self.rays_sensor_distances = [] for car in self.kinematic_cars: if self.cbox_all_cars_visual_sensors.isChecked(): # temp_sensor_mask = pygame.Surface((self.screen_width, self.screen_height)) # self.optimized_front_sensor(self.kinematic_cars[car], temp_sensor_mask, display_obstacle_on_sensor=True) # self.optimized_rear_sensor(self.kinematic_cars[car], temp_sensor_mask, display_obstacle_on_sensor=True) # image_rect = pygame.Rect((440, 160), (400, 400)) # sensor_sub = temp_sensor_mask.subsurface(image_rect) # self.sensor_masks[car] = sensor_sub self.rays_sensor_distances.append([self.enable_front_sensor(self.kinematic_cars[car], self.screen, self.rays_nr), self.enable_rear_sensor(self.kinematic_cars[car], self.screen, self.rays_nr)]) def activate_sensors(self, car): """ Check if any sensor has been activated. :return: """ self.sensor_mask.fill((0, 0, 0)) if self.cbox_front_sensor.isChecked(): self.optimized_front_sensor(car, self.sensor_mask, display_obstacle_on_sensor=True) if self.cbox_rear_sensor.isChecked(): self.optimized_rear_sensor(car, self.sensor_mask, display_obstacle_on_sensor=True) if self.cbox_distance_sensor.isChecked(): if self.cbox_rear_sensor.isChecked() is False and self.cbox_front_sensor.isChecked() is False: self.rays_sensor_distances = [self.enable_front_sensor(car, self.screen, self.rays_nr), self.enable_rear_sensor(car, self.screen, self.rays_nr)] def record_data_function(self, car_tags, index): """ Data recording. :param car_tags: tags of the cars you want to record :param index: image index :return: """ image_name = 'image_' + str(index) + '.png' index += 1 # check if the car tags exists for tag in car_tags: if tag in self.kinematic_cars: car = self.kinematic_cars[tag] if self.state_buf_path is None: raise OSError('state_buf_path is empty.') if self.replay_data_path is None: raise OSError('replay_data_path is empty.') actions = [car.position.x, car.position.y, float(round(car.angle, 3)), float(round(car.acceleration, 3)), float(round(car.velocity.x, 3)), image_name] # Save state_buf write_state_buf(self.state_buf_path + '/' + str(tag) + '_state_buf' + '.csv', actions) # Save replay write_data(self.replay_data_path + '/' + str(tag) + '_replay' + '.csv', car.position, car.angle) else: raise ValueError('given car_tag does not exists') def custom(self, *args): """ custom function in which to modify or access data if you want to create a simulation on top of another simulation but modify some things but not the run function you can add this custom() function inside of your run function and override it in the child simulator, but do not override the parent run() function. :param args: custom arguments if needed :return: """ pass def run(self): """ main run loop :return: """ pass """ MPC FUNCTIONS """ @staticmethod def rotate_x_point(point_x, point_y, angle): return point_x * cos(np.deg2rad(angle)) - point_y * sin(np.deg2rad(angle)) @staticmethod def rotate_y_point(point_x, point_y, angle): return point_x * sin(np.deg2rad(angle)) + point_y * cos(np.deg2rad(angle)) def draw_mpc_prediction(self, *args, mpc_solution, car_tag): """ :param args: args[0] -> mpc_traj_points_carX, args[1] -> mpc_angle_carX :param mpc_solution: :param car_tag: :return: """ if car_tag == self.current_car: center_screen = (int(self.screen_width / 2), int(self.screen_height / 2)) else: position = self.global_cars_positions[car_tag] center_screen = Collision.calculate_center_for_car(self.kinematic_cars[car_tag], position) args[0].clear() for index in range(2, 20, 2): delta_position = ( mpc_solution[index] * cos(np.deg2rad(args[1])) + mpc_solution[index + 1] * sin(np.deg2rad(args[1])), mpc_solution[index] * (-sin(np.deg2rad(args[1]))) + mpc_solution[index + 1] * cos(np.deg2rad(args[1]))) x_point = center_screen[0] - int(delta_position[0] * self.ppu) y_point = center_screen[1] - int(delta_position[1] * self.ppu) traj_point = (x_point, y_point) args[0].append(traj_point) def prepare_mpc_input(self, car, waypoints): if car.car_tag == 'car_1': self.mpc_input_data_car1 = (ctypes.c_double * 14)() for index in range(6): self.mpc_input_data_car1[index*2] = waypoints[index][0] for index in range(6): self.mpc_input_data_car1[index*2+1] = waypoints[index][1] self.mpc_input_data_car1[12] = np.deg2rad(car.angle) self.mpc_input_data_car1[13] = car.velocity[0] elif car.car_tag == 'car_2': self.mpc_input_data_car2 = (ctypes.c_double * 14)() for index in range(6): self.mpc_input_data_car2[index * 2] = waypoints[index][0] for index in range(6): self.mpc_input_data_car2[index * 2 + 1] = waypoints[index][1] self.mpc_input_data_car2[12] = np.deg2rad(car.angle) self.mpc_input_data_car2[13] = car.velocity[0] else: raise ValueError("Car tag not defined.") def draw_trajectory(self, car, car_data): # draw trajectory """ :param car: :param car_data: :return: """ if car.car_tag == self.current_car: center_screen = (int(self.screen_width / 2), int(self.screen_height / 2)) else: position = self.global_cars_positions[car.car_tag] center_screen = Collision.calculate_center_for_car(car, position) trajectory_points = [] waypoints = [] min = 1000 idx = -1 if car.car_tag == 'car_1': prev_ref_index = self.prev_ref_index_car1 elif car.car_tag == 'car_2': prev_ref_index = self.prev_ref_index_car2 else: raise ValueError("Car tag not defined") for elem in range(prev_ref_index-40, prev_ref_index+40): dx = car_data[elem][0] - car.position[0] dy = car_data[elem][1] - car.position[1] d = abs(math.sqrt(dx**2+dy**2)) if d < min: min = d idx = elem prev_ref_index = idx if car.car_tag == 'car_1': self.prev_ref_index_car1 = prev_ref_index elif car.car_tag == 'car_2': self.prev_ref_index_car2 = prev_ref_index else: raise ValueError("Car tag not defined") for add_elem in range(idx, idx + 150, 15): if add_elem < len(car_data): delta_position = ( car.position[0] - car_data[add_elem][0], car.position[1] - car_data[add_elem][1]) x_point = center_screen[0] + int(delta_position[0] * self.ppu) y_point = center_screen[1] + int(delta_position[1] * self.ppu) traj_point = (x_point, y_point) trajectory_points.append(traj_point) if len(waypoints) < 9: waypoints.append((car_data[add_elem][0], car_data[add_elem][1])) # draw each trajectory point pygame.draw.circle(self.screen, (255, 255, 0), traj_point, 2, 2) # draw lines between trajectory points for traj_point, next_traj_point in zip(trajectory_points, trajectory_points[1:]): pygame.draw.aaline(self.screen, (255, 255, 0), traj_point, next_traj_point, 10) self.prepare_mpc_input(car, waypoints) if car.car_tag == 'car_1': if len(self.mpc_trajectory_points_car1) > 0: for traj_point, next_traj_point in zip(self.mpc_trajectory_points_car1, self.mpc_trajectory_points_car1[1:]): pygame.draw.aaline(self.screen, (0, 255, 0), traj_point, next_traj_point, 10) elif car.car_tag == 'car_2': if len(self.mpc_trajectory_points_car2) > 0: for traj_point, next_traj_point in zip(self.mpc_trajectory_points_car2, self.mpc_trajectory_points_car2[1:]): pygame.draw.aaline(self.screen, (0, 255, 0), traj_point, next_traj_point, 10) def mpc_thread(self, mpc_target_speed=30, mpc_dt=0.1): controller = MPCController(target_speed=mpc_target_speed, dt=mpc_dt) while True: mpc_solution_car1 = controller.control(self.mpc_input_data_car1, self.mpc_coords_car1) mpc_solution_car2 = controller.control(self.mpc_input_data_car2, self.mpc_coords_car2) self.mpc_delta_car1 = mpc_solution_car1[0] self.mpc_acc_car1 = mpc_solution_car1[1] self.mpc_delta_car2 = mpc_solution_car2[0] self.mpc_acc_car2 = mpc_solution_car2[1] self.draw_mpc_prediction(self.mpc_trajectory_points_car1, self.mpc_angle_car1, mpc_solution=mpc_solution_car1, car_tag='car_1') self.draw_mpc_prediction(self.mpc_trajectory_points_car2, self.mpc_angle_car2, mpc_solution=mpc_solution_car2, car_tag='car_2')
class Menu: def __init__(self): pygame.init() pygame.display.set_caption("GridSim") self.current_dir = os.path.dirname(os.path.abspath(__file__)) self.screen_width = config.screen_width self.screen_height = config.screen_height self.screen = pygame.display.set_mode((self.screen_width, self.screen_height)) self.screen.fill([255, 255, 255]) self.exit = False self.manual_driving_button = Button("manual driving", (500, 150), (350, 50), config.inactive_color, config.active_color) self.ga_button = Button("neuro-evolutionary", (500, 200), (350, 50), config.inactive_color, config.active_color) self.ga_train_button = Button("→ train", (500, 250), (350, 50), config.inactive_color, config.active_color) self.ga_predict_button = Button("→ predict", (500, 300), (350, 50), config.inactive_color, config.active_color) self.drl_button = Button("deep reinf. learning", (500, 250), (350, 50), config.inactive_color, config.active_color) # DQN self.drl_train_button = Button("→ train", (500, 300), (350, 50), config.inactive_color, config.active_color) self.drl_predict_button = Button("→ predict", (500, 350), (350, 50), config.inactive_color, config.active_color) self.record_button = Button("record data", (500, 300), (350, 50), config.inactive_color, config.active_color) self.replay_button = Button("replay", (500, 350), (350, 50), config.inactive_color, config.active_color) self.back_button = Button("back", (500, 400), (350, 50), config.inactive_color, (200, 0, 0)) self.exit_button = Button("exit", (500, 450), (350, 50), config.inactive_color, (200, 0, 0)) self.activation_cbox = Checkbox(1000, 50, "Print activations", True) self.sensors_cbox = Checkbox(1000, 70, "Enable visual sensors", True) self.distance_sensor_cbox = Checkbox(1000, 90, "Enable distance sensor", False) self.traffic_cbox = Checkbox(1000, 110, "Enable traffic", True) self.ga_buttons_interactions = False self.drl_buttons_interactions = False self.background_vid = cv2.VideoCapture("resources/backgrounds/zoomed-background-video.mp4") if self.background_vid.isOpened() is False: raise OSError("Error opening video stream or file") self.current_background_frame = None self.pause_background_video = False pygame.display.update() def display_error_message(self, error_message, position=(20, 20), sleep_time=2): font_render = pygame.font.SysFont(config.font, 40) font_render.set_bold(True) error_text = font_render.render(error_message, True, (250, 0, 0)) self.screen.blit(error_text, position) pygame.display.update() time.sleep(sleep_time) def background_video(self): frame_counter = 0 while self.background_vid.isOpened(): if self.pause_background_video is True: break ret, frame = self.background_vid.read(0) frame_counter += 1 if ret is True: frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB) frame = np.rot90(frame) frame = np.flipud(frame) self.current_background_frame = pygame.surfarray.make_surface(frame) if frame_counter == self.background_vid.get(cv2.CAP_PROP_FRAME_COUNT): frame_counter = 0 self.background_vid.set(cv2.CAP_PROP_POS_FRAMES, 0) self.background_vid.release() def checkbox_interactions(self): self.activation_cbox_interaction() self.sensors_cbox_interaction() self.traffic_cbox_interaction() def buttons_interactions(self): tag = False self.manual_driving_button_interaction() self.ga_button_interaction() if self.ga_buttons_interactions is True: tag = True self.ga_train_button_interaction() self.ga_predict_button_interaction() self.back_button_interaction() if tag is False: self.drl_button_interaction() if self.drl_buttons_interactions is True: tag = True self.drl_train_button_interaction() self.drl_predict_button_interaction() self.back_button_interaction() if tag is False: self.record_button_interaction() self.replay_button_interaction() self.exit_button_interaction() def all_interactions(self): self.activation_cbox_interaction() self.sensors_cbox_interaction() self.traffic_cbox_interaction() self.manual_driving_button_interaction() self.record_button_interaction() self.replay_button_interaction() self.exit_button_interaction() def manual_driving_button_interaction(self): mouse_pos = pygame.mouse.get_pos() if (self.manual_driving_button.coords[0] < mouse_pos[0] < self.manual_driving_button.coords[0] + self.manual_driving_button.dimensions[0] and self.manual_driving_button.coords[1] < mouse_pos[1] < self.manual_driving_button.coords[1] + self.manual_driving_button.dimensions[1]): self.manual_driving_button.button_light(self.screen, (75, -3)) mouse_click = pygame.mouse.get_pressed() if mouse_click[0] == 1: self.pause_background_video = True questions = ['Sensor size'] input_box = InputBoxMenu(self.screen, len(questions), (self.manual_driving_button.coords[0] + 25, self.manual_driving_button.coords[1] + 75), questions, [int]) input_box.help() inputs = input_box.ask_boxes() check = input_box.check_inputbox_input() error_message_pos = [20, 20] while check in input_box.errors: self.display_error_message('Error ' + check, position=tuple(error_message_pos), sleep_time=0) error_message_pos[1] += 40 inputs = input_box.ask_boxes() check = input_box.check_inputbox_input() sim = CitySimulator(self.screen, self.screen_width, self.screen_height, activations=self.activation_cbox.isChecked(), record_data=False, sensor_size=int(inputs[0]), traffic=self.traffic_cbox.isChecked(), sensors=self.sensors_cbox.isChecked(), distance_sensor=self.distance_sensor_cbox.isChecked(), enabled_menu=True) sim.run() quit() else: self.manual_driving_button.draw_button(self.screen, (75, -3)) def record_button_interaction(self): mouse_pos = pygame.mouse.get_pos() if (self.record_button.coords[0] < mouse_pos[0] < self.record_button.coords[0] + self.record_button.dimensions[0] and self.record_button.coords[1] < mouse_pos[1] < self.record_button.coords[1] + self.record_button.dimensions[1]): self.record_button.button_light(self.screen, (100, -3)) mouse_click = pygame.mouse.get_pressed() if mouse_click[0] == 1: questions = ['Sensor size', 'State_buf path', 'Replay_data path'] input_box = InputBoxMenu(self.screen, len(questions), (self.record_button.coords[0] + 25, self.record_button.coords[1] + 75), questions, [int, 'path + csv', 'path + csv']) input_box.help() inputs = input_box.ask_boxes() check = input_box.check_inputbox_input() error_message_pos = [20, 20] while check in input_box.errors: self.display_error_message('Error ' + check, position=tuple(error_message_pos), sleep_time=0) error_message_pos[1] += 40 inputs = input_box.ask_boxes() check = input_box.check_inputbox_input() rec = CitySimulator(self.screen, self.screen_width, self.screen_height, record_data=True, sensor_size=int(inputs[0]), state_buf_path=str(inputs[1]), replay_data_path=str(inputs[2]), traffic=self.traffic_cbox.isChecked(), sensors=self.sensors_cbox.isChecked(), distance_sensor=self.distance_sensor_cbox.isChecked(), enabled_menu=True) rec.run() quit() else: self.record_button.draw_button(self.screen, (100, -3)) def replay_button_interaction(self): mouse_pos = pygame.mouse.get_pos() if (self.replay_button.coords[0] < mouse_pos[0] < self.replay_button.coords[0] + self.replay_button.dimensions[0] and self.replay_button.coords[1] < mouse_pos[1] < self.replay_button.coords[1] + self.replay_button.dimensions[1]): self.replay_button.button_light(self.screen, (125, -3)) mouse_click = pygame.mouse.get_pressed() if mouse_click[0] == 1: questions = ['Sensor size', 'Replay_data path'] input_box = InputBoxMenu(self.screen, len(questions), (self.replay_button.coords[0] + 25, self.replay_button.coords[1] + 75), questions, [int, 'path + csv']) input_box.help() inputs = input_box.ask_boxes() check = input_box.check_inputbox_input() error_message_pos = [20, 20] while check in input_box.errors: self.display_error_message('Error ' + check, position=tuple(error_message_pos), sleep_time=0) error_message_pos[1] += 40 inputs = input_box.ask_boxes() check = input_box.check_inputbox_input() replay = Replay(self.screen, self.screen_width, self.screen_height, activations=self.activation_cbox.isChecked(), traffic=self.traffic_cbox.isChecked(), sensors=self.sensors_cbox.isChecked(), distance_sensor=self.distance_sensor_cbox.isChecked(), sensor_size=int(inputs[0]), enabled_menu=True) replay.replay(inputs[1], enable_trajectory=True) quit() else: self.replay_button.draw_button(self.screen, (125, -3)) def ga_button_interaction(self): mouse_pos = pygame.mouse.get_pos() if (self.ga_button.coords[0] < mouse_pos[0] < self.ga_button.coords[0] + self.ga_button.dimensions[0] and self.ga_button.coords[1] < mouse_pos[1] < self.ga_button.coords[1] + self.ga_button.dimensions[1]): self.ga_button.button_light(self.screen, (55, -3)) mouse_click = pygame.mouse.get_pressed() if mouse_click[0] == 1: self.ga_buttons_interactions = True else: self.ga_button.draw_button(self.screen, (55, -3)) def ga_train_button_interaction(self): mouse_pos = pygame.mouse.get_pos() if (self.ga_train_button.coords[0] < mouse_pos[0] < self.ga_train_button.coords[0] + self.ga_train_button.dimensions[0] and self.ga_train_button.coords[1] < mouse_pos[1] < self.ga_train_button.coords[1] + self.ga_train_button.dimensions[1]): self.ga_train_button.button_light(self.screen, (110, -3)) mouse_click = pygame.mouse.get_pressed() if mouse_click[0] == 1: self.pause_background_video = True questions = ['No_population', 'No_generations', 'Rays_nr'] input_box = InputBoxMenu(self.screen, len(questions), (self.ga_train_button.coords[0] + 25, self.ga_train_button.coords[1] + 75), questions, [int, int, int]) input_box.help() inputs = input_box.ask_boxes() check = input_box.check_inputbox_input() error_message_pos = [20, 20] while check in input_box.errors: self.display_error_message('Error ' + check, position=tuple(error_message_pos), sleep_time=0) error_message_pos[1] += 40 inputs = input_box.ask_boxes() check = input_box.check_inputbox_input() agent = NeuroEvolutionary(self.screen, self.screen_width, self.screen_height, 0, False, False, False, None, None, False, population_size=int(inputs[0]), num_generations=int(inputs[1]), shape=int(inputs[2])) agent.neuro_trainer.train(agent.kinematic_ga.neuro_eval) quit() else: self.ga_train_button.draw_button(self.screen, (110, -3)) def ga_predict_button_interaction(self): mouse_pos = pygame.mouse.get_pos() if (self.ga_predict_button.coords[0] < mouse_pos[0] < self.ga_predict_button.coords[0] + self.ga_predict_button.dimensions[0] and self.ga_predict_button.coords[1] < mouse_pos[1] < self.ga_predict_button.coords[1] + self.ga_predict_button.dimensions[1]): self.ga_predict_button.button_light(self.screen, (110, -3)) mouse_click = pygame.mouse.get_pressed() if mouse_click[0] == 1: self.pause_background_video = True questions = ['Model name'] input_box = InputBoxMenu(self.screen, len(questions), (self.ga_predict_button.coords[0] + 25, self.ga_predict_button.coords[1] + 75), questions, ['name']) input_box.help() inputs = input_box.ask_boxes() if os.path.exists('./used_models/ga/' + inputs[0] + '.h5') is False: self.display_error_message("Model doesn't exists in /used_models/ga/. Loading default model.") # replace with standard_model after training a good model ↓ inputs[0] = 'model_2000' agent = NeuroEvolutionary(self.screen, self.screen_width, self.screen_height, 0, False, False, False, None, None, False) agent.kinematic_ga.load_model(inputs[0]) while pygame.key.get_pressed() != pygame.K_ESCAPE: agent.ga_sim.run_ga(agent.kinematic_ga.model) quit() else: self.ga_predict_button.draw_button(self.screen, (110, -3)) def drl_button_interaction(self): mouse_pos = pygame.mouse.get_pos() if (self.drl_button.coords[0] < mouse_pos[0] < self.drl_button.coords[0] + self.drl_button.dimensions[0] and self.drl_button.coords[1] < mouse_pos[1] < self.drl_button.coords[1] + self.drl_button.dimensions[1]): self.drl_button.button_light(self.screen, (25, -3)) mouse_click = pygame.mouse.get_pressed() if mouse_click[0] == 1: self.drl_buttons_interactions = True else: self.drl_button.draw_button(self.screen, (25, -3)) def drl_train_button_interaction(self): mouse_pos = pygame.mouse.get_pos() if (self.drl_train_button.coords[0] < mouse_pos[0] < self.drl_train_button.coords[0] + self.drl_train_button.dimensions[0] and self.drl_train_button.coords[1] < mouse_pos[1] < self.drl_train_button.coords[1] + self.drl_train_button.dimensions[1]): self.drl_train_button.button_light(self.screen, (110, -3)) mouse_click = pygame.mouse.get_pressed() if mouse_click[0] == 1: self.pause_background_video = True questions = ['No_episodes', 'Rays_nr'] input_box = InputBoxMenu(self.screen, len(questions), (self.drl_train_button.coords[0] + 25, self.drl_train_button.coords[1] + 75), questions, [int, int]) input_box.help() inputs = input_box.ask_boxes() check = input_box.check_inputbox_input() error_message_pos = [20, 20] while check in input_box.errors: self.display_error_message('Error ' + check, position=tuple(error_message_pos), sleep_time=0) error_message_pos[1] += 40 inputs = input_box.ask_boxes() check = input_box.check_inputbox_input() agent = DqnSimulator(self.screen, self.screen_width, self.screen_height, 0, False, False, False, None, None, False, rays_nr=int(inputs[1])) agent.train_conv_dqn(int(inputs[0])) quit() else: self.drl_train_button.draw_button(self.screen, (110, -3)) def drl_predict_button_interaction(self): mouse_pos = pygame.mouse.get_pos() if (self.drl_predict_button.coords[0] < mouse_pos[0] < self.drl_predict_button.coords[0] + self.drl_predict_button.dimensions[0] and self.drl_predict_button.coords[1] < mouse_pos[1] < self.drl_predict_button.coords[1] + self.drl_predict_button.dimensions[1]): self.drl_predict_button.button_light(self.screen, (110, -3)) mouse_click = pygame.mouse.get_pressed() if mouse_click[0] == 1: self.pause_background_video = True questions = ['Rays_nr'] input_box = InputBoxMenu(self.screen, len(questions), (self.drl_predict_button.coords[0] + 25, self.drl_predict_button.coords[1] + 75), questions, [int]) input_box.help() inputs = input_box.ask_boxes() check = input_box.check_inputbox_input() error_message_pos = [20, 20] while check in input_box.errors: self.display_error_message('Error ' + check, position=tuple(error_message_pos), sleep_time=0) error_message_pos[1] += 40 inputs = input_box.ask_boxes() check = input_box.check_inputbox_input() agent = DqnSimulator(self.screen, self.screen_width, self.screen_height, 0, False, False, False, None, None, False, rays_nr=int(inputs[0])) agent.predict_conv_dqn() quit() else: self.drl_predict_button.draw_button(self.screen, (110, -3)) def exit_button_interaction(self): mouse_pos = pygame.mouse.get_pos() if (self.exit_button.coords[0] < mouse_pos[0] < self.exit_button.coords[0] + self.exit_button.dimensions[0] and self.exit_button.coords[1] < mouse_pos[1] < self.exit_button.coords[1] + self.exit_button.dimensions[1]): self.exit_button.button_light(self.screen, (140, -3)) mouse_click = pygame.mouse.get_pressed() if mouse_click[0] == 1: quit() else: self.exit_button.draw_button(self.screen, (140, -3)) def back_button_interaction(self): mouse_pos = pygame.mouse.get_pos() if (self.back_button.coords[0] < mouse_pos[0] < self.back_button.coords[0] + self.back_button.dimensions[0] and self.back_button.coords[1] < mouse_pos[1] < self.back_button.coords[1] + self.back_button.dimensions[1]): self.back_button.button_light(self.screen, (140, -3)) mouse_click = pygame.mouse.get_pressed() if mouse_click[0] == 1: self.pause_background_video = False if self.ga_buttons_interactions is True: self.ga_buttons_interactions = False elif self.drl_buttons_interactions is True: self.drl_buttons_interactions = False else: self.back_button.draw_button(self.screen, (140, -3)) def activation_cbox_interaction(self): mouse_pos = pygame.mouse.get_pos() if pygame.mouse.get_pressed()[0]: if self.activation_cbox.onCheckbox(mouse_pos): self.activation_cbox.changeState() self.activation_cbox.update() def sensors_cbox_interaction(self): mouse_pos = pygame.mouse.get_pos() if pygame.mouse.get_pressed()[0]: if self.sensors_cbox.onCheckbox(mouse_pos): self.sensors_cbox.changeState() elif self.distance_sensor_cbox.onCheckbox(mouse_pos): self.distance_sensor_cbox.changeState() self.sensors_cbox.update() self.distance_sensor_cbox.update() def traffic_cbox_interaction(self): mouse_pos = pygame.mouse.get_pos() if pygame.mouse.get_pressed()[0]: if self.traffic_cbox.onCheckbox(mouse_pos): self.traffic_cbox.changeState() self.traffic_cbox.update() def main_menu(self): video_thread = threading.Thread(target=self.background_video) video_thread.daemon = True video_thread.start() while not self.exit: if self.current_background_frame is not None: self.screen.blit(self.current_background_frame, (0, 0)) # self.screen.fill(config.background_color) # let menu simple self.checkbox_interactions() self.buttons_interactions() pygame.display.update() for event in pygame.event.get(): if event.type == pygame.QUIT: self.exit = True pygame.quit()
class Simulator: def __init__( self, screen, screen_width, screen_height, car_x=5, car_y=27, sensor_size=50, rays_nr=8, activations=False, record_data=False, replay_data_path=None, state_buf_path=None, sensors=False, distance_sensor=False, enabled_menu=False, # relative paths to the current folder object_map_path=None, background_path=None, car_image_path=None, traffic_car_image_path=None, object_car_image_path=None): pygame.init() self.screen_width = screen_width self.screen_height = screen_height self.screen = screen # The color of the object mask # Yellow self.bkd_color = [255, 255, 0, 255] self.current_dir = os.path.dirname(os.path.abspath(__file__)) self.car = Car(car_x, car_y) if car_image_path is not None: self.car_image_path = os.path.join(self.current_dir, car_image_path) self.car_image = pygame.image.load( self.car_image_path).convert_alpha() else: self.car_image = None if traffic_car_image_path is not None: self.traffic_image_path = os.path.join(self.current_dir, traffic_car_image_path) self.traffic_car_image = pygame.image.load( self.traffic_image_path).convert_alpha() else: self.traffic_car_image = None if object_car_image_path is not None: self.object_car_image_path = os.path.join(self.current_dir, object_car_image_path) self.object_car_image = pygame.image.load( self.object_car_image_path).convert_alpha() else: self.object_car_image = None if object_map_path is not None: self.object_map_path = os.path.join(self.current_dir, object_map_path) self.object_map = pygame.image.load( self.object_map_path).convert_alpha() else: self.object_map = None self.print_activations = activations self.model_path = os.path.join(self.current_dir, 'used_models/activations_model.h5') if os.path.exists(self.model_path) is False: raise OSError("model to path doesn't exists") self.background_path = os.path.join(self.current_dir, background_path) self.background = pygame.image.load(self.background_path).convert() self.bgWidth, self.bgHeight = self.background.get_rect().size pygame.font.init() self.used_font = pygame.font.SysFont('Comic Sans MS', 30) self.input_image = pygame.surfarray.array3d(self.screen) self.sensors = sensors self.distance_sensor = distance_sensor self.sensor_size = sensor_size self.rays_nr = rays_nr self.rays_sensor_distances = None self.sensor_mask = pygame.Surface( (self.screen_width, self.screen_height)) self.object_mask = pygame.Surface( (self.screen_width, self.screen_height)) self.record_data = record_data self.enabled_menu = enabled_menu self.replay_data_path = replay_data_path self.state_buf_path = state_buf_path self.ppu = 16 self.exit = False self.clock = pygame.time.Clock() self.ticks = 60 self.dt = None self.cbox_front_sensor = Checkbox(self.screen_width - 200, 10, 'Enable front sensor', self.sensors) self.cbox_rear_sensor = Checkbox(self.screen_width - 200, 35, 'Enable rear sensor', self.sensors) self.cbox_distance_sensor = Checkbox(self.screen_width - 200, 60, 'Enable distance sensor', self.distance_sensor) def on_road(self, car, screen): Ox = 32 Oy = 16 center_world_x = int(self.screen_width / 2) center_world_y = int(self.screen_height / 2) bot_right_x = center_world_x + int( Ox * cos(radians(-car.angle))) - int(Oy * sin(radians(-car.angle))) bot_right_y = center_world_y + int( Ox * sin(radians(-car.angle))) + int(Oy * cos(radians(-car.angle))) bot_left_x = center_world_x - int(Ox * cos(radians(-car.angle))) - int( Oy * sin(radians(-car.angle))) bot_left_y = center_world_y - int(Ox * sin(radians(-car.angle))) + int( Oy * cos(radians(-car.angle))) top_left_x = center_world_x - int(Ox * cos(radians(-car.angle))) + int( Oy * sin(radians(-car.angle))) top_left_y = center_world_y - int(Ox * sin(radians(-car.angle))) - int( Oy * cos(radians(-car.angle))) top_right_x = center_world_x + int( Ox * cos(radians(-car.angle))) + int(Oy * sin(radians(-car.angle))) top_right_y = center_world_y + int( Ox * sin(radians(-car.angle))) - int(Oy * cos(radians(-car.angle))) if (np.array_equal(screen.get_at( (bot_right_x, bot_right_y)), self.bkd_color) or np.array_equal(screen.get_at( (bot_left_x, bot_left_y)), self.bkd_color) or np.array_equal(screen.get_at( (top_left_x, top_left_y)), self.bkd_color) or np.array_equal(screen.get_at( (top_right_x, top_right_y)), self.bkd_color)): Collision.offroad(car) return False else: return True def compute_sensor_distance(self, car, base_point, sensor_length, sensor_angle, data_screen, draw_screen): end_point_x = base_point[0] + sensor_length * cos( radians(sensor_angle - car.angle)) end_point_y = base_point[1] + sensor_length * sin( radians(sensor_angle - car.angle)) for index in range(0, sensor_length): coll_point_x = base_point[0] + index * cos( radians(sensor_angle - car.angle)) coll_point_y = base_point[1] + index * sin( radians(sensor_angle - car.angle)) if np.array_equal( data_screen.get_at((int(coll_point_x), int(coll_point_y))), self.bkd_color): break pygame.draw.line(draw_screen, (0, 255, 0), base_point, (coll_point_x, coll_point_y), True) pygame.draw.line(draw_screen, (255, 0, 0), (coll_point_x, coll_point_y), (end_point_x, end_point_y), True) coll_point = (coll_point_x, coll_point_y) distance = euclidean_norm(base_point, coll_point) # print(distance) return distance def enable_sensor(self, car, draw_screen, rays_nr): """ distance sensor :param car: :param data_screen: :param draw_screen: :param rays_nr: :return: """ center_rect = Collision.center_rect(self.screen_width, self.screen_height) mid_of_front_axle = Collision.point_rotation(car, 0, 16, center_rect) distance = np.array([]) for angle_index in range(120, 240, int(round(120 / rays_nr))): distance = np.append( distance, self.compute_sensor_distance(car, mid_of_front_axle, 200, angle_index, self.object_mask, draw_screen)) return distance def optimized_front_sensor(self, act_mask, display_obstacle_on_sensor=False): """ front visual sensor :param act_mask: :param display_obstacle_on_sensor: :return: """ # act_mask is a separate image where you can only see what the sensor sees center_rect = Collision.center_rect(self.screen_width, self.screen_height) mid_of_front_axle = Collision.point_rotation(self.car, -1, 16, center_rect) arc_points = get_arc_points(mid_of_front_axle, 150, radians(90 + self.car.angle), radians(270 + self.car.angle), self.sensor_size) offroad_edge_points = [] for end_point in arc_points: points_to_be_checked = list( get_equidistant_points(mid_of_front_axle, end_point, 25)) check = False for line_point in points_to_be_checked: if np.array_equal( self.object_mask.get_at( (int(line_point[0]), int(line_point[1]))), self.bkd_color): check = True break if check is False: offroad_edge_points.append(end_point) else: offroad_edge_points.append(line_point) for index in range(0, len(arc_points)): if offroad_edge_points[index] == arc_points[index]: pygame.draw.line(self.screen, (0, 255, 0), mid_of_front_axle, arc_points[index], True) pygame.draw.line(act_mask, (0, 255, 0), mid_of_front_axle, arc_points[index], True) else: pygame.draw.line(self.screen, (0, 255, 0), mid_of_front_axle, offroad_edge_points[index], True) pygame.draw.line(act_mask, (0, 255, 0), mid_of_front_axle, offroad_edge_points[index], True) if display_obstacle_on_sensor is True: pygame.draw.line(self.screen, (255, 0, 0), offroad_edge_points[index], arc_points[index], True) pygame.draw.line(act_mask, (255, 0, 0), offroad_edge_points[index], arc_points[index], True) def optimized_rear_sensor(self, act_mask, display_obstacle_on_sensor=False): """ rear visual sensor :param car: :param object_mask: :param act_mask: :param display_obstacle_on_sensor: :return: """ # act_mask is a separate image where you can only see what the sensor sees center_rect = Collision.center_rect(self.screen_width, self.screen_height) mid_of_rear_axle = Collision.point_rotation(self.car, 65, 16, center_rect) arc_points = get_arc_points(mid_of_rear_axle, 150, radians(-90 + self.car.angle), radians(90 + self.car.angle), self.sensor_size) offroad_edge_points = [] for end_point in arc_points: points_to_be_checked = list( get_equidistant_points(mid_of_rear_axle, end_point, 25)) check = False for line_point in points_to_be_checked: if np.array_equal( self.object_mask.get_at( (int(line_point[0]), int(line_point[1]))), self.bkd_color): check = True break if check is False: offroad_edge_points.append(end_point) else: offroad_edge_points.append(line_point) for index in range(0, len(arc_points)): if offroad_edge_points[index] == arc_points[index]: pygame.draw.line(self.screen, (0, 255, 0), mid_of_rear_axle, arc_points[index], True) pygame.draw.line(act_mask, (0, 255, 0), mid_of_rear_axle, arc_points[index], True) else: pygame.draw.line(self.screen, (0, 255, 0), mid_of_rear_axle, offroad_edge_points[index], True) pygame.draw.line(act_mask, (0, 255, 0), mid_of_rear_axle, offroad_edge_points[index], True) if display_obstacle_on_sensor is True: pygame.draw.line(self.screen, (255, 0, 0), offroad_edge_points[index], arc_points[index], True) pygame.draw.line(act_mask, (255, 0, 0), offroad_edge_points[index], arc_points[index], True) def initialize_activation_model(self, desired_layer_output): """ activation model :param desired_layer_output: :return: """ if self.print_activations is True and self.model_path is None: raise ValueError('no model_path given.') model = load_model(self.model_path) print('Using model...') model.summary() init_activations_display_window(desired_layer_output, 2048, 1024, 0.7) layer_names = [] for layer in model.layers: layer_names.append(layer.name) image_buf = np.zeros((1, 500, 500, 3)) state_buf = np.zeros((1, 4)) layer_outputs = [layer.output for layer in model.layers] activation_model = models.Model(inputs=model.input, outputs=layer_outputs) return layer_names, image_buf, state_buf, activation_model def custom_drawing(self, *args): """ custom drawing function add drawings to simulator :param args: arguments :return: """ pass def draw_sim_environment(self, print_coords=False): # Drawing """ principal draw function that builds the simulator environment :param print_coords: print_coors on screen bool :return: """ stagePosX = self.car.position[0] * self.ppu stagePosY = self.car.position[1] * self.ppu rel_x = stagePosX % self.bgWidth rel_y = stagePosY % self.bgHeight self.object_mask.blit(self.object_map, (rel_x - self.bgWidth, rel_y - self.bgHeight)) self.object_mask.blit(self.object_map, (rel_x, rel_y)) self.object_mask.blit(self.object_map, (rel_x - self.bgWidth, rel_y)) self.object_mask.blit(self.object_map, (rel_x, rel_y - self.bgHeight)) self.screen.blit(self.background, (rel_x - self.bgWidth, rel_y - self.bgHeight)) self.screen.blit(self.background, (rel_x, rel_y)) self.screen.blit(self.background, (rel_x - self.bgWidth, rel_y)) self.screen.blit(self.background, (rel_x, rel_y - self.bgHeight)) if self.cbox_front_sensor is not None: self.cbox_front_sensor.update() if self.cbox_rear_sensor is not None: self.cbox_rear_sensor.update() if self.cbox_distance_sensor is not None: self.cbox_distance_sensor.update() if self.cbox_front_sensor.isChecked( ) is True or self.cbox_rear_sensor.isChecked() is True: self.sensors = True else: self.sensors = False if self.cbox_distance_sensor.isChecked() is True: self.distance_sensor = True else: self.distance_sensor = False rotated = pygame.transform.rotate(self.car_image, self.car.angle) rot_rect = rotated.get_rect() center_x = int(self.screen_width / 2) - int(rot_rect.width / 2) center_y = int(self.screen_height / 2) - int(rot_rect.height / 2) # draw the ego car self.screen.blit(rotated, (center_x, center_y)) self.custom_drawing() if print_coords is True: myfont = pygame.font.SysFont('Arial', 30) text1 = myfont.render('Car pos x: ' + str(round(stagePosX, 2)), True, (250, 0, 0)) text2 = myfont.render('Car pos y: ' + str(round(stagePosY, 2)), True, (250, 0, 0)) text3 = myfont.render('rel x: ' + str(round(rel_x, 2)), True, (250, 0, 0)) text4 = myfont.render('rel y: ' + str(round(rel_y, 2)), True, (250, 0, 0)) text5 = myfont.render( 'velocity: ' + str(round(self.car.velocity.x, 2) * self.ppu / 4) + ' km/h', True, (250, 0, 0)) self.screen.blit(text1, (20, 20)) self.screen.blit(text2, (20, 50)) self.screen.blit(text3, (20, 80)) self.screen.blit(text4, (20, 110)) self.screen.blit(text5, (20, 140)) return stagePosX, stagePosY, rel_x, rel_y def return_to_menu(self): """ if enabled_menu is True this function returns to main_menu :return: """ if self.enabled_menu is True: from car_kinematic_city_menu import Menu menu = Menu() menu.main_menu() return else: return def key_handler(self, dt, rs_pos_list): # User input """ key handler that coordinates the car movement with user keyboard input :param car: :param dt: :param rs_pos_list: :return: """ pressed = pygame.key.get_pressed() if pressed[pygame.K_ESCAPE]: if self.print_activations is True: cv2.destroyAllWindows() self.return_to_menu() quit() if pressed[pygame.K_r]: self.car.reset_car(rs_pos_list) if pressed[pygame.K_UP]: self.car.accelerate(dt) elif pressed[pygame.K_DOWN]: self.car.brake(dt) elif pressed[pygame.K_SPACE]: self.car.handbrake(dt) else: self.car.cruise(dt) if pressed[pygame.K_RIGHT]: self.car.steer_right(dt) elif pressed[pygame.K_LEFT]: self.car.steer_left(dt) else: self.car.no_steering() def event_handler(self, mouse_button_pressed): # Event queue """ event handler for sensors check_boxes, exit event or mouse pressing events :param mouse_button_pressed: :return: """ for event in pygame.event.get(): if event.type == pygame.QUIT: self.exit = True if event.type == pygame.MOUSEBUTTONDOWN: mouse_pos = pygame.mouse.get_pos() if self.cbox_front_sensor.onCheckbox( mouse_pos) and mouse_button_pressed is False: self.cbox_front_sensor.changeState() if self.cbox_rear_sensor.onCheckbox( mouse_pos) and mouse_button_pressed is False: self.cbox_rear_sensor.changeState() if self.cbox_distance_sensor.onCheckbox( mouse_pos) and mouse_button_pressed is False: self.cbox_distance_sensor.changeState() mouse_button_pressed = True if event.type == pygame.MOUSEBUTTONUP: mouse_button_pressed = False @staticmethod def convert_surface_to_opencv_img(surface): """ convert a surface to RGB opencv image :param surface: surface to be converted :return: """ if type(surface) == pygame.Surface: sensor_img = pygame.surfarray.array3d(surface) sensor_img = np.rot90(sensor_img, axes=(0, 1)) sensor_img = np.flipud(sensor_img) sensor_img = cv2.cvtColor(sensor_img, cv2.COLOR_BGR2RGB) return sensor_img else: raise ValueError("Given surface is not a pygame.Surface") def access_simulator_data(self, car_data=False, visual_sensor_data=False, distance_sensor_data=False): """ car_data: acceleration -> car_data[0] ; steering -> car_data[1] ; angle -> car_data[2] ; velocity -> car_data[3] sensor_data: subsurface with sensor image :param car_data: if you want to access car_data set to true :param visual_sensor_data: if you want to access sensor_data set to true :param distance_sensor_data: if you want to access rays_sensor_data set to true and check the cbox in the simulator for rays_sensor. :return: """ if car_data is True: car_acc = self.car.acceleration car_steering = self.car.steering car_angle = self.car.angle car_velocity = self.car.velocity.x car_data = [car_acc, car_steering, car_velocity, car_angle] return car_data elif visual_sensor_data is True: if self.sensors is True: image_rect = pygame.Rect((390, 110), (500, 500)) sub = self.sensor_mask.subsurface(image_rect) return sub else: return None elif distance_sensor_data is True: if self.distance_sensor is True: if self.rays_sensor_distances is not None: return self.rays_sensor_distances else: return [] else: return [] else: raise ValueError("Please specify what data type to be returned.") def activate_sensors(self): """ this function checks if any sensor has been activated :return: """ if self.cbox_front_sensor.isChecked(): self.optimized_front_sensor(self.sensor_mask, display_obstacle_on_sensor=True) if self.cbox_rear_sensor.isChecked(): self.optimized_rear_sensor(self.sensor_mask, display_obstacle_on_sensor=True) if self.cbox_distance_sensor.isChecked(): if self.cbox_rear_sensor.isChecked( ) is False and self.cbox_front_sensor.isChecked() is False: self.rays_sensor_distances = self.enable_sensor( self.car, self.screen, self.rays_nr) def record_data_function(self, index): """ recording tab :param index: image index :return: """ image_name = 'image_' + str(index) + '.png' index += 1 if self.state_buf_path is None: raise OSError('state_buf_path is empty.') if self.replay_data_path is None: raise OSError('replay_data_path is empty.') actions = [ self.car.position.x, self.car.position.y, float(round(self.car.angle, 3)), float(round(self.car.acceleration, 3)), float(round(self.car.velocity.x, 3)), image_name ] # Save state_buf write_state_buf(self.state_buf_path, actions) # Save replay write_data(self.replay_data_path, self.car.position, self.car.angle) def custom(self, *args): """ custom function in which to modify or access data if you want to create a simulation on top of another simulation but modify some things but not the run function you can add this custom() function inside of your run function and override it in the child simulator, but do not override the parent run() function. :param args: custom arguments if needed :return: """ pass def run(self): """ main run loop :return: """ pass