自动驾驶仿真:Carla基础API的使用
附赠自动驾驶最全的学习资料和量产经验:链接
在这一期的分享里,我们将在Carla的仿真世界里创造一辆奔驰的小野马和带刺的玫瑰…不好意思串场了,我们将创造一辆奔驰自动驾驶汽车,在空荡的城市里穿梭,并且将车载相机与激光雷达接受的数据存储到硬盘中。
在我们开始运行python script之前,记得先开启CarlaUE4。
$ cd Unreal/CarlaUE4
$ ~/UnrealEngine_4.XX/Engine/Binaries/Linux/UE4Editor "$PWD/CarlaUE4.uproject"
0. 将Carla Library安装到你的python3里
我们之前虽然已经make好了Carla的PythonAPI, 但是并没有将它的库安装到我们默认的python3里,如果你查看carla自带的example, 会发现都要先进行以下操作:
import glob
import os
import sys
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
import carla
每次这样操作既不美观,还容易搞错路径,所以我们需要先搞以下几步,从此一劳永逸:
cd ~/carla/PythonAPI/carla/dist/
unzip carla-0.9.10-py3.6-linux-x86_64.egg -d carla-0.9.10-py3.6-linux-x86_64
cd carla-0.9.10-py3.6-linux-x86_64
接下来打开你的文档编辑器,建立一个setup.py, 将以下内容复制进去。
from distutils.core import setup
setup(name='carla',
version='0.9.10',
py_modules=['carla'],
)
然后通过pip安装到你的python3当中,从此可以直接import carla了。
pip3 install -e ~/carla/PythonAPI/carla/dist/carla-0.9.10-py3.6-linux-x86_64
1. Client and World
这两个词将会贯穿我们整个教程。
Client我们在第一节提到过,用户通过Client载体与python API与仿真环境交互,所以我们第一部就是要创建Client,并且设置一个timeout时间防止连接时间过久。
client=carla.Client('localhost',2000)client.set_timeout(2.0)
其中2000是端口,2.0是秒数。
接下来我们就要通过这个构建的Client来获取仿真世界(World)。我们如果想让仿真世界有任何变化,都要对这个获取的world进行操作。
world = client.get_world()
作为一个简单明了的示例,我们可以先试着改变一下世界的天气。
weather = carla.WeatherParameters(cloudiness=10.0,
precipitation=10.0,
fog_density=10.0)
world.set_weather(weather)
2. Actor 与 Blueprint
创立了世界之后,就要开始安放我们的主角——actor了。顾名思义,Actor意味演员,在仿真世界里则代表可以移动的物体,包括汽车,传感器(因为传感器要安在车身上)以及行人。
- 2.1. 生成(spawn) Actor
如果我们想生成一个Actor, 必须要先定义它的蓝图(Blueprint),这就好比造房子前要先话设计图一样。
# 拿到这个世界所有物体的蓝图
blueprint_library = world.get_blueprint_library()
# 从浩瀚如海的蓝图中找到奔驰的蓝图
ego_vehicle_bp = blueprint_library.find('vehicle.mercedes-benz.coupe')
# 给我们的车加上特定的颜色
ego_vehicle_bp.set_attribute('color', '0, 0, 0')
构建好蓝图以后,下一步便是选定它的出生点。我们可以给固定的位子,也可以赋予随机的位置,不过这个位置必须是空的位置,比如你不能将奔驰扔在一棵树上。
# 找到所有可以作为初始点的位置并随机选择一个
transform = random.choice(world.get_map().get_spawn_points())
# 在这个位置生成汽车
ego_vehicle = world.spawn_actor(ego_vehicle_bp, transform)
- 2.2 操纵(Handling)Actor
汽车生成以后,我们便可以随意挪动它的初始位置,定义它的动态参数。
# 再给它挪挪窝
location = ego_vehicle.get_location()
location.x += 10.0
ego_vehicle.set_location(location)
# 把它设置成自动驾驶模式
ego_vehicle.set_autopilot(True)
# 我们可以甚至在中途将这辆车“冻住”,通过抹杀它的物理仿真
# actor.set_simulate_physics(False)
- 2.3 注销(Destroy) Actor
当这个脚本运行完后要记得将这个汽车销毁掉,否则它会一直存在于仿真世界,可能影响其他脚本的运行哦。
# 如果注销单个Actor
ego_vehicle.destroy()
# 如果你有多个Actor 存在list里,想一起销毁。
client.apply_batch([carla.command.DestroyActor(x) for x in actor_list])
3.Sensor搭建
有了车子之后,我们就可以往上放各种各样的sensor啦!在这里先简单介绍下Carla有哪些Sensors, 有了车子之后,我们就可以往上放各种各样的sensor啦!在这里先简单介绍下Carla有哪些Sensors, 在Python API reference 里有对每一种数据格式类别的详细介绍。
Sensor | Sensor输出数据形式 | 功能 | 类别 |
---|---|---|---|
RGB Camera | carla.Image | 普通的RGB相机 | Cameras |
深度相机 | carla.Image | 深度相机,以灰度图形式储存 | Cameras |
分割相机 | carla.Image | 直接输出景物分割图,不同颜色代表不同的种类 | Cameras |
Collision | carla.CollisionEvent | 汽车发生碰撞时启动,会将事故的信息记录下来 | Detector |
Lane invasion | carla.LaneInvasionEvent | 汽车变道时启动,将Lane ID与汽车ID记录下来 | Detector |
Obstacle | carla.ObstacleDetectionEvent | 将可能挡在前方行驶道路上的物体记下 | Detector |
GNSS | carla.GNSSMeasurement | 记录车子的地理位置 | Other |
IMU | carla.IMUMeasurement | 记录汽车的轴加速度与角加速度 | Other |
LIDAR | carla.LidarMeasurement | 激光雷达 | Other |
Radar | carla.RadarMeasurement | 声波雷达 | Other |
Semantic LIDAR | carla.SemanticLidarMeasurement | 除了3D点云外,还提供额外的Semantic信息 | Other |
在这个教程里,我们会建立Camera与激光雷达。
- Camera构建
与汽车类似,我们先创建蓝图,再定义位置,然后再选择我们想要的汽车安装上去。不过,这里的位置都是相对汽车中心点的位置(以米计量)。
camera_bp=blueprint_library.find('sensor.camera.rgb')camera_transform=carla.Transform(carla.Location(x=1.5,z=2.4))camera=world.spawn_actor(camera_bp,camera_transform,attach_to=ego_vehicle)
我们还要对相机定义它的callback function,定义每次仿真世界里传感器数据传回来后,我们要对它进行什么样的处理。在这个教程里我们只需要简单地将文件存在硬盘里。
camera.listen(lambda image: image.save_to_disk(os.path.join(output_path, '%06d.png' % image.frame)))
- Lidar构建
Lidar可以设置的参数比较多,对Lidar模型不熟也没有关系,我在后面会另开文章详细介绍激光雷达模型,现在就知道我们设置了一些常用参数就好。
lidar_bp = blueprint_library.find('sensor.lidar.ray_cast')
lidar_bp.set_attribute('channels', str(32))
lidar_bp.set_attribute('points_per_second', str(90000))
lidar_bp.set_attribute('rotation_frequency', str(40))
lidar_bp.set_attribute('range', str(20))
接着把lidar放置在奔驰上, 定义它的callback function.
lidar_location = carla.Location(0, 0, 2)
lidar_rotation = carla.Rotation(0, 0, 0)
lidar_transform = carla.Transform(lidar_location, lidar_rotation)
lidar = world.spawn_actor(lidar_bp, lidar_transform, attach_to=ego_vehicle)
lidar.listen(lambda point_cloud: \
point_cloud.save_to_disk(os.path.join(output_path, '%06d.ply' % point_cloud.frame)))
4. 观察者(spectator)放置
当我们去观察仿真界面时,我们会发现,自己的视野并不会随我们造的小车子移动,所以经常会跟丢它。解决这个问题的办法就是把spectator对准汽车,这样小汽车就永远在我们的视野里了!
spectator = world.get_spectator()
transform = ego_vehicle.get_transform()
spectator.set_transform(carla.Transform(transform.location + carla.Location(z=20),
carla.Rotation(pitch=-90)))
放置观察者后效果如下,我们将以俯视的角度观察它的运行:
5. 查看储存的照片与3D点云
储存的RGB相机图如下:
查看点云图需要另外安装meshlab, 然后进入meshlab后选择import mesh:
sudo apt-get update -y
sudo apt-get install -y meshlab
meshlab