大家好,我是李慢慢。
本期介绍一个python库,scenariogeneration,用来创建动态场景(OpenScenario格式)和静态地图(OpenDrive格式),用于自动驾驶仿真。
目录:
1、简介
2、官方资料
3、库的下载安装
4、示例代码
5、创建静态地图
6、创建动态场景
7、场景播放效果
8、写在最后
1、简介
以下截图是官方对scenariogeneration库的介绍。
scenariogeneration是一个Python库,用来生成OpenSCNARIO(.xosc)和OpenDRIVE(.xodr)文件。
啰嗦一句:
OpenX系列是ASAM推出的用于道路网络和驾驶模拟的格式标准。OpenX系列套件包括OpenDRIVE、OpenSCENARIO、OpenLABEL、OpenEDD、OpenCRG、OpenOntology和Open Simulation Interface等内容。其中,OpenDRIVE文件描述仿真测试场景的静态部分(如道路拓扑结构、交通标志标线等);OpenSCENARIO文件描述仿真测试场景的动态部分(如交通车的行为)。
ASAM官网:
2、官方资料
scenariogeneration库包含以下几个类:
scenariogeneration.esmini_runner
scenariogeneration.helpers
scenariogeneration.scenario_generator
scenariogeneration.xodr
scenariogeneration.xosc
官方使用说明文档:
官方API接口说明:
https://pyoscx.github.io/scenariogeneration/index.html
点击上述的链接即可查看每个模块或者函数的使用方法:
源代码下载:
https://github.com/pyoscx/scenariogeneration
源代码中可以查看所有源代码、使用说明、更新说明、示例代码等内容。
3、库的下载及安装
scenariogeneration的python库的下载方式如下:
pip install scenariogeneration
我的python版本是3.8,我这里已经安装过scenariogeneration了,再度安装,会提示已经安装,并告知安装位置。
按图索骥,可以找到我们安装的库:
安装完成后,也可以用pip list查看安装的库。
pip list
安装完成后,运行python,import进来scenariogeneration的库,即可开始使用。
至此,基础环境已经配置完成了。
冗长的前文看起来头晕,其实核心只有一句安装代码:
pip install scenariogeneration
4、示例代码
虽然scenariogeneration已经提供了必要的使用文档及接口说明,但从零开始看必然昏昏欲睡,查看官方自带的示例代码,是最快的学习方法。
在下载的源代码文件中,有一个文件夹【example】,里面就是各种示例代码。
xodr的:
xosc的:
generator的:
以xodr的示例代码为例,只需要用python运行对应的py文件,就能生成同名的xodr文件。
5、创建静态地图
跟随示例代码,我们来看一下生成一个最简单的直路,需要的最简单的代码:
from scenariogeneration import xodr
# 创建一个OpenDrive实例
my_odr = xodr.OpenDrive("myroad")
# 创建一条直路
road_1 = xodr.create_road(geometry=[xodr.Line(100)],
id=0,
left_lanes=2,
right_lanes=3,
lane_width=3.5,
center_road_mark=xodr.RoadMark(xodr.RoadMarkType.solid, 0.2),
road_type=-1)
# 将道路添加到OpenDrive
my_odr.add_road(road_1)
# Adjust initial positions of the roads looking at succ-pred logic
my_odr.adjust_roads_and_lanes()
# 将上述道路保存下来
my_odr.write_xml("test_001_straight_road.xodr")
以下是【test_001_straight_road.xodr】可视化的效果。
本处用了另一个开源可视化工具truevision,可以查看以下文章,获取安装及使用方法。
接下来,简单看看道路的连接。
代码如下:
from scenariogeneration import xodr
# 创建3条道路
roads = []
# 起始车道-100m直道
roads.append(xodr.create_road(xodr.Line(100), id=0, left_lanes=2, right_lanes=2))
# 终止车道-100m直道
roads.append(xodr.create_road(xodr.Line(100), id=1, left_lanes=2, right_lanes=2))
# 中间车道-100m螺旋车道
roads.append(xodr.create_road(xodr.Spiral(0.001, 0.02, 100), id=3, left_lanes=2, right_lanes=2, road_type=1))
# 定义螺旋车道的连接关系
roads[2].add_predecessor(xodr.ElementType.road, 0, xodr.ContactPoint.end)
roads[2].add_successor(xodr.ElementType.road, 1, xodr.ContactPoint.start)
# 创建junction
junction = xodr.create_junction(roads[2:], 1, roads[0:2])
# 创建OpenDrive对象,并添加进去所有道路
odr = xodr.OpenDrive("myroad")
for r in roads:
odr.add_road(r)
odr.adjust_roads_and_lanes()
odr.add_junction(junction)
# 将上述道路保存下来
odr.write_xml("test_002_roads_connection.xodr")
以下是【test_002_roads_connection.xodr】可视化的效果。
6、创建动态场景
下面参考官方示例脚本【route_in_crossing.py】,改写了一个更简单的十字路口转弯的场景。车辆转弯的路线(Route)可自由定义。
import os
from scenariogeneration import xosc
# 创建一辆车:主车
bb = xosc.BoundingBox(2, 5, 1.8, 2.0, 0, 0.9)
fa = xosc.Axle(0.523598775598, 0.8, 1.68, 2.98, 0.4) # 前轴距
ba = xosc.Axle(0.523598775598, 0.8, 1.68, 0, 0.4) # 后轴距
my_vehicle = xosc.Vehicle("my_car", xosc.VehicleCategory.car, bb, fa, ba, 69, 10, 10)
# 创建一个Entity,然后将前面创建的车辆添加进去
egoname = "Ego"
entities = xosc.Entities()
entities.add_scenario_object(egoname, my_vehicle)
# 初始化车辆行为
init = xosc.Init()
init.add_init_action(egoname, xosc.TeleportAction(xosc.LanePosition(50, 0, 1, 0)))
init.add_init_action(
egoname,
xosc.AbsoluteSpeedAction(10, xosc.TransitionDynamics(xosc.DynamicsShapes.step, xosc.DynamicsDimension.time, 1),),)
# 定义道路地图
road = xosc.RoadNetwork(roadfile="../xodr/fabriksgatan.xodr", scenegraph="../models/fabriksgatan.osgb")
# 创建一个Route
ego_route = xosc.Route("ego_route")
ego_route.add_waypoint(xosc.LanePosition(30, 0, 1, 0), xosc.RouteStrategy.fastest)
ego_route.add_waypoint(xosc.LanePosition(50, 0, 1, 3), xosc.RouteStrategy.fastest)
#
# 创建一个Trigger-Action,Trigger为仿真一开始即开始,Action为路线规划Route。
ego_action = xosc.AssignRouteAction(ego_route)
ego_event = xosc.Event("ego_event", xosc.Priority.overwrite)
ego_event.add_action("ego_route", ego_action)
ego_event.add_trigger(
xosc.ValueTrigger(
"target_start",
0,
xosc.ConditionEdge.none,
xosc.SimulationTimeCondition(1, xosc.Rule.greaterThan),))
# 创建一个StoryBoard对象,设置主车的行为为上述Trigger-Action
ego_man = xosc.Maneuver("ego_man")
ego_man.add_event(ego_event)
** = xosc.StoryBoard(
init,
xosc.ValueTrigger(
"stop_simulation",
0,
xosc.ConditionEdge.rising,
xosc.SimulationTimeCondition(10, xosc.Rule.greaterThan),
"stop",),)
**.add_maneuver(ego_man, egoname)
# 实例化一个Scenario对象
sce = xosc.Scenario(
"adaptspeed_example",
"User",
xosc.ParameterDeclarations(),
entities=entities,
storyboard=**,
roadnetwork=road,
catalog=xosc.Catalog(),
)
# 将Scenario对象保存为和脚本同名的文件(.xosc)
sce.write_xml(os.path.basename(__file__).replace(".py", ".xosc"))
该脚本运行后,将会生成和脚本同名的xosc文件。
7、场景播放效果
以下是调用esmini播放场景文件的脚本:
# coding=utf-8
import os
# file_path = "./trajectory_example.xosc"
file_path = "./lmm_route_in_crossing.xosc"
esmini_path = "D:/esmini/esmini-demo_win/esmini-demo/bin/esmini"
os.system(esmini_path + str(" --window 60 60 1024 576 --osc ") + file_path)
8、写在最后
简单来说,scenariogeneration的核心包是xodr(处理OpenDRIVE文件的)和xosc(处理OpenSCENARIO文件的);scenario_generator则是用来进行参数泛化生成大量的场景;esmimi_runner是做可视化的,可以播放前面xodr创建的地图和xosc创建的场景。其中esmimi_runner只是调用提前装好的esmini软件,这个esmini也是开源的,查看下面的文章可以查阅使用方法。
如上,使用esmini和scenariogeneration的组合,可以自己搭建起来一个简单的免费的仿真场景制作工具链。使用脚本来做场景和地图,和用可视化工具编写相比,看似复杂很多,但隐藏了一个很大的好处,就是可以做参数化,一旦掌握了这个库的使用方法,可以更快速更大规模生成自己需要的地图和场景。
你也去试试吧。
本文仅为对scenariogeneration库的简单探索。关于更多更细节的功能,诸君自行查阅官方文档哦。
瑞斯拜。