前言:我想验证SLAM代码的效果,所以需要构建一个能提供自己和周围动车的位姿/轨迹和语义分割、bbx的真实值的复杂动态环境(最好能超过目前KITTI-Tracking序列的动态复杂度),所以要能设置CARLA世界中动车的密度、速度、与自己的相对距离、相对方向,和自己的速度;并能记录双目RGB和实例分割、轨迹、BBX。
目录
3.17 show_recorder_actors_blocked.py
3.18 show_recorder_collisions.py
3.19 show_recorder_file_info.py
3.21 visualize_multiple_sensors.py
3.23 sensor_synchronization.py
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因为不知道竖直方向的视场角。
>>相机相对安装位置
左目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俯视图,如下图所示,附加了在一些比较好视角下的采集图像。