最近几天一直在做一个CVRP问题,需要计算两点之间的路径距离与时间,直接采用经纬度计算直线距离会有很大的误差。正常来说,直接调用百度或者高德地图提供的API接口即可轻松实现,但是由于项目最终需要部署在内网,所以只能采用离线地图来计算路径距离。
作为一个完全没接触过离线地图的小白,接到这个任务后内心是崩溃的。在找了无数的教程、看了无数的文档、踩了无数的坑之后,终于实现了这一功能,必须记录一下。
首先是工具与技术路线的选择,作为小白,经过一通搜索后,下载了无数的软件后,终于明白了,要做到离线路径规划或者导航,必须要有两要素。首先是地图数据(一般是地图瓦片,格式为jpg或者png,这里必须注意百度地图瓦片编号与高德地图瓦片编号规则是不同的!!!)以及路网数据(一般为pbf等格式),然后是本地服务(就是根据地图数据实现路径规划的算法等服务)。确定好需要的工具以及数据后,咱们直接开始!
操作步骤
地图
地图数据去这里https://www.openstreetmap.org/或者这里Geofabrik Download Server下载。比如我需要浙江省的地图路网数据,就下载一个名为’zhejiang-latest.osm.pbf‘的文件。这里也可以在此下载浙江省地图数据。
搭建本地服务(window环境)
地图准备好后,就需要搭建我们本地的服务了。这里注意,搭建本地服务需要准备好我们的本地环境,因我Graphhopper是基于java开发的,因此我们需要下载Java JDK,从Oracle官网下载并安装JDK,并配置好环境变量。然后是maven,同样下载安装配置环境变量,可以参考Maven安装与配置(详细步骤)_apachemaven安装与配置_liyitongxue的博客-CSDN博客。
下载Graphhopper
然后我们可以开始下载Graphhopper,这里可以直接在GitHub搜索Graphhopper即可。
这里建议不要直接克隆master分支,可以选择stable分支(踩了好多坑之后,才发现master分支好像没有graphhopper.sh文件,这个文件在后面很重要!)
将该分支克隆到本地之后,会发现里面有一个文件名为config-example.yml的文件,采用文本编辑器打开,将文件开头数据修改成自己的文件路径,端口选择8989端口。
到这里有些教程会让你直接在命令行执行以下命令构建路网数据,生成索引文件:
./graphhopper.sh build
然后执行
./graphhopper.sh web
然后是打开网址http://127.0.0.1:8989即可。
但是对于像我这样的小白,这里可能会遇到很多问题,这里我们逐一展开解决(每一个都是让人心态崩溃的坑)。
坑1-本地服务问题
首先是本地服务问题,一般直接在浏览器里输入http://127.0.0.1:8989是会显示拒绝访问,这里的域名是本地服务器,这一般是由于没安装IIS服务。解决方法很简单:在控制面板/程序/启用或关闭Windows功能中选择以下两项安装。将两项全点上就行。如果输入ip地址http://127.0.0.1显示以下界面,就算是跳出这个坑了。
坑2-cygwin问题
下一个坑是Cygwin,这里同样是下载安装。windows下安装Cygwin详细教程_快乐小胡!的博客-CSDN博客
坑3-wget问题
如果到这里还是显示8989端口拒绝访问,可能是wget没有下载安装。这里的wget是linux里面的下载工具,我们在windows下可以搜索wget for windows下载安装。Wget for windows——优雅地实现批量下载 – 知乎 (zhihu.com)
本地服务,启动!
解决完以上问题之后,终于可以进行搭建我们自己的本地服务了。但是如果还是按照有些教程上进入graphhopper根目录后输入
./graphhopper.sh build
还是会出现问题,会跳出以下窗口,几十秒后又会自动关闭。
这行命令的作用是:下载所需的依赖,构建GraphHopper的路网数据,并生成索引文件。经过多方查找资料,发现应该输入
#先进入到graphhopper目录下,再执行以下语句 ./graphhopper.sh -a web -i china-latest.osm.pbf #china-latest.osm.pdf是下载的路图
跳出以下界面则配置完成
如果报以下错误
-bash: ./graphhopper.sh: /bin/bash^M: bad interpreter: No such file or directory
可以尝试使用以下方式进行解决
sed -i 's/\r$//' ./graphhopper.sh #解决linux 跟Windows 对于换行符不同的区别
如果不成功可能是因为解析的地图数据过大导致内存溢出发生错误: 可以在执行启动之前先扩大内存
export JAVA_OPTS="-Xmx4g -Xms4g"#加大至4G内存
最终效果
到此,所有操作全部完成,在浏览器输入http://127.0.0.1:8989即可进入以下网页,进行路径规划。
也可以通过python调用本地服务器接口,将结果传入python程序,进行后续一系列操作。
最终效果
import requestsurl = 'http://127.0.0.1:8989/route?point=27.939648,120.934602&point=27.936577,120.931941&profile=car&layer=OpenStreetMap'response = requests.get(url) info = response.json()['paths'][0]print(info) # 获取json# print(info['distance']) # 获取路径距离,单位为米# print(info['time']) # 获取路径时间,单位为毫秒print(round(info['distance']/1000,2)) # 单位转为千米print(round(info['time']/(60*1000),0)) # 单位转为分钟
转自:https://zhuanlan.zhihu.com/p/696558718