Carla Simulator自动驾驶模拟器 使用教程

前言:我想验证SLAM代码的效果,所以需要构建一个能提供自己和周围动车的位姿/轨迹和语义分割、bbx的真实值复杂动态环境(最好能超过目前KITTI-Tracking序列的动态复杂度),所以要能设置CARLA世界中动车的密度、速度、与自己的相对距离、相对方向,和自己的速度;并能记录双目RGB和实例分割、轨迹、BBX。

目录

1.CARLA 简介

2. 安装Carla客户端

3. 基础API的使用

3.1 client_bounding_boxes.py

3.2 draw_skeleton.py 

3.3 dynamic_weather.py

3.4 generate_traffic.py

3.5 lidar_to_camera.py

3.6 manual_control.py

3.7 tutorial.py

3.8 tutorial_gbuffer.py

3.9 automatic_control.py

3.10-13 manual_control_carsim.py manual_control_chrono.py manual_control_steeringwheel.py manual_control_gbuffer.py

3.14 no_rendering_mode.py

3.15 open3d_lidar.py

3.16 start_recording.py

3.17 show_recorder_actors_blocked.py

3.18 show_recorder_collisions.py

3.19 show_recorder_file_info.py

3.20 start_replaying.py

3.21 visualize_multiple_sensors.py

3.22 synchronous_mode.py

3.23 sensor_synchronization.py

3.24 vehicle_gallery.py

3.25 vehicle_physics.py

4. 编写自己的脚本


1.CARLA 简介

CRALA是一款开源仿真器,用于自动驾驶系统的开发、训练和验证。

1.1 采用服务器多客户端的架构,客户端数量具有可扩展性,多个客户端可挂载在同一或不同节点,来控制不同的“角色”。客户端client通过python脚本作为应用程序接口API来给服务器端下达指令,修改天气、车辆的型号和行为模式、车速等,交给由UnrealEngine引擎构建的服务器端进行虚拟世界的构建和渲染。

1.2 用户可通过CARLA提供的各API来控制仿真环境中的交通状况、行人属性、天气、采用的传感器等。其中,传感器套件包括:LIDARs,多目相机,深度传感器和GPS、IMU等,照片竟然还有畸变和动态模糊效果,用户可以将这些传感器附加attach到不同的车辆来收集各个时刻的数据。

1.3 用于规划和控制的快速仿真模式禁用图形渲染,以快速执行不需要图形的交通模拟和道路行为。

1.4 通过RoadRunner工具,用户可创建自己的地图

1.5 ScenarioRunner引擎可让用户基于行为模块自定义各种交通环境

1.6 提供ROS-bridge,让Carla与ROS和Autoware交互。所以建议用Ubuntu18.04-20.04进行安装,否则Win平台与ROS平台容易出现兼容问题。

1.7 提供自动驾驶基线来作为可运行代理,包括AutoWare代理Conditional Imitation Learning代理

1.8 OpenAsset模块允许添加自定的物体来给Client调用。

2. 安装Carla客户端

 具体安装过程:

手把手教你win11下安装carla并跑演示例子_carla 演示-CSDN博客

2.1 要求:系统是Windows或Linux。至少6GB(推荐8GB)的GPU。有硬盘空间20G。Python是CARLA主要的脚本语言,支持2.7或3.6-3.8。2个TCP端口(默认是2000和2001,确保不被防火墙或其他应用阻塞)和网络连接。如果做自驾开发最好是ubuntu系统。但我电脑没有AHCI数据传输模式所以目前装不了Ubuntu。

2.2 Windows 11安装Anaconda win11系统23年6月最新anaconda安装教程及配置环境变量_anaconda环境变量配置-CSDN博客

配置python3.7环境,这个版本要和carla版本一致。

【anaconda】conda创建、查看、删除虚拟环境(anaconda命令集)_conda 创建环境-CSDN博客

并查看pip版本是否符合CARLA版本的要求。

安装carla依赖库 pip3 install --user pygame numpy。(这个官网提供指令不全,具体见CARLA_0.9.14\WindowsNoEditor\PythonAPI\examples\requirement.txt列出的依赖库。)

2.3 选择Carla 的package安装方式。下载并解压缩CARLA_0.9.14.zip,它包含模拟器的预编译版本,Python API模块和一些用作示例的脚本。

双击运行CARlaUE4.exe,在我电脑上帧率可达到>60fps。

3. 基础API的使用

一共25个API,关于API的理解与应用,参考小飞自动驾驶系列分享 - 知乎 (zhihu.com)

如果报HTTP错连不上Carla Server (default 127.0.0.1:2000),或分辨率太高导致传感器显示不对:

Carla学习笔记(二)——摄像机画面显示错误的解决办法,无法连接后台服务的解决办法_carla显示多窗口-CSDN博客

但有时候HTTP连不上是因为对应脚本里client.set_timeout(2.0)即设置的连接时间上限太短了,可以改大点,我一般改成20。

其中manual_control是功能最全的,功能>automatic_control;tutorial和tutorial_gbuffer是官方提供的辅助入门脚本,有详细注释。

3.1 client_bounding_boxes.py

运行界面中,标注自己hero vehicle的包围盒,并manual control,W前,A左转,D右转,S刹车&倒车,空格手刹/制动。

该脚本在主函数中创建BasicSynchronousClient类的实例,并调用该实例的game_loop()函数。

game_loop()是主循环程序,负责 (1) 创建carla的一个客户端实例carla.Client('127.0.0.1', 2000),然后通过该客户端访问虚拟世界client.gt_world()。

(2) 然后调用BasicSynchronousClient类的setup_car()函数,负责:先访问虚拟世界的所有vehicle类型的第一个模型设计蓝图car_bp = world.get_blueprint_library().filter('vehicle.*'),并随机生成虚拟世界地图中一个空白地点location = random.choice(self.world.get_map().get_spawn_points())来作为车辆演员的起始地点,然后生成这个车辆演员car = world.spawn_actor(car_bp, location)。

(3) 因为要观察自己车辆的包围盒,所以要创建一个第三方视角,即一个观测的相机演员。所以调用BasicSynchronousClient类的setup_camera()函数,负责:(3.1)先确定相机相对于这个车辆演员的位置和姿态角camera_transform = carla.Transform(carla.Location(x=-5.5, z=2.8), carla.Rotation(pitch=-15));(3.2)然后调用BasicSynchronousClient类的camera_blueprint()函数,找到RGB相机的设计蓝图camera_bp =  world.get_blueprint_library().find('sensor.camera.rgb'),并将pygame界面的宽VIEW_WIDTH、高VIEW_HEIGHT、视场角VIEW_FOV 作为相机像素平面的宽高视场角;(3.3)结合相机模型的设计蓝图camera_bp和这个相对位姿camera_transform ,生成一个相机演员camera = world.spawn_actor(camera_bp, camera_transform, attach_to=car),其中attach_to属性表示相机跟随这个车辆演员运动而运动,相机演员的父节点是这个车辆演员;(3.4)相机接收自己的图像camera.listen(lambda image:weak_self().set_image(weak_self, image)),即如果capture=true,就将采集到的img赋值给BasicSynchronousClient类实例的self.image;(3.5)根据(3.2)中相机的像素平面参数来生成自己的内参矩阵calibration,用于3D BBX到成像平面的投影。

(4) 调用pygame模块,创建显示窗口。

(5) carla默认世界和客户端的时间戳是异步的,而采集RGB等信息并回传至客户端显示,就要保证二者之间是同步的,否则会造成数据丢失。所以调用BasicSynchronousClient类的set_synchronous_mode()函数,负责修改虚拟世界的同步模式world.get_settings().synchronous_mode = true。

(6) 进入控制--渲染循环 while true:(6.1) 调用BasicSynchronousClient类的render(){如果self.image非空,就调用pygame.display进行图像渲染};(6.2)调用ClientSideBoundingBoxes类的get_bounding_boxes()函数{返回所有车辆演员的、在相机可见范围内的 Bounding Boxes};(6.3)调用ClientSideBoundingBoxes类的draw_bounding_boxes()函数{将获取的有效bbx投影显示到相机成像平面上};(6.4)调用BasicSynchronousClient类的control(car){获取对car演员的控制权control = car.get_control(),根据用户的键盘按键pygame.key.get_pressed(),如果等于K_w或K_s或K_a或K_d或K_SPACE,就分别制定control动作control.throttle\reverse\steer\hand_brake,然后应用到car演员上car.apply_control(control),返回false;如果按键是K_ESCAPE,就返回true};(6.5)根据control()的返回值,如果按esc键,就停止while循环。

(7)最后,一定要销毁创建的车辆和相机演员.destroy(),否则会存在在世界中使其他程序报错;并恢复carla的异步模式;关闭pygame窗口。

3.2 draw_skeleton.py 

我修改分辨率为1920*1080,否则输出是有问题的(如下图)。

正确显示界面应该如下图,应该包含RGB采集的环境图像和行人演员的骨骼模型,要不然就不用设置tick()进行多传感器输出数据的同步处理了。

在键盘ctrl+c停止运行之前,调用main():

(1)创建pygame窗口,传参宽高视场角。

(2)创建client,访问world。

(3)生成RGB相机演员camera,设置属性宽高视场角。

(4)生成行人演员

首先 world.set_pedestrain_seed(1235)。

随机获取一个行人模型的蓝图ped_bp = random.choice(world.get_blueprint_library().filter("walker.pedestrain.*")),获取一个随机地点trans = carla.Transform.location = world.get_random_location_from_navigation()为起点,生成行人演员ped = world.spawn_actor(ped_bp, trans)。

注意,行人是carla自动控制的,即获取一个行人控制器蓝图walker_controller_bp= world.get_blueprint_library().find('controller.ai.walker')并生成该蓝图的行人控制器演员controller = world.spawn_actor(walker_controller_bp, carla.Transform(), ped),注意要连接控制的行人演员,并设置相对位姿为单位阵。并启动控制器演员controller.start(),生成随机地点为终点controller.go_to_location(world.get_random_location_from_navigation()),并设置最大速度controller.set_max_speed(1.7)。

(5)所以一共创建了三个演员:相机camera,行人ped,行人AI控制器controller,依次添加append进actor_list列表中。

(6)渲染的while True循环:除非按键ctrlc停止。

(6.1)参数blending负责修改行人的运动animation,ped.blend_pose(math.sin(belnding));参数turning负责相机绕行人转动位姿trans.location.x+=math.cos(turning)*-3/y+=math.sin(turning)*3\z始终为2\rotation.pitch和roll始终为-16和0\yaw=-360*(turning/math.pi*2)。每帧更新量分别为+=0.015和+=0.009。

(6.2)调用CarlaSyncMode类的tick()进行多传感器输出的同步,得到snapshot(没用到)和camera采集的环境图像image_rgb。

(6.3)图像转换为渲染数组 buffer = CarlaSyncMode::get_image_as_array(image_rgb){注意保证image转换的array是可写的,因为要添加绘制行人的骨骼,通过array2 = copy.deepcopy(array)}。

(6.4)获取行人的骨骼ped.get_bones(),并依次保存骨骼节点的名字name和位置world.location属性到boneIndex列表和points列表中。

(6.5)将骨骼节点(世界坐标系中)转换投影到成像平面上,调用CarlaSyncMode类的points2d = get_screen_points(camera, K根据pygame/camera宽高视野转换的camera内参矩阵/投影矩阵,image_w,image_h, points)。

(6.6)绘制

根据骨骼节点的名字及先验的相邻关系,绘制骨骼节点points_2d之间的连线(绿色),调用CarlaSyncMode类draw_skeleton(buffer, image_w, image_h, boneIndex, points_2d, (0, 255, 0), 2),修改buffer中对应位置像素点的color值。

绘制骨骼节点points_2d(红色),调用CarlaSyncMode类draw_points_on_buffer(buffer, image_w, image_h, points_2d[1:],(255,0,0),4)。

draw_image()调用pygame.display,pygame.display.flip()进行显示(write_image负责将buffer保存为png至_out文件夹下按照'%s_%06d.png'%("ped", snapshot.frame)命名)。

3.3 dynamic_weather.py

可以修改日照角度、雨雾多云等天气状态。

有三个类:sun storm weather

首先main()中传参:端口、天气变化速率speed_factor=1.0—>更新频率update_freq = 0.1/speed_factor。创建client,访问世界,获取天气world.get_weather()

然后进入while True循环:只要距离上一次刷新天气的过去时间elapsed_time>update_freq,就调用weather类的tick(speed_factor*elapsed_time)根据elapsed_time更新天气状态参数;然后将参数传给weather,更改世界的天气world.set_weather()

那么weather类初始化函数首先实例化Sun类和Storm类的实例。

然后weather::tick(elapsed_time)调用Sun::tick(elapsed_time)和Storm::tick(elapsed_time),然后更新weather.cloudiness\降水和降水量precipitation & precipitation_deposity\风力强度wind_intensity\fog_density\wetness\太阳方位角和高度角 sun_azimuth_angle & sun_altitude_angle。

那么Sun::tick(elapsed_time){根据elapsed_time更新方位角和高度角}

Storm::tick(elapsed_time){根据elapsed_time更新clouds rain puddles wetness wind fog等参数 }

3.4 generate_traffic.py

自定义生成车辆和行人的数量,然后进行Carla 自动控制

我设置创建100辆车,30个行人,但最多只能创建23个行人,否则会发生碰撞等交通事故。

这个脚本一共就两个函数:get_actor_blueprint(){获取要求种类的演员模型蓝图列表}和main()。但是这个脚本使用了carla的trafficManager模块

运行main(),直至ctrlC停止运行。

(1) 设置参数:端口号, number_of_vehicles, number_of_walker,安全生成演员模式safe, 生成演员类型filterV默认为vehicle.*...

(2) 生成client,访问world,访问traffic_manager = client.get_trafficmanager(args.tm_port)#default 8000。

设置traffic_mnager参数:引导车辆的全局距离traffic_manager.set_global_distance_to_leading_vehicle(2.5);set_respawn_dormant_vehicles;set_hybrid_physics_mode,set_hybrid_physics_radius;set_random_device_seed.

(3) 设置world.setting和traffic_manager的同步模式。

(4) 依次调用get_actor_blueprint()函数,分别生成车辆的蓝图列表bluepeints和行人的蓝图列表blueprintsWalkers。如果是safe模式,则过滤保留只为car的blueprints,并根据id对blueprints排序。

(5) 获取世界地图中空白地点spawn_points = world_get_map().get_spawn_points(),并打乱顺序。

(6) 引入carla的三个指令:

carla.command.SpawnActor\SetAutopilot\FutureActor

(7) 首先生成车辆:遍历spawn_points,获得每个出生点的id和transform,并设置blueprints列表中对应顺序的蓝图的color、driver_id和role_name属性,其中role_name可以为hero(全局只有一个)或autopolot自动驾驶,最后将对应的生成--自驾指令carla.command.SpawnActor(blueprint, transform).then(carla.command.SetAutopilot(carla.command.FutureActor, True, traffic_manager.get_port()))加入进指令列表batch,进行后续的批量化处理client.apply_batch_sync(batch, synchronous_master=True),并将能成功生成的演员添加进vehicle_list列表,否则输出报错。最后对vehicle_lists中每个vehicle演员,将车灯自控模式打开traffic_manager,update_vehicle_light(actor for actor in world.get_actors(vehicles_list), True)。

(8) 然后生成行人:设置跑和横穿马路的行人的比例。按要求的行人数量,依次生成一个随机地点world.get_random_location_from_navigation()来给生成地点spawn_point赋值,并append进全体行人的生成地点列表spawn_points中。

然后遍历每个生成地点,随机选一个行人蓝图walker_bp,设置属性is_invincible,speed(推荐值[1]为步速,[2]为跑速,或为0),然后将生成行人指令carla.command.SpawnActor(walker_bp, spawn_point)添加进指令列表batch中,调用client.apply_batch_sync(batch, True)进行批量操作,将成功生成的行人添加进行人演员列表walkers_list中,对应速度也保存至列表walker_speed中。

3.2 draw_skeleton.py,行人还需要设置控制器演员,和vehicle.autopilot类似。对walkers_list中每个演员,根据对应的controller.ai.walker类型的蓝图,将对应的sapwnActor指令添加进batch并批量化处理,并保留成功的controller至对应的walkers_list的"con",并依次将walker 和 对应 controller演员的id保存至all_actors列表 [controller actor controller actor ...]

all_actors.start(), all_actors.go_to_location(world.get_random_location_from_navigation()), all_actors.set_max_speed(...)

(9) 至此,已经生成了所有要求的车辆和行人,并开启了他们的自动驾驶/自动控制。

(10) 进行while true循环,更新world传输至client的信息。

(11) 最后,ctrl C终止后,批量销毁演员

车:client.apply_btch([carla.command.DestroyActor(x) for x in vehicles_list])

人:all_actors.stop()

client.apply_btch([carla.command.DestroyActor(x) for x in all_id)

3.5 lidar_to_camera.py

分辨率res为'1280x720'。结果如下图。这个脚本相对其他脚本写的非常模块化,可读性很好!

main()传端口号、相机分辨率、lidar探测范围等参数,然后调用tutorial()。

tutorial()首先创建client,访问world,获取所有蓝图bp_lib,访问traffic_manager,并设置world和traffic_manager为同步模式。

创建图像保存文件夹"_out"。

从bp_lib中筛选出vehicle.lincon.mkz_2017蓝图、sensor.camera.rgb蓝图、sensor.lidar.ray_cast蓝图,赋值给vehicle_bp、camera_bp、lidar_bp。并设置camera_bp参数image_size,lidar_bp参数upper_fov\channels\range等。然后生成演员vehicle(通过world.get_map().get_spawn_points()[0]生成起始位姿),并设置为autopilot模式;生成演员camera,以相对位姿x=1.6\z=1.6固定到vehicle演员上;生成演员lidar,同样以x=1\z=1.8固定在vehicle上。

通过camera演员的属性参数image_size和fov(当然也是通过args传参给camera_bp的)生成相机的投影矩阵/内参矩阵K。

注意,初始化两队列,image_queue\lidar_queue=Queue(),camera和lidar演员监听数据存放到这两个队列中,camera.listen(lambda, data:sensor_callback(data,image_queue)), lidar.listen(lambda, data:sensor_callback(data,lidar_queue))。注意,sensor_callback()是这个脚本的另一个函数,负责将data存放到对应队列中queue.put(data)

默认存500帧args.frames, for frame in range(args.frames) { 每帧的帧数 world_frame = world.get_snapshot().frame,queue.get对应的image_data和lidar_data,并且保证两个数据的帧数和世界帧数一致/同步assert world_frame = image_data.frame = lidar_data.frame。

然后将image_data.raw_data转化为RGB通道的数组im_array,将lidat_data.raw_data转化为数组p_cloud。

对p_cloud的xyz坐标构成的点云数组local_lidar_points,依次经过lidat.get_transform().get_matrix、camera.get_transform().get_inverse_matrix()、UE4坐标系转换为OpenCV系/相机系、K投影、归一化、去掉处于成像范围外和相机成像平面后的点、float转化为整数,得到最终的u_coord和v_coord。并获取保留点对应的亮度intensity并对其进行便于可视化的调整,转化为RGB值color_map。

将im_array中处于[u_coord,v_coord]处 或 以[u_coord,v_coord]为中心的半径为do_extent的方块内的 像素RGB值修改为color_map。

最后将修改后的im_array通过Pillow库的Image.fromarray()转化为图像并save至_out文件夹下save("_out/%08d.png"%image_data.frame) }

如果用户按ctrlC关闭,则finally: camera.destroy()\lidar.destroy()\vehicle.destroy()。

3.6 manual_control.py

这个脚本的功能和3.1 client_bounding_boxes.py 相似,可以手动控制车辆的运行、灯、门、视角、传感器等,改变天气,录制数据并回放等。对我很有用。

W油门throttke

S刹车brake

A/D左转右转steer left/right

Space手刹hand brake

Q反向,倒车 toggle reverse

P切换为自动驾驶toggle autopilot

M切换到手动档toggle manual transmission

,/.加减档位

CTRL+W切换为60k/h的匀速

车灯管理

传感器管理 提供不同视角、传感器类型有 深度 语义分割 实例分割 lidar 光流 运动背景差分 正畸前后的RGB图像 等等,很有用!

改变天气、打开关闭车门

选择地图图层(比如 buildings decals贴纸 foliage枝叶 groundparkedvehicles particles props支柱 streetlights walls all)

记录仿真过程,仿真过程回放...

比如,实例分割的运行界面截图

脚本包含全局函数:find_weather_presents(){获取carla预设的各种天气的属性值列表},

get_actor_display_name(actor)获取演员的具体类型名字符串,

get_actor_blueprints(world, filter, generation)获取符合filter generation参数要求的蓝图列表。

脚本包含11个类:World, KeyboardControl, HUD, FadingText, HelpText, CollisionSensor, LaneInvasionSensor, GnssSensor, IMUSensor, RadarSensor, CameraManager

注意要导入pygame库的相关交互按键。

main():传递端口号、pygame界面的分辨率。然后进行game_loop()直至用户CTRL+C。

game_loop()首先创建pygame界面。创建client,访问sim_world,设置world的同步模式;访问traffic manager,设置同步模式。

初始化HUD类实例hud(args.width, args.height)。

初始化World类实例world(sim_world, hud)。

初始化KeyBoardControl类实例controller(world)。

进入while true循环:

(1) 调用KeyboardControl类parse_events(){如果用户按终止按键,就返回true,就结束外层的while true循环;否则,根据按键,比如自动驾驶模式调用World::restart(){会创建传感器CollisionSensor, LaneInvasionSensor, GnssSensor, IMUSensor, RadarSensor,这些传感器的init函数都是创建演员绑定到world::player即vehicle演员,并开启监听模式;on_xxx()则是记录监听的数据,比如碰撞调用HUD::notification()输出碰谁了,碰撞历史以字典形式记录每帧的累计碰撞强度;车道线类型;GNSS IMU Radar的位置 点云数据},或 修改world.player或weather或camera或map等属性,并调用HUD::notification(){调用FadingText::set_text(){将操作信息添加到显示界面上}}}。

(2)调用World类的tick(){调用HUD类的tick(){收集显示界面左侧的环境、汽车的状态信息列表info_text}}

(3)调用World类的render(){

调用CameraManager::render(){pygame解析的图像/雷达传感器数组,进行pygame.flip()显示};

调用HUD::render(){绘制info_text,分成四种情况 线 方块 条状物 文字;

                               然后调用FadingText::render(){绘制操作信息},

                               调用HelpText::render(){}}

}

最终更新渲染显示界面pygame.display.flip()。

3.7 tutorial.py

本来应该先看这个脚本再看3.6。我补充设置了深度相机的分辨率camera_bp.set_attribute("image_size_x", str(1280))
        camera_bp.set_attribute("image_size_y", str(760))否则输出有问题。

具体的注释,作者已经写的很好。这个脚本负责创建一辆车并自动驾驶,一个深度depth相机绑定到车上并监听图像保存至out文件夹下,移动该车的位置(所以会观测到采集的图像不连贯),尝试创建其他10辆车world.try_spawn_actor()并设为自动驾驶(因为位置是作者自定的,不是world.get_map().get_spawn_points(),所以有可能不是空的,所以有可能不会成功)。最后不要忘了(批量)destroy所有演员。

3.8 tutorial_gbuffer.py

和3.7一样,辅导性的脚本,作者注释写的很好!这个脚本负责创建一辆车(自驾模式)、

创建一个RGB相机并绑定到车上,监听各种数据并保存。具体数据类型例子如下:

>>最终的RGB图像FinalColor

>>carla.GBufferTextureID.SceneDepth

>>carla.GBufferTextureID.SceneColor

>>carla.GBufferTextureID.SceneStencil

>>carla.GBufferTextureID.GBufferA

>>carla.GBufferTextureID.GBufferB

>>carla.GBufferTextureID.GBufferC

>>carla.GBufferTextureID.GBufferD

>>carla.GBufferTextureID.GBufferE不可获取,黑图

>>carla.GBufferTextureID.GBufferF不可获取,黑图

>>carla.GBufferTextureID.Velocity

>>carla.GBufferTextureID.SSAO

>>carla.GBufferTextureID.CustomDepth

>>carla.GBufferTextureID.CustomStencil

3.9 automatic_control.py

这个脚本是3.6 manual_control.py的一个基础。即3.6脚本提供自动驾驶和手动控制两种模式。

3.10-13 manual_control_carsim.py manual_control_chrono.py manual_control_steeringwheel.py manual_control_gbuffer.py

和manual_control.py差不多,就是manual_control_carsim多了carsim模式,不知道干啥的;注意manual_control_steeringwheel要结合罗技方向盘套装使用;manual_control_gbuffer按U键可以切换不同的渲染内容(参考3.8 tutorial_gbuffer的输出。)

manual_control_gbuffer提供的的其中一种渲染模式。

测试之前没实际操作的按键。

按backspace键可以换控制演员:而且初始视角真的很随机,甚至可以在车内司机后方。

R可以开始/停止录制传感器RGB图像至out文件夹。

V可以选不同的地图图层,Shift+B可以去掉图层,B可以加载图层。比如我选中all后去掉,就不会显示建筑物、树等:

3.14 no_rendering_mode.py

即2D模式,可自动、手动控制车运动。

tab关闭hero视角后(当然鼠标缩放hero视角也可以实现)终于看到地图全貌!

刚开始,按照Tango桌面项目定制了一个调色盘,有需要的可以看一下,一共8组,前7组分3个深浅度,最后一组分7个深浅度,还有黑白两色。这个我先不看了。

3.15 open3d_lidar.py

雷达点云以CityScapes颜色盘用Open3D可视化,注意UnrealEngine和O3D坐标系的手性相反。这个我先不看了。

3.16 start_recording.py

是3.16-19的源文件产生者,会生成10辆自动驾驶模式的车演员,并进行录制client.start_recorder(filename) & client.stop_recorder()(但我不知道log存的啥?打开是乱码,运行上述文件也没有什么输出),存放.log文件。

3.17 show_recorder_actors_blocked.py

没运行成功,应该是回放录制好的一段视频,调用crala.client.show_recorder_actors_blocked(文件路径,认定车被被阻塞时间,认定车被阻塞的最小移动距离)。

3.18 show_recorder_collisions.py

同理,调用carla.client.show_recorder_collisions(文件路径,碰撞发生的两方的类型(比如车碰车 车碰路灯 ...))。

3.19 show_recorder_file_info.py

同理,调用carla.client.show_recorder_file_info(文件路径,是否显示所有时刻的内容)进行记录或显示。

3.20 start_replaying.py

结合3.15录制的log,调用client.replay_file(filename...)

3.21 visualize_multiple_sensors.py

 visualize_multiple_sensors的结果:

main()创建代理client,调用run_simulation().

run_simulation(){

访问世界world,访问交通管理器trafficManager,设置它们的同步模式。

获取一个车辆蓝图,一个随机空白地点,生成演员vehicle,设置为自动驾驶模式,添加进车演员列表vehicle_list以方便最后批量销毁。

调用显示管理器DisplayManager::init(),两行三列划分窗口。

调用传感器管理器SensorManager::init(),分别创建三种传感器sensor.camera.rgb,sensor.lidar.ray_cast,sensor.lidar.ray_cast_semantic,首先是四个RGB相机演员,分别以x=0 z=2.4,yaw=-90 0 90 180的相对位置绑定到vehicle上,传回图像在display_manager的位置分别是(0,0) (0,1) (0,2) (1,1);然后是两个激光雷达演员。并进行监听,分别调用DisplayManager::save_rgb_image save_lidar_image save_semanticlidar_image,将图像转换至array再转换至pygame::surface对象。并添加进DisplayManager::sensor_list传感器列表中。

开始while true循环:调用DisplayManager::render(){对sensor_list中每个sensor,调用其对应的SensorManager::render(){将save_xxx_image()保存的surface在对应位置DisplayManager::get_display_offset()叠加至pygame窗口上blit},然后进行更新显示flip。

如果pygame被终止,就break while循环}

最后,调用DisplayManager::destroy(){对sensor_list中每个sensor,调用SensorManager::destroy(){演员destroy.()}}

将vehicle_list批量销毁。

恢复world的默认设置,即异步模式。和3.21一起看 

}

3.22 synchronous_mode.py

将同步接收的RGB和语义分割图像叠加显示,语义分割设置透明处理。

脚本按原设置分辨率800x600不对。我根据manual_control改成1280x720。并设置camara blueprint和camera_semseg blueprint的image_seize_x/y属性为1280 720.即添加下文绿色代码。

cam_bp = blueprint_library.find('sensor.camera.rgb')
        cam_bp.set_attribute('image_size_x', str(1280))
        cam_bp.set_attribute('image_size_y', str(720))

        camera_rgb = world.spawn_actor(
            cam_bp,
            carla.Transform(carla.Location(x=-5.5, z=2.8), carla.Rotation(pitch=-15)),
            attach_to=vehicle)
        actor_list.append(camera_rgb)

        cam_semseg_bp = blueprint_library.find('sensor.camera.semantic_segmentation')
        cam_semseg_bp.set_attribute('image_size_x', str(1280))
        cam_semseg_bp.set_attribute('image_size_y', str(720))

        camera_semseg = world.spawn_actor(
            cam_semseg_bp,  
            carla.Transform(carla.Location(x=-5.5, z=2.8), carla.Rotation(pitch=-15)),
            attach_to=vehicle)
        actor_list.append(camera_semseg)

运行界面:

main():client world ,一个随机的生成地点start_pose = random.choice(world.get_map().get_spawn_points()),waypoint= map.get_waypoints(start_pos.location)

生成演员vehicle camera.rgb camera.semantic_segmentation,保存至actor_list()。

调用CarlaSyncMode::init(),

whileTrue: {

调用CarlaSyncMode::tick(){获取传感器队列中的同步数据snap_shot\image_rgb\image_semseg,

随机获取下一个waypoint.next(1.5)作为vehicle的下刻位置。

将传图image_semseg转换为cityscapes的颜色盘。

调用全局函数draw_image(){将图像转换至array至surface,添加至显示窗口blit},分别叠加image_rgb和image_semseg(透明度alpha=100)。然后叠加帧率。最后显示flip。

如果用户关闭pygame串口,break while。

}

对actor_list进行destroy()。

3.23 sensor_synchronization.py

没有可视化界面,就是循环得监听多个传感器的数据,保证它们同步。

输出结果

在世界的原点处创建rgb lidar.ray_cast radar三种传感器,并添加进sensor_list中,各传感器监听数据加入sensor_queue队列。

while true{

获取world时刻 world.get_snapshot().frame用来保证多个传感器的同步

获取sensor_queue中数据,输出数据的时刻和对应的传感器演员。

}

销毁传感器演员,并设置世界为默认参数。

3.24 vehicle_gallery.py

车辆展示厅,绕着随机生成的不同类型的车转着观察两圈,再换下一个车型。

client world 

观众spectator = world.get_spectator()

随机生成一个地点location

遍历获取的vehicle类型的蓝图:{

在location上生成车辆演员,输出车的类型名称,

while angle from 0 to 356:

{

根据时间计算角度angle,

设置观众的位姿,位置=车的地点,姿态角=angle-90,spectator.set_transform()以实现绕着车观察两圈的效果。

}

}

最后销毁车辆。注意spectator只是一个视角,不是演员,所以不用销毁。

3.25 vehicle_physics.py

一台车跳两下,一高一低。

main():cleint world 设置同步。

获取model3类型的一辆车的蓝图,一个空白地点,生成演员,

获取演员的物理属性控制权限physics_vehicle = vehicle.get_physics_control,

就可以获得车的质量car_mass = physics_vehicle.mass

设置观察者视角:位置在车前20米,方向与车头方向相反,spectator=world.get_spectator(),spectator.set_transform()。

让车速为0set_target_velocity(carla.Vector3D(0,0,0))

对车在z(即向上)方向添加10倍质量的冲量vehicle.add_impluse(carla.Vector3D(0,0,10*car_mass))

再设置车到原位置,静止。

对车在z(即向上)方向添加100倍质量的力vehicle.add_force(carla.Vector3D(0,0,10*car_mass/0.1)) #理论上应该在一段时间内施加恒力或变力forces,但这个脚本是为了add_force和add_impluse方法的等效性,即a force more or less equivalent is impluse/delta.(但是不知道为啥一高一低,不应该是等高?)

再设置车到原位置,静止。

对应输出:

最后恢复world设置,销毁车辆。

4. 编写自己的脚本

4.1 功能设想

设置hero vehicle,自动驾驶模式,绑定双目rgb和instance segmentation传感器;添加尽量多的车(自动驾驶模式)和行人及walker.ai控制器。

while保存world.tick()&world.frame()的vehicle.transform()、三个图像、周围其他车辆的transform和BBX,存为KITTI-Tracking格式。

主要结合了generate_traffic.py和lidar2camera.py。

4.1.1 获取KITTI-Tracking 20参数

>> 分辨率

from PIL import Image

img=Image.open('000000.png')

print(img.size) #1241*376 #so I set the resolution of carla as 1280*720

>>相机内参:

fx=fy=718.856

cx=607.1928

cy=185.2157

双目bf = baseline*fx=386.1448,所以基线为0.5372 m(和KITTI论文数据0.54m一致)

fps为10帧/s

根据carla lidar2camera提供的计算公式:

focal=image_w/(2.0*np.tan(fov*np.pi/360.0)) 即 tan(fov/2) = (0.5*image_w)/focal,焦距focal=fx=fy

可得fov=2*arctan((0.5*image_w)/focal) = 81.6000deg。

carla.camera_bp.get_attribute("fov").as_float()输出90.0deg。注意carla的camera只有水平方向的视场角。

但是我不想引入太多背景纹理,所以缩小FOV为60°。所以要重新计算内参矩阵cx=0.5*width=640,cy=0.5*height=360,fx=0.5*width/arctan(0.5*fov),fy=fx因为不知道竖直方向的视场角。

>>相机相对安装位置

根据KITTI论文Vision meets robotics: The KITTI dataset - A Geiger, P Lenz, C Stiller, R Urtasun, 2013 (sagepub.com)

左目RGB相机与右目RGB相机距离0.54m。

左目灰度相机在车纵向中轴线(车身宽1.6m,而左目灰度相机距左侧车身0.8m);左目灰度相机与左目RGB相机、右目灰度相机与右目RGB相机距离0.06m。

all 相机离地高度为1.65m,距前轮线距离1.68m(车前后轮距2.71m),相机方向与车头方向一致,即roll=pitch=yaw=0。

根据carla client_bounding_boxes.py可知,车坐标系以自己中心点为原点(和KITTI Tracking不太一致是以地面处中心点为原点)。且坐标系为UE4的左手系x轴指向车头。

姑且认为RGB相机安装位置为车顶,所以左目RGB相机在车坐标系中的坐标为(x=-0.325,y=-0.06,z=0.825) ,右目RGB相机坐标为(x=-0.325,0.48,z=0.825)

4.1.2 other coeeficients: 最多可生成155个空白地点。一共40个vehicle设计蓝图,过滤掉摩托车和自行车和小型汽车microlino(不适合跟踪或容易发生碰撞或等待)后还有32个。vehicle 蓝图列表和spawn-points都不打乱顺序,排序后按顺序循环匹配生成演员,都设为自动驾驶模式。不生成行人。所有交通灯设置为绿灯防止hero等红灯浪费时间。

我想对复杂交通中的最佳actor设置为hero绑定相机,所以要知道上述固定模式下,哪个视角最复杂且合适,见4.2.

4.1.3 关于天气:太阳的方位角和方向角=90,因为晚上有路灯,而黄昏会有玻璃建筑物的反光,所以还是正常。关键是雾气fog_density=90会模糊掉背景信息,但无疑会大大增加复杂度尤其是动态情况已经很复杂的时候,非常具有挑战性。

4.2 地标地图

Carla9.14版本提供的的是Town10HD俯视图,如下图所示,附加了在一些比较好视角下的采集图像。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值