4. 逐点比较法圆弧插补:偏差判别、进给方向与终点判别

各位同学,今天我们来聊聊圆弧插补。说实话,直线插补搞明白了,圆弧插补的思路其实是一脉相承的。但圆弧有个麻烦——它的轨迹是弯的,偏差怎么算?往哪个方向走?什么时候停?这三个问题,就是逐点比较法圆弧插补的核心。

我记得刚入行那会儿,带我的老师傅跟我说过一句话:「直线插补是走直线,圆弧插补是画圆圈,但本质上都是在『猜』下一步该往哪走。」当时觉得这话挺玄乎,后来自己写代码调机床才明白,还真是这么回事。

4.1 圆弧插补的偏差判别函数

先说说偏差怎么算。对于直线插补,我们用的是点到直线的距离。对于圆弧,道理类似——看当前点是在圆内、圆上,还是圆外。

假设我们要加工一段圆弧,起点是 A,终点是 B,圆心在原点 O(0,0),半径为 R。那么对于任意一个点 P(x, y),它到圆心的距离平方是:

F = x² + y² - R²

这个 F 就是偏差判别函数。它的含义很直观:

  • F = 0:点在圆弧上,完美
  • F > 0:点在圆外,离圆心远了
  • F < 0:点在圆内,离圆心近了

你想想看,这个公式是不是比直线插补还简单?直线插补好歹要算个叉积,圆弧插补直接平方和减半径平方就完事了。

核心要点:偏差判别函数 F = x² + y² - R²,决定了刀具当前位置与理想圆弧的位置关系。

4.2 进给方向与终点判别

偏差算出来了,下一步就是决定往哪走。这里有个关键问题:圆弧有四个象限,每个象限的进给方向都不一样。

我给大家画个图,这样更清楚:

X Y O 第一象限 第二象限 第三象限 第四象限 逆时针 逆时针 逆时针 逆时针

上面这张图展示了四个象限的圆弧走向。注意看,我这里画的是逆时针圆弧。顺时针的情况正好相反,这个后面会细说。

进给方向的规则是这样的:

象限 偏差 F 进给方向 说明
第一象限 F ≥ 0 -X 向圆内走
F < 0 +Y 向圆外走
第二象限 F ≥ 0 -Y 向圆内走
F < 0 -X 向圆外走
第三象限 F ≥ 0 +X 向圆内走
F < 0 -Y 向圆外走
第四象限 F ≥ 0 +Y 向圆内走
F < 0 +X 向圆外走

这个表格看着复杂,其实有个规律:F ≥ 0 时往圆内走,F < 0 时往圆外走。至于具体是哪个轴、正方向还是负方向,取决于当前在哪个象限。

我的小技巧:记不住的时候,就想想「F ≥ 0 往圆心方向走,F < 0 远离圆心方向走」。然后根据当前象限的坐标轴方向,自然就能推出进给方向了。

再说终点判别。这个和直线插补一样,用总步数来判断。假设起点到终点的 X 方向步数为 Nx,Y 方向步数为 Ny,那么总步数就是:

N = |Nx| + |Ny|

每走一步,N 减 1。当 N = 0 时,说明到达终点。

4.3 四象限圆弧插补实现

好了,理论讲完了,咱们上代码。我习惯用 Python 来验证算法,因为调试方便,逻辑看得清楚。

def arc_interpolation(start, end, center, clockwise=False):
    """
    逐点比较法圆弧插补
    start: 起点坐标 (xs, ys)
    end: 终点坐标 (xe, ye)
    center: 圆心坐标 (xc, yc)
    clockwise: True为顺时针,False为逆时针
    """
    # 计算半径
    R = ((start[0] - center[0])**2 + (start[1] - center[1])**2)**0.5
    
    # 当前点
    x, y = start[0], start[1]
    
    # 计算总步数
    dx = abs(end[0] - start[0])
    dy = abs(end[1] - start[1])
    total_steps = int(dx + dy)
    
    # 记录路径
    path = [(x, y)]
    
    for step in range(total_steps):
        # 计算偏差
        F = (x - center[0])**2 + (y - center[1])**2 - R**2
        
        # 判断象限
        if x >= center[0] and y >= center[1]:
            quadrant = 1
        elif x < center[0] and y >= center[1]:
            quadrant = 2
        elif x < center[0] and y < center[1]:
            quadrant = 3
        else:
            quadrant = 4
        
        # 根据象限和偏差决定进给方向
        if clockwise:
            # 顺时针
            if quadrant == 1:
                if F >= 0:
                    y -= 1  # -Y
                else:
                    x += 1  # +X
            elif quadrant == 2:
                if F >= 0:
                    x -= 1  # -X
                else:
                    y -= 1  # -Y
            elif quadrant == 3:
                if F >= 0:
                    y += 1  # +Y
                else:
                    x -= 1  # -X
            else:  # quadrant == 4
                if F >= 0:
                    x += 1  # +X
                else:
                    y += 1  # +Y
        else:
            # 逆时针
            if quadrant == 1:
                if F >= 0:
                    x -= 1  # -X
                else:
                    y += 1  # +Y
            elif quadrant == 2:
                if F >= 0:
                    y -= 1  # -Y
                else:
                    x -= 1  # -X
            elif quadrant == 3:
                if F >= 0:
                    x += 1  # +X
                else:
                    y -= 1  # -Y
            else:  # quadrant == 4
                if F >= 0:
                    y += 1  # +Y
                else:
                    x += 1  # +X
        
        path.append((x, y))
    
    return path

这段代码我实际跑过,效果还不错。不过要注意,这里用的是整数坐标,实际数控系统中也是用整数脉冲当量来计算的。

曾经踩过的坑:有一次我在调试四象限圆弧插补时,发现刀具在象限交界处会「抖」一下。查了半天,原来是象限判断的边界条件没处理好。比如在 X 轴上,x == center[0] 时应该归到哪个象限?我的建议是:统一归到上一个象限,或者单独处理边界情况。

4.4 实际应用中的注意事项

最后聊几个实际项目中容易遇到的问题:

  • 过象限问题:圆弧从一个象限跨越到另一个象限时,进给方向会突变。这时候要特别注意,别让刀具「愣」在那里。
  • 圆弧半径太小:如果半径小于一个脉冲当量,那圆弧就变成了一团「毛线」。我建议最小半径至少是 5 个脉冲当量。
  • 终点误差:逐点比较法走出来的圆弧,终点不一定正好落在目标点上。一般允许半个脉冲当量的误差。

嗯,关于逐点比较法圆弧插补,核心内容就这些。偏差判别函数、进给方向、终点判别,这三个东西搞明白了,圆弧插补也就拿下了。下次咱们聊聊更高效的插补方法——数字积分法。


公众号:蓝海资料掘金营,微信deep3321