为了改进Spleeft对车把速度的测量,我在巴黎随西班牙BMX队训练期间,同步采集了线性编码器的数据。我用Python重写了iOS算法,并重点关注检测真实的休息期和完整的重复动作——否则传感器噪声可能会导致测量结果失真。.
我在从事体能训练工作期间,将开发 Spleeft 作为一项个人项目。编程帮助我将执教中的想法转化为测量杠铃速度的工具,也让我有机会展示自己在健身房之外的能力。.
随着人工智能让编程变得更加普及,我开始思考自己能在哪个领域做出最大的贡献。答案就在代码本身无法解决的部分:理解传感器数据,并在实际训练中提高测量结果的可靠性。正是这个问题,促使我开展了这个算法项目,我希望在此与大家分享。.
试试 Spleeft: 在 App Store 上下载 Spleeft 使用 iPhone 或 Apple Watch 追踪杠铃的速度。.
条形速度问题:漂移与虚假暂停
我之前在……中描述过的 Spleeft 优化, 那篇关于数据科学的原文, 该项目规模较小。我主要专注于调整现有算法的参数,并寻找能够提升其性能的参数组合。.
那项工作很有价值,但在花更多时间在真实的训练环境中测试Spleeft之后,我开始意识到一个更深层次的问题。.
主要困难并不只是计算速度。.
关键在于知道运动何时开始、何时结束,以及设备何时真正静止。.
Spleeft 使用加速度计数据。要计算速度,必须对加速度进行时间积分。这种方法在数学上很优雅,但也会带来一个无法避免的问题:即使加速度信号中存在微小的偏差或误差,在积分过程中也会累积,从而导致速度漂移。.
这种偏差可能源于以下几个方面:
- 传感器噪声;;
- 设备方向的微小变化;;
- 运动平面的变化;;
- 积分误差;;
- 过滤不完善;;
- 运动员或杠铃产生的振动;;
- 在杆体仍在运动时,存在加速度较低的时段。.
最后一点尤为重要。加速度接近零并不总是意味着速度为零。这也可能意味着该杆正在以相对恒定的速度运动。.
因此,真正的挑战并不只是找到“更多的零”。.
这是为了找到更好的零点。.
零点是一个可用于重新校准积分速度信号的时刻。如果重复测量开始前的零点不正确,积分将从错误的点开始。如果重复测量过程中出现虚假零点,可能会导致运动被过早截断或过早重新校准。.

这促使该项目确立了一项新原则:
首先提高静息状态检测和重复段分割的质量。然后评估速度。.
在巴黎采集杆速度数据
第一步是获得一款可与Spleeft配合使用的参考设备。.
一家知名的线性编码器厂商推出了一款设备,它不仅能提供速度数据,还能在真实的训练环境中采集原始数据。这正是我所需要的。.
在巴黎随西班牙BMX国家队集训期间,我在进行各项训练时收集了一大批数据:
- 深蹲;;
- 硬拉;;
- 力量 Clean;;
- 深蹲跳;;
- 其他综合力量训练。.

这些测量数据是同时采集的:
- Spleeft 记录了高频加速度计数据,其中包括采样率高达 800 Hz 的测试;;
- 线性编码器的采样频率约为100 Hz。.
这并非在完全受控条件下收集的实验室数据集。这是有意为之。.
我想了解,当该系统应用于教练实际使用它的环境时——即面对不同的练习、不同的负荷、不同的暂停时间、不同的动作策略以及不同的噪声来源——会发生什么情况。.
该数据集还使我能够比较两种截然不同的测量类型。.
编码器测量的是沿一条更明确的机械路径上的位移。Apple Watch 或 iPhone 则测量作用在设备、杠铃上,以及间接作用在运动员身上的力。它们检测到的信号并不完全相同。.
这一差异成为了该项目最重要的经验教训之一。.
用 Python 重构 Spleeft
在进行任何优化之前,我必须先在应用程序之外重现现有的 iOS 算法。.
这听起来很简单,但这却是整个过程中最重要的环节之一。.
该生成算法在 iPhone 和 Apple Watch 上使用 Swift 运行。不过,优化工作在 Python 中进行要容易得多,因为在 Python 中我可以处理大型数据集、生成图表,并测试成千上万甚至数百万种参数组合。.
问题在于,仅靠 Python 的近似计算是不够的。.
如果 Python 版本的行为与 Swift 版本不同,我就不会去优化 Spleeft 了。我会去优化另一个算法。.
因此,我开发了一个 Python 模拟器,用于重现 iOS 实现中的主要处理阶段:
- 读取加速度计和运动数据;;
- 速度重建;;
- 检测零速度更新;;
- 补偿信号漂移;;
- 将重复内容分段;;
- 计算平均速度及其他指标。.
随后,我根据 Swift 的输出结果对模拟器进行了验证。目的并非为了得到相似的结果,而是为了确保相同的原始信号能产生相同的重复次数以及几乎相同的指标。.
只有完成这一步,优化才有意义。.
超越原始的零点探测器
该算法的第一版已经包含了零速度重新校准功能,但其逻辑相对简单。.
在受控环境下,该设备表现良好。然而,某些训练项目暴露了其不足之处。卧推和硬拉尤其具有挑战性,因为当运动员稳定杠铃时,设备可能会产生额外的晃动。.
我开始从科学文献以及相关的惯性导航应用中,研究其他零速度检测方法。.
其中的一些想法包括:
- 多轴滤波加速度;;
- 陀螺仪信息;;
- 连续样本间的持久性要求;;
- 运动能;;
- 基于漂移的检查;;
- 保守型统计检测器;;
- 针对运动的不同状态设定不同的阈值。.
并非每个想法都奏效。.
例如,我研究了一种基于决策树的惯性状态分类器。这是一项有用的数据科学实验,但其性能不够可靠,因此无法在生产算法中作为硬性否决条件。.
这是一个重要的区别。.
该项目涉及机器学习实验和数据科学方法,但最终投入生产的解决方案并非一个仅仅对每个样本进行分类的“黑箱”模型。数据科学流程帮助我理解了信号特征,识别了故障模式,并设计出了一个更健壮的因果状态机。.
最终的系统仍然具有可解释性。.
在数百万种可能性中进行搜索
在模拟器和候选探测器准备就绪后,我开始进行系统性的参数搜索。.
对于每种候选配置,都会对相同的原始信号进行重新处理。这些参数控制了以下方面:
- 加速度阈值;;
- 连续样本的最小数量;;
- 过滤行为;;
- 移动条目规则;;
- 移动-退出规则;;
- 重新校准前所需的证据量;;
- 该系统是如何处理运动与静止之间的过渡的。.
此次搜索并非旨在寻找相对于编码器的速度误差最小的配置。.
那样就太狭隘了。.
第一个目标是确定一种能够最好地检测真实零速度时段,同时避免在活动期间出现虚假零点的组合。.
评估遵循以下级联流程:
- 这些有效零点是否被正确检测到了?
- 重复部分是否已被正确划分并计数?
- 一旦前两个条件都满足,速度指标与外部参考值的接近程度如何?
这个顺序很重要。.
如果重复运动的起始点或终点是由虚假零点定义的,那么即使其速度接近编码器,该重复运动也不一定就是测量正确的。.
这些数据只是我评估每次实验的参考依据之一。我将原始记录和生成的速度曲线保持在可见状态,然后对照我在自身训练以及与运动员进行测试时观察到的动作进行检查。 当出现明显的停顿时,我可以观察算法是否将速度值归零;当动作仍在持续时,我则能发现错误的修正。这些简单的目视检查,往往比另一个错误评分更能告诉我接下来该做哪些调整。.
用于运动的状态机
主要架构改进之一是添加了一个状态机,以补充零检测功能。.
该算法现在将运动视为一系列状态来进行推理,而不是将每个样本单独处理。.
简而言之,它会经历以下几种状态:
- 寻找运动的起点;;
- 检测到运动;;
- 寻找运动的终点;;
- 确认运动后确实进行了休息;;
- 对信号进行重新校准。.
这种结构有助于防止孤立的传感器事件立即改变对重复现象的解释。.
例如,在移动条形图中出现的一段短暂低加速度时段,不应自动被解释为静止状态。系统需要额外的证据:信号的方向、事件的持续时间以及更广泛的运动背景。.
状态机还让我得以将两个此前联系过于紧密的概念区分开来:
- 检测条形是否在移动;;
- 决定是否可以对综合速度进行重新校准。.
这一点特别有用,因为即使加速度暂时接近零,运动状态仍可保持活跃。.
编码器能告诉我什么——以及不能告诉我什么
我将编码器用作外部参考,但并未将其视为无可置疑的真实值。.
在每次迭代中,我都采用类似的方法处理编码器的数据,而不是简单地复制其专有算法导出的指标。这减少了解码器内部处理与Spleeft处理方式之间的差异所产生的影响。.
即便如此,该编码器也仅被视为参考,而非绝对标准。.
不同的设备具有不同的滤波器、延迟、检测规则和机械限制。导出的信号也可能与内部用于计算各项指标的信号并不完全相同。.
这就是为什么我决定不将成功简单地定义为:
“Spleeft的值与编码器的值接近。”
相反,我寻找的是一种内部一致、能正确检测重复,并在不同的练习和记录条件下表现稳健的算法。.
编码器帮助我发现了错误,并协助我调查了棘手的情况。它并没有取代批判性思维。.
使用真实用户数据对算法进行测试
完成实验室实验后,我又回过头来分析了在受控实验之外收集的数据。.
其中一些最有用的文件来自Spleeft用户,他们分享了该应用程序产生意外结果的案例示例。.
这些文件之所以有价值,是因为它们包含了现实生活中出现的问题:
- 不完美的停顿;;
- 意外的杆振动;;
- 缓慢的重复动作;;
- 不同的安装位置;;
- 技术上的变化;;
- 重复前或重复后的噪声;;
- 那些动作形式与深蹲不同的练习。.
我将新算法应用于这些历史数据集,并将其运行情况与之前的实现进行了比较。.
这一阶段帮助我们认识到一个重要原则:改进算法并不意味着不惜一切代价让它变得更复杂。这意味着要让算法逻辑更好地适应传感器和运动项目的实际状况。.
那段经历也塑造了 Spleeft的最新更新. 加速度计的测量存在局限性, ,即使经过仔细优化,情况依然如此,因此我希望教练们能够检查底层的记录,并根据自身情况判断结果是否可靠。.
在售价40欧元的Apple Watch SE上进行测试
我还想在真正的 Apple Watch 上测试这个新算法,而不是仅依赖 Python 模拟。.
为了让该项目与Spleeft的初衷保持一致,我花大约40欧元买了一块二手Apple Watch SE。这是能够运行该应用程序并实时处理信号的最便宜机型之一。.

这不仅仅是一次实践测试。.
Spleeft 的开发始终围绕着“基于速度的训练应当触手可及”这一理念。如果一种新算法只能在最昂贵的设备上运行,或者只能在完美的实验室环境中运行,那就不符合该项目的初衷。.
在现场测试期间,我对比了两种放置方式:
- 运动员手腕上的手表;;
- 手表直接固定在横杆上。.
这表明了传感器放置位置的重要性。.
在硬拉和卧推中,运动员手腕的动作可能会引入额外的干扰。由于运动员需要握住并稳定杠铃,因此传感器测量的不仅有杠铃的垂直位移,还包括手、手腕和身体的细微动作。.
将手表直接放在横杆上,能减轻部分噪音。.
这并不意味着横杆位置总是最佳选择,也不意味着手腕位置是错误的。这意味着,最佳算法也需要考虑到硬件的局限性以及设备的使用方式。.
无论数据科学多么先进,都无法完全弥补测量方案的缺陷。.
Spleeft 算法发生了哪些变化
新算法已走出测试阶段。其真正的考验在于,它在不同的练习、设备和训练环境中能否保持稳定的运行效果。我希望教练们能够自行对此进行评估。.
我还想明确说明这个数字背后的原理:Spleeft 利用检测到的休息时段来限制速度漂移,并借助状态机来识别重复动作。我们已通过记录的训练数据和外部设备对这些决策进行了验证。我在此分享这一方法,但具体参数将不予公开。.
我的收获
这个项目让我明白,一个有用的速度指标不仅仅取决于一个巧妙的算法。它还取决于传感器、运动方式、数据质量以及每个环节做出的决策。人工智能帮助我更快地进行探索和开发,但教练的经验对于判断哪些问题真正重要至关重要。.
Spleeft 至今仍是一个由这种好奇心驱动的个人项目。我将继续在实际训练中对其进行测试,并分享我的心得体会。.



