本专栏教程将记录从安装carla到调用carla的pythonAPI进行车辆操控并采集数据的全流程,带领大家从安装carla开始,到最终能够熟练使用carla仿真环境进行传感器数据采集和车辆控制.

第三节 在carla中遥控一台车并采集数据

本小节的目标是在carla中生成一台可操控的车辆,并且添加一个RGB相机到车辆上,然后操控车辆采集图像数据。本教程主要分成3步进行,第1步,我们要在地图中生成一台车辆。第2步,我们需要在车辆上添加一个传感器。第3步,我们需要添加一个键盘控制器来操控车辆。

本案例中会涉及到很多carla pythonAPI的调用,但是由于本案例比较简单,所以设计到的接口用法比较有限,更多的内容需要移步到carla的官方pythonAPI的网站上详细了解。在浏览下面的教程时,遇到难懂的函数用法,也可以去pythonAPI的网站上查阅。

文章目录

  • 第三节 在carla中遥控一台车并采集数据
    • 1. 基础概念
      • 1.1 Actors
      • 1.2 blueprint
      • 1.3 Spawning
    • 2. 准备工作
      • 2.1 导入第三方库
      • 2.2 定义全局变量
      • 2.3 创建表达世界对象的类
      • 2.4 添加可传入的参数
      • 2.5 创建客户端,配置仿真参数和同步模式
    • 3.关键内容
      • 3.1 生成车辆
      • 3.2 添加相机传感器
      • 3.3.添加控制器
      • 3.4.世界运行及其后处理
    • 4.相关链接

章节内容介绍:
第1小节介绍了一些涉及carla的重要概念。第2小节介绍了准备工作。第3小节介绍了主要内容。第4小节介绍了一些代码和文档链接。

  • 接口查阅链接:
    CARLA Python API在线网站
  • 配套代码:
    gitte代码库

1. 基础概念

本小节简要介绍一下carla中定义物体的一些用法,包括Actors,blueprint。

1.1 Actors

Actors,中文翻译为演员,是CARLA中的参与者是在模拟中执行动作的元素,他们可以影响其他参与者。CARLA的演员包括车辆和步行者,还有传感器、交通标志、交通灯和观众。充分了解如何对其进行操作至关重要。我们重点了解车辆和传感器。

1.2 blueprint

blueprint,中文翻译为蓝图,它们已经是带有动画和一系列属性的模型,帮助用户在模拟中顺利地加入新角色。这些属性包括车辆颜色、激光雷达传感器中的通道数量、步行者的速度等等。

蓝图库( blueprint library)中存放了很多可以用的蓝图。我们在创建演员时,可以直接从蓝图库中获取蓝图。

1.3 Spawning

Spawning,翻译为生成,用于创建演员。世界对象负责生成演员并跟踪这些演员。Spawning演员时需要只需要一张演员的蓝图( blueprint)和一个演员的坐标(Transform)。坐标(Transform)说明了演员的位置和旋转。

2. 准备工作

我们将从头讲解本脚本的编写过程。本小节主要介绍导入第三方库,定义全局变量,创建客户端等准备工作,为3,4,5小节铺垫。

2.1 导入第三方库

首先我们需要添加路径,以便python脚本运行时能够找到 CARLA module相关库的路径。

import glob
import os
import sys
# ==============================================================================
# -- Find CARLA module ---------------------------------------------------------
# ==============================================================================try:sys.path.append(glob.glob('../carla/dist/carla-*%d.%d-%s.egg' % (sys.version_info.major,sys.version_info.minor,'win-amd64' if os.name == 'nt' else 'linux-x86_64'))[0])
except IndexError:pass# ==============================================================================
# -- Add PythonAPI for release mode --------------------------------------------
# ==============================================================================
try:sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))) + '/carla')sys.path.append("../examples/")
except IndexError:pass

接着,我们需要import本脚本所需要的模块。
车辆控制模块我们直接从examples/manual_control.py模块中导入。


from manual_control import HUD,KeyboardControl
from manual_control import CameraManager,get_actor_display_name,find_weather_presets
from manual_control import CollisionSensor,LaneInvasionSensor,GnssSensor,IMUSensor
import numpy as np
import carla
import random
import time
import cv2
import pygame
import argparse

接着,为了能够实现可复现性,我们设置随机数种子

random.seed(123456)

2.2 定义全局变量

接下来我们需要定义一些全局变量:

# 设置演员列表
actors_list = []
#设置是否采用同步模式
synchronous_master=True
#设置汽车数量
num_vehicles=20 #设置采集的图片的参数
IM_WIDTH = 640
IM_HEIGHT = 480# 设置显示窗口大小
windos_width=1280
windos_height=720

2.3 创建表达世界对象的类

为了便于对世界对象的光照、天气等信息进行控制,添加一个World类。这个类是由examples/manual_control.py中的World类修改而来,主要修改的部分是,原脚本的车辆是随机选择的,而这里我们是对自己定义的车辆进行控制。


class World(object):def __init__(self, carla_world, hud, args,player):self.world = carla_worldself.sync = args.syncself.actor_role_name = args.rolenametry:self.map = self.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 = hudself.player = playerself.collision_sensor = Noneself.lane_invasion_sensor = Noneself.gnss_sensor = Noneself.imu_sensor = Noneself.radar_sensor = Noneself.camera_manager = Noneself._weather_presets = find_weather_presets()self._weather_index = 0self._actor_filter = args.filterself._actor_generation = args.generationself._gamma = args.gammaself.restart()self.world.on_tick(hud.on_world_tick)self.recording_enabled = Falseself.recording_start = 0self.constant_velocity_enabled = Falseself.show_vehicle_telemetry = Falseself.current_map_layer = 0self.map_layer_names = [carla.MapLayer.NONE,carla.MapLayer.Buildings,carla.MapLayer.Decals,carla.MapLayer.Foliage,carla.MapLayer.Ground,carla.MapLayer.ParkedVehicles,carla.MapLayer.Particles,carla.MapLayer.Props,carla.MapLayer.StreetLights,carla.MapLayer.Walls,carla.MapLayer.All]def restart(self):self.player_max_speed = 1.589self.player_max_speed_fast = 3.713# Keep same camera config if the camera manager exists.cam_index = self.camera_manager.index if self.camera_manager is not None else 0cam_pos_index = self.camera_manager.transform_index if self.camera_manager is not None else 0self.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)self.camera_manager = CameraManager(self.player, self.hud, self._gamma)self.camera_manager.transform_index = cam_pos_indexself.camera_manager.set_sensor(cam_index, notify=False)actor_type = get_actor_display_name(self.player)self.hud.notification(actor_type)if self.sync:self.world.tick()else:self.world.wait_for_tick()def next_weather(self, reverse=False):self._weather_index += -1 if reverse else 1self._weather_index %= len(self._weather_presets)preset = self._weather_presets[self._weather_index]self.hud.notification('Weather: %s' % preset[1])self.player.get_world().set_weather(preset[0])def next_map_layer(self, reverse=False):self.current_map_layer += -1 if reverse else 1self.current_map_layer %= len(self.map_layer_names)selected = self.map_layer_names[self.current_map_layer]self.hud.notification('LayerMap selected: %s' % selected)def load_map_layer(self, unload=False):selected = self.map_layer_names[self.current_map_layer]if unload:self.hud.notification('Unloading map layer: %s' % selected)self.world.unload_map_layer(selected)else:self.hud.notification('Loading map layer: %s' % selected)self.world.load_map_layer(selected)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 = Nonedef modify_vehicle_physics(self, actor):#If actor is not a vehicle, we cannot use the physics controltry:physics_control = actor.get_physics_control()physics_control.use_sweep_wheel_collision = Trueactor.apply_physics_control(physics_control)except Exception:passdef tick(self, clock):self.hud.tick(self, clock)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 = Noneself.camera_manager.index = Nonedef destroy(self):if self.radar_sensor is not None:self.toggle_radar()sensors = [self.camera_manager.sensor,self.collision_sensor.sensor,self.lane_invasion_sensor.sensor,self.gnss_sensor.sensor,self.imu_sensor.sensor]for sensor in sensors:if sensor is not None:sensor.stop()sensor.destroy()if self.player is not None:self.player.destroy()

2.4 添加可传入的参数

为了在使用python xxxx.py命令时可以传入ip地址等参数,我们使用argparser库创建了一个存储参数的变量args。添加这个参数主要是因为我们后面的编程依赖于manual_control.py中的库,而这个库中传入了args参数。如果在本地运行carla服务器则参数无需深入了解。

argparser = argparse.ArgumentParser(description='CARLA Manual Control Client')argparser.add_argument('-v', '--verbose',action='store_true',dest='debug',help='print debug information')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('-a', '--autopilot',action='store_true',help='enable autopilot')argparser.add_argument('--res',metavar='WIDTHxHEIGHT',default='1280x720',help='window resolution (default: 1280x720)')argparser.add_argument('--filter',metavar='PATTERN',default='vehicle.*',help='actor filter (default: "vehicle.*")')argparser.add_argument('--generation',metavar='G',default='2',help='restrict to certain actor generation (values: "1","2","All" - default: "2")')argparser.add_argument('--rolename',metavar='NAME',default='hero',help='actor role name (default: "hero")')argparser.add_argument('--gamma',default=2.2,type=float,help='Gamma correction of the camera (default: 2.2)')argparser.add_argument('--sync',action='store_true',help='Activate synchronous mode execution',default=True)args = argparser.parse_args()args.width, args.height = [int(x) for x in args.res.split('x')]

2.5 创建客户端,配置仿真参数和同步模式

下面就是创建一个客户端来运行本次脚本,参数为ip和端口号,都为默认值,无需修改。

client = carla.Client('127.0.0.1', 2000)

从客户端中获取世界对象:

    #获取世界对象world_sim = client.get_world()

接下来使用try except finally构成主处理流程:

设置同步模式,carla服务器默认运行在异步模式,由于我们需要在脚本中运行一个AI,所以需要使用同步模式synchronous_master = True.仿真步长设置为0.05s,使用 world_sim.apply_settings(settings)应用配置。

 #设置同步模式,carla服务器默认运行在异步模式,由于我们需要在脚本中运行一个AI,所以需要使用同步模式.init_setting=world_sim.get_settings()settings=world_sim.get_settings()if not settings.synchronous_mode:synchronous_master = True #同步标志位settings.synchronous_mode = True# 仿真步长设置为0.05ssettings.fixed_delta_seconds = 0.05# 设置正常运行渲染,交通流复杂时可以关闭渲染settings.no_rendering_mode=False# 将设置应用于世界world_sim.apply_settings(settings)

3.关键内容

3.1 生成车辆

本小节将结合代码讲解如何构建一个自己的客户端,并且实现车辆的生成。

通过第2节,我们做好了前期的准备工作。通过1.1我们了解到车辆属于carla中的演员,而一个演员是由一个蓝图和一个坐标组成的,下面就开始着手从蓝图和坐标创建一个车辆演员。

        # 车辆蓝图vehicles_blueprints=world_sim.get_blueprint_library().filter('*vehicle*')ego_blueprint = random.choice(vehicles_blueprints)# 车辆坐标spawn_points = world_sim.get_map().get_spawn_points()ego_spawn_point=random.choice(spawn_points)# 生成车辆ego_vehicleActor   = world_sim.spawn_actor(ego_blueprint,ego_spawn_point)print(f"ID: {ego_vehicleActor.id}  ,create ego vehicle sussesed!")actors_list.append(ego_vehicleActor)

step1:获取蓝图ego_blueprint。我们通过world_sim.get_blueprint_library()可以获得所有的蓝图库,然后.filter('*vehicle*')就可以把所有车辆的蓝图过滤出来,得到了车辆的蓝图列表vehicles_blueprints,这个列表中有很多不同种类的车,例如大众,奥迪,特斯拉等等,我们从这个车辆列表中随机选择一个 random.choice(vehicles_blueprints)

step2:获得坐标ego_spawn_point。我们通过world_sim.get_map().get_spawn_points()可以获得当前地图提供的所有生成点坐标,然后通过random.choice(spawn_points)随机选择一个坐标作为生成点坐标。

step3:生成演员ego_vehicleActor。通过world_sim.spawn_actor(ego_blueprint,ego_spawn_point)就创建了车辆演员。

3.2 添加相机传感器

如何从carla 中实时获取前是相机数据,便于下一步进行图像处理.
相机也同样是carla中的一个演员,所以也是通过world_sim.spawn_actor创建的,不同的是,这里的相机需要安装在车上,所以多了一个参数attach_to=ego_vehicleActor,意思是依附在车辆演员ego_vehicleActor上。

另外,在我们创建相机蓝图camera_bp时,可以通过.set_attribute()对其中的参数进行修改:camera_bp.set_attribute('image_size_x', f'{IM_WIDTH}') #图像宽度

生成相机演员camera_actor之后,使用camera_actor.listen(lambda image:process_img(image))对消息进行监听,受到消息后会在process_img()函数中处理。

        # ==============================================================================# --create a Image sensor  actor---------------------------------------------------------# ==============================================================================#下面要添加传感器,这里以添加RGB相机为例:# Create a transform to place the camera on top of the vehiclecamera_init_trans = carla.Transform(carla.Location(z=1.5))# We create the camera through a blueprint that defines its propertiescamera_bp = world_sim.get_blueprint_library().find('sensor.camera.rgb')# get the blueprint for this sensor# change the dimensions of the imagecamera_bp.set_attribute('image_size_x', f'{IM_WIDTH}') #图像宽度camera_bp.set_attribute('image_size_y', f'{IM_HEIGHT}')#图像高度camera_bp.set_attribute('fov', '110')#水平视长角 (度)camera_bp.set_attribute('sensor_tick','1.0')#消息间隔时间 (s)# We spawn the camera and attach it to our ego vehiclecamera_actor = world_sim.spawn_actor(camera_bp, camera_init_trans, attach_to=ego_vehicleActor)actors_list.append(camera_actor)# # 有了RGB相机,下面我们需要对数据进行订阅和存储# # Start camera with PyGame callbackif listen_flag:camera_actor.listen(lambda image:process_img(image))

在消息处理的process_img函数中,我们把接收到的图片保存在out/下,命名为当前图片的帧。并且,我们也提供了转换成numpy的方法image.raw_data,可以用于在线处理。

def process_img(image):print("get a img!")image.save_to_disk('out/%06d.png' % image.frame)i = np.array(image.raw_data)  # convert to an arrayi2 = i.reshape((IM_HEIGHT, IM_WIDTH, 4))  # was flattened, so we're going to shape it.i3 = i2[:, :, :3]  # remove the alpha (basically, remove the 4th index  of every pixel. Converting RGBA to RGB)return i3/255.0  # normalize

3.3.添加控制器

使用pygame创建显示界面。

        # ==============================================================================# --create a pygame display  windows---------------------------------------------------------# ==============================================================================# 这里使用pygame模块pygame.init()pygame.font.init()# 使用pygame创建显示窗口display=pygame.display.set_mode((windos_width,windos_height),pygame.HWSURFACE | pygame.DOUBLEBUF)display.fill((0,0,0))pygame.display.flip()

调用automatic_control.py中的库创建车辆信息打印窗口hud,创建世界变量控制器world, 创建键盘控制器controller

# ==============================================================================# --create a infomation windos and controler---------------------------------------------------------# ==============================================================================# 创建车辆信息打印窗口hud = HUD(windos_width,windos_height)# 创建世界变量控制器,用于控制天气、地图等信息(禁用了车辆信息更换)world = World(world_sim, hud, args,ego_vehicleActor)# 创建键盘控制器,用于操控车辆controller = KeyboardControl(world, args.autopilot)

3.4.世界运行及其后处理

默认以同步方式运行世界模拟,也就是客户端的更新时间和服务器的更新时间保持一致。

        # 真实世界更新if args.sync:world_sim.tick()else:world_sim.wait_for_tick()clock = pygame.time.Clock()while True:if args.sync:world_sim.tick()clock.tick_busy_loop(60)if controller.parse_events(client, world, clock, args.sync):breakworld.tick(clock)world.render(display)pygame.display.flip()

在代码最后,我们需要写一个后处理来销毁演员。由于演员创建后不会自动销毁,会在后台占用内存和计算资源,所以在推出程序时,我们需要销毁已经创建的演员。

        # 摧毁已经创建的actors# camera_actor.destroy()print('\ndestroying %d actors' % len(actors_list))client.apply_batch([carla.command.DestroyActor(x) for x in actors_list])if world is not None:world.destroy()pygame.quit()print('\nCancelled by user. Bye!')settings.synchronous_mode = Falseworld_sim.apply_settings(settings)print("finally processed!")

4.相关链接

配套代码:
gitte代码库

官方指南入口:

  1. Python API reference
  2. Actors and blueprints
  3. World and client
  4. World

其他教程:

  1. Alex_996

  2. 一骑红尘荔枝来

[carla入门教程]-3 在carla中遥控汽车并采集传感器数据(一个简单Demo,附代码)相关推荐

  1. [carla入门教程]-1 安装carla环境

    本专栏教程将记录我从安装carla到调用carla的pythonAPI进行车辆操控的全流程,带领大家从安装carla开始,到最终能够熟练使用carla仿真环境进行传感器数据采集和车辆控制. 第一节 c ...

  2. [carla入门教程]-6 小项目:基于carla-ros-bridge构建一个小型比赛赛道

    本专栏教程将记录从安装carla到调用carla的pythonAPI进行车辆操控并采集数据的全流程,带领大家从安装carla开始,到最终能够熟练使用carla仿真环境进行传感器数据采集和车辆控制. 第 ...

  3. [carla入门教程]-5 使用ROS与carla通信

    本专栏教程将记录从安装carla到调用carla的pythonAPI进行车辆操控并采集数据的全流程,带领大家从安装carla开始,到最终能够熟练使用carla仿真环境进行传感器数据采集和车辆控制. 第 ...

  4. ASP.NET Core 入门教程 8、ASP.NET Core + Entity Framework Core 数据访问入门

    ASP.NET Core 入门教程 8.ASP.NET Core + Entity Framework Core 数据访问入门 原文:ASP.NET Core 入门教程 8.ASP.NET Core ...

  5. 可见的轮廓线用虚线绘制_CAD制图初学入门教程:CAD软件中如何绘制轴测图?

    在使用浩辰CAD软件绘制图纸的过程中经常会需要绘制轴测图,但是有些CAD制图初学入门者不知道如何在CAD制图软件中绘制轴测图,下面小编就来给大家分享一下浩辰CAD软件绘制轴测图的CAD制图初学入门教程 ...

  6. leafLet入门教程兼leafLet API中文文档参考

    leafLet官方文档链接(英文原版):https://leafletjs.com/reference-1.3.4.html#marker-bindpopup 文章目录 leafLet教程 一.简单入 ...

  7. 《零基础看得懂的C语言入门教程 》——(十一)C语言自定义函数真的很简单

    一.学习目标 了解C语言的自定义函数的使用方法 了解C语言自定义函数的传参 了解C语言自定义函数的返回值 目录 C语言真的很难吗?那是你没看这张图,化整为零轻松学习C语言. 第一篇:(一)脱离学习误区 ...

  8. 独家 | 在机器学习中利用统计插补来处理缺失值(附代码)

    作者:Jason Brownlee 翻译:吴振东 校对:冯羽 本文约4500字,建议阅读10分钟 本文以病马数据集为例,帮助你了解在机器学习领域如何利用统计策略来处理缺失值,对代码进行了较为详细的讲解 ...

  9. 从实例一步一步入门学习SpringCloud的Eureka、Ribbon、Feign、熔断器、Zuul的简单使用(附代码下载)

    场景 SpringCloud -创建统一的依赖管理: https://blog.csdn.net/BADAO_LIUMANG_QIZHI/article/details/102530574 Sprin ...

最新文章

  1. php base64解码图片 base64加密图片还原
  2. SQL学习(三)之子句和函数
  3. 使用未初始化的内存是什么意思_单根内存条的极限容量是多少?内存条上的2R X 8代表了什么意思?...
  4. java 什么时候用递归_如果要用Java实现算法,一定慎用递归
  5. oracle 10g中没有refhost.xml,解决win7 安装oracle10g的问题
  6. 中文任务型对话系统中的领域分类
  7. python 图像处理_Python中的十大图像处理工具
  8. 不附加数据库 ASP.NET调用.sql文件
  9. 虚拟机中Linux克隆后相关配置-1
  10. 21天Jmeter打卡Day18 前置处理器_熟悉常用组件
  11. 关于VS中Compile Symbol 使用方法
  12. AE插件:TV Distortion Bundle mac(画面像素破损信号干扰失真插件)支持ae2021(2.6.0)
  13. 【UNIX网络编程】|【07】SCTP协议探究
  14. 密信Mesign本地部署企业密钥管理系统解决方案
  15. html图片无损压缩,有损压缩和无损压缩的区别是什么
  16. spring事务管理tx:Advice详解
  17. 医院运维管理平台(模板)
  18. 对高尔顿数据集实现线性回归分析
  19. keras-文本图片文字识别
  20. 特警把那盅犯形容的汝么厉害

热门文章

  1. Linux那些事儿之我是Hub(9)While You Were Sleeping(二)
  2. 万能的 JS(万字、基础、原理、面试、持续更新。。。)
  3. 计算机硬盘的容量比光盘大得多,gis水平考题.doc
  4. ENC降噪DSP|USB麦克风芯片|USB耳机芯片|TYPE-C麦克风芯片|192K/24位麦克风芯片|虚拟7.1耳机芯片|双麦克风耳机降噪芯片|ASS5060芯片
  5. Project Server 2010安装部署手册(1.5版)
  6. 免格式化制作老毛桃PE工具
  7. 马斯洛提出动机理论_科普 | 马斯洛需求理论 #2
  8. JAVA----钉钉机器人-订单提醒功能
  9. 内存卡里的照片删了怎么恢复?
  10. 工业3D视觉,为智能制造打开新视域