Example #1
0
    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
Example #2
0
    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()])
Example #3
0
 def test_constructor(self):
     """tests constructor"""
     checkbox = Checkbox([["Option", "option"]],
                         get_mock_input(),
                         get_mock_output(),
                         name=cb_name)
     self.assertIsNotNone(checkbox)
Example #4
0
    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)
Example #5
0
 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)
Example #6
0
 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)
Example #7
0
    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)
Example #8
0
 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),
     }
Example #9
0
    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()
Example #10
0
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()
Example #13
0
    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)
Example #14
0
#
############################################################

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")
Example #15
0
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')
Example #18
0
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()
Example #19
0
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