逐点比较法(二):逐点比较法圆弧插补、象限处理、终点判断
上一章我们聊了直线插补,这次轮到圆弧了。说实话,圆弧插补比直线要绕一点——不是技术上的难,而是逻辑上多了个象限判断。我刚开始做运动控制时,就在象限处理上栽过跟头。嗯,今天咱们把它彻底讲透。
圆弧插补的基本思路
逐点比较法做圆弧插补,核心思想还是那个老套路:每走一步,算一下当前位置相对于理想圆弧的偏差,然后决定下一步往哪走。
你想想看,圆弧和直线最大的区别是什么?直线只有一个方向偏差,圆弧却有两个——半径偏差和角度位置。说白了,我们要判断当前点是在圆弧内侧还是外侧。
核心公式:
设圆心在原点,圆弧起点为 (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|,因为圆弧路径是弯曲的。
常用的终点判断方法有两种:
- 总步数法:预先算出圆弧上需要走的总步数 N = |Xₑ - X₀| + |Yₑ - Y₀|,每走一步减一,减到零就停。
- 坐标比较法:每走一步,判断当前坐标是否到达终点坐标。但要注意,由于圆弧是曲线,可能先经过终点坐标再偏离,所以一般配合一个容差范围。
我个人更推荐总步数法。原因很简单——可靠。坐标比较法在跨象限时容易误判,尤其是终点正好在象限边界上的情况。
终点判断的工程建议:
- 总步数法:简单粗暴,不会漏判
- 配合一个「超时保护」:如果步数走完了还没到终点附近,主动报错
- 终点容差:一般设 0.5 个脉冲当量,防止因累积误差停在终点附近
完整流程——一张图说清楚
下面我把整个圆弧插补的流程画出来。你跟着走一遍,应该就全通了。
流程看着长,但实际跑起来很快。每一步就是几个整数加减法,加上一次象限判断。在几十微秒的控制周期里,完全够用。
一个完整的例子
咱们走一个具体的例子,你跟着算一遍就明白了。
参数:第一象限逆圆弧,圆心 (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 没同步更新——偏差越算越偏
- 起点不在坐标轴上时,初始偏差没算对——第一步就偏了