class LeaderboardEvaluator(object): """ TODO: document me! """ ego_vehicles = [] # Tunable parameters client_timeout = 10.0 # in seconds wait_for_world = 20.0 # in seconds frame_rate = 20.0 # in Hz def __init__(self, args, statistics_manager): """ Setup CARLA client and world Setup ScenarioManager """ self.statistics_manager = statistics_manager self.sensors = None self.sensor_icons = [] self._vehicle_lights = carla.VehicleLightState.Position | carla.VehicleLightState.LowBeam # First of all, we need to create the client that will send the requests # to the simulator. Here we'll assume the simulator is accepting # requests in the localhost at port 2000. self.client = carla.Client(args.host, args.port) if args.timeout: self.client_timeout = args.timeout self.client.set_timeout(self.client_timeout) self.traffic_manager = self.client.get_trafficmanager(args.traffic_manager_port) dist = pkg_resources.get_distribution("carla") if dist.version != 'leaderboard': if LooseVersion(dist.version) < LooseVersion('0.9.10'): raise ImportError("CARLA version 0.9.10.1 or newer required. CARLA version found: {}".format(dist)) # Load agent module_name = os.path.basename(args.agent).split('.')[0] sys.path.insert(0, os.path.dirname(args.agent)) self.module_agent = importlib.import_module(module_name) # Create the ScenarioManager self.manager = ScenarioManager(args.timeout, args.debug > 1) # Time control for summary purposes self._start_time = GameTime.get_time() self._end_time = None # Create the agent timer self._agent_watchdog = Watchdog(args.timeout) signal.signal(signal.SIGINT, self._signal_handler) def _signal_handler(self, signum, frame): """ Terminate scenario ticking when receiving a signal interrupt """ if self._agent_watchdog and not self._agent_watchdog.get_status(): raise RuntimeError("Timeout: Agent took longer than {}s to setup".format(self.client_timeout)) elif self.manager: self.manager.signal_handler(signum, frame) def __del__(self): """ Cleanup and delete actors, ScenarioManager and CARLA world """ self._cleanup() if hasattr(self, 'manager') and self.manager: del self.manager if hasattr(self, 'world') and self.world: del self.world def _cleanup(self): """ Remove and destroy all actors """ # Simulation still running and in synchronous mode? if self.manager and self.manager.get_running_status() \ and hasattr(self, 'world') and self.world: # Reset to asynchronous mode settings = self.world.get_settings() settings.synchronous_mode = False settings.fixed_delta_seconds = None self.world.apply_settings(settings) self.traffic_manager.set_synchronous_mode(False) if self.manager: self.manager.cleanup() CarlaDataProvider.cleanup() for i, _ in enumerate(self.ego_vehicles): if self.ego_vehicles[i]: self.ego_vehicles[i].destroy() self.ego_vehicles[i] = None self.ego_vehicles = [] if self._agent_watchdog: self._agent_watchdog.stop() if hasattr(self, 'agent_instance') and self.agent_instance: self.agent_instance.destroy() self.agent_instance = None if hasattr(self, 'statistics_manager') and self.statistics_manager: self.statistics_manager.scenario = None def _prepare_ego_vehicles(self, ego_vehicles, wait_for_ego_vehicles=False): """ Spawn or update the ego vehicles """ if not wait_for_ego_vehicles: for vehicle in ego_vehicles: self.ego_vehicles.append(CarlaDataProvider.request_new_actor(vehicle.model, vehicle.transform, vehicle.rolename, color=vehicle.color, vehicle_category=vehicle.category)) else: ego_vehicle_missing = True while ego_vehicle_missing: self.ego_vehicles = [] ego_vehicle_missing = False for ego_vehicle in ego_vehicles: ego_vehicle_found = False carla_vehicles = CarlaDataProvider.get_world().get_actors().filter('vehicle.*') for carla_vehicle in carla_vehicles: if carla_vehicle.attributes['role_name'] == ego_vehicle.rolename: ego_vehicle_found = True self.ego_vehicles.append(carla_vehicle) break if not ego_vehicle_found: ego_vehicle_missing = True break for i, _ in enumerate(self.ego_vehicles): self.ego_vehicles[i].set_transform(ego_vehicles[i].transform) # sync state CarlaDataProvider.get_world().tick() def _load_and_wait_for_world(self, args, town, ego_vehicles=None): """ Load a new CARLA world and provide data to CarlaDataProvider """ self.world = self.client.load_world(town) settings = self.world.get_settings() settings.fixed_delta_seconds = 1.0 / self.frame_rate settings.synchronous_mode = True self.world.apply_settings(settings) self.world.reset_all_traffic_lights() CarlaDataProvider.set_client(self.client) CarlaDataProvider.set_world(self.world) CarlaDataProvider.set_traffic_manager_port(args.traffic_manager_port) self.traffic_manager.set_synchronous_mode(True) self.traffic_manager.set_random_device_seed(args.traffic_manager_seed) self.traffic_manager.set_hybrid_physics_mode(True) # Wait for the world to be ready if CarlaDataProvider.is_sync_mode(): self.world.tick() else: self.world.wait_for_tick() if CarlaDataProvider.get_map().name != town: raise Exception("The CARLA server uses the wrong map!" "This scenario requires to use map {}".format(town)) def _register_statistics(self, config, checkpoint, entry_status, crash_message=""): """ Computes and saved the simulation statistics """ # register statistics current_stats_record = self.statistics_manager.compute_route_statistics( config, self.manager.scenario_duration_system, self.manager.scenario_duration_game, crash_message ) print("\033[1m> Registering the route statistics\033[0m") self.statistics_manager.save_record(current_stats_record, config.index, checkpoint) self.statistics_manager.save_entry_status(entry_status, False, checkpoint) def _load_and_run_scenario(self, args, config): """ Load and run the scenario given by config. Depending on what code fails, the simulation will either stop the route and continue from the next one, or report a crash and stop. """ crash_message = "" entry_status = "Started" print("\n\033[1m========= Preparing {} (repetition {}) =========".format(config.name, config.repetition_index)) print("> Setting up the agent\033[0m") # Prepare the statistics of the route self.statistics_manager.set_route(config.name, config.index) # Set up the user's agent, and the timer to avoid freezing the simulation try: self._agent_watchdog.start() agent_class_name = getattr(self.module_agent, 'get_entry_point')() self.agent_instance = getattr(self.module_agent, agent_class_name)(args.agent_config) config.agent = self.agent_instance # Check and store the sensors if not self.sensors: self.sensors = self.agent_instance.sensors() track = self.agent_instance.track AgentWrapper.validate_sensor_configuration(self.sensors, track, args.track) self.sensor_icons = [sensors_to_icons[sensor['type']] for sensor in self.sensors] self.statistics_manager.save_sensors(self.sensor_icons, args.checkpoint) self._agent_watchdog.stop() except SensorConfigurationInvalid as e: # The sensors are invalid -> set the ejecution to rejected and stop print("\n\033[91mThe sensor's configuration used is invalid:") print("> {}\033[0m\n".format(e)) traceback.print_exc() crash_message = "Agent's sensors were invalid" entry_status = "Rejected" self._register_statistics(config, args.checkpoint, entry_status, crash_message) self._cleanup() sys.exit(-1) except Exception as e: # The agent setup has failed -> start the next route print("\n\033[91mCould not set up the required agent:") print("> {}\033[0m\n".format(e)) traceback.print_exc() crash_message = "Agent couldn't be set up" self._register_statistics(config, args.checkpoint, entry_status, crash_message) self._cleanup() return print("\033[1m> Loading the world\033[0m") # Load the world and the scenario try: self._load_and_wait_for_world(args, config.town, config.ego_vehicles) self._prepare_ego_vehicles(config.ego_vehicles, False) scenario = RouteScenario(world=self.world, config=config, debug_mode=args.debug) self.statistics_manager.set_scenario(scenario.scenario) # Night mode if config.weather.sun_altitude_angle < 0.0: for vehicle in scenario.ego_vehicles: vehicle.set_light_state(carla.VehicleLightState(self._vehicle_lights)) # Load scenario and run it if args.record: self.client.start_recorder("{}/{}_rep{}.log".format(args.record, config.name, config.repetition_index)) self.manager.load_scenario(scenario, self.agent_instance, config.repetition_index) except Exception as e: # The scenario is wrong -> set the ejecution to crashed and stop print("\n\033[91mThe scenario could not be loaded:") print("> {}\033[0m\n".format(e)) traceback.print_exc() crash_message = "Simulation crashed" entry_status = "Crashed" self._register_statistics(config, args.checkpoint, entry_status, crash_message) if args.record: self.client.stop_recorder() self._cleanup() sys.exit(-1) print("\033[1m> Running the route\033[0m") # Run the scenario try: self.manager.run_scenario() except AgentError as e: # The agent has failed -> stop the route print("\n\033[91mStopping the route, the agent has crashed:") print("> {}\033[0m\n".format(e)) traceback.print_exc() crash_message = "Agent crashed" except Exception as e: print("\n\033[91mError during the simulation:") print("> {}\033[0m\n".format(e)) traceback.print_exc() crash_message = "Simulation crashed" entry_status = "Crashed" # Stop the scenario try: print("\033[1m> Stopping the route\033[0m") self.manager.stop_scenario() self._register_statistics(config, args.checkpoint, entry_status, crash_message) if args.record: self.client.stop_recorder() # Remove all actors scenario.remove_all_actors() self._cleanup() except Exception as e: print("\n\033[91mFailed to stop the scenario, the statistics might be empty:") print("> {}\033[0m\n".format(e)) traceback.print_exc() crash_message = "Simulation crashed" if crash_message == "Simulation crashed": sys.exit(-1) def run(self, args): """ Run the challenge mode """ route_indexer = RouteIndexer(args.routes, args.scenarios, args.repetitions) if args.resume: route_indexer.resume(args.checkpoint) self.statistics_manager.resume(args.checkpoint) else: self.statistics_manager.clear_record(args.checkpoint) route_indexer.save_state(args.checkpoint) while route_indexer.peek(): # setup config = route_indexer.next() # run self._load_and_run_scenario(args, config) route_indexer.save_state(args.checkpoint) # save global statistics print("\033[1m> Registering the global statistics\033[0m") global_stats_record = self.statistics_manager.compute_global_statistics(route_indexer.total) StatisticsManager.save_global_record(global_stats_record, self.sensor_icons, route_indexer.total, args.checkpoint)
class NoCrashEvaluator(object): """ TODO: document me! """ ego_vehicles = [] # Tunable parameters client_timeout = 10.0 # in seconds wait_for_world = 20.0 # in seconds frame_rate = 20.0 # in Hz def __init__(self, args, statistics_manager): """ Setup CARLA client and world Setup ScenarioManager """ self.statistics_manager = statistics_manager self.sensors = None self.sensor_icons = [] # First of all, we need to create the client that will send the requests # to the simulator. Here we'll assume the simulator is accepting # requests in the localhost at port 2000. self.client = carla.Client(args.host, int(args.port)) if args.timeout: self.client_timeout = float(args.timeout) self.client.set_timeout(self.client_timeout) self.traffic_manager = self.client.get_trafficmanager( int(args.trafficManagerPort)) dist = pkg_resources.get_distribution("carla") if dist.version != 'leaderboard': if LooseVersion(dist.version) < LooseVersion('0.9.10'): raise ImportError( "CARLA version 0.9.10.1 or newer required. CARLA version found: {}" .format(dist)) # Load agent module_name = os.path.basename(args.agent).split('.')[0] sys.path.insert(0, os.path.dirname(args.agent)) self.module_agent = importlib.import_module(module_name) # Create the ScenarioManager self.manager = ScenarioManager(args.timeout, args.debug > 1) # Time control for summary purposes self._start_time = GameTime.get_time() self._end_time = None # Create the agent timer self._agent_watchdog = Watchdog(int(float(args.timeout))) signal.signal(signal.SIGINT, self._signal_handler) self.town = args.town def _signal_handler(self, signum, frame): """ Terminate scenario ticking when receiving a signal interrupt """ if self._agent_watchdog and not self._agent_watchdog.get_status(): raise RuntimeError("Timeout: Agent took too long to setup") elif self.manager: self.manager.signal_handler(signum, frame) def __del__(self): """ Cleanup and delete actors, ScenarioManager and CARLA world """ self._cleanup() if hasattr(self, 'manager') and self.manager: del self.manager if hasattr(self, 'world') and self.world: del self.world def _cleanup(self): """ Remove and destroy all actors """ # Simulation still running and in synchronous mode? if self.manager and self.manager.get_running_status() \ and hasattr(self, 'world') and self.world: # Reset to asynchronous mode settings = self.world.get_settings() settings.synchronous_mode = False settings.fixed_delta_seconds = None self.world.apply_settings(settings) self.traffic_manager.set_synchronous_mode(False) if self.manager: self.manager.cleanup() CarlaDataProvider.cleanup() for i, _ in enumerate(self.ego_vehicles): if self.ego_vehicles[i]: self.ego_vehicles[i].destroy() self.ego_vehicles[i] = None self.ego_vehicles = [] if self._agent_watchdog: self._agent_watchdog.stop() if hasattr(self, 'agent_instance') and self.agent_instance: self.agent_instance.destroy() self.agent_instance = None if hasattr(self, 'statistics_manager') and self.statistics_manager: self.statistics_manager.scenario = None def _load_and_wait_for_world(self, args): """ Load a new CARLA world and provide data to CarlaDataProvider """ self.world = self.client.load_world(args.town) settings = self.world.get_settings() settings.fixed_delta_seconds = 1.0 / self.frame_rate settings.synchronous_mode = True self.world.apply_settings(settings) self.world.reset_all_traffic_lights() CarlaDataProvider.set_client(self.client) CarlaDataProvider.set_world(self.world) CarlaDataProvider.set_traffic_manager_port(int( args.trafficManagerPort)) self.traffic_manager.set_synchronous_mode(True) self.traffic_manager.set_random_device_seed( int(args.trafficManagerSeed)) # Wait for the world to be ready if CarlaDataProvider.is_sync_mode(): self.world.tick() else: self.world.wait_for_tick() if CarlaDataProvider.get_map().name != args.town: raise Exception("The CARLA server uses the wrong map!" "This scenario requires to use map {}".format( args.town)) # def _register_statistics(self, config, checkpoint, entry_status, crash_message=""): # """ # Computes and saved the simulation statistics # """ # # register statistics # current_stats_record = self.statistics_manager.compute_route_statistics( # config, # self.manager.scenario_duration_system, # self.manager.scenario_duration_game, # crash_message # ) # print("\033[1m> Registering the route statistics\033[0m") # self.statistics_manager.save_record(current_stats_record, config.index, checkpoint) # self.statistics_manager.save_entry_status(entry_status, False, checkpoint) def _load_and_run_scenario(self, args, route, weather_idx, traffic_idx): """ Load and run the scenario given by config. Depending on what code fails, the simulation will either stop the route and continue from the next one, or report a crash and stop. """ crash_message = "" entry_status = "Started" start_idx, target_idx = route traffic_lvl = ['Empty', 'Regular', 'Dense'][traffic_idx] print( "\n\033[1m========= Preparing {} {}: {} to {}, weather {} =========" .format(args.town, traffic_lvl, start_idx, target_idx, weather_idx)) print("> Setting up the agent\033[0m") # Set up the user's agent, and the timer to avoid freezing the simulation try: self._agent_watchdog.start() agent_class_name = getattr(self.module_agent, 'get_entry_point')() self.agent_instance = getattr(self.module_agent, agent_class_name)(args.agent_config) # Check and store the sensors if not self.sensors: self.sensors = self.agent_instance.sensors() track = self.agent_instance.track AgentWrapper.validate_sensor_configuration( self.sensors, track, args.track) self._agent_watchdog.stop() except SensorConfigurationInvalid as e: # The sensors are invalid -> set the ejecution to rejected and stop print("\n\033[91mThe sensor's configuration used is invalid:") print("> {}\033[0m\n".format(e)) traceback.print_exc() crash_message = "Agent's sensors were invalid" entry_status = "Rejected" self._cleanup() sys.exit(-1) except Exception as e: # The agent setup has failed -> start the next route print("\n\033[91mCould not set up the required agent:") print("> {}\033[0m\n".format(e)) traceback.print_exc() crash_message = "Agent couldn't be set up" self._cleanup() return print("\033[1m> Loading the world\033[0m") # Load the world and the scenario try: self._load_and_wait_for_world(args) scenario = NoCrashEvalScenario(world=self.world, agent=self.agent_instance, start_idx=start_idx, target_idx=target_idx, weather_idx=weather_idx, traffic_idx=traffic_idx, debug_mode=args.debug) self.manager.load_scenario(scenario, self.agent_instance, 0) except Exception as e: # The scenario is wrong -> set the ejecution to crashed and stop print("\n\033[91mThe scenario could not be loaded:") print("> {}\033[0m\n".format(e)) traceback.print_exc() crash_message = "Simulation crashed" entry_status = "Crashed" if args.record: self.client.stop_recorder() self._cleanup() sys.exit(-1) print("\033[1m> Running the route\033[0m") # Run the scenario try: self.manager.run_scenario() except AgentError as e: # The agent has failed -> stop the route print("\n\033[91mStopping the route, the agent has crashed:") print("> {}\033[0m\n".format(e)) traceback.print_exc() crash_message = "Agent crashed" except Exception as e: print("\n\033[91mError during the simulation:") print("> {}\033[0m\n".format(e)) traceback.print_exc() crash_message = "Simulation crashed" entry_status = "Crashed" # Stop the scenario try: print("\033[1m> Stopping the route\033[0m") self.manager.stop_scenario() route_completion, lights_ran, duration = self.manager.get_nocrash_diagnostics( ) self.statistics_manager.log(self.town, traffic_idx, weather_idx, start_idx, target_idx, route_completion, lights_ran, duration) if args.record: self.client.stop_recorder() # Remove all actors scenario.remove_all_actors() self._cleanup() except Exception as e: print( "\n\033[91mFailed to stop the scenario, the statistics might be empty:" ) print("> {}\033[0m\n".format(e)) traceback.print_exc() crash_message = "Simulation crashed" if crash_message == "Simulation crashed": sys.exit(-1) def run(self, args): """ Run the challenge mode """ # if args.resume: # route_indexer.resume(args.checkpoint) # self.statistics_manager.resume(args.checkpoint) # else: # self.statistics_manager.clear_record(args.checkpoint) # route_indexer.save_state(args.checkpoint) # Load routes with open(f'runners/suite/nocrash_{args.town}.txt', 'r') as f: routes = [tuple(map(int, l.split())) for l in f.readlines()] weathers = {'train': [1, 3, 6, 8], 'test': [10, 14]}.get(args.weather) traffics = [0, 1, 2] for traffic, route, weather in itertools.product( traffics, routes, weathers): if self.statistics_manager.is_finished(self.town, route, weather, traffic): continue self._load_and_run_scenario(args, route, weather, traffic) # save global statistics print("\033[1m> Registering the global statistics\033[0m")