高二暑假,刚刚从 OI 退下来的我重新拾起骑行。地图是一大痛点:百度高德还没什么像样的对自行车道数据的集成,即使有,寻路算法的支持也很拉跨;我也舍不得掷金买码表。想起摸鱼时乱逛的 OpenStreetMap 数据还算完善,最后找到 OSMAnd,发现轨迹录制等一众实用功能,录制的坐标系统竟然是 WGS84,大喜。
但依然还是没法把环城绿道算进路线。从我家附近的入口到零公里点的结果,会从小路穿插,似乎没有对自行车道或者连续性的特别偏好。当然,对于追求速度的用户,这可能是合适的。不过,每个城市的路况不同,离线地图的容量难说照顾到每条路的路况,更别提大陆在 OSM 上的数据不算丰富。”这样“的策略真的合适吗?偏要给我的 travel bike 算出环城绿道的线路,又该怎样做呢?
OSMAnd 是个开源软件,这意味着修改配置或许会比较容易。搜索得到官网的半吊子说明页,指向 GitHub 的 routing.xml 配置文件模板。阅读即得:
- 默认有三个配置文件:car, bicycle, foot;
- 每条路径的权重是
distance/minimum(maxDefaultSpeed, speed*priority) + height penalty + obstacle penalties + turn penalties + ...,其中每一项在文件中均有对应板块; - 支持设置布尔、数值变量,从而实现简单的条件逻辑;
- 支持通过
t, v等选中特定路径对象 (OSM 的 way 和 point) 并对其加权; - access 板块启用/禁用某种 way;
- speed 板块对某种 way 赋默认速度;
- priority 板块对某种 way 赋额外权重,对应上式的
priority; - obstacle 对某个 point 设置罚时或禁用等;
- 寻路用 A*,其全局的
heuristicCoefficient和双向搜索与否可调。
详见仓库维护的模板文件。
一开始我是这样改的。简单来说,我根据每个默认配置的语义,赋一个经验值。例如对于 <way highway="trunk/primary/secondary/tertiary/..." /> 一律改成 $[18,24] \text{kph}$ 不等;<way highway="cycleway" />, <way bicycle="designated/official/..." /> 改成 $24 \text{kph}$;红绿灯的penalty 赋值为 $20 \text{s}$。优先级方面,单从语义上为偏好、避开的类型分别赋 $>1,<1$ 的权, trunk, cycleway 等赋权为 $[1.0,1.5]$ 不等。至于“从小路穿插”,有几种方式加以控制:一是给小路赋低速、低权值;二是 <way attribute="penalty_transition"> 一节中给小路加罚时,等等。
导入 \Android\data\net.osmand.plus\files\routing,并在成都的绿道网络和广东绿道网络试验了一番。效果并不理想:它的结果甚至更趋向于百度地图式的“大路短距”。
实际上,由于交通灯数据匮乏,<select value="18" t="crossing/highway" v="traffic_signals" />, <select value="30" t="crossing" v="island;traffic_signals" /> 作用甚微:往往在干道上作匀速直线运动,所以无法很好反映实际。同时,行驶偏好没有得到充分体现:或许天府大道的非机动车道很宽敞,但我宁愿从绿道绕路。
因此,把 trunk 等类型的城市道路的默认速度改为 $18 \text{kph}$ 甚至更低(按平均速度算),同时拔高自行车道的 priority、降低城市道路的,并提高 maxDefaultSpeed 以容纳加权后的绿道行驶速度,才得以用新的配置勉强算出图一的结果。



近期评论