插补:机头走斜线或弧线时,需要 XY 同时到达某个点,就得需要 X 走一点 Y 走一点,这个算法过程就是 插补
所有插补算法推演只在第一象限,软件点数据密化放大数据后,会与直线/圆弧重合
1、逐步对比法直线插补
前置知识:
1 | F>=0 F=F-|Y| |

$$
A(0,0) \ \ \ \ \ B(6,4)
$$
- 一开始要求得终点步骤,根据X与Y值,可以看出最多需要移动6+4次到达终点,所以终点判断为10
- 偏差判别是当前位置处于大于等于0的区域还是小于等于0的区域,如果是处于大于等于0的区域,可以看出来,此时需要X增加一步,才能趋于终点,如果当前位置处于小于0的区域,此时需要Y增加一步,那么映射到现实中,就是机器XY轴各向前动了一个脉冲,最终不断的交替运动到达终点
- 坐标给进就是偏差判别后的进步标志位,决定当前步骤X或Y哪一个前进
- 偏差计算就是根据上面的公式,以及当前坐标所在位置,计算出下一步的XY坐标给进
- 首先当前坐标肯定位于起点A(0,0),根据偏差判别,此时需要X进一步,则坐标给进+X,此时F>=0,偏差计算代入
F>=0 F=F-|Y|,F减去终点坐标Y值,得到下一次的偏差,此时完成一步,终点判断减去1。下一次再根据偏差判别进行 坐标给进与偏差计算,往复循环,直到终点判断为0,偏差计算的步数也来到了B(6,4) - 根据坐标给进,依次按一格坐标移动XY,即可得到插补路径
- 如果坐标不在0点?在其他象限?把起点作为0点映射计算,然后再转换回去就行
| 步数 | 偏差判别 | 坐标给进 | 偏差计算 | 终点判断 |
|---|---|---|---|---|
| 0 | F(0,0) = 0 | E=6+4 =10 | ||
| 1 | F(0,0)>=0 | +X | F(1,0)= 0-4 = -4 | E=9 |
| 2 | F(1,0)<0 | +Y | F(1,1)= -4+6 = 2 | E=8 |
| 3 | F(1,1)>=0 | +X | F(2,1)= 2-4 = -2 | E=7 |
| 4 | F(2,1)<0 | +Y | F(2,2)= -2+6 = 4 | E=6 |
| 5 | F(2,2)>=0 | +X | F(3,2)= 4-4 = 0 | E=5 |
| 6 | F(3,2)>=0 | +X | F(4,2)= 0-4 = -4 | E=4 |
| 7 | F(4,2)<0 | +Y | F(4,3)= -4+6 = 2 | E=3 |
| 8 | F(4,3)>=0 | +X | F(5,3)= 2-4 = -2 | E=2 |
| 9 | F(5,3)<0 | +Y | F(5,4)= -2+6 = 4 | E=1 |
| 10 | F(5,4)>=0 | +X | F(6,4)= 4-4 = 0 | E=0 |
根据计算过程可以整理参考简单伪代码如下
1 | comparedLine() |
2、逐步对比法圆弧插补
前置知识:
$$
F>=0 \ \ \ \ \ \ F=F-2|Y|+1
\F<0 \ \ \ \ \ \ F=F+2|X|+1
\ 一象限顺时针,二象限逆,三象限顺,四象限逆
\
\F>=0 \ \ \ \ \ \ F=F-2|X|+1
\F<0 \ \ \ \ \ \ F=F+2|Y|+1
\一象限逆时针,二象限顺,三象限逆,四象限顺
\公式中的XY为终点坐标XY
$$

$$
A(0,5) \ \ \ \ \ B(5,0)
$$
- 一开始要求得终点步骤,根据X与Y值,可以看出最多需要移动5+5次到达终点,所以终点判断为10
- 偏差判别是当前位置处于大于等于0的区域还是小于等于0的区域,如果是处于大于等于0的区域,可以看出来,此时需要Y减少一步,才能趋于终点,如果当前位置处于小于0的区域,此时需要X增加一步,那么映射到现实中,就是机器XY轴各向前动了一个脉冲,最终不断的交替运动到达终点
- 坐标给进就是偏差判别后的进步标志位,决定当前步骤X或Y哪一个前进
- 偏差计算就是根据上面的公式,以及当前坐标所在位置,计算出下一步的XY坐标给进
- 首先当前坐标肯定位于起点A(0,5),根据偏差判别,此时需要Y退后一步,则坐标给进-Y,此时F>=0,显然这是个顺时针,偏差计算代入
F>=0 F=F-2|Y|+1,得到下一次的偏差,此时完成一步,终点判断减去1。下一次再根据偏差判别进行 坐标给进与偏差计算,往复循环,直到终点判断为0,偏差计算的步数也来到了B(5,0) - 根据坐标给进,依次按一格坐标移动XY,即可得到插补路径
| 步数 | 偏差判别 | 坐标给进 | 偏差计算 | 坐标计算 | 终点判断 |
|---|---|---|---|---|---|
| 0 | F(0,0) = 0 | x=0,y=5 | E=5+5 =10 | ||
| 1 | F(0,0)>=0 | -Y | F(1,0)= 0-2*5+1 = -9 | x=0,y=4 | E=9 |
| 2 | F(1,0)<0 | +X | F(1,1)= -9+2*0+1 = -8 | x=1,y=4 | E=8 |
| 3 | F(1,1)<0 | +X | F(2,1)= -8+2*1+1 = -5 | x=2,y=4 | E=7 |
| 4 | F(2,1)<0 | +X | F(2,2)= -5+2*2+1 = 0 | x=3,y=4 | E=6 |
| 5 | F(2,2)>=0 | -Y | F(3,2)= 0-2*4+1 = -7 | x=3,y=3 | E=5 |
| 6 | F(3,2)<0 | +X | F(4,2)= -7+6+1 = 0 | x=4,y=3 | E=4 |
| 7 | F(4,2)>=0 | -Y | F(4,3)= 0-6+1 = -5 | x=4,y=2 | E=3 |
| 8 | F(4,3)<0 | +X | F(5,3)= -5+8+1 = 4 | x=5,y=2 | E=2 |
| 9 | F(5,3)>=0 | -Y | F(5,4)= 4-4+1 = 1 | x=5,y=1 | E=1 |
| 10 | F(5,4)>=0 | -Y | F(6,4)= 1-2*1+1 = 0 | x=5,y=0 | E=0 |
根据计算过程可以整理参考简单伪代码如下
1 | comparedLine() |
3、数字积分法直线插补
前置知识:
- 累加寄存器:数字积分法的操作就是将路程分割
n份,每 周期 累加一份,如果 溢出 就进给。一般溢出值就是单位1 - 因为实际运用问题,机器在存储数据时是采用二进制的形式。为了节省空间和加快运算,Max是多少,就采用多少位的 累加器 运算。也就是2^n-1,能放得下即可。比如终点E(7,5),Max为7,采用三位(最大可存8)累加器计算。所以分割份数m总是2的次方,而且列表时也不写十进制,而是写二进制。

$$
A(0,0) \ \ \ \ \ B(7,5)
$$
- ```c
- 此计算分为X积分器,Y积分器
- X积分器包括√vX、√rX、ΔX
- X积分器包括√vY、√rY、ΔY
- √vX保存终点的X坐标,√vY保存终点的Y坐标
- √rX为 √rX=√vX+√rX ,当√rX运算累计值大于累加器值,视为溢出,使用累加器值减去√rX再赋值给√rX,同时ΔX因为累加器溢出+1
- √rY为 √rY=√vY+√rY ,当√rY运算累计值大于累加器值,视为溢出,使用累加器值减去√rY再赋值给√rY,同时ΔY因为累加器溢出+1
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
- 一开始确定累加器,Max是多少,就采用多少位的 累加器 运算,比如终点B(7,5),Max为7,采用三位(最大可存8)累加器计算,即2^3=8
- 在√vX保存终点的X坐标111(7),√vY保存终点的Y坐标101(5),其余都为0
- 然后开始计算,√rX与√rY固定不变,√rX=√vX+√rX,√rY=√vY+√rY,√rX或√rY如果任一超过累加器,视为溢出,使用累加器值减去√rX、√rY再赋值给√rX、√rY,同时ΔX、ΔY因为累加器溢出+1
[^如 ]: 111+111 > 2^3 -> 7+7-8 = 6 =110
- 往复循环,直到√rX与√rY都加上111减去累加器为0,当前位置也来到了B(7,5)
- 根据ΔX、ΔY的值变化,依次按一格坐标移动XY,即可得到插补路径
| 步数 | √vX | √rX | ΔX | √vY | √rY | ΔY |
| ---- | :--: | :------------: | :--: | :--: | :--: | :--: |
| 0 | 111 | 0 | 0 | 101 | 0 | 0 |
| 1 | 111 | 111(111+0) | 0 | 101 | 101 | 0 |
| 2 | 111 | 110(111+111) | 1 | 101 | 010 | 1 |
| 3 | 111 | 101(111+110) | 1 | 101 | 111 | 0 |
| 4 | 111 | 100(111+101) | 1 | 101 | 100 | 1 |
| 5 | 111 | 011(111+100) | 1 | 101 | 001 | 1 |
| 6 | 111 | 010(111+011) | 1 | 101 | 110 | 0 |
| 7 | 111 | 001(111+010) | 1 | 101 | 011 | 1 |
| 8 | 111 | 000(111+001) | 1 | 101 | 000 | 1 |
根据计算过程可以整理参考简单伪代码如下
```c
ddaLine()
{
int vx, vy, rx=0, ry = 0;
int dx=0, dy=0;
float x, y = 0.0;
x += start.x();
y += start.y();
dx = end.x() - start.x();
dy = end.y() - start.y();
vx = abs(end.x() - start.x());
vy = abs(end.y() - start.y());
rx += vx;
ry += vy;
int max_val = max(abs(vx), abs(vy));
// 数控技术中,对于分割数m牵扯到 寄存器 的概念。
// 也就是2^n-1,能放得下即可 比如终点(7,5),max为7,采用三位8累加器计算。
int acc = 1;
while (acc < max_val) {
acc <<= 1; // 左移一位,相当于乘以2
}
draw(x, y);
for (int i = 0; i < acc; i++) {
rx += vx;
ry += vy;
if (rx >= acc) {
x++;
rx -= acc;
}
if (ry >= acc) {
y--;
ry -= acc;
}
draw(x, y);
}
}
4、数字积分法圆弧插补
前置知识:
累加寄存器:数字积分法的操作就是将路程分割
n份,每 周期 累加一份,如果 溢出 就进给。一般溢出值就是单位1因为实际运用问题,机器在存储数据时是采用二进制的形式。为了节省空间和加快运算,Max是多少,就采用多少位的 累加器 运算。也就是2^n-1,能放得下即可。比如终点E(7,5),Max为7,采用三位(最大可存8)累加器计算。所以分割份数m总是2的次方,而且列表时也不写十进制,而是写二进制。

1 | $$ |
1 | 此计算分为X积分器,Y积分器 |
一开始确定累加器,Max是多少,就采用多少位的 累加器 运算,比如终点B(0,5),Max为5,采用三位(最大可存8)累加器计算,即2^3=8
在√vX保存起点的Y坐标0,√vY保存起点的X坐标101(5),Ex与Ey为步数5
然后开始计算,√rX=√vX+√rX,√rY=√vY+√rY,√rX或√rY如果任一超过累加器,视为溢出,使用累加器值减去√rX、√rY再赋值给√rX、√rY,同时ΔX因溢出-1时√vY-1,ΔY因溢出+1时√vX+1
往复循环,直到Ex与Ey都为0,当前位置也来到了B(0,5)
根据√rX、√rY的值变化,依次按一格坐标移动XY,即可得到插补路径
| 步数 | √vX | √rX | ΔX | Ex | √vY | √rY | ΔY | Ey |
|---|---|---|---|---|---|---|---|---|
| 0 | 000 | 000 | 0 | 101 | 101 | 0 | 0 | 101 |
| 1 | 000 | 000 | 0 | 101 | 101 | 101 | 0 | 101 |
| 2 | 000 | 000 | 0 | 101 | 101 | 010 | 1 | 100 |
| 001(Ey) | ||||||||
| 3 | 001 | 001 | 0 | 101 | 101 | 111 | 0 | 100 |
| 4 | 001 | 010 | 0 | 101 | 101 | 100 | 1 | 011 |
| 010(Ey) | ||||||||
| 5 | 010 | 100 | 0 | 101 | 101 | 001 | 1 | 010 |
| 011(Ey) | ||||||||
| 6 | 011 | 111 | 0 | 101 | 101 | 110 | 0 | 010 |
| 7 | 011 | 010 | -1 | 100 | 101 | 011 | 1 | 001 |
| 100(Ey) | 100(Ex) | |||||||
| 8 | 100 | 110 | 0 | 100 | 100 | 111 | 0 | 001 |
| 9 | 100 | 010 | -1 | 100 | 100 | 011 | 1 | 000 |
| 101(Ey) | 011(Ex) | |||||||
| 10 | 101 | 111 | 0 | 011 | 011 | |||
| 11 | 101 | 100 | -1 | 010 | 011 | |||
| 010(Ex) | ||||||||
| 12 | 101 | 001 | -1 | 001 | 010 | |||
| 13 | 101 | 110 | 0 | 001 | 001 | |||
| 14 | 101 | 011 | -1 | 000 | 000 |
根据计算过程可以整理参考简单伪代码如下
1 | ddaCircle() |