最近几天一直在做一个CVRP问题,需要计算两点之间的路径距离与时间,直接采用经纬度计算直线距离会有很大的误差。正常来说,直接调用百度或者高德地图提供的API接口即可轻松实现,但是由于项目最终需要部署在内网,所以只能采用离线地图来计算路径距离。

作为一个完全没接触过离线地图的小白,接到这个任务后内心是崩溃的。在找了无数的教程、看了无数的文档、踩了无数的坑之后,终于实现了这一功能,必须记录一下。

首先是工具与技术路线的选择,作为小白,经过一通搜索后,下载了无数的软件后,终于明白了,要做到离线路径规划或者导航,必须要有两要素。首先是地图数据(一般是地图瓦片,格式为jpg或者png,这里必须注意百度地图瓦片编号与高德地图瓦片编号规则是不同的!!!)以及路网数据(一般为pbf等格式),然后是本地服务(就是根据地图数据实现路径规划的算法等服务)。确定好需要的工具以及数据后,咱们直接开始!

操作步骤

地图

地图数据去这里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

然后是打开网址127.0.0.1:8989即可。

但是对于像我这样的小白,这里可能会遇到很多问题,这里我们逐一展开解决(每一个都是让人心态崩溃的坑)。

坑1-本地服务问题

首先是本地服务问题,一般直接在浏览器里输入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内存

最终效果

到此,所有操作全部完成,在浏览器输入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