import numpy as np from openpilot.common.params import Params from openpilot.tools.sim.lib.common import SimulatorState, vec3 from openpilot.tools.sim.bridge.common import World from openpilot.tools.sim.lib.camerad import W, H class CarlaWorld(World): def __init__(self, client, high_quality, dual_camera, num_selected_spawn_point, town): super().__init__(dual_camera) import carla low_quality_layers = carla.MapLayer(carla.MapLayer.Ground | carla.MapLayer.Walls | carla.MapLayer.Decals) layers = carla.MapLayer.All if high_quality else low_quality_layers world = client.load_world(town, map_layers=layers) settings = world.get_settings() settings.fixed_delta_seconds = 0.01 world.apply_settings(settings) world.set_weather(carla.WeatherParameters.ClearSunset) self.world = world world_map = world.get_map() blueprint_library = world.get_blueprint_library() vehicle_bp = blueprint_library.filter('vehicle.tesla.*')[1] vehicle_bp.set_attribute('role_name', 'hero') spawn_points = world_map.get_spawn_points() assert len(spawn_points) > num_selected_spawn_point, \ f'''No spawn point {num_selected_spawn_point}, try a value between 0 and {len(spawn_points)} for this town.''' self.spawn_point = spawn_points[num_selected_spawn_point] self.vehicle = world.spawn_actor(vehicle_bp, self.spawn_point) physics_control = self.vehicle.get_physics_control() physics_control.mass = 2326 physics_control.torque_curve = [[20.0, 500.0], [5000.0, 500.0]] physics_control.gear_switch_time = 0.0 self.vehicle.apply_physics_control(physics_control) self.vc: carla.VehicleControl = carla.VehicleControl(throttle=0, steer=0, brake=0, reverse=False) self.max_steer_angle: float = self.vehicle.get_physics_control().wheels[0].max_steer_angle self.params = Params() self.steer_ratio = 15 self.carla_objects = [] transform = carla.Transform(carla.Location(x=0.8, z=1.13)) def create_camera(fov, callback): blueprint = blueprint_library.find('sensor.camera.rgb') blueprint.set_attribute('image_size_x', str(W)) blueprint.set_attribute('image_size_y', str(H)) blueprint.set_attribute('fov', str(fov)) blueprint.set_attribute('sensor_tick', str(1/20)) if not high_quality: blueprint.set_attribute('enable_postprocess_effects', 'False') camera = world.spawn_actor(blueprint, transform, attach_to=self.vehicle) camera.listen(callback) return camera self.road_camera = create_camera(fov=40, callback=self.cam_callback_road) if dual_camera: self.road_wide_camera = create_camera(fov=120, callback=self.cam_callback_wide_road) # fov bigger than 120 shows unwanted artifacts else: self.road_wide_camera = None # re-enable IMU imu_bp = blueprint_library.find('sensor.other.imu') imu_bp.set_attribute('sensor_tick', '0.01') self.imu = world.spawn_actor(imu_bp, transform, attach_to=self.vehicle) gps_bp = blueprint_library.find('sensor.other.gnss') self.gps = world.spawn_actor(gps_bp, transform, attach_to=self.vehicle) self.params.put_bool("UbloxAvailable", True) self.carla_objects = [self.imu, self.gps, self.road_camera, self.road_wide_camera, self.vehicle] def close(self): for s in self.carla_objects: if s is not None: try: s.destroy() except Exception as e: print("Failed to destroy carla object", e) def carla_image_to_rgb(self, image): rgb = np.frombuffer(image.raw_data, dtype=np.dtype("uint8")) rgb = np.reshape(rgb, (H, W, 4)) return np.ascontiguousarray(rgb[:, :, [0, 1, 2]]) def cam_callback_road(self, image): with self.image_lock: self.road_image = self.carla_image_to_rgb(image) def cam_callback_wide_road(self, image): with self.image_lock: self.wide_road_image = self.carla_image_to_rgb(image) def apply_controls(self, steer_angle, throttle_out, brake_out): self.vc.throttle = throttle_out steer_carla = steer_angle * -1 / (self.max_steer_angle * self.steer_ratio) steer_carla = np.clip(steer_carla, -1, 1) self.vc.steer = steer_carla self.vc.brake = brake_out self.vehicle.apply_control(self.vc) def read_sensors(self, simulator_state: SimulatorState): simulator_state.imu.bearing = self.imu.get_transform().rotation.yaw simulator_state.imu.accelerometer = vec3( self.imu.get_acceleration().x, self.imu.get_acceleration().y, self.imu.get_acceleration().z ) simulator_state.imu.gyroscope = vec3( self.imu.get_angular_velocity().x, self.imu.get_angular_velocity().y, self.imu.get_angular_velocity().z ) simulator_state.gps.from_xy([self.vehicle.get_location().x, self.vehicle.get_location().y]) simulator_state.velocity = self.vehicle.get_velocity() simulator_state.valid = True simulator_state.steering_angle = self.vc.steer * self.max_steer_angle def read_cameras(self): pass # cameras are read within a callback for carla def tick(self): self.world.tick() def reset(self): import carla self.vehicle.set_transform(self.spawn_point) self.vehicle.set_target_velocity(carla.Vector3D())