# taxi-sim **Repository Path**: jeffreychan/taxi-sim ## Basic Information - **Project Name**: taxi-sim - **Description**: 基于sumo的网约车仿真项目 - **Primary Language**: Unknown - **License**: MIT - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 2 - **Created**: 2024-04-09 - **Last Updated**: 2024-04-09 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README ![](https://gitee.com/wild_ptr/taxi-sim/raw/master/docs/img/screenshot.png) ## 简介 一个基于SUMO的微观仿真项目,用于测试中心化控制的网约车运营算法/模型的效果。 ## 运行 进入项目根目录,运行命令行: ``` sudo pip install -r requirements.txt ``` ## 文件结构 ``` . ├── data │ ├── mylogs │ ├── pre_cal │ ├── settings │ ├── sumo_inputs │ ├── sumo_outputs │ ├── taxi_datas │ ├── taxi_zones │ └── temp │ └── rou ├── docs ├── history └── packages ``` - data目录用于放置 - 场景输入文件:与sumo进程的启动配置文件、模拟需要的输入文件(路网、车辆、人等)、以及其他预设文件 - log文件 - 临时文件 其中,mylogs放置控制脚本输出的日志信息,sumo_outputs放置sumo进程输出的日志信息。 - packages目录用于放置本python工程的代码 - docs目录用于放置项目过程中用以总结的文档 ## 研究目的 把在学校学到知识用在一个接近真实世界的模拟环境中,解决一个未来网约车运营会碰到的问题。 ## 数据来源 纽约市开放数据提供从2009年至2016年的出租车运营数据,包含超过10亿辆黄色和绿色出租车的载客数据。数据集共包含19个维度,我们保留了其中行程相关的关键维度共5个: pickup_datetime、pickup_longitude、pickup_latitude、dropoff_longitude、dropoff_latitude。 我们取了其中一天的数据作为输入到sumo的需求数据。 至于路网数据,我们用SUMO的netedit工具裁剪出纽约曼哈顿的一部分区域,也是作为sumo的输入数据。 ## 数据清洗与转换 SUMO提供了一些工具进行数据转换,将原数据转化成sumo能接受的格式。具体见SUMO官网教程。 ## 仿真环境搭建 本项目的仿真环境基于SUMO的提供的TraCI (**Tra**ffic **C**ontrol **I**nterface) API开发。TraCI的工作原理如下:sumo进程作为**服务端**,完成启动并载入场景数据后,将开启一个端口开始监听。外部的**客户端**sumo进程与服务端完成连接后,直到仿真结束,负责控制sumo的每一步模拟的执行。通过这种进程间通信的方式,客户端一方面可以取得模拟环境中的绝大部分数据,另一方面,还可以修改其中的部分变量[1]。如图,本项目的仿真环境主要由三部分组成:1)**场景数据输入**,2)**交通控制脚本**,3)**仿真运行日志数据输出**。 ## 控制脚本运行步骤 由于python版本的TraCI API最齐全,我们选择用python进行开发。TraCI的主要功能和国外的几个主流的微观交通仿真平台差不多,但值得一提的是sumo最近两年引入taxi-device(device是vehicle绑定的数据容器及功能(可以类比面向对象中的类)),以及为taxi-device开放的两个TraCI接口函数。我们可以基于taxi-device进行灵活度比较高的DRT(demand responsive transport)仿真。但是由于这几个接口比较简陋,加之我们采用了一个由现实地图转换过来的路网,路网数据本身就有一些清理不掉的小bug,在实际的开发中,需要很多额外的纠错机制,需要对sumo的内部微观模型(edge、lane、vehicle、person、intersection、stop等)有足够的理解,以及要妥善处理好性能问题。另外,虽然由于taxi-device只负责处理open订单(即未找到配对的订单),对于closed订单(即已找到配对或者已经完成的订单),taxi-device暂时还不能做到实时跟踪的功能,需要用户利用通用的TraCI函数进行持续的book-keeping。最后,由于车辆的状态有很多种(停靠、行驶、停止、过路口、甚至传送(teleport)),动态拼车的实现也十分麻烦。还有微观仿真引起的许多诸如此类的问题,篇幅有限就不一一阐述了。 上图展示了控制脚本的详细流程: A)在启动阶段,在进行各模块及参数的初始化之后,根据预先设定好的车队规模,往路网的各个子区域的中心投放车辆(网约车)。 B)每隔一个时间区间进行决策,在做决策之前,需要收集决策需要的信息,比如正在执行任务(serving)的车辆的位置和任务执行状态、刚刚进入路网的乘车需求、空闲车辆的位置、各种决策情况下的最快路径信息、各区域的供需状态等。另外,还要对刚刚加载入路网或者从Serving状态或Rebalancing状态转变为Vacant状态的车辆进行可视化调整。对于预测信息,在需求方,我们直接用未来的需求数据作为预测结果;在供给方,我们采取了一种效果较差(预测结果偏小)但是性能较好的方式进行预测,即开启子进程,将当前的部分路网信息(如车辆路线和车辆当前在路线的位置)导入到一个新的sumo进程,等待其跑完之后,分析其输出结果来得到未来一个时间窗内的各个区域的预测供给数(只适用于再平衡+一对一匹配情形)。 C)将收集到信息汇总起来并交给决策算法/模型接口,这个接口会返回一个(组)决策。 D)执行决策,检查决策合法性,如果合法且执行成功,修改相应的车队任务状态信息。并根据,具体子流程图如下。 E)打印/输出Log数据,只需输出sumo本身不支持输出的Log数据。 F)如果到达了预设的仿真时间上限,就关闭sumo进程,结束本次仿真。如果还没有就回到步骤B)。 通过这种方式,controller能够以可接受的性能收集到决策所需的所有信息,决策算法/模型只需基于这些信息进行求解,因此决策接口不需要考虑TraCI的调用,为不同的决策算法/模型的实施提供便利。 ## 模拟时间窗选取 我们选取了某天的17:00:00-21:00:00的订单数据。考虑到仿真一开始是车辆数远远多于订单数的,系统需要一个“预热”的过程才能达到和真实环境类似的情景,也就是不断有新需求和新供应产生。我们研究的对象就是“预热”之后的时间段。 ## 区域划分 下图为我们选取的一些曼哈顿地区的子区域,相关的shapefile可以在网上下载。仿真用到的是目的地和出发地都在这些区域的订单需求。 ![](https://gitee.com/wild_ptr/taxi-sim/raw/master/docs/img/subregions.png) ## 运行结果 因为系统需要一个预热过程才能反映出真实场景下的网约车服务,我们先看看400辆车的情景下,采用最小成本流求解指派问题的解法来进行网约车与乘客的一对一匹配。在17:00:00-21:00:00期间的服务中车辆数和空闲数车辆的实时曲线如下。 可以发现服务中车辆数在5000-7000秒有一个短暂的略微的下降趋势,说明系统整体边际需求和边际供应达到了一个近似平衡。于是,接下来的有些图是5000秒之后的数据,更具有代表性。 ### 线性规划再平衡调度模型 受[3]所提出的模型启发,我们建立了一个线性规划模型,目标为最小化平衡调度所引起的总时间成本,约束为保证各个区域在未来一段时间窗内,预计供给量大于等于预计需求量。 ### 数据分析 首先来看一下需求端。下图为每个子区域的需求波动情况。 ![](https://gitee.com/wild_ptr/taxi-sim/raw/master/docs/img/demandlines.png) 由于再平衡调度决策需要用到从现在起的一个时间窗每个子区域的供需数据,需求方比较好办,直接提前读取这个时间窗的每个区域的需求数就可以。但是供给方怎么预测呢——可以用每个子区域的供给数加上会在此时间窗内到达该子区域的服务中车辆和再平衡车辆作为预测供给数。以下为从4800秒直到仿真结束每600秒的预测供需差和实际供需差的热图。可见预测效果还是可以的。 ![](https://gitee.com/wild_ptr/taxi-sim/raw/master/docs/img/actpred.png) 以下的热图,从左到右4列,分别展示了没有再平衡调度的实际供需差、有再平衡的调度前预测供需差、有再平衡的调度后期望供需差、有再平衡的调度后实际供需差。可见平衡调度策略起了作用,各自区域的供需差减少了。 ![](https://gitee.com/wild_ptr/taxi-sim/raw/master/docs/img/4cols.png) 但是这么调度其实是有一点问题的,因为平衡调度任务的执行需要一定的时间。以下的箱线图展示了平衡调度任务的执行时间分布。 ![](https://gitee.com/wild_ptr/taxi-sim/raw/master/docs/img/box.png) 然后再来看看有多少平衡调度任务没能在规定的时间窗执行完毕。超出蓝色三角形的红点是没能在没能在规定的时间窗执行完毕的平衡调度任务。可见大部分都能在规定的时间窗内完成调度任务。 ![](https://gitee.com/wild_ptr/taxi-sim/raw/master/docs/img/scatter.png) 下面的频率分布直方图对比了没有再平衡和有再平衡两种情况下车辆的空闲时间占总时间的百分比分布。可见加入了再平衡策略后,总体上车辆的空闲率变高了(执行再平衡任务中的车辆也属于空闲状态) ![](https://gitee.com/wild_ptr/taxi-sim/raw/master/docs/img/hist.png) 再用直观的柱状图看看再平衡策略是否降低了乘客的等待时间。如图,除了9000-10200秒之间,其余的时间窗平衡调度模式是显著降低了乘客平均等待时间的。 ![](https://gitee.com/wild_ptr/taxi-sim/raw/master/docs/img/waittimebars.png) 最后补充几个图。如图,上面是有平衡调度时三种状态的车辆数的波动情况,下面是没有平衡调度时的情况。 ![](https://gitee.com/wild_ptr/taxi-sim/raw/master/docs/img/statuslines.png)