def __init__(self, new_start=None, new_end=None, new_max_speed=ROAD_DEFAULT_MAX_SPEED): """ Constructor method : creates a new road. """ self.start = new_start self.end = new_end self.max_speed = new_max_speed self.lanes = [Lane(self, i) for i in range(ROAD_DEFAULT_LANES)] self.traffic_lights_update = [lib.clock(), lib.clock()] self.traffic_lights = [True, False] # [at the beginning, at the end] # In order not to compute the unit vectors of the road several times, they are stored once they are computed self.parallel = None self.orthogonal = None self.start.host_road(self) self.end.host_road(self) width = 0 for lane in self.lanes: width += lane.width self.width = width
def __init__(self, new_track, new_x, new_y, new_spawning = False, new_radius = ROUNDABOUT_RADIUS_DEFAULT): """ Constructor method : creates a new roundabout. """ self.track = new_track self.position = Vector(TRACK_SCALE * new_x + TRACK_OFFSET_X, TRACK_SCALE * new_y + TRACK_OFFSET_Y) self.radius = new_radius self.incoming_roads = [] self.leaving_roads = [] self.cars = [] self.to_kill = [] self.slots_cars = {} self.max_cars = ROUNDABOUT_DEFAULT_MAX_CARS self.num_slots = ROUNDABOUT_DEFAULT_NUM_SLOTS self.rotation_speed = ROUNDABOUT_DEFAULT_ROTATION_SPEED self.spawning = new_spawning self.spawn_timer = lib.clock() self.last_shift = lib.clock() self.spawn_time = SPAWN_TIME self.slots_roads = [None] * self.num_slots self.local_load = 0 self.name = id(self) self.car_spiraling_time = {}
def __init__(self, new_track, new_x, new_y, new_spawning=False, new_radius=ROUNDABOUT_RADIUS_DEFAULT): """ Constructor method : creates a new roundabout. """ self.track = new_track self.position = Vector(TRACK_SCALE * new_x + TRACK_OFFSET_X, TRACK_SCALE * new_y + TRACK_OFFSET_Y) self.radius = new_radius self.incoming_roads = [] self.leaving_roads = [] self.cars = [] self.to_kill = [] self.slots_cars = {} self.max_cars = ROUNDABOUT_DEFAULT_MAX_CARS self.num_slots = ROUNDABOUT_DEFAULT_NUM_SLOTS self.rotation_speed = ROUNDABOUT_DEFAULT_ROTATION_SPEED self.spawning = new_spawning self.spawn_timer = lib.clock() self.last_shift = lib.clock() self.spawn_time = SPAWN_TIME self.slots_roads = [None] * self.num_slots self.local_load = 0 self.name = id(self) self.car_spiraling_time = {}
def update_car(self, car): """ Updates a given car on the roundabout """ if not (car in self.car_spiraling_time): self.car_spiraling_time[car] = [car.total_waiting_time, lib.clock()] car.total_waiting_time = self.car_spiraling_time[car][0] + lib.clock() - self.car_spiraling_time[car][1] if not(car.path is None) and self.leaving_roads: next_way = car.next_way(True) # Just read the next_way unless you really go there car_slot = lib.find_key(self.slots_cars, car) # The car has lost its slot if car_slot is None: raise Exception("ERROR (in Roundabout.update_car()) : a car has no slot !") # The car's slot is in front of a leaving road if self.slots_roads[car_slot] in self.leaving_roads: if (self.leaving_roads[next_way].is_free) and self.slots_roads[car_slot] == self.leaving_roads[next_way]: #la route sur laquelle on veut aller est vidée et surtout _en face_ du slot de la voiture car.join(self.leaving_roads[car.next_way(False) % len(self.leaving_roads)].get_free_lane()) # cette fois on fait une lecture destructive #la voiture n'a pas d'endroit où aller : on la met dans le couloir de la mort else: self.to_kill.append(car)
def __init__( self, new_start = None, new_end = None, new_max_speed = ROAD_DEFAULT_MAX_SPEED): """ Constructor method : creates a new road. """ self.start = new_start self.end = new_end self.max_speed = new_max_speed self.lanes = [Lane(self, i) for i in range(ROAD_DEFAULT_LANES)] self.traffic_lights_update = [lib.clock(), lib.clock()] self.traffic_lights = [True, False] # [at the beginning, at the end] # In order not to compute the unit vectors of the road several times, they are stored once they are computed self.parallel = None self.orthogonal = None self.start.host_road(self) self.end.host_road(self) width = 0 for lane in self.lanes: width += lane.width self.width = width
def update_car(self, car): """ Updates a given car on the roundabout """ if not (car in self.car_spiraling_time): self.car_spiraling_time[car] = [ car.total_waiting_time, lib.clock() ] car.total_waiting_time = self.car_spiraling_time[car][0] + lib.clock( ) - self.car_spiraling_time[car][1] if not (car.path is None) and self.leaving_roads: next_way = car.next_way( True) # Just read the next_way unless you really go there car_slot = lib.find_key(self.slots_cars, car) # The car has lost its slot if car_slot is None: raise Exception( "ERROR (in Roundabout.update_car()) : a car has no slot !") # The car's slot is in front of a leaving road if self.slots_roads[car_slot] in self.leaving_roads: if (self.leaving_roads[next_way].is_free) and self.slots_roads[ car_slot] == self.leaving_roads[next_way]: #la route sur laquelle on veut aller est vidée et surtout _en face_ du slot de la voiture car.join(self.leaving_roads[car.next_way(False) % len( self.leaving_roads)].get_free_lane() ) # cette fois on fait une lecture destructive #la voiture n'a pas d'endroit où aller : on la met dans le couloir de la mort else: self.to_kill.append(car)
def last_gate_update(self, gate): """ Return the time (in milliseconds) since the last update of a gate (0 or 1). """ current_time = lib.clock() return (current_time - self.traffic_lights_update[gate])
def timerEvent(self, event): """ /!\ Qt specific (please don't rename) Passes or uses timer events to update the simulation """ if event.timerId() == self.timer.timerId(): # Manage internal time events lib.delta_t = lib.clock() - self.last_update self.last_update = lib.clock() # Update the simulation and informations self.update_simulation() self.update_information() self.histogram.update() self.scene.update() else: QtGui.QFrame.timerEvent(self, event)
def update(self): """ Updates the roundabout : rotate the cars, dispatch them... """ #self.incoming_roads = sorted(self.incoming_roads, compa) # Make the cars rotate if lib.clock() - self.last_shift > ROUNDABOUT_ROTATION_RATE: self.last_shift = lib.clock() self.slots_roads = lib.shift_list(self.slots_roads) # Spawning mode if self.spawning and len(self.leaving_roads) and ( lib.clock() - self.spawn_timer > self.spawn_time): self.spawn_timer = lib.clock() num_possible_roads = len(self.leaving_roads) # Possible ways out. NB : the "1000/ " thing ensures *integer* probabilities. possible_roads_events = [(self.leaving_roads[i], 1000 / num_possible_roads) for i in range(num_possible_roads)] chosen_road = lib.proba_poll(possible_roads_events) if chosen_road.is_free: car_type_events = [(STANDARD_CAR, 80), (TRUCK, 15), (SPEED_CAR, 5)] new_car = __car__.Car(chosen_road.get_free_lane(), lib.proba_poll(car_type_events)) # Update traffic lights self._update_traffic_lights() # Update cars for car in self.cars: self.update_car(car) # Kill cars that have reached their destination for car in self.to_kill: car_slot = lib.find_key(self.slots_cars, car) self.slots_cars[car_slot] = None car.die() self.to_kill = []
def change_waiting_attitude(self, new_attitude): """ Changes, if needed, the waiting attitude of a car """ # There is no change : do nothing if new_attitude == self.is_waiting: return None # Start a "waiting" phase : reset the counter if new_attitude: self.is_waiting = True self.start_waiting_time = lib.clock() self.last_waiting_time = 0 # Stop a "waiting" phase : look at the clock else: self.is_waiting = False self.last_waiting_time = lib.clock() - self.start_waiting_time self.total_waiting_time += self.last_waiting_time
def update(self): """ Updates the roundabout : rotate the cars, dispatch them... """ #self.incoming_roads = sorted(self.incoming_roads, compa) # Make the cars rotate if lib.clock() - self.last_shift > ROUNDABOUT_ROTATION_RATE: self.last_shift = lib.clock() self.slots_roads = lib.shift_list(self.slots_roads) # Spawning mode if self.spawning and len(self.leaving_roads) and (lib.clock() - self.spawn_timer > self.spawn_time): self.spawn_timer = lib.clock() num_possible_roads = len(self.leaving_roads) # Possible ways out. NB : the "1000/ " thing ensures *integer* probabilities. possible_roads_events = [(self.leaving_roads[i], 1000/num_possible_roads) for i in range(num_possible_roads)] chosen_road = lib.proba_poll(possible_roads_events) if chosen_road.is_free: car_type_events = [(STANDARD_CAR, 80), (TRUCK , 15), (SPEED_CAR , 5)] new_car = __car__.Car(chosen_road.get_free_lane(), lib.proba_poll(car_type_events)) # Update traffic lights self._update_traffic_lights() # Update cars for car in self.cars: self.update_car(car) # Kill cars that have reached their destination for car in self.to_kill: car_slot = lib.find_key(self.slots_cars, car) self.slots_cars[car_slot] = None car.die() self.to_kill = []
def set_gate(self, road, state): """ Sets the state of the traffic lights on the road. road (Road) : the road whose traffic lights are affected state (bool) : the state (False = red, True = green) of the gate """ # Set which gate is to be updated if id(road.start) == id(self): current_gate = ENTRANCE else: current_gate = EXIT # Update if necessary if road.traffic_lights[current_gate] != state: road.traffic_lights_update[current_gate] = lib.clock() road.traffic_lights[current_gate] = state
def __init__(self, parent=None): """ Builds the main window. """ QtGui.QMainWindow.__init__(self, parent) # Set parameters lib.delta_t = 0 self.last_update = lib.clock() self.selected_car = None self.selected_roundabout = None # Set the interface self.setup_interface() # Start the timer self.timer = QtCore.QBasicTimer() self.timer.start(10, self)
def __init__(self, parent = None): """ Builds the main window. """ QtGui.QMainWindow.__init__(self, parent) # Set parameters lib.delta_t = 0 self.last_update = lib.clock() self.selected_car = None self.selected_roundabout = None # Set the interface self.setup_interface() # Start the timer self.timer = QtCore.QBasicTimer() self.timer.start(10, self)
def find_path(self, origin, destination, max_time = 1): """ Performs an A* pathfinding to get a path from origin to destination. Returns a list of integers, representing the roads to take. origin (Roundabout) destination (Roundabout) max_time (float) : maximum time allowed for the pathfinding algorithm (in seconds) """ # Before we start, let's check we need to do something if origin == destination or self._heuristic_weight(origin, destination) == 0: return None # Add the starting point to the "open" list self.open_list.append(origin) self.g_cost[origin] = 0 self.h_cost[origin] = self.f_cost[origin] = self._heuristic_weight(origin, destination) self.start_time = lib.clock() nearest_parent = {} self.path = PATH_INEXISTENT #while (lib.clock() - self.start_time) < max_time: while len(self.open_list): # The "parent" node, around which we look, is always the first node of the "open" list # This node is transferred to the "closed" list current_parent = self.open_list[0] self.closed_list.append(current_parent) del self.open_list[0] # The "parent" node is the destination : the path has been found. if current_parent == destination: self.path = PATH_FOUND break # Set the first element of the open list as the one that has the smallest F-cost for (i, node) in enumerate(self.open_list): if self.f_cost[self.open_list[0]] > self.f_cost[node]: (self.open_list[i], self.open_list[0]) = (self.open_list[0], node) # Check the adjacent nodes children = [road.end for road in current_parent.leaving_roads] for child in children: # Not already in the closed list neither in the open list if not (child in self.closed_list) and not (child in self.open_list): # Compute its G-cost, H-cost and F-cost self.g_cost[child] = self.g_cost[current_parent] + road.weight self.h_cost[child] = self._heuristic_weight(child, destination) self.f_cost[child] = self.g_cost[child] + self.h_cost[child] nearest_parent[child] = current_parent # Add the node to the open list, keeping the order (the first node has the smallest F-cost) if len(self.open_list) and (self.f_cost[self.open_list[0]] > self.f_cost[child]): self.open_list.insert(0, child) else: self.open_list.append(child) # Already in the open list : check to see if this path is a better one than the currently known path elif child in self.open_list: # Compute the G-cost of this possible new path current_g_cost = self.g_cost[current_parent] + road.weight # This path is shorter (lower G-cost) : store this path as default to reach this node if current_g_cost < self.g_cost[child]: # Set this path as the shortest path to reach this node nearest_parent[child] = current_parent self.g_cost[child] = current_g_cost self.f_cost[child] = self.g_cost[current_parent] + self.h_cost[child] # Do not forget to update the F-cost ! # Check if the open list is still in the right order if self.f_cost[self.open_list[0]] > self.f_cost[child]: i = self.open_list.index(child) (self.open_list[0], self.open_list[i]) = (self.open_list[i], self.open_list[0]) # Save the path if it exists. if self.path == PATH_FOUND: current_node = destination self.path = [] self.path_length = 0 while current_node != origin: self.path.insert(0, current_node) if current_node in nearest_parent: current_node = nearest_parent[current_node] else: raise Exception('ERROR (in gps.find_path()): ill-formed parent list, a node has no parent.') self.path_length += 1 return self._build_path() return None