逐点比较法(二):逐点比较法圆弧插补、象限处理、终点判断

上一章我们聊了直线插补,这次轮到圆弧了。说实话,圆弧插补比直线要绕一点——不是技术上的难,而是逻辑上多了个象限判断。我刚开始做运动控制时,就在象限处理上栽过跟头。嗯,今天咱们把它彻底讲透。

圆弧插补的基本思路

逐点比较法做圆弧插补,核心思想还是那个老套路:每走一步,算一下当前位置相对于理想圆弧的偏差,然后决定下一步往哪走。

你想想看,圆弧和直线最大的区别是什么?直线只有一个方向偏差,圆弧却有两个——半径偏差和角度位置。说白了,我们要判断当前点是在圆弧内侧还是外侧。

核心公式:

设圆心在原点,圆弧起点为 (X₀, Y₀),终点为 (Xₑ, Yₑ)。

偏差函数:F = X² + Y² - R²

  • F = 0:点在圆弧上
  • F > 0:点在圆弧外侧
  • F < 0:点在圆弧内侧

这个公式其实很好记。X² + Y² 就是当前点到圆心的距离平方,减去半径平方,正负一目了然。我在项目里调试圆弧轨迹时,经常用这个公式做离线校验,比看波形直观多了。

第一象限逆圆弧的进给规则

我们先从最简单的第一象限逆圆弧说起。为什么先讲逆圆弧?因为顺时针和逆时针的进给方向正好相反,搞混了轨迹就反着跑了。

规则其实就两条:

  • F ≥ 0:点在圆弧外侧或圆弧上,向 -X 方向走一步(靠近圆弧内侧)
  • F < 0:点在圆弧内侧,向 +Y 方向走一步(靠近圆弧外侧)

你可能会问:为什么外侧走 -X,内侧走 +Y?

我习惯这么理解:逆圆弧是从起点逆时针画到终点。在圆弧外侧时,你需要往圆心方向拉回来,也就是 -X 方向;在圆弧内侧时,你需要往外推出去,也就是 +Y 方向。这样轨迹才能贴着圆弧走。

偏差计算的递推公式

每次走一步都算 X² + Y² - R² 太慢了,计算量大不说,还容易累积误差。所以我们要用递推公式——根据上一步的偏差和这一步的移动方向,快速算出新偏差。

进给方向 新偏差公式 坐标更新
-X Fnew = Fold - 2X + 1 X = X - 1
+Y Fnew = Fold + 2Y + 1 Y = Y + 1

注意看,递推公式里只有加减法和移位操作,没有乘方。这就是逐点比较法高效的原因——全是整数运算,适合嵌入式实时控制。

我的小技巧:

实际写代码时,我习惯把 2X 和 2Y 单独维护成变量,每次更新坐标后同步更新。这样就不用每次重新算乘法了,速度能快一截。

象限处理——这才是真正的坑

好了,第一象限搞定了。但实际加工中,圆弧可能出现在任意象限,而且有顺圆和逆圆之分。象限处理不对,轨迹直接飞出去。

我曾经在一个三轴平台上调试圆弧插补,第一象限跑得稳稳的,一到第二象限就开始画歪线。查了半天,发现是象限切换时进给方向没跟着变。

不同象限的进给规则是这样的:

象限 逆圆弧 (F≥0) 逆圆弧 (F<0) 顺圆弧 (F≥0) 顺圆弧 (F<0)
一 -X +Y -Y +X
二 +Y -X +X -Y
三 +X -Y +Y -X
四 -Y +X -X +Y

看着有点乱是吧?我教你一个记忆方法:逆圆弧的进给方向是「逆时针转」,顺圆弧是「顺时针转」。你拿笔在纸上画一下,每个象限的进给方向其实就是沿着圆弧切线方向往里或往外偏一点。

注意:

象限切换时,偏差函数 F 要重新计算!不能直接用上一象限的递推结果。因为跨象限后,圆弧的曲率方向变了,旧偏差值不适用。

我见过有人在这里偷懒,结果轨迹在象限边界上出现明显的折线。

终点判断——怎么知道走完了?

圆弧插补的终点判断比直线复杂。直线可以用总步数来判断,但圆弧的步数不是简单的 |ΔX| + |ΔY|,因为圆弧路径是弯曲的。

常用的终点判断方法有两种:

  1. 总步数法:预先算出圆弧上需要走的总步数 N = |Xₑ - X₀| + |Yₑ - Y₀|,每走一步减一,减到零就停。
  2. 坐标比较法:每走一步,判断当前坐标是否到达终点坐标。但要注意,由于圆弧是曲线,可能先经过终点坐标再偏离,所以一般配合一个容差范围。

我个人更推荐总步数法。原因很简单——可靠。坐标比较法在跨象限时容易误判,尤其是终点正好在象限边界上的情况。

终点判断的工程建议:

  • 总步数法:简单粗暴,不会漏判
  • 配合一个「超时保护」:如果步数走完了还没到终点附近,主动报错
  • 终点容差:一般设 0.5 个脉冲当量,防止因累积误差停在终点附近

完整流程——一张图说清楚

下面我把整个圆弧插补的流程画出来。你跟着走一遍,应该就全通了。

逐点比较法圆弧插补流程图 开始 初始化:起点坐标、终点坐标 象限判断、总步数 N 根据象限选择进给规则 计算偏差 F,判断 F ≥ 0? 是 否 沿规则方向进给 沿规则方向进给 更新坐标、偏差 F、步数 N N = N - 1 N = 0? 说明: 每走一步,先判断象限 再根据 F 值选方向

流程看着长,但实际跑起来很快。每一步就是几个整数加减法,加上一次象限判断。在几十微秒的控制周期里,完全够用。

一个完整的例子

咱们走一个具体的例子,你跟着算一遍就明白了。

参数:第一象限逆圆弧,圆心 (0,0),起点 (5,0),终点 (0,5),半径 R = 5。

步数 当前点 (X,Y) 偏差 F F 符号 进给方向 新坐标 新偏差
0 (5,0) 0 =0 -X (4,0) 0 - 2×5 + 1 = -9
1 (4,0) -9 <0 +Y (4,1) -9 + 2×0 + 1 = -8
2 (4,1) -8 <0 +Y (4,2) -8 + 2×1 + 1 = -5
3 (4,2) -5 <0 +Y (4,3) -5 + 2×2 + 1 = 0
4 (4,3) 0 =0 -X (3,3) 0 - 2×4 + 1 = -7
5 (3,3) -7 <0 +Y (3,4) -7 + 2×3 + 1 = 0
6 (3,4) 0 =0 -X (2,4) 0 - 2×3 + 1 = -5
7 (2,4) -5 <0 +Y (2,5) -5 + 2×4 + 1 = 4
8 (2,5) 4 >0 -X (1,5) 4 - 2×2 + 1 = 1
9 (1,5) 1 >0 -X (0,5) 1 - 2×1 + 1 = 0

走了 9 步,到达终点 (0,5)。你看,轨迹并不是完美的圆弧,而是一系列阶梯状的折线。这就是逐点比较法的特点——用折线逼近圆弧,步距越小,精度越高。

工程经验:

实际项目中,步距(脉冲当量)一般设 0.01mm 到 0.1mm。步距越小,轨迹越光滑,但插补频率要求越高。我一般根据电机最高转速和控制器算力来折中——别为了追求光滑把 CPU 跑满了,系统稳定性更重要。

常见坑点总结

最后,我把这些年踩过的坑列一下,你写代码时注意避开:

  • 象限切换时忘记重算偏差——轨迹在边界上出现折角
  • 顺圆和逆圆的进给方向搞反——圆弧往反方向画
  • 终点判断只用坐标比较——跨象限时可能永远到不了终点
  • 递推公式里的 2X 和 2Y 没同步更新——偏差越算越偏
  • 起点不在坐标轴上时,初始偏差没算对——第一步就偏了