def wrapper(*args, **kwargs): self.write("Started: {}".format(func.__name__), debug_level) timer = Timer() res = func(*args, **kwargs) exec_time = timer.stop() self.write("Finished: {}, execution time: {} seconds".format(func.__name__, round(exec_time, 2)), debug_level) return res
class MainView(View): MVG_AVG_SIZE = 3 __frame_timer: Timer __frame_count: int __frame_mvg_average: int __fps: int """ Draws the model state onto the screen. """ def __init__(self, services: Services, model: Model, root_view: Optional[View]) -> None: super().__init__(services, model, root_view) self._services.ev_manager.register_tick_listener(self) self.__frame_timer = Timer() self.__frame_count = 0 self.__frame_mvg_average = 0 self.__fps = 0 self.__screen = None self._initialised = False def notify(self, event: Event) -> None: """ Receive events posted to the message queue. """ super().notify(event) if isinstance(event, QuitEvent): self._initialised = False self._services.graphics.window.quit() def initialise(self) -> None: self.__frame_timer = Timer() def tick(self) -> None: if not self._initialised: return self.update() def update(self) -> None: if self.__frame_timer.stop() >= 1: if self.__frame_mvg_average == 0: self.__fps = self.__frame_count else: self.__fps += (self.__frame_count - self.__fps) / self.__frame_mvg_average self.__frame_mvg_average = min(self.__frame_mvg_average + 1, self.MVG_AVG_SIZE) self.__frame_count = 0 self.__frame_timer = Timer() self._services.debug.write("FPS: " + str(self.__fps), DebugLevel.MEDIUM) for child in self._children: child.update() # update window self._services.graphics.window.update() self.__frame_count += 1
class SelectorManager(object): def __init__(self): self._selector = None self._timer = Timer() def set_selector(self, selector): self._selector = selector def apply(self, event): self._timer.start() result = self._selector.apply(event) if self._selector else True self._timer.stop() return result def __str__(self): return str(self._timer)
class BasicTesting: """ Basic class used to assess the performance of an algorithms All tests must inherit from this class """ timer: Timer display_info: List[MapDisplay] key_frame: Callable[[List, Dict], None] cv: Condition key_frame_skip_count: int total_time: int def __init__(self, services: Services) -> None: self._services = services self.timer = None self.display_info = [] self.key_frame = lambda *args, **kwargs: None self.cv = None self.key_frame_skip_count = 0 self.total_time = 0 self.last_frame_time = 0 self.requires_key_frame = False self.reset() def reset(self) -> None: """ This method resets the testing state """ self.display_info = [] self.cv = None self.key_frame_skip_count = 0 self.total_time = 0 self.last_frame_time = 0 if self._services.settings.simulator_key_frame_speed == 0 or not self._services.settings.simulator_graphics: self.key_frame = lambda *args, **kwargs: None else: self.key_frame = self.key_frame_internal def set_condition(self, cv: Condition) -> None: """ Setter for condition :param cv: The condition is used to synchronize key frames """ self.cv = cv def algorithm_start(self) -> None: """ Marks the start of the algorithms """ self._services.debug.write( "Algorithm " + str(self._services.algorithm.algorithm_type) + " started..", DebugLevel.BASIC) self.timer = Timer() def is_terminated(self) -> bool: return self._services.algorithm.instance.testing != self def key_frame_internal(self, ignore_key_frame_skip: bool = False, only_render: List[int] = None, root_key_frame=None) -> None: """ Internal key frame handler """ if self.timer is None: self._services.debug.write_error( "Algorithm " + str(self._services.algorithm.algorithm_type) + " hasn't started yet!") return self.timer.pause() if root_key_frame: root_key_frame.instance.testing.key_frame( ignore_key_frame_skip=ignore_key_frame_skip, only_render=only_render) def sleep_pred(): return not self.requires_key_frame or self.is_terminated() # skip render frame if ignore_key_frame_skip or self.key_frame_skip_count >= self._services.settings.simulator_key_frame_skip: self.display_info = self._services.algorithm.instance.set_display_info( ) if only_render: self.display_info = [self.display_info[i] for i in only_render] if self.cv is not None: with self.cv: self.requires_key_frame = True self.cv.notify() cond_var_wait_for(self.cv, sleep_pred) self.key_frame_skip_count = 0 else: self.key_frame_skip_count += 1 # limit key frame speed if self.cv is not None: t = time.time() sleep_dt = self._services.settings.simulator_key_frame_speed - ( t - self.last_frame_time) self.last_frame_time = t while sleep_dt > 0: with self.cv: self.requires_key_frame = True self.cv.notify() cond_var_wait_for(self.cv, sleep_pred) nt = time.time() sleep_dt = sleep_dt - nt + t t = nt if self.is_terminated(): from simulator.models.map_model import AlgorithmTerminated raise AlgorithmTerminated() self.timer.resume() def algorithm_done(self) -> None: """ Marks the end of the algorithms """ if self.timer is None: self._services.debug.write_error( "Algorithm " + str(self._services.algorithm.algorithm_type) + "did not start!") return self.total_time = self.timer.stop() if self._services.settings.simulator_graphics: self.display_info = self._services.algorithm.instance.set_display_info( ) self.print_results() self._services.debug.write("", DebugLevel.BASIC, timestamp=False) def get_results(self) -> Dict[str, Any]: """ Returns the test results :return: The test results """ trace: List[Trace] = self._services.algorithm.map.trace grid: Optional[DenseMap] = self._services.algorithm.map if isinstance(grid, SparseMap): grid: DenseMap = grid.convert_to_dense_map() return { "map": self._services.algorithm.map, "map_obstacles_percentage": self.get_occupancy_percentage_grid(grid.grid, DenseMap.WALL_ID), "goal_found": self._services.algorithm.map.is_goal_reached(grid.agent.position), "distance_to_goal": self.distance_from_agent_to_goal(grid), "original_distance_to_goal": self.get_original_distance(grid), "trace": trace, "total_steps": len(trace), "total_distance": self.get_euclidean_distance_traveled(trace, grid.agent), "smoothness_of_trajectory": self.get_smoothness(trace, grid.agent), "obstacle_clearance": self.get_average_clearance(trace, self._services.algorithm.map), "total_time": self.total_time, "algorithm_type": self._services.algorithm.algorithm_type, } def print_results(self) -> None: """ Prints the test results """ results: Dict[str, Any] = self.get_results() self._services.debug.write("Map: " + str(results["map"]), DebugLevel.MEDIUM) self._services.debug.write( "Original distance: {0:.2f}".format( results["original_distance_to_goal"]), DebugLevel.BASIC) self._services.debug.write( "Occupancy percentage: {0:.2f}%".format( results["map_obstacles_percentage"]), DebugLevel.BASIC) self._services.debug.write( "Goal was " + ("FOUND" if results["goal_found"] else "NOT FOUND"), DebugLevel.BASIC) if not results["goal_found"]: self._services.debug.write( "Distance to goal: " + str(results["distance_to_goal"]) + " (Original: {})".format(results["original_distance_to_goal"])) self._services.debug.write( "Total steps: " + str(results["total_steps"]), DebugLevel.BASIC) self._services.debug.write( "Total distance: {0:.2f}".format(results["total_distance"]), DebugLevel.BASIC) self._services.debug.write( "Trajectory Smoothness: {0:.2f}".format( results["smoothness_of_trajectory"]), DebugLevel.BASIC) self._services.debug.write( "Total time: " + str(results["total_time"]) + " seconds", DebugLevel.BASIC) self._services.debug.write("Trace: " + str(results["trace"]), DebugLevel.MEDIUM) @staticmethod def get_occupancy_percentage_grid(grid: np.array, token: int) -> float: """ Searches for token in grid and returns the occupancy percentage of the token :param grid: The grid :param token: The search token :return: The percentage """ tokens: int = np.sum(grid == token) return BasicTesting.get_occupancy_percentage_size( Size(*grid.shape), tokens) @staticmethod def get_original_distance(mp: Map): agent_pos = mp.trace[0].position if mp.trace else None return BasicTesting.distance_from_agent_to_goal(mp, agent_pos) @staticmethod def distance_from_agent_to_goal(mp: Map, agent_pos: Point = None): if agent_pos is None: agent_pos = mp.agent.position dist = np.linalg.norm(np.array(agent_pos) - np.array(mp.goal.position)) return dist @staticmethod def get_occupancy_percentage_size(size: Size, items_nr: int) -> float: """ Returns the percentage of present items given the size :param size: The size :param items_nr: The number of items :return: The percentage """ return (items_nr / reduce(mul, size, 1)) * 100 @staticmethod def get_euclidean_distance_traveled(trace: List[Trace], agent: Agent) -> float: if (not trace) or trace[-1].position != agent.position: trace.append(Trace(agent.position)) dist = 0 for i in range(1, len(trace)): dist += np.linalg.norm( np.array(trace[i - 1].position) - np.array(trace[i].position)) return dist @staticmethod def get_smoothness(trace: List[Trace], agent: Agent) -> float: if (not trace) or trace[-1].position != agent.position: trace.append(Trace(agent.position)) angle = 0 prev_angle = None for i in range(1, len(trace)): if (not trace[i - 1].position == trace[i].position): unit_vector1 = np.array(trace[i - 1].position - trace[i].position) / np.linalg.norm( np.array(trace[i - 1].position - trace[i].position)) t = [0] * (len(agent.position) - 1) t = tuple([1] + t) dot_product = np.dot(unit_vector1, t) if prev_angle is None: prev_angle = np.arccos(dot_product) continue angle += abs(prev_angle - np.arccos(dot_product)) prev_angle = np.arccos(dot_product) return (angle / len(trace)) @staticmethod def get_average_clearance(trace: List[Trace], grid: Map) -> float: if isinstance(grid, DenseMap): obstacles = np.transpose(np.where(grid.grid == grid.WALL_ID)) else: obstacles = np.full(grid.size, grid.CLEAR_ID, dtype=np.uint8) for o in grid.obstacles: if type(o) is Obstacle: # we don't want extended wall obstacles[o.position.values] = grid.WALL_ID obstacles = np.transpose(np.where(obstacles == grid.WALL_ID)) if len(grid.obstacles) == 0: return 0 obstacle_dists = [] for t in trace: pos = np.array(t.position.values) obstacles_shifted = obstacles - pos norms = np.linalg.norm(obstacles_shifted, axis=1) min_dist = np.min(norms) obstacle_dists.append(min_dist) return sum(obstacle_dists) / len(obstacle_dists) @property def map(self) -> str: return "map" @map.getter def map(self) -> Map: return self._services.algorithm.map
#!/usr/bin/env python ''' Created by Samvel Khalatyan, May 02, 2012 Copyright 2012, All rights reserved ''' from __future__ import print_function import sys import tempfile from utility.timer import Timer if "__main__" == __name__: tests = int(sys.argv[1]) if 1 < len(sys.argv) else 1000 print("run", tests, "tests") timer = Timer() filename = tempfile.mktemp() with open(filename, "w") as output_: for test in range(tests): timer.start() output_.write("this is a test string which should go into file\n") timer.stop() print(timer) print("(outpus is saved in:", filename, ")")
class MapModel(Model): speed: int key_frame_is_paused: bool last_thread: Thread frame_timer: Timer condition: Condition processing_key_frame: bool def __init__(self, services: Services) -> None: super().__init__(services) self._services.ev_manager.register_tick_listener(self) self.last_thread = None self.key_frame_is_paused = False self.cv = Condition() self.processing_key_frame = False self.frame_timer = Timer() self.speed = 1 self._services.algorithm.set_root() def move_forward(self, e) -> None: self.reset() if self._services.algorithm.map.size.n_dim == 3: p = Point(e.position.x, e.position.y + self.speed, e.position.z) else: p = Point(e.position.x, e.position.y + self.speed) self.move_valid_entity(e, p) def move_backwards(self, e) -> None: self.reset() if self._services.algorithm.map.size.n_dim == 3: p = Point(e.position.x, e.position.y - self.speed, e.position.z) else: p = Point(e.position.x, e.position.y - self.speed) self.move_valid_entity(e, p) def move_up(self, e) -> None: if self._services.algorithm.map.size.n_dim == 3: self.reset() p = Point(e.position.x, e.position.y, e.position.z + self.speed) self.move_valid_entity(e, p) def move_down(self, e) -> None: if self._services.algorithm.map.size.n_dim == 3: self.reset() p = Point(e.position.x, e.position.y, e.position.z - self.speed) self.move_valid_entity(e, p) def move_left(self, e) -> None: self.reset() if self._services.algorithm.map.size.n_dim == 3: p = Point(e.position.x - self.speed, e.position.y, e.position.z) else: p = Point(e.position.x - self.speed, e.position.y) self.move_valid_entity(e, p) def move_right(self, e) -> None: self.reset() if self._services.algorithm.map.size.n_dim == 3: p = Point(e.position.x + self.speed, e.position.y, e.position.z) else: p = Point(e.position.x + self.speed, e.position.y) self.move_valid_entity(e, p) def move_valid_entity(self, e, p) -> None: if self._services.algorithm.map.is_agent_valid_pos(p): if self.is_agent(e): self.move(p, False) self._services.debug.write("Moved agent to: " + str(p), DebugLevel.MEDIUM) else: self.move_goal(p, False) self._services.debug.write("Moved goal to: " + str(p), DebugLevel.MEDIUM) def is_agent(self, e) -> bool: return e is self._services.algorithm.map.agent def reset(self) -> None: self.stop_algorithm() self._services.algorithm.reset_algorithm() if self.processing_key_frame: self.processing_key_frame = False with self.cv: self.requires_key_frame = False self.cv.notify_all() with self.cv: cond_var_wait_for( self.cv, lambda: self.last_thread is None or self.requires_key_frame, timeout=0.8) if self.last_thread is not None: self.requires_key_frame = False self.cv.notify_all() cond_var_wait_for(self.cv, lambda: self.last_thread is None, timeout=0.8) self.requires_key_frame = False if self.last_thread is None: self._services.ev_manager.post(KeyFrameEvent(refresh=True)) def move(self, to: Point, should_reset: bool = True) -> None: if should_reset: self.reset() self._services.algorithm.map.move_agent(to, True) self._services.ev_manager.broadcast(StateEntityUpdateEvent()) def move_goal(self, to: Point, should_reset: bool = True) -> None: if should_reset: self.reset() self._services.algorithm.map.move(self._services.algorithm.map.goal, to, True) self._services.ev_manager.broadcast(StateEntityUpdateEvent()) def stop_algorithm(self) -> None: self.key_frame_is_paused = True def resume_algorithm(self) -> None: self.key_frame_is_paused = False def toggle_pause_algorithm(self) -> None: self.key_frame_is_paused = not self.key_frame_is_paused @property def requires_key_frame(self) -> bool: return self._services.algorithm.instance.testing is not None and self._services.algorithm.instance.testing.requires_key_frame @requires_key_frame.setter def requires_key_frame(self, value) -> None: if self._services.algorithm.instance.testing is not None: self._services.algorithm.instance.testing.requires_key_frame = value def tick(self) -> None: if self.processing_key_frame: self.processing_key_frame = False with self.cv: self.requires_key_frame = False self.cv.notify_all() if not self.key_frame_is_paused and self.last_thread is not None: MAX_FRAME_DT = 1 / 16 dt = self.frame_timer.stop() if self.requires_key_frame or (dt < MAX_FRAME_DT): with self.cv: if cond_var_wait_for(self.cv, lambda: self.requires_key_frame or self.last_thread is None, timeout=(MAX_FRAME_DT - dt)): self.processing_key_frame = True self._services.ev_manager.post(KeyFrameEvent()) self.frame_timer = Timer() def compute_trace(self) -> None: if self.last_thread: return self.reset() def compute_wrapper() -> None: terminated = False self.key_frame_is_paused = False if self._services.settings.simulator_key_frame_speed > 0: self._services.algorithm.instance.set_condition(self.cv) self._services.ev_manager.post(KeyFrameEvent(refresh=True)) try: self._services.algorithm.instance.find_path() except AlgorithmTerminated: self._services.debug.write("Terminated algorithm", DebugLevel.BASIC) self._services.ev_manager.post(KeyFrameEvent(refresh=True)) terminated = True if self._services.settings.simulator_key_frame_speed == 0: # no animation hence there hasn't been a chance to render # the last state of the algorithm. self._services.ev_manager.post(KeyFrameEvent(refresh=True)) self._services.ev_manager.broadcast( StateTerminatedEvent() if terminated else StateDoneEvent()) with self.cv: self.last_thread = None self.cv.notify() self.last_thread = Thread(target=compute_wrapper, daemon=True) self.last_thread.start() def toggle_convert_map(self) -> None: if isinstance(self._services.algorithm.map, DenseMap): self._services.debug.write("Converting map to SparseMap", DebugLevel.BASIC) mp = self._services.algorithm.map.convert_to_sparse_map() elif isinstance(self._services.algorithm.map, SparseMap): self._services.debug.write("Converting map to DenseMap", DebugLevel.BASIC) mp = self._services.algorithm.map.convert_to_dense_map() else: self._services.debug.write("Map conversion not applicable", DebugLevel.BASIC) return if mp is None: self._services.debug.write("Map conversion not applicable", DebugLevel.BASIC) return self.reset() timer: Timer = Timer() self._services.algorithm.map = mp self._services.debug.write( "Done converting. Total time: " + str(timer.stop()), DebugLevel.BASIC) self._services.debug.write(self._services.algorithm.map, DebugLevel.MEDIUM) self._services.ev_manager.post(KeyFrameEvent()) def notify(self, event: Event) -> None: """ Called by an event in the message queue. """ if isinstance(event, ResetEvent): self.reset()
def generate_map_from_image(self, image_name: str, rand_entities: bool = False, entity_radius: int = None, house_expo_flag: bool = False) -> Map: """ Generate a map from an image Load the image from the default location and save the map in the default location :param image_name: The image name :return: The map """ self.__services.debug.write( "Started map generation from image: " + str(image_name) + " With House_expo = " + str(house_expo_flag), DebugLevel.BASIC) timer: Timer = Timer() # loading image if house_expo_flag: surface: np.ndarray = self.__services.resources.house_expo_dir.load( image_name) else: surface: np.ndarray = self.__services.resources.images_dir.load( image_name) height, width, _ = surface.shape self.__services.debug.write( "Image loaded with Resolution:" + str(width) + " x " + str(height), DebugLevel.HIGH) grid = np.full(surface.shape[:-1], Map.CLEAR_ID, dtype=np.uint8) agent_avg_location: np.ndarray = np.array([.0, .0]) agent_avg_count: int = 1 goal_avg_location: np.ndarray = np.array([.0, .0]) if house_expo_flag: ''' We can optimize for house_expo dataset by skipping the check for the goal and agent at each pixel, instead, we can only identify obstacles ''' self.__services.debug.write("Begin iteration through map", DebugLevel.HIGH) for idx in np.ndindex(surface.shape[:-1]): if Generator.is_in_color_range(surface[idx], Generator.WALL_COLOR): grid[idx] = DenseMap.WALL_ID else: for idx in np.ndindex(surface.shape[:-1]): if Generator.is_in_color_range(surface[idx], Generator.AGENT_COLOR, 5): agent_avg_location, agent_avg_count = \ Generator.increment_moving_average(agent_avg_location, agent_avg_count, np.array(idx[::-1])) elif Generator.is_in_color_range(surface[idx], Generator.GOAL_COLOR, 5): goal_avg_location, goal_avg_count = \ Generator.increment_moving_average(goal_avg_location, goal_avg_count, np.array(idx[::-1])) if Generator.is_in_color_range(surface[idx], Generator.WALL_COLOR): grid[idx] = DenseMap.WALL_ID agent_avg_location = np.array(agent_avg_location, dtype=int) goal_avg_location = np.array(goal_avg_location, dtype=int) agent_radius: float = 0 if rand_entities: self.__place_random_agent_and_goal(grid, Size(height, width)) self.__services.debug.write("Placed random agent and goal ", DebugLevel.HIGH) else: grid[tuple(agent_avg_location[::-1])] = DenseMap.AGENT_ID grid[tuple(goal_avg_location[::-1])] = DenseMap.GOAL_ID if not house_expo_flag: ''' We can optimize the house_expo generation by skipping this step, as we have already defined the agent radius ''' self.__services.debug.write( "Skipped agent_radius change checking ", DebugLevel.HIGH) for idx in np.ndindex(surface.shape[:-1]): if Generator.is_in_color_range(surface[idx], Generator.AGENT_COLOR, 5): ''' If color at x y is red (agent) then change the radius of the agent to the max Change the agent radius to the max between the old radius (from previous iteration ) and the magnitude of the agent location - the point and the magnitude of the agent location - the point and the magnitude of the agent location - the point This basically defines the agent radius as the largest red size. But we don't need to do this as we are supplying our own radius ''' agent_radius = max( agent_radius, np.linalg.norm(agent_avg_location - np.array(idx[::-1]))) agent_radius = int(agent_radius) if entity_radius: agent_radius = entity_radius res_map: DenseMap = DenseMap(grid) res_map.agent.radius = agent_radius res_map.goal.radius = agent_radius self.__services.debug.write( "Generated initial dense map in " + str(timer.stop()) + " seconds", DebugLevel.BASIC) timer = Timer() res_map.extend_walls() self.__services.debug.write( "Extended walls in " + str(timer.stop()) + " seconds", DebugLevel.BASIC) map_name: str = str(image_name.split('.')[0]) + ".pickle" if house_expo_flag: path = os.path.join(os.path.join(DATA_PATH, "maps"), "house_expo") self.__services.resources.house_expo_dir.save( map_name, res_map, path) else: self.__services.resources.maps_dir.save(map_name, res_map) self.__services.debug.write( "Finished generation. Map is in resources folder", DebugLevel.BASIC) return res_map