三峰累计爬升被低估,因为两步路过滤过多起伏

作者: , 共 3742 字 , 共阅读 0

很早以前,大家都说三峰的累计爬升是 1800 米或者 1750 米。去年我们用 5 小时 20 分跑完三峰的时候,两步路记录的累计爬升只有 1622 米!

两步路轨迹

该轨迹(越野跑路线,横切了望京塔和北尖)的地址是:https://2bulu.com/track/t-7XsfjWfqGH3p%25252FR2KBg5Tzw%25253D%25253D.htm

我们下载了轨迹的原始文件,抽取出其中的位置数据。在 5 个小时 20 分钟中,两步路的该轨迹包含 3319 个位置,大部分抽样时间在 4 秒到 12 秒不等。每个位置有四个字段,分别为时间、精度、纬度和海拔,比如前几个点的数据如下:

时间 经度 纬度 海拔
8:42:56 116.100694 40.051520 127.25
8:43:01 116.100661 40.051479 127.25
8:43:07 116.100656 40.051417 128.29
8:43:13 116.100656 40.051355 127.39
8:43:17 116.100661 40.051295 126.18

只看海拔数据如下:

海拔数据

如果直接用这 3319 个海拔数据,两两之间的距离计算海拔变化来计算,该路线的累计爬升将高达 2012 米!远高于两步路给的 1622 米的累计爬升。但 2012 米的爬升肯定是高估的,因为 GPS 获得的数据会有误差。

一个极端的例子是平路跑圈。如果在学校操场上跑圈,每个样本点上 GPS 的海拔也会有微小的几厘米几十厘米的上上下下的误差,如果时间很长,取点量过多,同样会造成很高的累计爬升。比如平地跑步 1 小时取样 1000 个点,每个点就算平均 10 厘米的误差,也会带来 100 米的累计爬升。

在上面三峰路线的轨迹中, 3319 个位置,其相邻点之间的上山和下山转换了 384 次,这显然是不可能的,其中大部分都是因为取样的误差造成的。所以我们需要过滤掉这些误差,一些细小的起伏,更可能是 GPS 轨迹的误差带来的,而不是真正的上山和下山。

我的实验结果表明,两步路对起伏过滤太严格,导致严重低估了路线的累计爬升。忽略指定的起伏幅度后,能计算的累计爬升数据如下:  

忽略起伏幅度 累计爬升 起伏次数  
- 2,012 384 
5 米 1,842 36 
10 米 1,775 18 
15 米 1,752 14 
20 米 1,736 10 
25 米 1,715 10 
30 米 1,715 10 
35 米 1,715 10 
40 米 1,679
45 米 1,679 8
50 米 1,679
55 米 1,679
60 米 1,621 6

根据这个实验,两步路事实上忽略了 60 米以下的起伏,才让三峰路线的累计爬升计算跌到 1622 米的幅度!当然由于算法可能的不一致,这个忽略幅度只是估计值,但这足以说明两步路在计算累计爬升时的严格程度。忽略六十米以下的起伏后是什么情况呢?此时三峰路线被简化为 7 个点,只有六段起伏:

六段起伏

7 个点 6 段起伏如下:

时间 经度 纬度 海拔 大致位置
8:42:56 116.10069 40.05152 127  大觉寺
11:00:52 116.04700 40.07900 1,264 阳台山
11:22:42 116.03184 40.08247 1,014  
11:59:14 116.01440 40.07257 1,270 妙峰山
12:30:22 116.03327 40.06262 758  涧沟村
12:56:54 116.04141 40.05783 987  
14:03:55 116.10050 40.05074 133  大觉寺

这就有点太狠了,连北尖都被过滤了,茶棚到阳台山中间的土包也被过滤了,还有一些更小的起伏被过滤了。

这也是为什么很多人总觉得两步路给的爬升过低的真实原因,很多人就喜欢用两步路的海拔纠偏功能。但前文已研究,海拔纠偏是用一个错误来解决另一个错误,会带来更大的不准确性。

那三峰路线真正的爬升是多少呢,我感觉路线上起伏转换次数在 15 次左右,对应的过滤幅度应该是 10 到 15 米。以 15 米为例,路线上起伏 14 次,状况如下图,累计爬升 1750 米。这可能是三峰路线的真实爬升。

忽略15米起伏后共起伏14次

附录:路线起伏的算法非常类似于股票走势里的分段算法,过滤小波段,识别大波段。代码开源在:https://gitee.com/zhiqiang.org/outdoor

核心算法是不断循环下面操作(因为规模不大,未对效率做优化):

  • 合并同样走势的波段,即若某个点前后的走势一样,这个点是无效的,可删除。
  • 查找最小的波动,若该波段过小,删除该波段(即波段的两边端点)。

详细代码如下,也可直接看源文件

    def calc_cum_up_down(self, ignore):
        points = self.points[:]
        while True:
            merged = merge(points)
            removed = remove_minimum(merged, ignore)

            if len(removed) == len(points):
                alts = [p1[3] - p0[3] for p0, p1 in zip(removed[:-1], removed[1:])]
                times = [p[0] for p in removed]

                return (sum([alt for alt in alts if alt > 0]),
                        sum([alt for alt in alts if alt < 0]),
                        removed,
                        [ p if p[0] in times else [*p[:3], ""] for p in self.points ])
            else:
                points = removed


def merge(points):
    """ 合并爬升、下降路段 """

    current_direction = points[1][3] - points[0][3]
    merged = [points[0], ]

    for (p1, p2) in zip(points[:-1], points[1:]):
        alt = p2[3] - p1[3]
        if alt * current_direction >= 0:
            current_direction = p2[3] - merged[-1][3]
        else:
            merged.append(p1)
            current_direction = alt

    merged.append(points[-1])

    return merged

def remove_minimum(points, ignore):
    """ 删除海拔变化最短的一段的路径 """

    if len(points) <= 2:    return points

    alts = [abs(p2[3] - p1[3]) for p1, p2 in zip(points[:-1], points[1:])]
    min_alt = min(alts)
    if min_alt > ignore:
        return points

    min_i = alts.index(min_alt)

    if min_i == 0:
        return [points[0], *points[2:]]
    elif min_i == len(alts) - 1:
        return [*points[:-2], points[1]]
    else:
        return [*points[:min_i], *points[min_i+2:]]

Q. E. D.

类似文章:
很多人在使用两步路记录自己的徒步轨迹后,会习惯性的使用两步路的海拔纠偏功能。以清明节全程徒步华山的轨迹为例,纠偏效果如下:
今天终于走了一次标准的三峰路线,里程 22 公里, 1750 米的总爬升。累趴了。线路已上传到两步路
户外 » 三峰路线
这周六,和孩子一起走了一次三峰,有如神助,大大打破了之前 7 个多小时的记录。这次 9:43 出发,下午 2:03 到达,总用时 5 小时 20 分钟。我们保存了行进中的轨迹20241123 三峰,用时 520,根据该轨迹,我们分析一下这个速度,为下一次三峰破五做准备。
周末组织一群孩子家长走了三峰拉练路线,从涧沟村出发,途径罗芭地南尖、罗芭地北尖、妙儿洼茶棚、 阳台山山顶、三界碑、妙峰山山顶、回香阁,最后回到涧沟村。
春节到了,又是了抢红包的时节。不过我对于这背后的数学和算法更感兴趣。
周末和孩子一起走了大觉寺北尖阳台山两峰环穿路线,强度比三峰略低,但也不小了。走下来膝盖疼,脚板疼。
基于将工作文件在家里电脑和公司电脑上的转移、Kindle 上电子书的管理的需求,我用 Matlab 写了几个函数,用来实现这些需求。
三峰即「萝芭地北尖、阳台山、妙峰山」,是北京户外爱好者最爱的徒步路线,也是测速专用。标准三峰路线大约 22 公里,爬升 1750 米。我们先从简单的路线走起,这就是这次的 10 公里 800 米爬升路线。
很早开始,两步路就无法上传香山区域(包括好汉坡)相关的路线,提示路线无法备份,因此也无法直接分享。现在两步路上能搜索到的香山或好汉坡相关的路线都是绝版。
周末和绿野童军的超大部队走了一次三峰小环线,从涧沟村出发,沿虎头崖、萝芭地北尖、妙儿洼茶棚,再返回涧沟村。总里程 8 公里,爬升只有 400 米,是一条非常简单的路线。
很多人在使用两步路记录自己的徒步轨迹后,会习惯性的使用两步路的海拔纠偏功能。以清明节全程徒步华山的轨迹为例,纠偏效果如下: