一、SUMO&CARLA背景

SUMO (Simulation of Urban MObility) 是一个开源的交通模拟软件包,被广泛用于模拟城市交通系统,包括车辆、公交和行人流动。而CARLA (Car Learning to Act) 是一个开源的自动驾驶仿真模拟器,提供了一个用于自动驾驶研究的实验平台,包括物理和感知模拟。

本文主要介绍SUMO和CARLA在真实的地图进行交通流仿真,实现高阶的自动驾驶仿真模拟,复杂的交通流可以很好地运行在NOA等功能。

CARLA&SUMO加载交通流框架:

在这里插入图片描述

CARLA&SUMO联合仿真框架:
在这里插入图片描述


二、OpenSteerMap使用

1)OpenStreetMap简介

OpenStreetMap(OSM)是一个合作项目,旨在创建一个自由且可编辑的世界地图。它由志愿者使用GPS设备、航空摄影、其他免费资源或者直接的地面观察来收集数据。

2)OpenStreetMap官网:

https://www.openstreetmap.org(需要科学上网)
在这里插入图片描述

3)导出OSM地图

在这里插入图片描述

在这里插入图片描述

三、OSM TO XODR

1)OSM转XODR

OSM文件需要转换成XODR(OpenDrive)给CARLA加载,当然CARLA也可以直接加载OSM文件,为了后续Roadrunner介入修改路网以及添加建筑等信息,因此转换成XODR。

import io
import carla
import os
import xml.etree.ElementTree as ET
# 注意:这里只是目录路径,不包括 proj.db 文件本身,运行这个需要安装库pyproj,
# 为了消除pj_obj_create: Cannot find proj.db错误,不消除也不影响。
os.environ['PROJ_LIB'] = 'D:\Python\Lib\site-packages\pyproj\proj_dir\share\proj'

#osm文件路径
osm_path = r'C:\Users\Desktop\map2.osm'

# Read the .osm data
f = io.open(osm_path, mode="r", encoding="utf-8")
osm_data = f.read()
f.close()

# Define the desired settings. In this case, default values.
settings = carla.Osm2OdrSettings()
# Set OSM road types to export to OpenDRIVE
settings.set_osm_way_types(["motorway", "motorway_link", "trunk", "trunk_link", "primary", "primary_link", "secondary", "secondary_link", "tertiary", "tertiary_link", "unclassified", "residential"])
settings.use_offsets =False
settings.center_map =False
# Convert to .xodr
xodr_data = carla.Osm2Odr.convert(osm_data, settings)

# 解析 XML 数据
root = ET.fromstring(xodr_data)

roads = root.findall('.//road')
#修改道路的中文名称,这会影响CARLA加载地图
for index,road in enumerate(roads):
    road_name = road.attrib.get('name')
    for char in road_name:
        #如果道路的名称存在中文字符,则修改道路名称
        if '\u4e00' <= char <= '\u9fa5':
            road_name = ''.join(['road',str(index)])
            road.set('name',road_name)

# 查找 <header> 标签
header = root.find('.//header')

# 修改原点信息,原点太远地图也无法顺利加载
if header is not None:
    # 提取地图区域,以south和west作为地图区域的原点
    north = float(header.attrib.get('north'))
    south = float(header.attrib.get('south'))
    east = float(header.attrib.get('east'))
    west = float(header.attrib.get('west'))
    # 新原点计算
    x_orig = abs(round(east - west,6))
    y_orig = abs(round(north - south))
    header.set('north', str(y_orig))
    header.set('south', '0')
    header.set('east', str(x_orig))
    header.set('west','0')

# 根据新生成的原点,修改道路坐标
# OSM导出的坐标过大,无法正常加载
geometries = root.findall('.//geometry')
for geometry in geometries:
    x = float(geometry.attrib.get('x'))
    y = float(geometry.attrib.get('y'))
    new_x = str(round(x - west,6))
    new_y = str(round(y - south,6))
    # 修改 x 和 y 属性值
    geometry.set('x', new_x)
    geometry.set('y', new_y)
    # 读取修改后的 x 和 y 属性值
    new_x = geometry.attrib.get('x')
    new_y = geometry.attrib.get('y')

# 保存修改后的 XML 数据到文件中
tree = ET.ElementTree(root)
tree.write('modified_file.xodr')

# 保存修改后的 XODR 数据到文件中
with open(r"C:\Users\Desktop\map2.xodr", 'w') as f:
    f.write(ET.tostring(root, encoding='unicode'))

四、CARLA加载XODR

1)打开CARLA客户端

在这里插入图片描述

2)脚本加载XODR

import carla

try:
    print("================ Starting ================")
# 创建一个客户端
    client = carla.Client('localhost', 2000)
    client.set_timeout(5)
# 加载OpenDrive地图
    xodr_path = r'C:\Users\mini\Desktop\map2.xodr'
    with open(xodr_path, encoding='utf-8') as od_file:
        data = od_file.read()
        vertex_distance = 2.0  # in meters
        max_road_length = 500.0  # in meters
        wall_height = 0.5      # in meters
        extra_width = 1      # in meters
        world = client.generate_opendrive_world(
            data, carla.OpendriveGenerationParameters(
                vertex_distance=vertex_distance,
                max_road_length=max_road_length,
                wall_height=wall_height,
                additional_width=extra_width,
                smooth_junctions=True,
                enable_mesh_visibility=True))
    print("the current world is:", world)
#
except Exception as e:
    print("Exception detected:", e)
finally:
    pass
    print("================ ending ================")

在这里插入图片描述

注:加载之后地图是这样的,因为地图比较大,道路离原点比较远。不过这不影响使用,在运行CARLA的时候可以绑定Camera到NPC上,这样就可以看到道路画面。


五、CARLA工程修改

1)打开CARLA工程
在这里插入图片描述
2)修改spawn_npc_sumo.py

spawn_npc_sumo.py是需要修改的,主要是CARLA NPC视野切换,这样才能观察到车在道路行驶。
在这里插入图片描述

synchronization.tick(flag)
#切换NPC视野
if flag:
    start_time = start
    flag = False
else:
    process_time = time.time() - start_time
    #经过8s就自动切换NPC视野
    if process_time >= 8.0:
        flag = True

3)修改run_synchronization.py
在这里插入图片描述

#genarate camera in carla
if flag:
    # 查找Camera蓝图
    camera_bp = self.carla.world.get_blueprint_library().find('sensor.camera.rgb')
    # 设置生成Camera的附加类型为SpringArmGhost
    Atment_SpringArmGhost = carla.libcarla.AttachmentType.Rigid
    # 设置Camera的安装坐标系
    Camera_transform = carla.Transform(carla.Location(x=-10, y=0, z=5),
                        carla.Rotation(pitch=-10, yaw=0, roll=0))
    #获取carla中的actor
    vehicle_list = self.carla.world.get_actors().filter('vehicle.*')
    if vehicle_list:
        actor = random.choice(vehicle_list)
    # 生成Camera
    self.camera = self.carla.world.spawn_actor(camera_bp, Camera_transform, attach_to=actor,
                                        attachment_type=Atment_SpringArmGhost)
# 设置观察者视图
if self.camera:
    spectator = self.carla.world.get_spectator()
    spectator.set_transform(self.camera.get_transform())

六、开始联合仿真

1)终端运行spawn_npc_sumo.py(确保SUMO正常安装运行,网上很多安装教程)

python spawn_npc_sumo.py -n 10 -w 20 --tls-manager carla --sumo-gui

运行spawn_npc_sumo.py之后,SUMO GUI会自动打开,并且看到路网被正确加载。

在这里插入图片描述
2)SUMO运行

![在这里插入图片描述](https://img-blog.csdnimg.cn/direct/c77e1b5117b040dcbf2954bdf5551119.png

在这里插入图片描述
在这里插入图片描述


七、仿真结束

1)在Pycharm终端按下CTRL+C,然后手动关闭SUMO GUI才能结束这次联合仿真。

2)此次联合仿真的难点我认为在于OSM转换成XODR的时候,因为刚开始使用脚本导出的XODR并不能直接加载到CARLA中去,后续不断尝试修改OSM2XODR脚本才能正常加载。

另外,我新创建了一个公众号,有兴趣的可以关注下~

在这里插入图片描述

Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐