我们将创造一辆奔驰自动驾驶汽车,在空荡的城市里穿梭,并且将车载相机与激光雷达接受的数据存储到硬盘中。
在我们开始运行 python script
之前,记得先开启 CarlaUE4
。
cd Unreal/CarlaUE4 | ||
~/UnrealEngine_4.XX/Engine/Binaries/Linux/UE4Editor "$PWD/CarlaUE4.uproject" |
# 将 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 |
# Client
与 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) |
# Actor
与 Blueprint
创立了世界之后,就要开始安放我们的主角 —— actor
了。顾名思义, Actor
意味演员,在仿真世界里则代表可以移动的物体,包括汽车,传感器(因为传感器要安在车身上)以及行人。
# 生成 Actor
如果我们想生成一个 Actor
, 必须要先定义它的蓝图,这就好比造房子前要先话设计图一样。
# 拿到这个世界所有物体的蓝图 | |
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) |
# 操纵 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) |
# 注销 Actor
当这个脚本运行完后要记得将这个汽车销毁掉,否则它会一直存在于仿真世界,可能影响其他脚本的运行哦。
# 如果注销单个 Actor | |
ego_vehicle.destroy() | |
# 如果你有多个 Actor 存在 list 里,想一起销毁。 | |
client.apply_batch([carla.command.DestroyActor(x) for x in actor_list]) |
# Sensor
搭建
有了车子之后,我们就可以往上放各种各样的 sensor
啦!在这里先简单介绍下 Carla
有哪些 Sensors
, 有了车子之后,我们就可以往上放各种各样的 sensor
啦!在这里先简单介绍下 Carla
有哪些 Sensors
, 在 https://carla.readthedocs.io/en/latest/python_api/ 里有对每一种数据格式类别的详细介绍。
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))) |
# 观察者放置
当我们去观察仿真界面时,我们会发现,自己的视野并不会随我们造的小车子移动,所以经常会跟丢它。解决这个问题的办法就是把 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))) |
放置观察者后效果如下,我们将以俯视的角度观察它的运行:
# 查看储存的照片与 3D 点云
储存的 RGB 相机图如下:
查看点云图需要另外安装 meshlab
, 然后进入 meshlab
后选择 import mesh
:
sudo apt-get update -y | ||
sudo apt-get install -y meshlab | ||
meshlab |