写在前面
本人系某985高校23级智能交通系统工程博士新生,但硕士期间主要研究方向为基于数据驱动的过程控制系统故障诊断,也因此算是一个彻头彻尾的交通小白。
然而时间不等人,进组的第一个项目就必须使用SUMO软件来进行交通流建模,可没接触过科班教学的我在各类论坛上均没有找到SUMO的详细教程,也不想且没时间去啃SUMO的指导手册!
趁此机会!想将学习过程中的一些基础内容与大家分享,也算是用网络见证一下自己的进步!
如果大家有什么相关的教程推荐!请速速种草!
当然,如有错误,也欢迎各位批评指正!
Introduction
目前车联网和车路协同 (V2X) 是自动驾驶和智能交通领域研究的核心问题之一。简单来说,V2X 就是为车辆提供了上帝视角,可以获取更大范围、更准确的信息,从而优化驾驶决策。
在各种智能交通场景中,platooning (车辆编队) 是一个很热门的话题。借助 V2X, platooning 可以减小车辆之间的安全距离。较小的安全距离可以增加道路的吞吐量,对于在高速公路上行驶的卡车编队,还可以减小风阻,降低能耗。由于各方面的限制,很难在实车、实路上测试智能交通算法的性能。在这种情况下,仿真测试可以在一定程度上验证算法的有效性。
V2X 仿真主要包括两个方面,即交通场景和网络通讯,其中SUMO 可以实现交通场景的仿真,而网络通讯方面的仿真软件有OMNeT++, NS3 等。在此基础上,相关研究人员开发了相关框架来进行仿真:
-
Veins (vehicles in network simulation) = SUMO + OMNeT++,是针对车联网的仿真软件。
-
Plexe (platooning extension for veins) = Plexe-SUMO + Plexe-Veins,是在Veins得基础上Plexe 是在 Veins 中加入了 platooning 的元素。
在做对网络通讯方面的真实度要求不高的 V2X 仿真时,即不需要模拟实际联网中的延迟、丢包等情况时,通常采用 Plexe-SUMO,来为代码撰写提供便利。因此,Plexe-Sumo也成为了该种条件下的编队协同驾驶模拟的优异选择。
Plexe-Sumo的Github下载链接:https://github.com/michele-segata/plexe-pyapi
安装Plexe-Sumo的python API流程如下:
# sumo安装
cd
git clone --recursive https://github.com/eclipse/sumo
sudo apt-get install cmake python libxerces-c-dev libfox-1.6-dev libgl1-mesa-dev libglu1-mesa-dev libgdal-dev libproj-dev
# sumo的系统环境变量设置
cd ~/sumo/build/cmake_modules
cmake ../..
make -j8
echo "export SUMO_HOME=~/sumo" >> ~/.bashrc
echo "export PATH=$SUMO_HOME/bin:$SUMO_HOME/tools:$PATH" >> ~/.bashrc
# plexe-pyapi安装
cd
git clone https://github.com/michele-segata/plexe-pyapi.git
cd plexe-pyapi
pip install --user .
Framework
Core File - utils.py
plexe库中的核心模块,其中包含多个函数,每个函数的参数及其含义通过表格进行阐述。
add_vehicle() | 使用traci.vehicle.add模块 根据sumo版本加入车辆 |
---|---|
plexe | 类接口 |
vid | 设置车辆id |
position | 车辆起始位置 |
lane | 道路 |
speed | 车辆起始速度 |
vtype | 车辆类别 |
add_platooning_vehicle() | 在add_vehicle的基础上加入一辆车至编队中 |
---|---|
plexe | 类接口 |
vid | 设置的车辆ID |
position | 车辆起始位置 |
lane | 道路 |
speed | 车辆起始速度 |
cacc_spacing | CACC状态下的车辆间距 |
real_engine = False | 真实车辆动力学模型或一阶滞后模型 |
type = “vtypeauto” | rou文件类型设置 |
communicate() | 按拓扑结构中的设置与领航车和前车进行交互,支撑CACC与Fake CACC的应用 |
---|---|
plexe | 类接口 |
topology | 拓扑结构 |
get_distance() | 计算v1与v2两车的欧式距离 |
---|---|
plexe | 类接口 |
v1 | 车辆1 |
v2 | 车辆2 |
start_sumo() | 使用指定的配置文件启动或重新启动Sumo仿真, |
---|---|
config_file | Sumo配置文件 |
already_running | True: 仅加载给定的配置文件;False: 重新启动Sumo |
gui | 开始可视化界面 |
running() | 使用指定的配置文件启动或重新启动Sumo仿真, |
---|---|
config_file | Sumo配置文件 |
already_running | True: 仅加载给定的配置文件;False: 重新启动Sumo |
gui | 是否启动可视化界面 |
Configuration File
freeway.gui.xml: Sumo中的界面配置文件;
freeway.net.xml: Sumo中的路网配置文件,提供路网的初步构造;
freeway.rou.xml: Sumo中的车辆配置文件,对路网中各个道路边缘的长度与相关参数进行配置(vType id
),(通过vehicle id
指定车辆类型并规定器路径,plexe中并未通过该方式及进行配置);
freeway.sumo.cfg: Sumo中的运行配置文件,提供输入的路网(net)配置与车辆(rou)配置文件、运行时长与步长、过程等…
vehicles.xml: 车辆动力学配置文件,提供车辆的变速箱比率、齿轮箱、引擎(换挡规则)等车辆参数,目前包括Alfa Romeo 147 1.6 Twin Spark、Bugatti Veyron、Audi R8三项。
Demo
最新版本种官方共提供了7项Demo,分别为
- autofeeddemo.py:
- brakedemo.py: platoon: 编队协同刹车
- dashboard-demo.py:
- enginedemo.py: 三车启动性能对比(车辆动力学)
- joindemo.py: 从中间加入 platoon
- overtake-and-keep-right-test.py: 单辆车超车
- platoon-lane-change-test.py: platoon 协同换道超车
joindemo.py
该Demo文件实现了车辆编队过程中单一车辆车加入编队的过程。
- 变量的初始化定义:
# 导入相关函数包
import os
import sys
import random
import traci # sumo内置函数包
# 导入plexe--sumo中的函数
from utils import add_platooning_vehicle, communicate, get_distance, start_sumo, running
# 导入相关参数
from plexe import Plexe, ACC, CACC, FAKED_CACC, RPM, GEAR, ACCELERATION, SPEED
# 确认Sumo的环境变量是否声明,若声明则确认Sumo中工具包位置
if 'SUMO_HOME' in os.environ:
tools = os.path.join(os.environ['SUMO_HOME'], 'tools')
sys.path.append(tools)
else:
sys.exit("please declare environment variable 'SUMO_HOME'")
# 该Demo中的参数初始化
LENGTH = 4 # 单车长度
DISTANCE = 5 # 车头间距
JOIN_DISTANCE = DISTANCE * 2 # 加入车队时需保留间距
SPEED = 120 / 3.6 # 巡航速度
# 行动状态(0为人工驾驶,1为ACC, 2为CACC):
GOING_TO_POSITION = 0 # 前往
OPENING_GAP = 1 # 打开间隙
COMPLETED = 2 # 完成加入编组
# 行动参与者 (仅考虑一个编队,车辆编号依次为v.0,v.1,...)
LEADER = "v.0" # 领航(0开始)
JOIN_POSITION = 3 # 加入位置
FRONT_JOIN = "v.%d" % (JOIN_POSITION - 1) # 前车编号
BEHIND_JOIN = "v.%d" % JOIN_POSITION # 后车编号
N_VEHICLES = 8 # 车队中车辆总数+1
JOINER = "v.%d" % N_VEHICLES # 加入车辆编号
- 该Demo中的函数模块定义:
add_vehicles() 初始车辆定义模块
在仿真中加入一个包含n辆车的车队与一个距离较远希望加入车队的车辆。
def add_vehicles(plexe, n, real_engine=False):
# 初始化车队拓扑结构
topology = {}
# 编队车辆遍历
# 调用utils中的模块,实现编队设置
for i in range(n):
# 定义车辆id与初始状态
vid = "v.%d" % i
add_platooning_vehicle(plexe, vid, (n - i + 1) * (DISTANCE + LENGTH)+50, 0, SPEED, DISTANCE, real_engine)
# 定义车辆所在车道,并标记该车道为不安全
plexe.set_fixed_lane(vid, 0, safe=False)
# 定义车辆的运动模式
traci.vehicle.setSpeedMode(vid, 0)
# 定义领航车和跟随车辆分别为ACC和CACC控制模式
if i == 0:
plexe.set_active_controller(vid, ACC)
else:
plexe.set_active_controller(vid, CACC)
# 定义每辆车的前车与领航车的拓扑结构
if i > 0:
topology[vid] = {"front": "v.%d" % (i - 1), "leader": LEADER}
# 添加一辆希望加入编队的车辆
vid = "v.%d" % n
add_platooning_vehicle(plexe, vid, 10, 1, SPEED, DISTANCE, real_engine)
plexe.set_fixed_lane(vid, 1, safe=False)
traci.vehicle.setSpeedMode(vid, 0)
plexe.set_active_controller(vid, ACC)
# 定义CACC的相关参数,此处定义CACC中加入编队时的车辆间距
plexe.set_path_cacc_parameters(vid, distance=JOIN_DISTANCE)
return topology
get_in__position() 加入编队模块
通过更改拓扑结构和为加入车辆提供领航车辆与前车,使加入车辆靠近加入位置
此时,加入车辆加速,与前车和领航车之间通过使用GPS位置的CACC来进行控制。
def get_in_position(plexe, jid, fid, topology):
# 定义加入车辆的拓扑结构
topology[jid] = {"leader": LEADER, "front": fid}
# 提升加入车辆的巡航速度,设置其控制方式为基于GPS位置的CACC
plexe.set_cc_desired_speed(jid, SPEED + 15)
plexe.set_active_controller(jid, FAKED_CACC)
return topology
opengap() 车队打开插入空隙模块
通过创建临时车队,将后方车辆打开空隙,即后方所有车辆组成以后方车辆为领航者的临时编队
def open_gap(plexe, vid, jid, topology, n):
# 确认后方第一台车辆的id
index = int(vid.split(".")[1])
# 对后方所有车辆进行遍历,将其领航车辆定义为后方第一台车,即演化为一临时车队
for i in range(index + 1, n):
topology["v.%d" % i]["leader"] = vid
# 将后方编队的领航车辆的前方车辆定义为加入车辆
topology[vid]["front"] = jid
#设置加入车辆的控制方式为基于GPS位置的CACC,并定义车间距
plexe.set_active_controller(vid, FAKED_CACC)
plexe.set_path_cacc_parameters(vid, distance=JOIN_DISTANCE)
return topology
reset__leader() 后方车队的领航车辆重置
def reset_leader(vid, topology, n):
# 确认后方第一台车辆的id
index = int(vid.split(".")[1])
for i in range(index + 1, n):
# 重新定义后方车队的领航车辆为前方车队的领航车
topology["v.%d" % i]["leader"] = LEADER
return topology
- 该Demo中的主程序模块定义:
main() 主程序
def main(demo_mode, real_engine, setter=None):
# 定义随机种子以使得车辆颜色随机
random.seed(1)
# 启动Sumo仿真
start_sumo("cfg/freeway.sumo.cfg", False)
# 初始化Plexe类
plexe = Plexe()
# 建立traci与plexe的步骤监听器
traci.addStepListener(plexe)
# 定义开始时间和模态
step = 0
state = GOING_TO_POSITION # 即'0'模态
# 从step开始至6000结束,按步长运行,'demo_mode'是是否采用演示模式的参数
while running(demo_mode, step, 6000):
# 当处于演示模式时,单次仿真结束后进行重置
if demo_mode and step == 6000:
start_sumo("cfg/freeway.sumo.cfg", True)
step = 0
state = GOING_TO_POSITION
random.seed(1)
# traci模块控制仿真前进一个步长
traci.simulationStep()
if step == 0:
# 仿真开始时,创建一个车队
topology = add_vehicles(plexe, N_VEHICLES, real_engine)
# 将追踪车辆'Joiner'的视图标识符定义为'"View #0"'
traci.gui.trackVehicle("View #0", JOINER)
# 设置追踪视图的缩放级别,数值越大缩放越小
traci.gui.setZoom("View #0", 20000)
if step % 10 == 1:
# 定义车辆间每100ms根据拓扑结构与领航车辆和前车交互
# 支撑CACC和FakeCACC的应用
communicate(plexe, topology)
if step == 100:
# 仿真开始1s后,加入车辆开始靠近车队
topology = get_in_position(plexe, JOINER, FRONT_JOIN, topology)
if state == GOING_TO_POSITION and step > 0:
# 当加入车辆与前车距离足够接近时,后方车辆打开间隙
if get_distance(plexe, JOINER, FRONT_JOIN) < JOIN_DISTANCE + 1:
state = OPENING_GAP
topology = open_gap(plexe, BEHIND_JOIN, JOINER, topology, N_VEHICLES)
if state == OPENING_GAP:
# 当间隙足够大时,完成加入车辆的操作
if get_distance(plexe, BEHIND_JOIN, FRONT_JOIN) > 2 * JOIN_DISTANCE + 2:
state = COMPLETED
# 换道
plexe.set_fixed_lane(JOINER, 0, safe=False)
# 重新定义加入车辆的控制方式及相关参数
plexe.set_active_controller(JOINER, CACC)
plexe.set_path_cacc_parameters(JOINER, distance=DISTANCE)
plexe.set_active_controller(BEHIND_JOIN, CACC)
plexe.set_path_cacc_parameters(BEHIND_JOIN, distance=DISTANCE)
# 重新设置后方车辆的领航车辆为第一辆车
topology = reset_leader(BEHIND_JOIN, topology, N_VEHICLES)
if real_engine and setter is not None:
# 如果使用仪表板模式,则更新面板上的值
tracked_id = traci.gui.getTrackedVehicle("View #0")
if tracked_id != "":
ed = plexe.get_engine_data(tracked_id)
vd = plexe.get_vehicle_data(tracked_id)
setter(ed[RPM], ed[GEAR], vd.speed, vd.acceleration)
step += 1
traci.close()
欢迎各位批评指正!
下一章将针对SUMO的底层和初步使用方法进行介绍,敬请期待!
Ref:
[1] 基于 Plexe-SUMO 的 V2X 仿真 - 简书 (jianshu.com)
Tool:
[1] ChatGPT