
我是李慢慢。
最近机缘巧合,又基于Carla做了个驾驶员视角的效果。
这里简单记录下。
1、先看效果:
2、方法原理
a、创建仿真世界的客户端client
b、通过client创建主车
c、通过主车创建6个camera
d、获得每个camera的输出图像
e、将所有图像部署在一个pygame窗口里
f、仿真世界每次tick,camera的图像都会更新一次
记录下完整代码如下:
# client_to_show_ego_6_views.py# 2022-11-27# by limanman# 多窗口显示驾驶员视角的demo程序import carlaimport argparseimport randomimport timeimport numpy as nptry:import pygamefrom pygame.locals import K_ESCAPEfrom pygame.locals import K_qexcept ImportError:raise RuntimeError('cannot import pygame, make sure pygame package is installed')class CustomTimer:def __init__(self):try:self.timer = time.perf_counterexcept AttributeError:self.timer = time.timedef time(self):return self.timer()class DisplayManager:def __init__(self, grid_size, window_size):pygame.init()pygame.font.init()self.display = pygame.display.set_mode(window_size, pygame.HWSURFACE | pygame.DOUBLEBUF)self.grid_size = grid_sizeself.window_size = window_sizeself.sensor_list = []def get_window_size(self):return [int(self.window_size[0]), int(self.window_size[1])]def get_display_size(self):return [int(self.window_size[0] / self.grid_size[1]), int(self.window_size[1] / self.grid_size[0])]def get_display_offset(self, gridPos):dis_size = self.get_display_size()return [int(gridPos[1] * dis_size[0]), int(gridPos[0] * dis_size[1])]def add_sensor(self, sensor):self.sensor_list.append(sensor)def get_sensor_list(self):return self.sensor_listdef render(self):if not self.render_enabled():returnfor s in self.sensor_list:s.render()pygame.display.flip()def destroy(self):for s in self.sensor_list:s.destroy()def render_enabled(self):return self.display != Noneclass SensorManager:def __init__(self, world, display_man, sensor_type, transform, attached, sensor_options, display_pos, reverse):self.surface = Noneself.world = worldself.display_man = display_manself.display_pos = display_posself.sensor = self.init_sensor(sensor_type, transform, attached, sensor_options)self.sensor_options = sensor_optionsself.timer = CustomTimer()self.time_processing = 0.0self.tics_processing = 0self.display_man.add_sensor(self)self.reverse = reversedef init_sensor(self, sensor_type, transform, attached, sensor_options):if sensor_type == 'RGBCamera':camera_bp = self.world.get_blueprint_library().find('sensor.camera.rgb')disp_size = self.display_man.get_display_size()print("===size:", str(disp_size[0]), str(disp_size[1]))camera_bp.set_attribute('image_size_x', str(disp_size[0]))camera_bp.set_attribute('image_size_y', str(disp_size[1]))camera_bp.set_attribute('fov', str(40))#for key in sensor_options:camera_bp.set_attribute(key, sensor_options[key])camera = self.world.spawn_actor(camera_bp, transform, attach_to=attached)print("camera_attributes:", camera.attributes)for i in camera.attributes:print("camera_attributes:", i, camera.attributes[i])camera.listen(self.save_rgb_image)return cameraelse:return Nonedef get_sensor(self):return self.sensordef save_rgb_image(self, image):t_start = self.timer.time()image.convert(carla.ColorConverter.Raw)array = np.frombuffer(image.raw_data, dtype=np.dtype("uint8"))array = np.reshape(array, (image.height, image.width, 4))array = array[:, :, :3]array = array[:, :, ::-1]if self.reverse == True:array = np.flip(array, axis=1) # 将画面左右翻转if self.display_man.render_enabled():self.surface = pygame.surfarray.make_surface(array.swapaxes(0, 1))t_end = self.timer.time()self.time_processing += (t_end - t_start)self.tics_processing += 1def render(self):if self.surface is not None:offset = self.display_man.get_display_offset(self.display_pos)self.display_man.display.blit(self.surface, offset)def destroy(self):self.sensor.destroy()class WindowCameraRear(object):def __init__(self):# === 1, 创建pygame窗口 ===pygame.init() # 内部各功能模块进行初始化创建及变量设置,默认调用self.size = width, height = 1024, 600 # 设置游戏窗口大小,分别是宽度和高度self.screen = pygame.display.set_mode(self.size) # 初始化显示窗口pygame.display.set_caption("我的小游戏程序") # 设置显示窗口的标题内容self.my_display = pygame.display.set_mode(self.size, pygame.HWSURFACE | pygame.DOUBLEBUF)# pygame_clock = pygame.time.Clock()def sensor_image(self, image):print("self:", self)print("image:", image)array = np.frombuffer(image.raw_data, dtype=np.dtype("uint8"))array = np.reshape(array, (image.height, image.width, 4))array = array[:, :, :3]array = array[:, :, ::-1]array = np.flip(array, axis=1) # 将画面左右翻转self.surface = pygame.surfarray.make_surface(array.swapaxes(0, 1))self.my_display.blit(self.surface, (0, 0))def run_simulation(args, client):"""This function performed one test run using the args parametersand connecting to the carla client passed."""display_manager = Nonevehicle = Nonevehicle_list = []timer = CustomTimer()try:# Getting the world andworld = client.get_world()original_settings = world.get_settings()if args.sync:traffic_manager = client.get_trafficmanager(8000)settings = world.get_settings()traffic_manager.set_synchronous_mode(True)settings.synchronous_mode = Truesettings.fixed_delta_seconds = 0.05world.apply_settings(settings)# Instanciating the vehicle to which we attached the sensorsbp = world.get_blueprint_library().filter('charger_2020')[0]vehicle = world.spawn_actor(bp, random.choice(world.get_map().get_spawn_points()))vehicle_list.append(vehicle)vehicle.set_autopilot(True)# Display Manager organize all the sensors an its display in a window# If can easily configure the grid and the total window sizedisplay_manager = DisplayManager(grid_size=[2, 3], window_size=[args.width, args.height])SensorManager(world, display_manager, 'RGBCamera',carla.Transform(carla.Location(x=3.5, y=0, z=1.5), carla.Rotation(yaw=-40)),vehicle, {}, display_pos=[0, 0], reverse=False)SensorManager(world, display_manager, 'RGBCamera',carla.Transform(carla.Location(x=3.5, y=0, z=1.5), carla.Rotation(yaw=+00)),vehicle, {}, display_pos=[0, 1], reverse=False)SensorManager(world, display_manager, 'RGBCamera',carla.Transform(carla.Location(x=3.5, y=0, z=1.5), carla.Rotation(yaw=+40)),vehicle, {}, display_pos=[0, 2], reverse=False)SensorManager(world, display_manager, 'RGBCamera',carla.Transform(carla.Location(x=0.7, y=-1.0, z=1.1), carla.Rotation(yaw=-170)),vehicle, {}, display_pos=[1, 0], reverse=True)SensorManager(world, display_manager, 'RGBCamera',carla.Transform(carla.Location(x=0.7, y=0, z=1.3), carla.Rotation(yaw=-180)),vehicle, {}, display_pos=[1, 1], reverse=True)SensorManager(world, display_manager, 'RGBCamera',carla.Transform(carla.Location(x=0.7, y=+1.0, z=1.1), carla.Rotation(yaw=+170)),vehicle, {}, display_pos=[1, 2], reverse=True)# ######################################################## Simulation loopcall_exit = Falsetime_init_sim = timer.time()while True:# Carla Tickif args.sync:world.tick()else:world.wait_for_tick()# Render received datadisplay_manager.render()for event in pygame.event.get():if event.type == pygame.QUIT:call_exit = Trueelif event.type == pygame.KEYDOWN:if event.key == K_ESCAPE or event.key == K_q:call_exit = Truebreakif call_exit:breakfinally:if display_manager:display_manager.destroy()client.apply_batch([carla.command.DestroyActor(x) for x in vehicle_list])world.apply_settings(original_settings)def main():argparser = argparse.ArgumentParser(description='CARLA Sensor tutorial')argparser.add_argument('--host',metavar='H',default='127.0.0.1',help='IP of the host server (default: 127.0.0.1)')argparser.add_argument('-p', '--port',metavar='P',default=2000,type=int,help='TCP port to listen to (default: 2000)')argparser.add_argument('--sync',action='store_true',help='Synchronous mode execution')argparser.add_argument('--async',dest='sync',action='store_false',help='Asynchronous mode execution')argparser.set_defaults(sync=True)argparser.add_argument('--res',metavar='WIDTHxHEIGHT',default='1280x720',help='window resolution (default: 1280x720)')args = argparser.parse_args()args.width, args.height = [int(x) for x in args.res.split('x')]try:client = carla.Client(args.host, args.port)client.set_timeout(5.0)run_simulation(args, client)except KeyboardInterrupt:print('\nCancelled by user. Bye!')if __name__ == '__main__':main()
真实又臭又长。
古德拜。