예제 #1
0
    def __init__(self,
                 carla_settings: CarlaConfig,
                 agent_settings: AgentConfig,
                 npc_agent_class,
                 competition_mode=False,
                 start_bbox: np.ndarray = np.array([5, -5, 0, 13, 5, 50]),
                 lap_count=10):
        """

        Args:
            carla_settings: CarlaConfig instance
            agent_settings: AgentConfig instance
            npc_agent_class: an agent class
            competition_mode: [Optional] True/False
            start_bbox: [Optional] array of [minx, miny, minz, maxx, maxy, maxz].
                        [5, -5, 0, 13, 5, 50] is the bbox for easy_map.
                        [-815, 20, -760, -770, 120, -600] is the bbox for berkeley_minor_map
            lap_count: [Optional] total lap count

        """
        self.carla_settings = carla_settings
        self.agent_settings = agent_settings
        self.carla_bridge = CarlaBridge()
        self.npc_agent_class = npc_agent_class
        self.world = None
        self.client = None
        self.controller = None
        self.display = None
        self.agent = None

        self.npc_agents: Dict[npc_agent_class, Any] = {}
        self.agent_collision_counter = 0

        self.competition_mode = competition_mode
        self.start_bbox = start_bbox
        self.lap_count = lap_count
        self.completed_lap_count = 0
        self.sensor_data = SensorsData()
        self.vehicle_state = Vehicle()

        self.start_simulation_time: Optional[float] = None
        self.start_vehicle_position: Optional[np.array] = None
        self.end_simulation_time: Optional[float] = None
        self.end_vehicle_position: Optional[np.array] = None

        self.logger = logging.getLogger(__name__)
        self.timestep_counter = 0
예제 #2
0
    def __init__(self, carla_settings: CarlaConfig,
                 agent_settings: AgentConfig, npc_agent_class):
        self.carla_settings = carla_settings
        self.agent_settings = agent_settings
        self.carla_bridge = CarlaBridge()
        self.npc_agent_class = npc_agent_class
        self.world = None
        self.client = None
        self.controller = None
        self.display = None
        self.agent = None

        self.npc_agents: Dict[npc_agent_class, Any] = {}
        self.agent_collision_counter = 0

        self.logger = logging.getLogger(__name__)
        self.timestep_counter = 0
예제 #3
0
    def __init__(self,
                 carla_settings: CarlaConfig,
                 agent_settings: AgentConfig,
                 npc_agent_class,
                 competition_mode=False,
                 max_collision=1000):
        """

        Args:
            carla_settings:
            agent_settings:
            npc_agent_class:
            competition_mode: if True, will exist when max_collision is reached
            max_collision: number of maximum collision allowed
        """
        self.carla_settings = carla_settings
        self.agent_settings = agent_settings
        self.carla_bridge = CarlaBridge()
        self.npc_agent_class = npc_agent_class
        self.world = None
        self.client = None
        self.controller = None
        self.display = None
        self.agent = None

        self.npc_agents: Dict[npc_agent_class, Any] = {}
        self.agent_collision_counter = 0

        self.competition_mode = competition_mode
        self.max_collision = max_collision
        self.start_simulation_time: Optional[float] = None
        self.start_vehicle_position: Optional[np.array] = None
        self.end_simulation_time: Optional[float] = None
        self.end_vehicle_position: Optional[np.array] = None

        self.logger = logging.getLogger(__name__)
        self.timestep_counter = 0
예제 #4
0
class CarlaRunner:
    def __init__(self,
                 carla_settings: CarlaConfig,
                 agent_settings: AgentConfig,
                 npc_agent_class,
                 competition_mode=False,
                 max_collision=1000):
        """

        Args:
            carla_settings:
            agent_settings:
            npc_agent_class:
            competition_mode: if True, will exist when max_collision is reached
            max_collision: number of maximum collision allowed
        """
        self.carla_settings = carla_settings
        self.agent_settings = agent_settings
        self.carla_bridge = CarlaBridge()
        self.npc_agent_class = npc_agent_class
        self.world = None
        self.client = None
        self.controller = None
        self.display = None
        self.agent = None

        self.npc_agents: Dict[npc_agent_class, Any] = {}
        self.agent_collision_counter = 0

        self.competition_mode = competition_mode
        self.max_collision = max_collision
        self.start_simulation_time: Optional[float] = None
        self.start_vehicle_position: Optional[np.array] = None
        self.end_simulation_time: Optional[float] = None
        self.end_vehicle_position: Optional[np.array] = None

        self.logger = logging.getLogger(__name__)
        self.timestep_counter = 0

    def set_carla_world(self) -> Vehicle:
        """
        Initiating the vehicle with loading messages
        Returns:
            Vehicle Information
        """

        try:
            pygame.init()
            pygame.font.init()
            self.logger.debug(f"Connecting to {self.carla_settings.host}: "
                              f"{self.carla_settings.port}")
            self.client = carla.Client(self.carla_settings.host,
                                       self.carla_settings.port)
            self.client.set_timeout(self.carla_settings.timeout)
            self.display = pygame.display.set_mode(
                (self.carla_settings.width, self.carla_settings.height),
                pygame.HWSURFACE | pygame.DOUBLEBUF)

            self.logger.debug(f"Setting HUD")
            hud = HUD(self.carla_settings.width, self.carla_settings.height)

            self.logger.debug("Setting up world")
            self.world = World(carla_world=self.client.get_world(),
                               hud=hud,
                               carla_settings=self.carla_settings,
                               agent_settings=self.agent_settings)

            if self.carla_settings.should_spawn_npcs:
                self.spawn_npcs()

            self.logger.debug(f"Connecting to Keyboard controls")
            self.controller = KeyboardControl(
                world=self.world, carla_setting=self.carla_settings)
            self.logger.debug("All settings done")

            return self.carla_bridge. \
                convert_vehicle_from_source_to_agent(self.world.player)

        except Exception as e:
            self.logger.error(
                f"Unable to initiate the world due to error: {e}")
            raise e

    def start_game_loop(self,
                        agent,
                        use_manual_control=False,
                        max_timestep=1e20):
        """Start running the vehicle and stop when finished running
        the track"""

        self.agent = agent
        try:
            self.logger.debug("Initiating game")
            self.agent.start_module_threads()
            clock = pygame.time.Clock()
            self.start_simulation_time = self.world.hud.simulation_time
            self.start_vehicle_position = self.agent.vehicle.transform.location.to_array(
            )
            while True and self.timestep_counter < max_timestep:

                # make sure the program does not run above 60 frames per second
                # this allow proper synchrony between server and client
                clock.tick_busy_loop(60)
                should_continue, carla_control = self.controller.parse_events(
                    client=self.client, world=self.world, clock=clock)

                self.agent_collision_counter = self.get_num_collision()
                if self.competition_mode and self.agent_collision_counter > self.max_collision:
                    should_continue = False

                if not should_continue:
                    break

                self.world.tick(clock)
                self.world.render(display=self.display)
                pygame.display.flip()
                sensor_data, new_vehicle = self.convert_data()
                if self.carla_settings.save_semantic_segmentation and self.world.semantic_segmentation_sensor_data:
                    self.world.semantic_segmentation_sensor_data.save_to_disk(
                        (Path("./data/output") / "ss" /
                         f"frame_{self.agent.time_counter}.png").as_posix(),
                        cc.CityScapesPalette)

                if self.carla_settings.should_spawn_npcs:
                    self.execute_npcs_step()

                if self.agent_settings.enable_autopilot:
                    if self.agent is None:
                        raise Exception(
                            "In autopilot mode, but no agent is defined.")
                    agent_control = self.agent.run_step(
                        vehicle=new_vehicle, sensors_data=sensor_data)
                    if not use_manual_control:
                        carla_control = self.carla_bridge. \
                            convert_control_from_agent_to_source(agent_control)
                self.world.player.apply_control(carla_control)

                self.timestep_counter += 1
        except Exception as e:
            self.logger.error(f"Error happened, exiting safely. Error: {e}")

        finally:
            self.on_finish()

    def on_finish(self):
        self.logger.debug("Ending Game")

        if self.agent is not None:
            self.end_vehicle_position = self.agent.vehicle.transform.location.to_array(
            )
        else:
            self.end_vehicle_position = self.start_vehicle_position
        if self.world is not None:
            self.end_simulation_time = self.world.hud.simulation_time
            self.world.destroy()
            self.logger.debug("All actors are destroyed")
        try:
            pygame.quit()
        except Exception as e:
            self.logger.debug(
                f"Cannot quit pygame normally, force quitting. Error: {e}")
        self.logger.debug("Game ended")

    def convert_data(self) -> Tuple[SensorsData, Vehicle]:
        """
        Convert data from source to agent

        Returns:
            sensors_data: sensor data for agent
            new_vehicle: the current player's vehicle state

        """
        sensor_data: SensorsData = \
            self.carla_bridge.convert_sensor_data_from_source_to_agent(
                {
                    "front_rgb": None if self.world.front_rgb_sensor_data is None
                    else self.world.front_rgb_sensor_data,
                    "rear_rgb": None if self.world.rear_rgb_sensor_data is None
                    else self.world.rear_rgb_sensor_data,
                    "front_depth":
                        None if self.world.front_depth_sensor_data is None else
                        self.world.front_depth_sensor_data,
                    "imu": self.world.imu_sensor
                }
            )
        new_vehicle = self.carla_bridge.convert_vehicle_from_source_to_agent(
            self.world.player)
        return sensor_data, new_vehicle

    def execute_npcs_step(self):
        # TODO this can be parallelized
        try:
            for agent, actor in self.npc_agents.items():
                new_vehicle = self.carla_bridge.convert_vehicle_from_source_to_agent(
                    actor)
                curr_control: VehicleControl = agent.run_step(
                    sensors_data=SensorsData(), vehicle=new_vehicle)
                carla_control = self.carla_bridge.convert_control_from_agent_to_source(
                    curr_control)
                actor.apply_control(carla_control)
        except Exception as e:
            self.logger.error(f"Failed to execute step for NPC. "
                              f"Error: {e}")

    def spawn_npcs(self):
        # parse npc file
        npc_config_file_path = Path(self.carla_settings.npc_config_file_path)
        assert npc_config_file_path.exists(
        ), f"NPC file path {npc_config_file_path.as_posix()} does not exist"
        npc_configs = json.load(npc_config_file_path.open('r'))

        npc_configs: List[AgentConfig] = [
            AgentConfig.parse_obj(config) for config in npc_configs
        ]

        self.world.spawn_npcs(npc_configs)
        self.npc_agents = {
            self.npc_agent_class(vehicle=actor, agent_settings=npc_config):
            actor
            for actor, npc_config in self.world.npcs_mapping.values()
        }

    def get_num_collision(self):
        collision_sensor: CollisionSensor = self.world.collision_sensor
        return len(collision_sensor.history)
예제 #5
0
class CarlaRunner:
    def __init__(self,
                 carla_settings: CarlaConfig,
                 agent_settings: AgentConfig,
                 npc_agent_class,
                 competition_mode=False,
                 start_bbox: np.ndarray = np.array([5, -5, 0, 13, 5, 50]),
                 lap_count=10):
        """

        Args:
            carla_settings: CarlaConfig instance
            agent_settings: AgentConfig instance
            npc_agent_class: an agent class
            competition_mode: [Optional] True/False
            start_bbox: [Optional] array of [minx, miny, minz, maxx, maxy, maxz].
                        [5, -5, 0, 13, 5, 50] is the bbox for easy_map.
                        [-815, 20, -760, -770, 120, -600] is the bbox for berkeley_minor_map
            lap_count: [Optional] total lap count

        """
        self.carla_settings = carla_settings
        self.agent_settings = agent_settings
        self.carla_bridge = CarlaBridge()
        self.npc_agent_class = npc_agent_class
        self.world = None
        self.client = None
        self.controller = None
        self.display = None
        self.agent = None

        self.npc_agents: Dict[npc_agent_class, Any] = {}
        self.agent_collision_counter = 0

        self.competition_mode = competition_mode
        self.start_bbox = start_bbox
        self.lap_count = lap_count
        self.completed_lap_count = 0
        self.sensor_data = SensorsData()
        self.vehicle_state = Vehicle()

        self.start_simulation_time: Optional[float] = None
        self.start_vehicle_position: Optional[np.array] = None
        self.end_simulation_time: Optional[float] = None
        self.end_vehicle_position: Optional[np.array] = None

        self.logger = logging.getLogger(__name__)
        self.timestep_counter = 0

    def set_carla_world(self) -> Vehicle:
        """
        Initiating the vehicle with loading messages
        Returns:
            Vehicle Information
        """

        try:
            pygame.init()
            pygame.font.init()
            self.logger.debug(f"Connecting to {self.carla_settings.host}: "
                              f"{self.carla_settings.port}")

            self.client = carla.Client(self.carla_settings.host,
                                       self.carla_settings.port)
            if not self.check_version(client=self.client):
                self.logger.error(
                    f"Version Mismatch: Client = {self.client.get_client_version()}, "
                    f"Server = {self.client.get_server_version()}. \n"
                    f"HINT: Please change carla_version to either 0.9.9 or 0.9.10 "
                    f"in ROAR_Sim.configurations.carla_version.txt")
                exit(1)

            if self.carla_settings.should_visualize_with_pygame is True:
                self.display = pygame.display.set_mode(
                    (self.carla_settings.width, self.carla_settings.height),
                    pygame.HWSURFACE | pygame.DOUBLEBUF)

            self.logger.debug(f"Setting HUD")
            hud = HUD(self.carla_settings.width, self.carla_settings.height)

            self.logger.debug("Setting up world")

            self.world = World(carla_world=self.client.get_world(),
                               hud=hud,
                               carla_settings=self.carla_settings,
                               agent_settings=self.agent_settings)

            if self.carla_settings.should_spawn_npcs:
                self.spawn_npcs()

            self.logger.debug(f"Connecting to Keyboard controls")
            self.controller = KeyboardControl(
                world=self.world, carla_setting=self.carla_settings)
            self.logger.debug("All settings done")

            return self.carla_bridge. \
                convert_vehicle_from_source_to_agent(self.world.player)

        except Exception as e:
            self.logger.error(
                f"Unable to initiate the world due to error: {e}")
            raise e

    def start_game_loop(self,
                        agent,
                        use_manual_control=False,
                        starting_lap_count=0):
        """Start running the vehicle and stop when finished running
        the track"""

        self.agent = agent
        lap_count = starting_lap_count
        has_entered_bbox = False
        should_restart_lap = False
        try:
            self.logger.debug("Initiating game")
            self.agent.start_module_threads()
            clock = pygame.time.Clock()
            self.start_simulation_time = time.time()
            self.start_vehicle_position = self.agent.vehicle.transform.location.to_array(
            )

            while True:

                # make sure the program does not run above 60 frames per second
                # this allow proper synchrony between server and client
                clock.tick_busy_loop(60)
                should_continue, carla_control = self.controller.parse_events(
                    client=self.client, world=self.world, clock=clock)

                self.agent_collision_counter = self.get_num_collision()

                if self.competition_mode:
                    is_currently_in_bbox = self.is_within_start_finish_bbox(
                        curr_pos=self.agent.vehicle.transform.location.
                        to_array())
                    if has_entered_bbox is True and is_currently_in_bbox is False:
                        has_entered_bbox = False
                    elif has_entered_bbox is False and is_currently_in_bbox is True:
                        has_entered_bbox = True
                        lap_count += 1
                        if lap_count > self.lap_count:
                            # if i have reached target number of lap counts, break out of game loop
                            break
                        else:
                            self.logger.info(
                                f"Going onto Lap {lap_count} out of {self.lap_count}"
                            )

                    if len(self.world.collision_sensor.history) > 0:
                        should_restart_lap = True

                    if should_restart_lap:
                        should_continue = False

                # check for exiting condition
                if should_continue is False:
                    break

                self.world.tick(clock)
                self.world.render(display=self.display)
                if self.carla_settings.should_visualize_with_pygame is True:
                    pygame.display.flip()
                self.fetch_data_async()
                sensor_data, new_vehicle = self.sensor_data.copy(
                ), self.vehicle_state.copy()

                if self.carla_settings.save_semantic_segmentation and self.world.semantic_segmentation_sensor_data:
                    Thread(target=lambda: self.world.
                           semantic_segmentation_sensor_data.save_to_disk(
                               (Path("./data/output_oct_10") / "ss" /
                                f"frame_{self.agent.time_counter}.png").
                               as_posix(), cc.CityScapesPalette),
                           args=()).start()

                if self.carla_settings.should_spawn_npcs:
                    self.execute_npcs_step()

                if self.agent_settings.enable_autopilot:
                    if self.agent is None:
                        raise Exception(
                            "In autopilot mode, but no agent is defined.")
                    agent_control = self.agent.run_step(
                        vehicle=new_vehicle, sensors_data=sensor_data)
                    if not use_manual_control:
                        carla_control = self.carla_bridge. \
                            convert_control_from_agent_to_source(agent_control)
                self.world.player.apply_control(carla_control)
                self.timestep_counter += 1

            self.completed_lap_count = lap_count - 1
        except Exception as e:
            self.logger.error(f"Error happened, exiting safely. Error: {e}")
        finally:
            if self.competition_mode and should_restart_lap:
                self.restart_on_lap(agent=agent,
                                    use_manual_control=use_manual_control,
                                    starting_lap_count=lap_count - 1)
            else:
                self.on_finish()

    def restart_on_lap(self, agent, use_manual_control: bool,
                       starting_lap_count: int):
        self.logger.info(f"Restarting on Lap {starting_lap_count}")
        self.on_finish()
        self.set_carla_world()
        agent.__init__(vehicle=agent.vehicle,
                       agent_settings=agent.agent_settings)
        self.start_game_loop(agent=agent,
                             use_manual_control=use_manual_control,
                             starting_lap_count=starting_lap_count)

    def on_finish(self):
        self.logger.debug("Ending Game")
        if self.agent is not None:
            self.agent.shutdown_module_threads()
            self.end_vehicle_position = self.agent.vehicle.transform.location.to_array(
            )
        else:
            self.end_vehicle_position = self.start_vehicle_position
        if self.world is not None:
            self.end_simulation_time = time.time()
            self.world.destroy()
            self.logger.debug("All actors are destroyed")
        try:
            pygame.quit()
        except Exception as e:
            self.logger.debug(
                f"Cannot quit pygame normally, force quitting. Error: {e}")
        self.logger.debug("Game ended")

    def is_within_start_finish_bbox(self, curr_pos: np.ndarray) -> bool:
        min_bounding_box = self.start_bbox[:3]
        max_bounding_box = self.start_bbox[3:]
        return all(
            np.logical_and(min_bounding_box < curr_pos,
                           curr_pos < max_bounding_box))

    def fetch_data_async(self):
        t = Thread(target=self.convert_data, args=())
        t.start()

    def convert_data(self):
        """
        Convert data from source to agent

        Returns:
            sensors_data: sensor data for agent
            new_vehicle: the current player's vehicle state

        """
        try:
            self.sensor_data: SensorsData = \
                self.carla_bridge.convert_sensor_data_from_source_to_agent(
                    {
                        "front_rgb": None if self.world.front_rgb_sensor_data is None
                        else self.world.front_rgb_sensor_data,
                        "rear_rgb": None if self.world.rear_rgb_sensor_data is None
                        else self.world.rear_rgb_sensor_data,
                        "front_depth":
                            None if self.world.front_depth_sensor_data is None else
                            self.world.front_depth_sensor_data,
                        "imu": self.world.imu_sensor
                    }
                )
            if self.world.player.is_alive:
                self.vehicle_state = self.carla_bridge.convert_vehicle_from_source_to_agent(
                    self.world.player)
        except Exception as e:
            print("Error", e)
            self.logger.error(e)

    def execute_npcs_step(self):
        # TODO this can be parallelized
        try:
            for agent, actor in self.npc_agents.items():
                new_vehicle = self.carla_bridge.convert_vehicle_from_source_to_agent(
                    actor)
                curr_control: VehicleControl = agent.run_step(
                    sensors_data=SensorsData(), vehicle=new_vehicle)
                carla_control = self.carla_bridge.convert_control_from_agent_to_source(
                    curr_control)
                actor.apply_control(carla_control)
        except Exception as e:
            self.logger.error(f"Failed to execute step for NPC. "
                              f"Error: {e}")

    def spawn_npcs(self):
        # parse npc file
        npc_config_file_path = Path(self.carla_settings.npc_config_file_path)
        assert npc_config_file_path.exists(
        ), f"NPC file path {npc_config_file_path.as_posix()} does not exist"
        npc_configs = json.load(npc_config_file_path.open('r'))

        npc_configs: List[AgentConfig] = [
            AgentConfig.parse_obj(config) for config in npc_configs
        ]

        self.world.spawn_npcs(npc_configs)
        self.npc_agents = {
            self.npc_agent_class(vehicle=actor, agent_settings=npc_config):
            actor
            for actor, npc_config in self.world.npcs_mapping.values()
        }

    def get_num_collision(self):
        collision_sensor: CollisionSensor = self.world.collision_sensor
        return len(collision_sensor.history)

    def check_version(self, client):
        return ("0.9.9" in client.get_server_version()) == (
            "0.9.9" in client.get_client_version())
예제 #6
0
    def __init__(self, carla_world: carla.World, hud: HUD,
                 carla_settings: CarlaConfig, agent_settings: AgentConfig):
        """Create a World with the given carla_world, head-up display and
        server setting."""

        self.logger = logging.getLogger(__name__)
        self.carla_settings: CarlaConfig = carla_settings
        self.agent_settings: AgentConfig = agent_settings
        self.carla_world: carla.World = carla_world

        self.clean_spawned_all_actors()

        self.actor_role_name = carla_settings.role_name
        try:
            self.map = self.carla_world.get_map()
        except RuntimeError as error:
            print('RuntimeError: {}'.format(error))
            print('  The server could not send the OpenDRIVE (.xodr) file:')
            print('  Make sure it exists, has the same name of your town, '
                  'and is correct.')
            sys.exit(1)
        self.hud = hud
        self.carla_bridge = CarlaBridge()
        self._spawn_point_id = agent_settings.spawn_point_id
        self._actor_filter = carla_settings.carla_vehicle_blueprint_filter
        self._car_color = carla_settings.car_color
        self._gamma = carla_settings.gamma
        self.player = None
        self.collision_sensor = None
        self.lane_invasion_sensor = None
        self.gnss_sensor = None
        self.imu_sensor = None
        self.radar_sensor = None
        self.camera_manager = None
        self.recording_enabled = False
        self.time_counter = 0

        self.front_rgb_sensor = None
        self.front_depth_sensor = None
        self.rear_rgb_sensor = None
        self.semantic_segmentation_sensor = None

        self.recording_start = 0
        # set weather
        self.logger.debug("Setting Weather")
        self.set_weather(
            carla_settings.carla_weather.to_carla_weather_params())

        # set player
        self.logger.debug("Setting Player")
        self.player = self.spawn_actor(
            actor_filter=self._actor_filter,
            player_role_name=self.actor_role_name,
            color=self._car_color,
            spawn_point_id=self._spawn_point_id,
        )
        # set camera
        self.logger.debug("Setting Camera")
        self.set_camera()

        # set sensor
        self.logger.debug("Setting Default Sensor")
        self.set_sensor()

        # set custom sensor
        self.logger.debug("Setting Custom Sensor")
        self.set_custom_sensor()
        self.front_rgb_sensor_data = None
        self.front_depth_sensor_data = None
        self.rear_rgb_sensor_data = None
        self.semantic_segmentation_sensor_data = None

        # spawn npc
        self.npcs_mapping: Dict[str, Tuple[Any, AgentConfig]] = {}

        settings = self.carla_world.get_settings()
        settings.synchronous_mode = self.carla_settings.synchronous_mode
        settings.no_rendering_mode = self.carla_settings.no_rendering_mode
        if self.carla_settings.synchronous_mode:
            settings.fixed_delta_seconds = self.carla_settings.fixed_delta_seconds
        self.carla_world.apply_settings(settings)
        self.carla_world.on_tick(hud.on_world_tick)
        self.logger.debug("World Initialized")
예제 #7
0
class World(object):
    """An World that holds all display settings"""
    def __init__(self, carla_world: carla.World, hud: HUD,
                 carla_settings: CarlaConfig, agent_settings: AgentConfig):
        """Create a World with the given carla_world, head-up display and
        server setting."""

        self.logger = logging.getLogger(__name__)
        self.carla_settings: CarlaConfig = carla_settings
        self.agent_settings: AgentConfig = agent_settings
        self.carla_world: carla.World = carla_world

        self.clean_spawned_all_actors()

        self.actor_role_name = carla_settings.role_name
        try:
            self.map = self.carla_world.get_map()
        except RuntimeError as error:
            print('RuntimeError: {}'.format(error))
            print('  The server could not send the OpenDRIVE (.xodr) file:')
            print('  Make sure it exists, has the same name of your town, '
                  'and is correct.')
            sys.exit(1)
        self.hud = hud
        self.carla_bridge = CarlaBridge()
        self._spawn_point_id = agent_settings.spawn_point_id
        self._actor_filter = carla_settings.carla_vehicle_blueprint_filter
        self._car_color = carla_settings.car_color
        self._gamma = carla_settings.gamma
        self.player = None
        self.collision_sensor = None
        self.lane_invasion_sensor = None
        self.gnss_sensor = None
        self.imu_sensor = None
        self.radar_sensor = None
        self.camera_manager = None
        self.recording_enabled = False
        self.time_counter = 0

        self.front_rgb_sensor = None
        self.front_depth_sensor = None
        self.rear_rgb_sensor = None
        self.semantic_segmentation_sensor = None

        self.recording_start = 0
        # set weather
        self.logger.debug("Setting Weather")
        self.set_weather(
            carla_settings.carla_weather.to_carla_weather_params())

        # set player
        self.logger.debug("Setting Player")
        self.player = self.spawn_actor(
            actor_filter=self._actor_filter,
            player_role_name=self.actor_role_name,
            color=self._car_color,
            spawn_point_id=self._spawn_point_id,
        )
        # set camera
        self.logger.debug("Setting Camera")
        self.set_camera()

        # set sensor
        self.logger.debug("Setting Default Sensor")
        self.set_sensor()

        # set custom sensor
        self.logger.debug("Setting Custom Sensor")
        self.set_custom_sensor()
        self.front_rgb_sensor_data = None
        self.front_depth_sensor_data = None
        self.rear_rgb_sensor_data = None
        self.semantic_segmentation_sensor_data = None

        # spawn npc
        self.npcs_mapping: Dict[str, Tuple[Any, AgentConfig]] = {}

        settings = self.carla_world.get_settings()
        settings.synchronous_mode = self.carla_settings.synchronous_mode
        settings.no_rendering_mode = self.carla_settings.no_rendering_mode
        if self.carla_settings.synchronous_mode:
            settings.fixed_delta_seconds = self.carla_settings.fixed_delta_seconds
        self.carla_world.apply_settings(settings)
        self.carla_world.on_tick(hud.on_world_tick)
        self.logger.debug("World Initialized")

    def spawn_actor(self,
                    actor_filter: str = "vehicle.tesla.model3",
                    player_role_name: str = "npc",
                    color: CarlaCarColor = CarlaCarColors.GREY,
                    spawn_point_id: int = random.choice(list(range(8)))):
        """Set up a hero-named player with Grey Tesla Model3 Vehicle """

        blueprint = self.carla_world.get_blueprint_library().find(actor_filter)
        blueprint.set_attribute("role_name", player_role_name)
        if blueprint.has_attribute("color"):
            blueprint.set_attribute("color", color.to_string())
        if blueprint.has_attribute("is_invincible"):
            self.logger.debug("TESLA IS INVINCIBLE")
            blueprint.set_attribute("is_invincible", "true")
        try:
            actor = \
                self.carla_world.spawn_actor(blueprint,
                                             self.map.get_spawn_points()[
                                                 spawn_point_id])
            return actor
        except Exception as e:
            raise ValueError(f"Cannot spawn actor at ID [{spawn_point_id}]. "
                             f"Error: {e}")

    def set_camera(self, cam_index: int = 0, cam_pos_index: int = 0):
        self.camera_manager = CameraManager(self.player, self.hud, self._gamma)
        self.camera_manager.transform_index = cam_pos_index
        self.camera_manager.set_sensor(cam_index, notify=False)
        actor_type = get_actor_display_name(self.player)
        self.hud.notification(actor_type)

    def set_sensor(self):
        self.collision_sensor = CollisionSensor(self.player, self.hud)
        self.lane_invasion_sensor = LaneInvasionSensor(self.player, self.hud)
        self.gnss_sensor = GnssSensor(self.player)
        self.imu_sensor = IMUSensor(self.player)

    def toggle_radar(self):
        if self.radar_sensor is None:
            self.radar_sensor = RadarSensor(self.player)
        elif self.radar_sensor.sensor is not None:
            self.radar_sensor.sensor.destroy()
            self.radar_sensor = None

    def tick(self, clock):
        self.time_counter += 1
        self.hud.tick(self, clock)
        if self.carla_settings.synchronous_mode:
            self.carla_world.tick()

    def render(self, display):
        self.camera_manager.render(display)
        self.hud.render(display)

    def destroy_sensors(self):
        self.camera_manager.sensor.destroy()
        self.camera_manager.sensor = None
        self.camera_manager.index = None

    def destroy(self):
        self.logger.debug(f"destroying all actors belonging to "
                          f"[{self.actor_role_name}] in this world")
        if self.radar_sensor is not None:
            self.toggle_radar()
        actors = [
            self.camera_manager.sensor,
            self.collision_sensor.sensor,
            self.lane_invasion_sensor.sensor,
            self.gnss_sensor.sensor,
            self.imu_sensor.sensor,
            self.player,
        ]
        for actor in actors:
            if actor is not None:
                actor.destroy()

        self._destroy_custom_sensors()
        for npc, _ in self.npcs_mapping.values():
            npc.destroy()

        self.clean_spawned_all_actors()

    def set_weather(self, new_weather: carla.WeatherParameters):
        self.carla_world.weather = new_weather

    def set_custom_sensor(self):
        Attachment = carla.AttachmentType
        self._destroy_custom_sensors()
        self.front_rgb_sensor = self._spawn_custom_sensor(
            blueprint_filter="sensor.camera.rgb",
            transform=self.carla_bridge.convert_transform_from_agent_to_source(
                self.agent_settings.front_rgb_cam.transform),
            attachment=Attachment.Rigid,
            attributes={
                "fov": self.agent_settings.front_rgb_cam.fov,
            })
        self.front_depth_sensor = self._spawn_custom_sensor(
            blueprint_filter="sensor.camera.depth",
            transform=self.carla_bridge.convert_transform_from_agent_to_source(
                self.agent_settings.front_depth_cam.transform),
            attachment=Attachment.Rigid,
            attributes={
                "fov": self.agent_settings.front_depth_cam.fov,
            })
        self.rear_rgb_sensor = \
            self._spawn_custom_sensor(
                blueprint_filter="sensor.camera.rgb",
                transform=self.carla_bridge.
                    convert_transform_from_agent_to_source(
                    self.agent_settings.rear_rgb_cam.transform),
                attachment=Attachment.Rigid,
                attributes={
                    "fov":
                        self.agent_settings.rear_rgb_cam.fov,
                })

        if self.carla_settings.save_semantic_segmentation:
            self.semantic_segmentation_sensor = self._spawn_custom_sensor(
                blueprint_filter="sensor.camera.semantic_segmentation",
                transform=self.carla_bridge.
                convert_transform_from_agent_to_source(
                    self.agent_settings.front_depth_cam.transform),
                attachment=Attachment.Rigid,
                attributes={"fov": self.agent_settings.front_depth_cam.fov},
            )

        weak_self = weakref.ref(self)
        self.front_rgb_sensor.listen(
            lambda image: World._parse_front_rgb_sensor_image(
                weak_self=weak_self, image=image))
        self.front_depth_sensor.listen(
            lambda image: World._parse_front_depth_sensor_image(
                weak_self=weak_self, image=image))
        self.rear_rgb_sensor.listen(
            lambda image: World._parse_rear_rgb_sensor_image(
                weak_self=weak_self, image=image))
        if self.carla_settings.save_semantic_segmentation:
            self.semantic_segmentation_sensor.listen(
                lambda image: World._parse_semantic_segmentation_image(
                    weak_self=weak_self, image=image))

    def _spawn_custom_sensor(self, blueprint_filter: str,
                             transform: carla.Transform,
                             attachment: carla.AttachmentType,
                             attributes: dict):
        blueprint = self.carla_world.get_blueprint_library(). \
            find(blueprint_filter)
        for key, val in attributes.items():
            if blueprint.has_attribute(key):
                blueprint.set_attribute(key, str(val))
            else:
                self.logger.error(f"Unable to set attribute [{key}] "
                                  f"for blueprint [{blueprint_filter}]")

        return self.carla_world.spawn_actor(blueprint, transform, self.player,
                                            attachment)

    def _destroy_custom_sensors(self):
        if self.front_rgb_sensor is not None:
            self.front_rgb_sensor.destroy()

        if self.front_depth_sensor is not None:
            self.front_depth_sensor.destroy()

        if self.rear_rgb_sensor is not None:
            self.rear_rgb_sensor.destroy()

        if self.semantic_segmentation_sensor is not None:
            self.semantic_segmentation_sensor.destroy()

    @staticmethod
    def _parse_front_rgb_sensor_image(weak_self, image):
        self = weak_self()
        if not self:
            return
        self.front_rgb_sensor_data = image

    @staticmethod
    def _parse_front_depth_sensor_image(weak_self, image):
        self = weak_self()
        if not self:
            return
        # image.convert(cc.Raw)
        self.front_depth_sensor_data = image

    @staticmethod
    def _parse_rear_rgb_sensor_image(weak_self, image):
        self = weak_self()
        if not self:
            return
        image.convert(cc.Raw)
        self.rear_rgb_sensor_data = image

    @staticmethod
    def _parse_semantic_segmentation_image(weak_self, image):
        self = weak_self()
        if not self:
            return
        # image.convert(cc.CityScapesPalette)
        self.semantic_segmentation_sensor_data = image

    def spawn_npcs(self, npc_configs: List[AgentConfig]):
        for npc_config in npc_configs:
            self.logger.debug(f"Spawning NPC [{npc_config.name}]")
            try:
                npc = self.spawn_actor(
                    spawn_point_id=npc_config.spawn_point_id)
                self.npcs_mapping[npc_config.name] = (npc, npc_config)
            except Exception as e:
                self.logger.error(f"Failed to Spawn NPC {'default'}."
                                  f"Error: {e}")

    def clean_spawned_all_actors(self):
        """
        This function is to clean all actors that are not traffic light/signals
        Returns:

        """
        for actor in self.carla_world.get_actors():
            if "traffic" not in actor.type_id and "spectator" not in actor.type_id:
                actor.destroy()