逐点比较法直线插补:偏差函数推导
各位同学,今天我们来聊聊直线插补里最经典的方法——逐点比较法。
这个方法,说白了就是让刀具一步一步走,每走一步都问自己一句:「我走偏了没?」
如果偏了,就赶紧纠正方向。就这么简单。
我在刚入行那会儿,第一次接触数控系统,看到「逐点比较」四个字,还以为是让刀具和图纸比来比去。后来才明白,它比的是「当前位置」和「理想直线」之间的偏差。
偏差函数的由来
假设我们要从起点 O(0,0) 走到终点 A(Xe, Ye)。
这条直线的方程是:
Y / X = Ye / Xe
整理一下:
Y * Xe - X * Ye = 0
现在,假设刀具走到了点 P(Xi, Yi)。
我们把 P 点的坐标代入上面的式子:
Fi = Yi * Xe - Xi * Ye
这个 Fi 就是偏差函数。
你想想看,如果 P 点在直线上,Fi 就等于 0。
如果 P 点在直线上方,Fi 大于 0。
如果 P 点在直线下方,Fi 小于 0。
嗯,这里要注意:我们说的「上方」和「下方」,是相对于直线的方向而言的。
核心结论:
- Fi = 0 → 点在直线上
- Fi > 0 → 点在直线上方
- Fi < 0 → 点在直线下方
我在项目中遇到过一个问题:有同事直接用浮点数计算 Fi,结果在长距离插补时累积了误差。我建议用整数运算,把 Xe 和 Ye 都放大到脉冲当量的整数倍,这样既快又准。
进给方向判定规则
有了偏差函数,下一步就是决定刀具往哪个方向走。
规则其实很直观:
- 如果 Fi ≥ 0:说明刀具在直线上方(或正好在线上),下一步应该向 X 正方向走一步,让刀具靠近直线。
- 如果 Fi < 0:说明刀具在直线下方,下一步应该向 Y 正方向走一步,把刀具拉回来。
说白了,就是「偏上就走 X,偏下就走 Y」。
我刚开始学的时候,总觉得这个规则是不是反了?后来画了个图才明白:
你想,如果刀具在直线上方,说明 Y 方向走多了,那就应该往 X 方向走走,把比例拉回来。
我的小技巧:
判断进给方向时,别死记硬背。你就在纸上画一条斜线,再画一个偏离的点,然后问自己:「如果我想让这个点回到线上,应该往哪个方向走一步?」答案自然就出来了。
不同象限的处理
上面说的是第一象限的情况。其他象限呢?
其实原理一样,只是方向不同。我整理了一个表格:
| 象限 | Fi ≥ 0 进给方向 | Fi < 0 进给方向 |
|---|---|---|
| 第一象限 | +X | +Y |
| 第二象限 | -X | +Y |
| 第三象限 | -X | -Y |
| 第四象限 | +X | -Y |
我曾经在调试四轴联动时,因为象限判断写错了,导致刀具在第三象限画出了一条反向的弧线。那次排查花了我整整一个下午。所以,象限判断一定要仔细。
终点判别方法
刀具一步一步走,什么时候停下来?
这就是终点判别要做的事。
常用的方法有三种:
方法一:总步数法
这是我最喜欢用的方法,简单可靠。
总步数 N = |Xe| + |Ye|
每走一步,N 减 1。当 N = 0 时,到达终点。
// 伪代码示例
int totalSteps = abs(Xe) + abs(Ye);
while (totalSteps > 0) {
// 计算偏差,决定进给方向
// 走一步
totalSteps--;
}
优点:计算量小,不需要比较坐标值。
缺点:如果中途有急停或回退,步数会乱。
方法二:坐标比较法
每次走完后,比较当前坐标和终点坐标。
如果 Xi == Xe 且 Yi == Ye,就停止。
这个方法直观,但要注意:浮点数比较时容易出问题。我建议用整数坐标,或者设定一个很小的容差范围。
注意:坐标比较法在圆弧插补中更常用。直线插补时,我一般用总步数法,因为更高效。
方法三:偏差值判别法
当 Fi 连续多次为 0 时,认为到达终点。
这个方法我不太推荐。因为如果直线斜率很陡,刀具可能在终点附近来回振荡,导致误判。
我曾经在一个老系统上见过这种问题,后来改成总步数法就解决了。
核心逻辑流程图
下面我用 SVG 画了一张流程图,把整个逐点比较法的逻辑串起来:
这张图把整个流程串起来了。你仔细看,其实就是一个循环:判断偏差 → 决定方向 → 走一步 → 更新偏差 → 判断终点。
我在教徒弟的时候,总让他们先把这个流程图背下来。因为只要流程图记住了,代码怎么写都错不了。
避坑指南:
我曾经在写终点判断时,把总步数 N 的初始值算错了。原因是忘了取绝对值。记住:总步数 = |Xe| + |Ye|,坐标值一定要取绝对值。
好了,逐点比较法直线插补的核心内容就这些。偏差函数告诉你偏没偏,进给规则告诉你怎么纠偏,终点判断告诉你什么时候停。三个环节环环相扣,缺一不可。
下次我们聊圆弧插补时,你会发现思路是类似的,只是偏差函数换了个形式。