有限条件下编队协同驾驶的仿真开发(一)

您所在的位置:网站首页 车路协同系统仿真软件 有限条件下编队协同驾驶的仿真开发(一)

有限条件下编队协同驾驶的仿真开发(一)

2024-07-15 12:22| 来源: 网络整理| 查看: 265

写在前面

本人系某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设置车辆idposition车辆起始位置lane道路speed车辆起始速度vtype车辆类别 add_platooning_vehicle()在add_vehicle的基础上加入一辆车至编队中plexe类接口vid设置的车辆IDposition车辆起始位置lane道路speed车辆起始速度cacc_spacingCACC状态下的车辆间距real_engine = False真实车辆动力学模型或一阶滞后模型type = “vtypeauto”rou文件类型设置 communicate()按拓扑结构中的设置与领航车和前车进行交互,支撑CACC与Fake CACC的应用plexe类接口topology拓扑结构 get_distance()计算v1与v2两车的欧式距离plexe类接口v1车辆1v2车辆2 start_sumo()使用指定的配置文件启动或重新启动Sumo仿真,config_fileSumo配置文件already_runningTrue: 仅加载给定的配置文件;False: 重新启动Sumogui开始可视化界面 running()使用指定的配置文件启动或重新启动Sumo仿真,config_fileSumo配置文件already_runningTrue: 仅加载给定的配置文件;False: 重新启动Sumogui是否启动可视化界面 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: 从中间加入 platoonovertake-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) 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



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3