3. 逐点比较法(二):圆弧插补原理,偏差计算与进给规则,终点判别方法

上一章我们聊了直线插补,说白了就是让刀具走一条笔直的路径。但实际加工中,圆弧才是最常见的轮廓——倒角、圆孔、弧形曲面,哪个都离不开它。逐点比较法处理圆弧的思路,其实和直线一脉相承:每一步都判断当前位置在圆弧的哪一侧,然后决定下一步往哪走。

我个人习惯把圆弧插补比作「走钢丝」——你每一步都要知道自己偏了没有,偏了就赶紧纠正。今天我们就把这个过程拆开来看。

3.1 圆弧插补的基本原理

先想一个问题:怎么判断一个点是在圆弧上、圆弧内还是圆弧外?

假设我们要加工第一象限的逆圆弧,圆心在原点,半径为 R。对于任意点 P(x, y),它到圆心的距离平方是 x² + y²。和 R² 比一比:

  • 如果 x² + y² = R²,点在圆弧上
  • 如果 x² + y² > R²,点在圆弧外
  • 如果 x² + y² < R²,点在圆弧内

嗯,这就是偏差判断的数学基础。我们定义偏差函数:

F = x² + y² - R²

F = 0 时在圆上,F > 0 在圆外,F < 0 在圆内。就这么简单。

核心思想:逐点比较法圆弧插补的本质,就是通过偏差 F 的符号,决定下一步进给方向,使刀具始终逼近理想圆弧。

3.2 进给规则:怎么走才能不跑偏?

知道了偏差,下一步就是「怎么走」。对于第一象限逆圆弧,规则很直观:

  • F ≥ 0:点在圆上或圆外,需要向圆内走,也就是沿 -X 方向进给一步
  • F < 0:点在圆内,需要向圆外走,也就是沿 +Y 方向进给一步

你想想看,这个逻辑其实和直线插补很像——都是「偏哪补哪」。只不过圆弧的偏差计算稍微复杂一点,因为每走一步,坐标变了,偏差也要跟着更新。

我的经验:刚开始学的时候,我总把进给方向和象限搞混。后来我总结了一个口诀:「逆圆外走 -X,内走 +Y;顺圆反过来」。记牢这个,写代码时就不容易晕。

3.3 偏差计算的递推公式

如果每一步都重新算 x² + y² - R²,计算量太大了。实际工程中,我们用的是递推公式——根据上一步的偏差和进给方向,快速算出下一步的偏差。

假设当前点 P(xᵢ, yⱼ),偏差 Fᵢⱼ = xᵢ² + yⱼ² - R²。

情况一:沿 -X 方向进给一步
新坐标:xᵢ₊₁ = xᵢ - 1,yⱼ 不变
新偏差:

Fᵢ₊₁,ⱼ = (xᵢ - 1)² + yⱼ² - R²
        = xᵢ² - 2xᵢ + 1 + yⱼ² - R²
        = Fᵢⱼ - 2xᵢ + 1

情况二:沿 +Y 方向进给一步
新坐标:xᵢ 不变,yⱼ₊₁ = yⱼ + 1
新偏差:

Fᵢ,ⱼ₊₁ = xᵢ² + (yⱼ + 1)² - R²
        = xᵢ² + yⱼ² + 2yⱼ + 1 - R²
        = Fᵢⱼ + 2yⱼ + 1

你看,只需要一次加法和一次乘法,比重新算平方快多了。我在项目中用过这个递推公式,在 8 位单片机上跑圆弧插补,速度完全够用。

注意:递推公式中的 xᵢ 和 yⱼ 是当前坐标值,不是步数。每次更新偏差后,别忘了同步更新坐标值,否则下一步的递推就会出错。我曾经在这个坑里栽过一次,调试了一下午才发现是坐标没更新。

3.4 终点判别方法

圆弧插补不能一直走,得知道什么时候停。终点判别有三种常用方法:

方法 原理 特点
总步数法 计算 X 方向和 Y 方向总步数 n = |Xₑ - Xₛ| + |Yₑ - Yₛ|,每走一步减 1 简单可靠,最常用
坐标比较法 实时比较当前坐标是否到达终点坐标 直观,但需注意象限切换
偏差归零法 当偏差 F = 0 且已走完理论弧长时停止 精度高,但实现复杂

我个人最推荐总步数法。为什么?因为它和进给方向无关,不管你怎么走,总步数是固定的。在项目里,我一般初始化时就算好总步数,然后每进给一步就减 1,减到 0 就停。简单、稳定、不出错。

避坑指南:我曾经在一个四轴联动项目里用了坐标比较法,结果因为象限切换时坐标值有微小误差,导致终点判断提前触发,圆弧缺了一小段。后来换成总步数法,问题立刻解决。所以,除非你有特殊需求,否则无脑选总步数法。

3.5 完整插补流程与 SVG 图解

把上面这些串起来,一个完整的圆弧插补流程是这样的:

  1. 初始化:设置起点坐标、终点坐标、圆心、半径,计算总步数 n
  2. 偏差判断:根据当前偏差 F 的符号,决定进给方向
  3. 进给一步:沿选定方向走一个脉冲当量
  4. 偏差更新:用递推公式计算新偏差
  5. 坐标更新:更新当前坐标值
  6. 终点判别:总步数减 1,若不为 0 则回到步骤 2
  7. 结束:到达终点,插补完成

下面这张图把这个流程画清楚了:

逐点比较法圆弧插补流程图 逐点比较法圆弧插补流程图(第一象限逆圆弧) 开始 初始化:起点、终点、半径 计算总步数 n F ≥ 0 ? F ≥ 0:沿 -X 进给 F = F - 2x + 1 F < 0:沿 +Y 进给 F = F + 2y + 1 更新坐标 x, y n - 1 = 0 ? 结束 是 否 是 否 说明 • 总步数 n = |Xe - Xs| + |Ye - Ys| • 每进给一步 n = n - 1

3.6 代码实现示例

理论说完了,上代码。下面是一个第一象限逆圆弧插补的 C 语言实现片段:

// 圆弧插补:第一象限逆圆弧
// 起点 (xs, ys),终点 (xe, ye),圆心 (0, 0)
void arc_interp(int xs, int ys, int xe, int ye) {
    int x = xs, y = ys;
    int F = x*x + y*y - R*R;  // 初始偏差
    int n = abs(xe - xs) + abs(ye - ys);  // 总步数
    
    while (n > 0) {
        if (F >= 0) {
            // 圆外/圆上,向 -X 走
            x--;
            F = F - 2*x - 1;  // 注意:x 已更新,公式用新 x
        } else {
            // 圆内,向 +Y 走
            y++;
            F = F + 2*y - 1;  // 注意:y 已更新,公式用新 y
        }
        n--;
        // 这里可以输出脉冲信号给电机
    }
}

注意:上面代码中递推公式的符号和前面推导略有不同,因为我在更新坐标后才计算偏差。如果你先算偏差再更新坐标,公式要反过来。这个细节很容易搞混,我建议你写代码时统一用一种顺序,并在注释里写清楚。

3.7 不同象限的进给规则

第一象限搞定了,其他象限怎么办?其实原理一样,只是进给方向不同。我整理了一张表:

象限 圆弧方向 F ≥ 0 进给 F < 0 进给
第一象限 逆圆弧 -X +Y
第一象限 顺圆弧 -Y +X
第二象限 逆圆弧 +Y -X
第二象限 顺圆弧 +X -Y
第三象限 逆圆弧 +X -Y
第三象限 顺圆弧 +Y -X
第四象限 逆圆弧 -Y +X
第四象限 顺圆弧 -X +Y

嗯,这张表看起来有点复杂。但如果你仔细观察,会发现一个规律:逆圆弧的进给方向,其实就是把坐标轴往圆内方向推;顺圆弧则相反。记住这个规律,比死记硬背强多了。

我的习惯:在实际项目中,我不会为每个象限单独写一套逻辑。我会把坐标做象限变换,统一映射到第一象限处理,最后再把结果映射回去。这样代码量少一半,也不容易出错。