4、圆弧插补算法详解:逐点比较法、DDA、角度逼近法、时间分割法

圆弧插补,说白了就是让刀具走出一个完美的圆弧。你想想看,数控系统里只有直线和圆弧两种基本轨迹,直线好办,但圆弧就有点讲究了。我这些年调试过的设备,十有八九的加工瑕疵都出在圆弧段。今天我把四种主流算法掰开揉碎了讲,都是实战中摸爬滚打出来的经验。

4.1 逐点比较法圆弧插补

这是最经典的方法,也是我入行时第一个学会的。它的核心思想就八个字:步步逼近,偏差判别

每次只走一步,走完就看看当前位置偏离圆弧有多远。偏内了就往外走,偏外了就往里走。就这么简单粗暴。

核心公式:

偏差判别:F = x² + y² - R²

F > 0:点在圆弧外,下一步向圆内走(-X 或 -Y)

F < 0:点在圆弧内,下一步向圆外走(+X 或 +Y)

举个例子,第一象限逆圆插补:

// 逐点比较法 - 第一象限逆圆
int x = 0, y = R;
int F = 0;  // 初始偏差

while (x <= y) {
    if (F >= 0) {
        // 点在圆弧外或圆弧上,向圆内走
        y--;
        F = F - 2*y + 1;
    } else {
        // 点在圆弧内,向圆外走
        x++;
        F = F + 2*x + 1;
    }
    // 输出插补点 (x, y)
}

我的经验:逐点比较法最大的优点是计算量小,适合老式单片机。但缺点也明显——速度不均匀。我在做雕刻机项目时发现,它在45度方向附近会明显抖动。后来加了速度前瞻才压下去。

4.2 DDA圆弧插补

DDA(数字微分分析器)法,说白了就是用积分的思想来走圆弧。它把圆弧运动分解成X和Y两个方向的速度分量,然后对时间积分。

为什么会这样?因为圆弧的参数方程是:

x = R * cos(θ)
y = R * sin(θ)

对时间求导,速度分量就是:

dx/dt = -R * sin(θ) = -y
dy/dt =  R * cos(θ) =  x

你看,X方向的速度和Y坐标有关,Y方向的速度和X坐标有关。这就是DDA的精髓——交叉积分

// DDA圆弧插补 - 第一象限逆圆
int x = R, y = 0;
int fx = 0, fy = 0;  // 积分累加器
int dt = 1;          // 时间步长

while (x >= 0 && y <= R) {
    fx += y;   // X方向积分
    fy += x;   // Y方向积分
    
    if (fx >= R) {
        x--;
        fx -= R;
    }
    if (fy >= R) {
        y++;
        fy -= R;
    }
    // 输出插补点 (x, y)
}

注意:DDA法有个坑——积分累加器会溢出。我曾经在16位单片机上吃过亏,R值一大,fx和fy就爆了。后来改用32位,或者做归一化处理才解决。

DDA法的好处是速度均匀,比逐点比较法平滑得多。但精度受积分步长限制,步长越小精度越高,计算量也越大。

4.3 角度逼近法

这个方法我是在做激光切割机时接触到的。它的思路很直接——把圆弧等分成小角度,然后直接算坐标

每次走一个固定角度Δθ,新的坐标就是:

x_new = R * cos(θ + Δθ)
y_new = R * sin(θ + Δθ)

但直接算三角函数太慢了,所以实际用的是递推公式:

x_new = x * cos(Δθ) - y * sin(Δθ)
y_new = x * sin(Δθ) + y * cos(Δθ)

你看,只要提前算好cos(Δθ)和sin(Δθ),后面全是乘加运算,快得很。

关键参数:

  • Δθ 越小,精度越高,但插补点数越多
  • 一般取 Δθ = 1° ~ 0.1°
  • 弦高误差:e ≈ R * (1 - cos(Δθ/2))
// 角度逼近法圆弧插补
float cos_dt = cos(0.1°);  // 预计算
float sin_dt = sin(0.1°);
float x = R, y = 0;

for (int i = 0; i < 900; i++) {  // 90度圆弧
    float x_new = x * cos_dt - y * sin_dt;
    float y_new = x * sin_dt + y * cos_dt;
    x = x_new;
    y = y_new;
    // 输出插补点 (x, y)
}

我的建议:角度逼近法最适合做高速圆弧插补。我在做PCB钻孔机时就用它,配合FPGA硬件加速,一个时钟周期就能算出一个点,速度拉满。

4.4 时间分割法

时间分割法,也叫数据采样插补。它是目前高档数控系统的主流方法。思路是:把时间切成小片,每片里走一段直线

说白了,就是用直线段去逼近圆弧。但关键是怎么切——不是等角度切,而是等时间切。

假设插补周期为T,进给速度为F,那么每步走的弧长就是:

ΔL = F * T

对应的角度变化:

Δθ = ΔL / R

然后就和角度逼近法一样递推了。但时间分割法更灵活,可以实时调整进给速度。

// 时间分割法圆弧插补
float T = 0.001;  // 插补周期 1ms
float F = 100;    // 进给速度 mm/s
float R = 50;     // 圆弧半径

float delta_L = F * T;
float delta_theta = delta_L / R;

float cos_dt = cos(delta_theta);
float sin_dt = sin(delta_theta);

float x = R, y = 0;
float theta = 0;

while (theta < PI/2) {
    float x_new = x * cos_dt - y * sin_dt;
    float y_new = x * sin_dt + y * cos_dt;
    x = x_new;
    y = y_new;
    theta += delta_theta;
    // 输出插补点 (x, y)
}

避坑指南:我曾经在时间分割法上栽过跟头——进给速度F和插补周期T不匹配,导致ΔL太大,圆弧变成了多边形。后来加了弦高误差校验,如果误差超限就自动加密插补点。

4.5 四种算法对比

算法 计算量 速度均匀性 精度 适用场景
逐点比较法 极小 中等 低端单片机、步进电机
DDA法 中等 中端数控、伺服系统
角度逼近法 中等 高速加工、激光切割
时间分割法 最好 最高 高档数控、多轴联动

选哪种?我的建议是:

  • 做玩具、小设备,用逐点比较法就够了
  • 做雕刻机、3D打印机,DDA法性价比最高
  • 做激光切割、高速铣床,上角度逼近法
  • 做五轴联动、精密加工,老老实实用时间分割法
圆弧插补算法分类与选型 圆弧插补算法 逐点比较法 DDA法 角度逼近法 时间分割法 计算量:极小 速度均匀性:差 精度:中等 适用:低端单片机 计算量:小 速度均匀性:好 精度:中等 适用:中端数控 计算量:中等 速度均匀性:好 精度:高 适用:高速加工 计算量:大 速度均匀性:最好 精度:最高 适用:高档数控 选型建议 玩具/小设备 → 逐点比较法 雕刻机/3D打印机 → DDA法 激光切割/高速铣床 → 角度逼近法 五轴联动/精密加工 → 时间分割法

嗯,四种算法就讲到这里。每种都有它的脾气,选对了事半功倍,选错了调试到哭。我个人建议,新手先从逐点比较法入手,理解偏差判别的思想,再逐步过渡到更高级的算法。一口吃不成胖子,做运动控制更是这样。

专注资料整理