Beispiel #1
0
class Environment(object):
    NUM_SENSORS = 5

    def __init__(self, circuit, render=False):
        self.circuit = circuit
        self.car = Car(self.circuit, num_sensors=self.NUM_SENSORS)

        # To render the environment
        self.render = render
        if render:
            self.ui = Interface(self.circuit, self.car)
            self.ui.show(block=False)

        # Build the possible actions of the environment
        self.actions = []
        for turn_step in range(-2, 3, 1):
            for speed_step in range(-1, 2, 1):
                self.actions.append((speed_step, turn_step))

        self.count = 0

    def reward(self) -> float:
        """Computes the reward at the present moment"""

        # This should return a float"""
        if not (self.isEnd()):
            reward = self.car.speed * (min(self.car.distances()))
        else:
            reward = -1
        return reward

    def isEnd(self) -> bool:
        """Is the episode over ?"""
        if (not (self.car.in_circuit())):
            return True
        return False

    def reset(self):
        self.count = 0
        self.car.reset()
        self.circuit.reset()
        return self.current_state

    @property
    def current_state(self):
        result = self.car.distances()
        result.append(self.car.speed)
        return result

    def step(self, i: int, greedy):
        """Takes action i and returns the new state, the reward and if we have
        reached the end"""
        self.count += 1
        self.car.action(*self.actions[i])

        state = self.current_state
        isEnd = self.isEnd()
        reward = self.reward()
        completed = self.circuit.laps * 100 + self.circuit.progression * 100

        if self.render:
            self.ui.update()

        return state, reward, isEnd, completed

    def mayAddTitle(self, title):
        if self.render:
            self.ui.setTitle(title)
Beispiel #2
0
class App:
    """Application principale"""
    def __init__(self):
        self.window = Tk()
        self.canvas = None
        self.forms = []
        self.setup_window()
        self.setup_window_components()
        self.is_drawing_mode = False
        self.is_drawing_line = False
        self.line_start_x = None
        self.line_start_y = None

    def setup_window(self):
        width = 800
        height = 650
        x = (self.window.winfo_screenwidth() / 2) - (width / 2)
        y = (self.window.winfo_screenheight() / 2) - (height / 2)
        if self.window.winfo_screenwidth() == 1920:
            self.window.geometry('%dx%d+%d+%d' % (width, height, x + 500, y))
        else:
            self.window.geometry('%dx%d+%d+%d' % (width, height, x - 500, y))
        self.window.title('Race Circuit')
        self.canvas = Canvas(self.window,
                             bg='#202827',
                             height=height - 40,
                             width=width)
        self.canvas.bind("<Button-1>", self.start_line)
        self.canvas.bind("<B1-Motion>", self.drawing_line)
        self.canvas.bind("<ButtonRelease-1>", self.draw_line)
        self.car = Car(self.canvas)
        # Car Control
        self.window.bind("<KeyPress-Up>", self.car.up)
        self.window.bind("<KeyPress-Down>", self.car.down)
        self.window.bind("<KeyPress-Left>", self.car.turn_left)
        self.window.bind("<KeyPress-Right>", self.car.turn_right)
        self.window.bind("<space>", self.car.stop)
        self.canvas.pack(side=BOTTOM)

    def setup_window_components(self):
        self.draw_line_btn = Button(self.window)
        self.draw_line_img = PhotoImage(file=ROOT_DIR +
                                        "/assets/draw_line.png")
        self.draw_line_btn.config(image=self.draw_line_img,
                                  command=self.active_drawing_mode)
        self.draw_line_btn.pack(side=LEFT)

        self.open_btn = Button(self.window)
        self.open_img = PhotoImage(file=ROOT_DIR + "/assets/open.png")
        self.open_btn.config(image=self.open_img,
                             command=self.choose_and_draw_from_file)
        self.open_btn.pack(side=LEFT)

        self.save_btn = Button(self.window)
        self.save_img = PhotoImage(file=ROOT_DIR + "/assets/save.png")
        self.save_btn.config(image=self.save_img, command=self.save_positions)
        self.save_btn.pack(side=LEFT)

        self.erase_btn = Button(self.window)
        self.erase_img = PhotoImage(file=ROOT_DIR + "/assets/erase.png")
        self.erase_btn.config(image=self.erase_img, command=self.erase)
        self.erase_btn.pack(side=LEFT)

        self.reset_btn = Button(self.window)
        self.reset_img = PhotoImage(file=ROOT_DIR + "/assets/reset.png")
        self.reset_btn.config(image=self.reset_img, command=self.reset)
        self.reset_btn.pack(side=LEFT)

    def reset(self):
        self.car.reset()

    def run(self, creative_mode=False):
        if creative_mode is False:
            circuit01_path = ROOT_DIR + "/saves/circuit01.txt"
            if os.path.exists(circuit01_path):
                self.draw_from_file(circuit01_path)

            self.car.draw()
            self.car.move()
        self.window.mainloop()

    def active_drawing_mode(self):
        """
        Fonction de callback appelée lorsque l'on appuie sur le bouton de dessin
        """
        self.is_drawing_mode = not self.is_drawing_mode
        if self.is_drawing_mode is True:
            self.draw_line_btn.config(bg='#aaa')
        else:
            self.draw_line_btn.config(bg='#d9d9d9')

    def start_line(self, event):
        """
        Fonction de callback appelée lorsque l'on clique dans le canvas
        a pour effet d'activer une variable de controle qui va dire que l'on est en train de dessiner
        ainsi que d'enregistrer la position x;y de départ de la ligne
        """
        # active une seconde variable qui servira de condition quant à l'écoute de l'event B1-Motion
        if self.is_drawing_mode:
            self.is_drawing_line = True
            self.line_start_x = event.x
            self.line_start_y = event.y

    def drawing_line(self, event):
        """
        Fonction de callback appelée lorsque l'on maintient le click enfoncé pour dessiner la ligne
        Si jamais on est en mode dessin et que l'on a bien cliquer pour commencer à dessiner,
        alors on supprime tous les dessins avec le tag 'temporary', et on crée une ligne avec la position de
        départ et la position courante de la souris
        """
        if self.is_drawing_mode and self.is_drawing_line:
            self.canvas.delete("temporary")
            line = self.canvas.create_line(self.line_start_x,
                                           self.line_start_y,
                                           event.x,
                                           event.y,
                                           width=3,
                                           fill="#A9ACAB")
            self.canvas.itemconfig(line, tags="temporary")

    def draw_line(self, event):
        """
        Lorsque l'on relache la souris, les lignes temporaires sont supprimées,
        et une ligne "définitive" est crée et ajoutée à une liste
        """
        if self.is_drawing_mode and self.is_drawing_line:
            self.canvas.delete("temporary")
            self.is_drawing_line = False
            line_coord = self.line_start_x, self.line_start_y, event.x, event.y
            line = self.canvas.create_line(*line_coord,
                                           width=3,
                                           fill="#A9ACAB")
            self.canvas.itemconfig(line, tags="track_segment")
            self.forms.append(line)

    def draw_point(self, point):
        self.canvas.create_oval(point[0] - 3,
                                point[1] - 3,
                                point[0],
                                point[1],
                                outline='red',
                                fill='red')

    def save_positions(self):
        if len(self.forms) == 0:
            print("Il n'y a rien à sauvegarder")
        else:
            positions = ""
            for form in self.forms:
                positions += str(self.canvas.coords(form)).replace(
                    "[", "").replace("]", "") + "\n"
            save_text_in_file(positions, saves_dir,
                              "save_" + now.strftime("%Y%d%m-%H%M%S"))

    def choose_and_draw_from_file(self):
        self.erase()
        file_path = choose_file(saves_dir)
        self.draw_from_file(file_path)

    def draw_from_file(self, file_path):
        with open(file_path, 'r') as file:
            for line in file:
                coords = line.replace(" ", "").rstrip().split(",")
                line_form = self.canvas.create_line(coords[0],
                                                    coords[1],
                                                    coords[2],
                                                    coords[3],
                                                    width=3,
                                                    fill="#A9ACAB")
                self.canvas.itemconfig(line_form, tags="track_segment")
                self.forms.append(line_form)

    def erase(self):
        self.canvas.delete("track_segment")
        self.forms = []
Beispiel #3
0
class Environment(object):
    NUM_SENSORS = 5

    def __init__(self, circuit, render=False):
        self.circuit = circuit
        self.car = Car(self.circuit, num_sensors=self.NUM_SENSORS)
        # To render the environment
        self.render = render
        if render:
            self.ui = Interface(self.circuit, self.car)
            self.ui.show(block=False)

        # Build the possible actions of the environment
        self.actions = []
        for turn_step in range(-2, 3, 1):
            for speed_step in range(-1, 2, 1):
                self.actions.append((speed_step, turn_step))
        self.count = 0

    def reward(self) -> float:
        """Computes the reward at the present moment"""

        # TODO(students): !!!!!!!!! IMPLEMENT THIS !!!!!!!!!!!!!!  """
        # This should return a float"""
        self.reward_val = self.circuit.progression
        return self.reward_val

    def isEnd(self) -> bool:
        """Is the episode over ?"""

        # TODO(students): !!!!!!!!! IMPLEMENT THIS !!!!!!!!!!!!!!  """
        # Should return true if we have reached the end of an episode, False
        # otherwise
        # print(self.reward_val)
        if not self.car.in_circuit() or self.car.speed < 10e-5:
            return True
        return False

    def reset(self):
        self.count = 0
        self.car.reset()
        self.circuit.reset()
        return self.current_state

    @property
    def current_state(self):
        result = self.car.distances()
        result.append(self.car.speed)
        return result

    def step(self, i: int, greedy):
        """Takes action i and returns the new state, the reward and if we have
        reached the end"""
        # print(self.car.speed)
        self.count += 1
        self.car.action(*self.actions[i])

        state = self.current_state
        isEnd = self.isEnd()
        reward = self.reward()

        if self.render:
            self.ui.update()

        return state, reward, isEnd

    def mayAddTitle(self, title):
        if self.render:
            self.ui.setTitle(title)