Carla简单入门-4 pygame与场景细节
本文写于2023年7月,文中所展示的版本为Ubuntu20.04以及Carla0.9.14,不同版本可能有一定的不同,欢迎各位伙伴们把遇到的问题和解决办法与其他人分享。
上篇文档中我们详细了解了多种传感器以及他们所对应的各种属性以及方法,这篇文章会介绍如何使用pygame来进行多传感器同时监控,同时还会介绍一些在场景搭建时候的细节,例如天气的控制等。
1. Pygame综述
Pygame本身是一个跨平台的游戏开发Python模块,我们想要在Carla中使用Pygame是因为它提供了非常有用且方便的图像实时渲染手段,这为我们实时可视化Carla中的各个传感器提供了很大的便利。而且Pygame作为游戏开发模块还提供了键盘的监听,这让我们也可以手动操控主车和其他车辆。下面就利用官方的简单demo来讲一下如何利用pygame实现最基础的传感器监控。
a. 第一步仍然是设定好整个模拟环境,包括加载地图,同步设置,交通管理器设置,生成车辆等等一系列设置:
import carla
import random
import pygame
import numpy as np
# 连接到客户端并检索世界对象
client = carla.Client('localhost', 2000)
world = client.get_world()
# 将模拟环境设定为同步模式
settings = world.get_settings()
settings.synchronous_mode = True
settings.fixed_delta_seconds = 0.05
world.apply_settings(settings)
# 将交通管理器设为同步模式
traffic_manager = client.get_trafficmanager()
traffic_manager.set_synchronous_mode(True)
# 设置种子,以便必要时行为可以重复
traffic_manager.set_random_device_seed(0)
random.seed(0)
# 设置观察者视角
spectator = world.get_spectator()
# 获取地图的生成点
spawn_points = world.get_map().get_spawn_points()
# 选择车辆模型范围
models = ['dodge', 'audi', 'model3', 'mini', 'mustang', 'lincoln', 'prius', 'nissan', 'crown', 'impala']
blueprints = []
for vehicle in world.get_blueprint_library().filter('*vehicle*'):
if any(model in vehicle.id for model in models):
blueprints.append(vehicle)
# 设置车辆生成数量上限
max_vehicles = 50
max_vehicles = min([max_vehicles, len(spawn_points)])
vehicles = []
# 在随机生成点位生成随机车辆
for i in range(0,max_vehicles):
spawn_point = random.choice(spawn_points)
temp = world.try_spawn_actor(random.choice(blueprints), spawn_point)
if temp is not None:
vehicles.append(temp)
# 将生成的车辆设定为自动驾驶模式
for vehicle in vehicles:
vehicle.set_autopilot(True)
b. 在对模拟环境进行完基础的设置之后我们设置后续carla中传感器的回调函数,以及pygame的渲染函数:
# 相机传感器回调,将相机的原始数据重塑为2D RGB,并应用于PyGame表面
def pygame_callback(data, obj):
img = np.reshape(np.copy(data.raw_data), (data.height, data.width, 4))
img = img[:,:,:3]
img = img[:, :, ::-1]
obj.surface = pygame.surfarray.make_surface(img.swapaxes(0,1))
# 渲染物体
class RenderObject(object):
def __init__(self, width, height):
init_image = np.random.randint(0,255,(height,width,3),dtype='uint8')
self.surface = pygame.surfarray.make_surface(init_image.swapaxes(0,1))
c. 接下来我们来看主车的控制系统,因为pygame可以方便的进行键盘监听,所以我们在这里加入手动键盘控制主车的选项:
# 检测键盘输入并且根据输入来设定主车各个控制属性的状态
def parse_control(self, event):
if event.type == pygame.KEYDOWN:
# 当按下回车键时切换自动驾驶状态
if event.key == pygame.K_RETURN:
self._autopilot = not self._autopilot
self._vehicle.set_autopilot(self._autopilot)
# 按下方向键上键时将油门属性设定为True
if event.key == pygame.K_UP:
self._throttle = True
# 按下方向键下键时将刹车属性设定为True
if event.key == pygame.K_DOWN:
self._brake = True
# 按下方向键右键时将方向盘属性设定为1
if event.key == pygame.K_RIGHT:
self._steer = 1
# 按下方向键左键时将方向盘属性设定为-1
if event.key == pygame.K_LEFT:
self._steer = -1
# 抬起按键时将属性重设为默认值
if event.type == pygame.KEYUP:
if event.key == pygame.K_UP:
self._throttle = False
if event.key == pygame.K_DOWN:
self._brake = False
self._control.reverse = False
if event.key == pygame.K_RIGHT:
self._steer = None
if event.key == pygame.K_LEFT:
self._steer = None
# 将当前控制属性转化为carla.VehicleControl()的控制信息以应用
def process_control(self):
if self._throttle:
self._control.throttle = min(self._control.throttle + 0.05, 1)
self._control.gear = 1
self._control.brake = False
elif not self._brake:
self._control.throttle = 0.0
if self._brake:
# 当按住方向下键并且车辆处于静止状态,切换到倒车档位并加速
if self._vehicle.get_velocity().length() < 0.01 and not self._control.reverse:
self._control.brake = 0.0
self._control.gear = 1
self._control.reverse = True
self._control.throttle = min(self._control.throttle + 0.1, 1)
elif self._control.reverse:
self._control.throttle = min(self._control.throttle + 0.1, 1)
else:
self._control.throttle = 0.0
self._control.brake = min(self._control.brake + 0.3, 1)
else:
self._control.brake = 0.0
if self._steer is not None:
if self._steer == 1:
self._steer_cache += 0.03
if self._steer == -1:
self._steer_cache -= 0.03
min(0.7, max(-0.7, self._steer_cache))
self._control.steer = round(self._steer_cache,1)
else:
if self._steer_cache > 0.0:
self._steer_cache *= 0.2
if self._steer_cache < 0.0:
self._steer_cache *= 0.2
if 0.01 > self._steer_cache > -0.01:
self._steer_cache = 0.0
self._control.steer = round(self._steer_cache,1)
# 将存储在self._control的控制信息应用
self._vehicle.apply_control(self._control)
d. 下来我们需要生成主车并且将摄像头绑定到主车上:
# 为主车随机选择一个蓝图
ego_vehicle = random.choice(vehicles)
# 生成绑定到主车的摄像头
camera_init_trans = carla.Transform(carla.Location(x=-5, z=3), carla.Rotation(pitch=-20))
camera_bp = world.get_blueprint_library().find('sensor.camera.rgb')
camera = world.spawn_actor(camera_bp, camera_init_trans, attach_to=ego_vehicle)
# 设定camera读取数据后调用回调函数
camera.listen(lambda image: pygame_callback(image, renderObject))
# 获得相机画面尺寸
image_w = camera_bp.get_attribute("image_size_x").as_int()
image_h = camera_bp.get_attribute("image_size_y").as_int()
# 初始化渲染的物体和控制的物体
renderObject = RenderObject(image_w, image_h)
controlObject = ControlObject(ego_vehicle)
e. 接下来我们就可以初始化pygame窗口了:
# 初始化pygame视窗,在这里会弹出一个新的pygame弹窗
pygame.init()
gameDisplay = pygame.display.set_mode((image_w,image_h), pygame.HWSURFACE | pygame.DOUBLEBUF)
gameDisplay.fill((0,0,0))
gameDisplay.blit(renderObject.surface, (0,0))</