仿真运行与结果分析
在微观交通流仿真软件SUMO中,仿真运行是将预先定义的交通网络、车辆、驾驶行为等参数输入到仿真环境中,通过计算模拟车辆在路网中的行驶过程。而结果分析则是对仿真运行产生的数据进行处理和解读,以获取有用的交通性能指标和可视化结果。本节将详细介绍如何运行SUMO仿真并进行结果分析。
1. 仿真运行
SUMO仿真可以通过多种方式启动,包括命令行、Python脚本、图形界面等。本部分将介绍这些启动方法及其应用场景。
1.1 命令行启动
命令行启动是最基础也是最常用的方法。通过命令行,可以直接指定仿真配置文件和输出文件,进行精确控制。
1.1.1 基本命令
# 基本命令格式sumo -c<config_file>-n<net_file>-r<route_file>-o<output_file>config_file: 配置文件,包含所有仿真参数。net_file: 交通网络文件,定义了道路、交叉口等。route_file: 路径文件,定义了车辆的行驶路径。output_file: 输出文件,用于保存仿真结果。
1.1.2 示例
假设我们有一个简单的交通网络文件my_net.net.xml,路径文件my_routes.rou.xml,配置文件my_config.sumocfg,我们可以通过以下命令启动仿真:
sumo -c my_config.sumocfg -n my_net.net.xml -r my_routes.rou.xml -o my_output.xml配置文件示例:
<configurationxmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:noNamespaceSchemaLocation="http://sumo.sf.net/xsd/sumoConfiguration.xsd"><input><net-filevalue="my_net.net.xml"/><route-filesvalue="my_routes.rou.xml"/></input><output><summary-outputvalue="my_output.xml"/></output><time><beginvalue="0"/><endvalue="3600"/></time><report><no-step-logvalue="true"/></report></configuration>命令行解释:
-c my_config.sumocfg:指定配置文件。-n my_net.net.xml:指定交通网络文件。-r my_routes.rou.xml:指定路径文件。-o my_output.xml:指定输出文件。
1.2 Python脚本启动
Python脚本启动提供了更灵活的控制方式,可以通过代码动态生成仿真参数和处理仿真结果。
1.2.1 使用traci模块
traci模块是SUMO提供的Python接口,可以实现实时控制仿真。
示例代码:
importtraciimportsumoimportsumolib# 启动仿真sumoBinary=sumolib.checkBinary('sumo')sumoCmd=[sumoBinary,"-c","my_config.sumocfg"]sumo.start(sumoCmd)# 模拟3600秒forstepinrange(3600):traci.simulationStep()# 获取当前步的车辆信息vehicles=traci.vehicle.getIDList()forvehicleinvehicles:print(f"Step{step}: Vehicle{vehicle}at{traci.vehicle.getPosition(vehicle)}")# 结束仿真traci.close()代码解释:
sumolib.checkBinary('sumo'):检查SUMO可执行文件的路径。sumoCmd:定义启动命令。sumo.start(sumoCmd):启动SUMO仿真。traci.simulationStep():进行一步仿真。traci.vehicle.getIDList():获取当前仿真步的所有车辆ID。traci.vehicle.getPosition(vehicle):获取指定车辆的位置。traci.close():结束仿真。
1.3 图形界面启动
图形界面启动适用于需要可视化监控仿真过程的场景。可以通过SUMO的GUI模式启动仿真。
1.3.1 启动命令
sumo-gui -c my_config.sumocfgsumo-gui:启动SUMO的图形界面。-c my_config.sumocfg:指定配置文件。
2. 结果分析
结果分析是将仿真运行产生的数据进行处理,以提取有用的交通性能指标。SUMO提供了多种输出文件格式,包括XML、CSV等,可以通过不同的工具进行分析。
2.1 基本输出文件
SUMO仿真可以生成多种输出文件,包括车辆轨迹、交通流量、旅行时间等。
2.1.1 车辆轨迹文件
车辆轨迹文件记录了每个车辆在仿真过程中的位置、速度等信息。
示例文件:
<vehicleid="0"depart="0.00"><routeedges="1to2 2to3"/><trajectory><timesteptime="0.00"><positionx="0.00"y="0.00"speed="0.00"/></timestep><timesteptime="1.00"><positionx="10.00"y="0.00"speed="10.00"/></timestep><!-- 更多时间步的数据 --></trajectory></vehicle>解析代码:
importxml.etree.ElementTreeasET# 读取车辆轨迹文件tree=ET.parse('my_output.xml')root=tree.getroot()# 遍历每个车辆forvehicleinroot.findall('vehicle'):vehicle_id=vehicle.get('id')fortimestepinvehicle.findall('trajectory/timestep'):time=timestep.get('time')position=timestep.find('position')x=position.get('x')y=position.get('y')speed=position.get('speed')print(f"Vehicle{vehicle_id}at time{time}: Position ({x},{y}), Speed{speed}")代码解释:
ET.parse('my_output.xml'):解析XML文件。root.findall('vehicle'):获取所有车辆节点。vehicle.get('id'):获取车辆ID。timestep.get('time'):获取时间步。position.get('x')、position.get('y')、position.get('speed'):获取车辆的位置和速度。
2.1.2 交通流量文件
交通流量文件记录了每个时间段内通过每个边的车辆数量。
示例文件:
<edgeDataid="1to2"from="0"to="3600"><intervalbegin="0"end="3600"><edgeid="1to2"departed="10"arrived="8"/></interval></edgeData>解析代码:
importxml.etree.ElementTreeasET# 读取交通流量文件tree=ET.parse('my_flow.xml')root=tree.getroot()# 遍历每个边foredge_datainroot.findall('edgeData'):edge_id=edge_data.get('id')forintervalinedge_data.findall('interval'):begin=interval.get('begin')end=interval.get('end')foredgeininterval.findall('edge'):departed=edge.get('departed')arrived=edge.get('arrived')print(f"Edge{edge_id}from{begin}to{end}: Departed{departed}, Arrived{arrived}")代码解释:
ET.parse('my_flow.xml'):解析XML文件。root.findall('edgeData'):获取所有边数据节点。edge_data.get('id'):获取边ID。interval.get('begin')、interval.get('end'):获取时间段。edge.get('departed')、edge.get('arrived'):获取离开和到达的车辆数量。
2.2 高级分析工具
除了直接解析输出文件,还可以使用高级分析工具进行更复杂的分析。
2.2.1 使用pandas进行数据处理
pandas是一个强大的数据处理库,可以方便地对仿真结果进行分析。
示例代码:
importpandasaspd# 读取CSV格式的仿真结果data=pd.read_csv('my_output.csv')# 计算平均速度mean_speed=data['speed'].mean()print(f"Average speed:{mean_speed}m/s")# 计算每个时间段的流量data['interval']=(data['time']//300)*300# 每300秒为一个时间段flow_data=data.groupby('interval').size()print(flow_data)代码解释:
pd.read_csv('my_output.csv'):读取CSV文件。data['speed'].mean():计算速度的平均值。data['interval'] = (data['time'] // 300) * 300:将时间步划分成时间段。data.groupby('interval').size():计算每个时间段的车辆数量。
2.2.2 使用matplotlib进行可视化
matplotlib是一个常用的绘图库,可以将仿真结果以图表形式展示。
示例代码:
importpandasaspdimportmatplotlib.pyplotasplt# 读取CSV格式的仿真结果data=pd.read_csv('my_output.csv')# 计算每个时间段的流量data['interval']=(data['time']//300)*300# 每300秒为一个时间段flow_data=data.groupby('interval').size()# 绘制流量图plt.figure(figsize=(10,6))plt.plot(flow_data.index,flow_data.values,marker='o')plt.xlabel('Time (s)')plt.ylabel('Number of Vehicles')plt.title('Vehicle Flow over Time')plt.grid(True)plt.show()代码解释:
pd.read_csv('my_output.csv'):读取CSV文件。data['interval'] = (data['time'] // 300) * 300:将时间步划分成时间段。data.groupby('interval').size():计算每个时间段的车辆数量。plt.plot(flow_data.index, flow_data.values, marker='o'):绘制流量图。plt.xlabel('Time (s)')、plt.ylabel('Number of Vehicles')、plt.title('Vehicle Flow over Time'):设置图表标签和标题。plt.grid(True):添加网格线。plt.show():显示图表。
3. 自定义输出
SUMO允许用户自定义输出文件的内容和格式,以便更好地满足特定分析需求。
3.1 自定义输出参数
在配置文件中,可以通过<output>标签添加自定义输出参数。
示例配置文件:
<configurationxmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:noNamespaceSchemaLocation="http://sumo.sf.net/xsd/sumoConfiguration.xsd"><input><net-filevalue="my_net.net.xml"/><route-filesvalue="my_routes.rou.xml"/></input><output><summary-outputvalue="my_output.xml"/><edge-based-vehicle-positions-outputvalue="my_positions.xml"/><lane-traffic-data-outputvalue="my_traffic.xml"/></output><time><beginvalue="0"/><endvalue="3600"/></time><report><no-step-logvalue="true"/></report></configuration>参数解释:
<summary-output>:记录仿真总结信息。<edge-based-vehicle-positions-output>:记录基于边的车辆位置信息。<lane-traffic-data-output>:记录基于车道的交通数据。
3.2 自定义输出文件解析
自定义输出文件的解析方法与基本输出文件类似,但需要根据文件格式进行调整。
示例代码:
importxml.etree.ElementTreeasET# 读取自定义位置文件tree=ET.parse('my_positions.xml')root=tree.getroot()# 遍历每个时间步fortimestepinroot.findall('timestep'):time=timestep.get('time')forvehicleintimestep.findall('vehicle'):vehicle_id=vehicle.get('id')edge_id=vehicle.get('edge')position=vehicle.get('pos')print(f"Time{time}: Vehicle{vehicle_id}on edge{edge_id}at position{position}")代码解释:
ET.parse('my_positions.xml'):解析XML文件。root.findall('timestep'):获取所有时间步节点。timestep.get('time'):获取时间步。vehicle.get('id')、vehicle.get('edge')、vehicle.get('pos'):获取车辆ID、所在边ID和位置。
4. 实时数据收集与分析
通过traci模块,可以在仿真运行过程中实时收集数据并进行分析。
4.1 实时收集车辆位置
示例代码:
importtraciimportsumolibimporttime# 启动仿真sumoBinary=sumolib.checkBinary('sumo-gui')sumoCmd=[sumoBinary,"-c","my_config.sumocfg"]traci.start(sumoCmd)# 模拟3600秒forstepinrange(3600):traci.simulationStep()vehicles=traci.vehicle.getIDList()forvehicleinvehicles:position=traci.vehicle.getPosition(vehicle)print(f"Step{step}: Vehicle{vehicle}at{position}")time.sleep(0.1)# 适当延时,以便观察# 结束仿真traci.close()代码解释:
traci.start(sumoCmd):启动SUMO仿真。traci.simulationStep():进行一步仿真。traci.vehicle.getIDList():获取当前仿真步的所有车辆ID。traci.vehicle.getPosition(vehicle):获取指定车辆的位置。time.sleep(0.1):适当延时,以便在图形界面中观察仿真过程。
4.2 实时计算交通流量
示例代码:
importtraciimportsumolibimporttime# 启动仿真sumoBinary=sumolib.checkBinary('sumo-gui')sumoCmd=[sumoBinary,"-c","my_config.sumocfg"]traci.start(sumoCmd)# 初始化流量计数器flow_counts={edge:0foredgeintraci.edge.getIDList()}# 模拟3600秒forstepinrange(3600):traci.simulationStep()vehicles=traci.vehicle.getIDList()forvehicleinvehicles:edge_id=traci.vehicle.getRoadID(vehicle)ifedge_idinflow_counts:flow_counts[edge_id]+=1ifstep%300==0:# 每300秒输出一次流量print(f"Time{step}seconds: Flow counts{flow_counts}")time.sleep(0.1)# 适当延时,以便观察# 结束仿真traci.close()代码解释:
flow_counts = {edge: 0 for edge in traci.edge.getIDList()}:初始化流量计数器。traci.vehicle.getRoadID(vehicle):获取车辆所在边ID。flow_counts[edge_id] += 1:每检测到一个车辆,对应边的流量计数器加1。if step % 300 == 0:每300秒输出一次流量计数。time.sleep(0.1):适当延时,以便在图形界面中观察仿真过程。
5. 仿真结果的验证与校准
仿真结果的验证与校准是确保仿真模型准确性的关键步骤。可以通过与实际交通数据进行对比,调整模型参数以提高仿真精度。
5.1 数据对比
示例代码:
importpandasaspdimportnumpyasnp# 读取仿真结果sim_data=pd.read_csv('my_output.csv')# 读取实际交通数据real_data=pd.read_csv('real_traffic.csv')# 计算仿真结果与实际数据的平均速度对比sim_mean_speed=sim_data['speed'].mean()real_mean_speed=real_data['speed'].mean()print(f"Simulated mean speed:{sim_mean_speed}m/s")print(f"Real mean speed:{real_mean_speed}m/s")# 计算速度误差speed_error=np.abs(sim_mean_speed-real_mean_speed)/real_mean_speed*100print(f"Speed error:{speed_error:.2f}%")代码解释:
sim_data = pd.read_csv('my_output.csv'):读取仿真结果。real_data = pd.read_csv('real_traffic.csv'):读取实际交通数据。sim_data['speed'].mean()、real_data['speed'].mean():计算仿真结果和实际数据的平均速度。np.abs(sim_mean_speed - real_mean_speed) / real_mean_speed * 100:计算平均速度的误差百分比。