这是一篇面向开发和调试的算法文档。读完后你应该能回答三件事: 算法在算什么、为什么这么算、界面上每个元素对应公式里的哪个量。
全文用一个贯穿例子:一块 5×5 的受力区域,压力沿主对角线(左上—右下)分布,左上端更重。
1. 算法要做什么
阵列式压力传感器的数据就是一张二维表:每个格子一个力值。画成三维曲面(坐标做底面、力值做高度),哪里轻哪里重一目了然。

图 1:起点。 左:压力曲面沿对角线隆起、左上端更高;右:同一组数据的 2D 视图和每格数值。人眼能看出"不均匀",算法要把这件事变成数字结论。
用户拿压头按传感器时,“按得不规范"有两种情况,物理上完全不同:
| 问题类型 | 表现 | 用户该怎么修 |
|---|---|---|
| 位置偏移 | 压头放歪了位置,但贴得是平的。压力分布形状正常,只是整体挪了位 | 照着箭头把压头挪过去 |
| 姿态歪斜 | 位置可能很正,但压头翘了边。翘起的一侧轻、压下的一侧重,分布形状被扭曲 | 停下来,检查贴合,重新放平 |
修法完全不同,所以算法输出两个相互独立的结论,各管一类:
- 位置通道:受力中心偏在哪 → 画面上画一个箭头;
- 扭转通道:压力沿哪条线失衡、哪侧重 → 画面上画一条双向轴线 + 偏重侧铺色。
后面所有设计都是围绕这两个通道展开的。第 2~3 节分别讲两个通道怎么算,第 4 节给出完整流程汇总,第 5 节讲界面怎么读,第 6 节讲能力边界和参数。
2. 位置通道:算受力中心(质心)
2.1 符号约定
后面所有公式共用这套记号:
- 受力区域(下称"斑块”)内的格子编号为 $i = 1, 2, \dots, n$;
- $V_i$:第 $i$ 格的力值(热力图上显示的那个数);
- $p_i = (r_i, c_i)$:第 $i$ 格中心的坐标,$r$ 是行号(向下),$c$ 是列号(向右);
- $\sum_i$:只对斑块内的 $n$ 个格子求和。
2.2 公式
把每格的力值当权重,对格子位置做加权平均,得到的点就是受力中心(质心):
受力重的格子会把这个点往自己那边拉。拿它和参考中心(压头的几何中心,或稳定接触区域的几何中心)一比,差值的方向就是界面上那个橙色箭头的方向。
2.3 为什么用它
质心对"整体挪动"是最可靠的度量:分布整体往哪挪,它一分不差地跟着往哪挪,而且和分布的形状无关。它也是最便宜的算法——一次遍历,O(N)。
但它有一个致命盲区,这正是下一节的主题。
3. 扭转通道:检测姿态歪斜
这一节是全文的主体。按推导顺序分五步:
- 先看清楚质心为什么看不见歪斜(3.1);
- 排除另一个直觉方案——逐点梯度(3.2);
- 用二阶矩把歪斜"捞"出来(3.3);
- 扣掉斑块形状自身的底数(3.4);
- 拆出强度 λ 和方向(3.5、3.6)。
3.1 质心的盲区:对角失衡时它纹丝不动
取姿态歪斜里最典型的形态——对角翘曲:左上、右下两个角重,另外两个角轻。用最小的 2×2 斑块演示:
1+ε 1−ε (左上角 = 右下角 = 1+ε)
1−ε 1+ε (右上角 = 左下角 = 1−ε)
其中 1 是基准读数(均匀受压时每格都读 1),$\varepsilon$ 是失衡幅度:重的格比基准高 $\varepsilon$,轻的格低 $\varepsilon$。$\varepsilon$ 越大翘得越狠,$\varepsilon = 0$ 就是完全均匀。
问题出在:四个格子关于中心对称,重的和轻的两两对称,加权平均时互相抵消——不管 ε 多大,质心永远在正中心。

图 2:质心盲区的实测。 左:图 1 的倾斜数据,不均匀肉眼可见,但受力中心(圆点)相对几何中心(十字)只偏了 0.50 格;右:一组"纯扭转"数据(主对角重、反对角轻),肉眼同样歪,中心偏移精确为 0.00,而后面要算的失衡强度 λ 高达 0.136。
原因可以一句话说清:质心只回答"力整体偏向哪边",而对角翘曲不是"偏向哪边",是"沿某条线的两侧重新分配"——重侧更重、轻侧更轻,总量没变,中心自然不动。 这类形态绕中心转 180° 后图形不变,任何"把分布压成一个点"的统计量都对它无能为力。

图 3:质心的盲区与人眼的朝向响应。 上排:均匀受压、主对角翘曲、反对角翘曲、中心加重,四种完全不同的形态,受力中心全部落在正中——对质心来说它们是同一个输入。下排:把纯扭转数据喂给不同朝向的"脊探测器",响应在 45° 和 135° 达到峰值,峰值幅度恰好等于失衡强度 λ。人眼一眼能看到的"沿对角线有一条脊",本质上就是这种带方向的二阶信息——第 3.3 节的工具就是把它补给了程序。
3.2 为什么不用逐点梯度
既然质心是"全局平均"丢了细节,那反过来,逐格看压力曲面的梯度(每格的最陡上坡方向)行不行?不行,有三个硬伤:

图 4:梯度是局部量,扭转是全局形态。 (a) 对角翘曲的压力曲面是一条脊;(b) 纯扭转数据上每格的上坡方向——脊线两侧的箭头两两相向,加起来几乎归零;(c) 纯扭转的几何本质是马鞍面:整体旋转 180° 图形不变。
- 方向互相抵消。 对角翘曲时,轻角的梯度指向重角、重角内部的梯度互相背离,逐格相加的矢量和恰好只正比于质心偏移——绕回了 3.1 的盲区。
- 小网格上噪声致命。 阵列常常只有 5×5,一格噪声就能翻转局部差分的符号;压到量程顶的格子在差分眼里是一堵无限陡的悬崖。
- 输出没法用。 用户要的是一句话结论,不是 25 支箭头。
结论:梯度和曲率是局部量,而"压头歪没歪"是全局问题。需要的是另一种全局量——对全场加权求和(噪声互相抵消),但不像质心那样把方向信息丢掉。这就是二阶矩。
3.3 二阶矩:把歪斜从盲区里捞出来
先算每格相对受力中心 $(\bar r, \bar c)$ 的偏移:
再用 $V_i$ 当权重,把"偏移量自己乘自己"做加权平均,拼成一个 2×2 的协方差矩阵 M:
(横线表示按 $V_i$ 加权平均。)三个元素各有分工:
- $m_{rr}$:压力沿行方向散得多开;
- $m_{cc}$:压力沿列方向散得多开;
- $m_{rc}$:行偏移和列偏移是否联动——它就是"对角结构"的探测器。
代回 3.1 的 2×2 例子验证(此时 $dr$、$dc$ 都是 $\pm 0.5$):
- $m_{rr}$、$m_{cc}$:每格 $dr^2 = dc^2 = 0.25$,与权重无关,$\varepsilon$ 完全被消掉——这两个元素看不见对角翘曲;
- $m_{rc}$:对角格 $dr\,dc = +0.25$,反对角格 $dr\,dc = -0.25$:
质心丢掉的那个 $\varepsilon$,在交叉项 $m_{rc}$ 里被一比一地捡了回来:$\varepsilon$ 多大它就多大,$\varepsilon = 0$ 它就是 0。歪斜信号找到了。
3.4 扣掉形状的底数:基线 M₀ 与偏差张量 D
直接拿 M 判定会误报。设想一种情况:压力完美均匀(每格都是 1),但斑块本身是个 L 形。L 形沿长臂方向天然散得开,M 照样各向异性——M 里叠了两个来源:压力不均匀(要检测的)和斑块形状(必须扣除的)。
处理办法是实验设计里最朴素的思想——造一个对照组再相减。对照组就是零假设:“假设压力完全均匀,这个形状的二阶矩是多少?“具体做法:还是那 $n$ 个格子,把权重从 $V_i$ 换成等权(每格 $1/n$)再算一遍,得到 $M_0$,即纯由形状贡献的底数。然后:
- 分子 $M - M_0$:只留压力不均匀的净效应。均匀压力下无论斑块形状多不规则,分子严格为零——形状底数被彻底扣除;
- 分母 $\operatorname{tr}(M_0)$($M_0$ 两对角元之和,即形状的总散布):做归一化,让 D 无量纲、与传感器和压头尺寸无关,不同大小的斑块、不同设备之间可以直接比。
3.5 拆出强度:λ
D 仍是 2×2 对称矩阵,里面还混着两种性质不同的成分:
- 各向同性成分:压力整体向中心收拢、或向边缘摊开——只有松紧、没有方向,说不出"沿哪条线歪”;
- 有方向的成分:沿某条线的失衡——判定要用的就是它。
把两者拆开。取 D 的对角元差的一半和交叉元:
各向同性部分单独存为 $iso = \operatorname{tr}(D)/2$,剩下的方向部分拼成 $\begin{pmatrix} a & b \\ b & -a \end{pmatrix}$。失衡强度定义为:
λ 有三个好用的性质,所以它成为"报不报倾斜"的判据:
- 无量纲纯数字——阈值可以跨设备统一(起步值 0.05,见第 6 节);
- 旋转不变——屏幕坐标系转 45°,$D_{rr}$ 和 $D_{rc}$ 会互相混,λ 不变;
- 就是方向部分的特征值模长——数学上严格等于"有方向那一半成分"的大小。
($iso$ 只作为诊断信息保留、不进提示,因为它翻译不成用户能执行的动作。)

图 5:减基线、归一化、分解,套到贯穿例子上。 左:虚线椭圆是等权基线 $M_0$(形状底数),实线椭圆是加权二阶矩 M(实际压力),两者之差就是压力不均匀的净效应;中:实算数值——M 的交叉项 +0.558 显著非零(正是 3.3 节 $m_{rc}=\varepsilon/4$ 的放大版),$M_0$ 的交叉项为 0(方形斑块自身没有对角倾向),相减归一后 D 的交叉项 = +0.139;右:分解结果——$|iso|=0.042$ 很小(整体松紧没变化),λ=0.139 远超 0.05 阈值,触发倾斜提示。
3.6 拆出方向:主轴 + 偏重侧
λ 只回答"有多歪”,还差两个信息:沿哪条线歪、哪一侧重。
沿哪条线——主轴。 方向部分矩阵的主特征向量有闭式解:
$v$ 是单位向量,指向失衡最强的方向。界面上那条紫色双向虚线就是它。
有一个数学事实必须讲清楚,因为它直接决定了界面形态:方向部分的两个特征值是 $+\lambda$ 和 $-\lambda$,沿 $+v$ 和 $-v$ 的异常强度相等。张量只能给出一根"轴"(一条线),给不出"指向"——“左上重右下轻"和"左下重右上轻"算出的是同一个 D。所以轴向在界面上画成双向虚线,这是数学事实,不是设计取舍。
哪侧重——半平面均值比较。 张量给不出指向,就回到原始数据直接对照:记 $g$ 为斑块的等权几何中心,算每格在主轴上的带符号投影
$t_i > 0$ 的格子在轴的一侧,$t_i < 0$ 的在另一侧,比较两侧每格均值 $\overline{V}_{+}$ 和 $\overline{V}_{-}$。注意用均值不用总和——两侧格子数经常不等,比总和的话格多的一侧几乎必然赢,那是比面积不是比压强。

图 6:主轴 + 两侧均值 → 倾斜提示。 左:紫色双向虚线是主失衡轴(本例恰为 45° 对角方向),铺色一侧每格均值 5.20、另一侧 2.60,差异显著——左上侧偏重;右:数值结论翻译成用户文案的全过程。画面上没有第二个箭头:轴向用双向虚线表达,偏重侧用铺色表达——“箭头代表动作,颜色和轴线代表问题”。
至此,扭转通道的三件输出凑齐了:λ(报不报)、轴向(哪条线)、偏重侧(哪侧重)。
4. 完整流程一页速查
每帧数据按下面的顺序走一遍(全程一次遍历 + 一个 2×2 闭式特征分解,O(N),可实时):
| 步骤 | 计算 | 产出 |
|---|---|---|
| 1 | 力值过进入阈值 → 提取连通斑块(≥ 4 格) | 斑块格子集 $\{i\}$ |
| 2 | 饱和预处理:$w_i = \min(V_i, V_{95})$($V_{95}$ = 斑块内第 95 百分位) | 截断后的权重 |
| 3 | 加权质心 $C_{actual}$(第 2 节) | 位置偏移 → 箭头 |
| 4 | 加权二阶矩 M(3.3) | — |
| 5 | 等权二阶矩 $M_0$,$D = (M-M_0)/\operatorname{tr}(M_0)$(3.4) | 净偏差张量 |
| 6 | $a = (D_{rr}-D_{cc})/2$,$b = D_{rc}$,$\lambda = \sqrt{a^2+b^2}$(3.5) | 失衡强度 |
| 7 | λ 超阈值且面积 ≥ 9 格 → 主轴 $v$(3.6) | 失衡轴向 |
| 8 | 半平面投影分组,比较两侧均值(3.6) | 偏重侧 |
几个贯穿全文的对应关系,方便记忆:
- 位置偏移 ↔ 质心(一阶矩) ↔ 单头箭头;
- 姿态歪斜 ↔ 二阶矩的交叉结构 ↔ 双向轴线 + 铺色;
- 均匀压力 → D = 0、λ = 0,形状再怪也不误报(3.4 的对照思想保证了这一点)。
5. 界面怎么读
5.1 位置通道:重心坐标与箭头

图 7:位置通道。 画面三要素:白色十字(参考中心)、橙色圆点(受力中心)、橙色单头箭头。阅读顺序:先看箭头,再看数值,最后确认有没有倾斜提示。
三个容易读错的地方:
- 箭头只给方向,长度不代表该挪多远;
- 偏差数值用 cell 还是 mm,取决于有没有可靠的物理布局,没有就老老实实用 cell;
- 参考中心是算法选的参照点(优先级:已知压头几何中心 > 稳定帧接触掩码中心 > 高压力核心中心兜底),不是精密测出的压头机械中心——界面文案不能含糊;
- 画面上同时出现倾斜提示时,箭头作废:先把姿态修好,位置结论才有意义。
5.2 扭转通道:λ、轴向、铺色

图 8:扭转通道。 λ 只负责报不报(表盘上的阈值线),轴向负责哪条线,铺色负责哪侧重。
三层信息各回答一个问题:
- λ 报不报。 超过阈值(0.05 起步)才提示"可能压头倾斜”。界面上最多说"轻度/明显",具体数值放详情面板。阈值只能实测校准,数学推不出来(见第 6 节);
- 轴向说哪条线。 “沿左上—右下方向失衡”——方向信息的本体,永远输出;轴是双向的,这是数学事实不是文案取舍;
- 铺色说哪侧重。 只有两侧均值差异显著时才出现。三种文案形态——指认偏重侧 / 只说"沿该方向集中" / “方向不确定”——分别对应数据充分、方向明确但侧重不显著、数据退化三种结局。

图 9:一个箭头回答不了所有问题。 均匀分布和对角失衡都可能让受力中心落在正中;前者可以说"受力中心已对齐",后者必须提示"可能压头倾斜"并用双向轴 + 方位词标出方向。不能画第二个箭头——箭头会被读成"往那边推",而扭转不是推能修好的。
5.3 辅助显示:180° 对称差红蓝格
一侧整体偏重的形态,有一种更直观的显示办法:记 $V(p)$ 为位置 $p$ 的力值,$2g - p$ 是 $p$ 绕几何中心 $g$ 转 180° 后斜对面的格子,两格相减:
红格 = 比斜对面重,蓝格 = 比斜对面轻,灰 = 相同。直观到不需要解释。
但它有明确的职责边界:Δ 对"一侧偏重"敏感,对 180° 旋转对称的马鞍面(对角翘曲)恒为零——那种情况下 Δ 全灰、λ 却显著。所以分工是:判定永远交给 λ,Δ 只负责展示;反过来纯一侧偏重时 λ 很小(实测 0.013),由重心箭头负责。两个通道各守各的边界。
另外,形状不规则的斑块(L 形、带孔)必须沿真实格子边缘描边界;用外接矩形会把空洞和未受力区域圈进去,用户就看不到真实的接触范围。

图 10:真实边界与外接框的区别。
6. 能力边界与初始参数
6.1 它做不到的事
这些边界都是从推导里自然长出来的,不是免责声明:
- 它看的是这一次按压的力,不是传感器本身。传感器制造均不均匀、标定曲线该不该改,一概回答不了;
- 它不会说"第几格坏了"。单格读数异常可能是坏点,也可能只是噪声、接触边缘或压到量程顶;
- 它给不出压头的真实倾角。紫色轴说的是"压力沿哪条线失衡",是统计方向,拿它反算倾角是过度解读;
- 压到量程顶的数据救不回来。能做的只是提示"读数可能不可靠",不会拿外推数字装精确;
- 接触面积太小(不到 9 格)做不了扭转分析。此时只能报"受力中心已对齐(未检查倾斜)"——注意是"没查",不是"查了没问题"。
一句话定位:这是一个针对当前 2D 接触数据的施力偏移与倾斜风险提示器。它能回答"压力中心偏向哪、先往哪边挪",也能在箭头为零时发现"可能压歪了";再多的做不到,也不该假装做到。
6.2 初始参数(首轮验证用,非物理标准)
尤其注意 λ 阈值 0.05:λ 是无量纲统计量,多大的 λ 对应真实翘曲只能靠实测标定。建议拿代表性压头,正常接触和故意偏压各测一组,按误报/漏报情况收敛。
| 参数 | 起步值 | 调大 / 调小的影响 |
|---|---|---|
| 进入阈值 | ADC/力值/压强各存一份 | 过低进噪声,过高切掉接触边缘 |
| 最小连通格数 | 4 | 过滤碎点;过高漏掉小接触 |
| 位置允许偏差 | 按 cell 或 mm 配置 | 决定何时显示"已对齐" |
| 扭转最小面积 | 9 格 | 小区域只报位置结论 |
| 扭转阈值 λ | 0.05 | 越低越敏感、也越容易误报 |
| 饱和提示比例 | 0.3 | 超过后降低可信度,不修正数据 |
| 中心平滑帧数 | 5 | 越大越稳但响应越慢;区域重连时重置 |
附录:每个零件的学科出处
这套算法没有专名,因为它是各领域成熟工具的组合,没有原创部件。想深挖的读者按下表检索即可:
| 本文的叫法 | 学科出处 | 在这里干了什么 |
|---|---|---|
| 质心 / 一阶几何矩 | 统计学、图像矩分析 | 位置通道:整体偏移 → 箭头 |
| 多极展开(偶极/四极) | 物理学 | 双通道的理论框架:位置偏移是一阶(偶极)分量,扭转是二阶(四极)分量 |
| 二阶中心矩 / 协方差矩阵 | 图像矩、主成分分析(PCA) | 把对角失衡从质心盲区里捞出来 |
| 对照基线扣除 | 实验设计 / 统计学 | 扣掉斑块形状的底数,得 D |
| 各向同性 / 偏量分解 | 连续介质力学(静水压 + 偏应力,与 von Mises 应力同族) | 剥掉整体松紧,得 λ;“扭转"一词即从"剪切"借来 |
| 结构张量双角度表示 | 朝向分析 | 主轴;解释轴为何双向无指向 |
| 半平面均值比较 | 统计对照检验 | 判断哪侧偏重 |
| 180° 中心对称差 | 中心对称分解 | Δ 红蓝格:直观显示 |