Files
OrcaSlicer/doc/developer-reference/Axis_Component_Limits_Explained.md
xiaoyeliu b43cfaaaf9 2.2.0 flutter & WCP & Network Test (#54)
* Add docs about time_estimate

* Fix: Problems with graceful program exit caused by Flutter refactoring

* Add: sw_OpenBrowser() & sw_OpenOrcaWebview

* Fix: NetworkTestDialog Crash & Add: Lan Device test \ cloud test
2025-12-09 10:39:27 +08:00

8.6 KiB
Raw Blame History

轴向速度和加速度限制详解:斜向移动如何计算

核心问题

对于一条斜向G-code命令G1 X100 Y100 F6000,如何应用各轴的速度/加速度限制?

关键概念:分量 vs 合成

1. 速度的分解

位置: src/libslic3r/GCode/GCodeProcessor.cpp:2804-2824

// 计算每个轴的速度分量feedrate
for (unsigned char a = X; a <= E; ++a) {
    curr.axis_feedrate[a] = curr.feedrate * delta_pos[a] * inv_distance;
    // 这里计算的是每个轴的速度分量

    curr.abs_axis_feedrate[a] = std::abs(curr.axis_feedrate[a]);

    if (curr.abs_axis_feedrate[a] != 0.0f) {
        float axis_max_feedrate = get_axis_max_feedrate(..., static_cast<Axis>(a));
        if (axis_max_feedrate != 0.0f)
            min_feedrate_factor = std::min<float>(min_feedrate_factor,
                axis_max_feedrate / curr.abs_axis_feedrate[a]);
    }
}

// 如果有轴超限,按比例降低整体速度
curr.feedrate *= min_feedrate_factor;

详细示例:斜向移动

示例1: 45度对角线移动

G-code命令:

G1 X100 Y100 F6000

物理参数:

起点: (0, 0)
终点: (100, 100)
delta_X = 100mm
delta_Y = 100mm
距离 = √(100² + 100²) = 141.42mm
目标速度 = 6000 mm/min = 100 mm/s

步骤1: 计算各轴速度分量

inv_distance = 1 / 141.42 = 0.00707

// X轴速度分量
axis_feedrate[X] = 100 mm/s × 100mm × 0.00707
                 = 100 × 0.707
                 = 70.7 mm/s

// Y轴速度分量
axis_feedrate[Y] = 100 mm/s × 100mm × 0.00707
                 = 70.7 mm/s

// Z轴速度分量
axis_feedrate[Z] = 0 mm/s (Z移动)

// E轴速度分量假设挤出10mm
axis_feedrate[E] = 100 mm/s × 10mm × 0.00707
                 = 7.07 mm/s

物理意义:

  • 打印头沿对角线以100 mm/s移动
  • X轴方向的速度分量是70.7 mm/s
  • Y轴方向的速度分量是70.7 mm/s
  • 验证: √(70.7² + 70.7²) = 100 mm/s ✓

步骤2: 检查各轴速度限制

假设配置:

machine_max_speed_x = 500 mm/s
machine_max_speed_y = 500 mm/s
machine_max_speed_z = 12 mm/s
machine_max_speed_e = 120 mm/s

检查过程:

min_feedrate_factor = 1.0

// X轴检查
abs_axis_feedrate[X] = 70.7 mm/s
axis_max_feedrate[X] = 500 mm/s
70.7 < 500  不需要降速
factor = 500 / 70.7 = 7.07
min_feedrate_factor = min(1.0, 7.07) = 1.0

// Y轴检查
abs_axis_feedrate[Y] = 70.7 mm/s
axis_max_feedrate[Y] = 500 mm/s
70.7 < 500  不需要降速
min_feedrate_factor = min(1.0, 7.07) = 1.0

// E轴检查
abs_axis_feedrate[E] = 7.07 mm/s
axis_max_feedrate[E] = 120 mm/s
7.07 < 120  不需要降速
min_feedrate_factor = min(1.0, 16.97) = 1.0

结果: min_feedrate_factor = 1.0所有轴都不超限保持100 mm/s

步骤3: 应用降速(如果需要)

curr.feedrate *= min_feedrate_factor;  // 100 × 1.0 = 100 mm/s

示例2: Z轴限制导致降速

场景: 斜向上移动

G-code命令:

G1 X100 Y100 Z20 F6000

物理参数:

delta_X = 100mm
delta_Y = 100mm
delta_Z = 20mm
距离 = √(100² + 100² + 20²) = 144.57mm
目标速度 = 100 mm/s

计算各轴速度分量

inv_distance = 1 / 144.57 = 0.00692

axis_feedrate[X] = 100 × 100 × 0.00692 = 69.2 mm/s
axis_feedrate[Y] = 100 × 100 × 0.00692 = 69.2 mm/s
axis_feedrate[Z] = 100 × 20 × 0.00692 = 13.84 mm/s  ⚠️

检查Z轴限制

// Z轴检查
abs_axis_feedrate[Z] = 13.84 mm/s
axis_max_feedrate[Z] = 12 mm/s
13.84 > 12  超限!

// 计算需要降速的因子
factor = 12 / 13.84 = 0.867
min_feedrate_factor = min(1.0, 0.867) = 0.867

应用降速

// 降低整体速度
curr.feedrate *= 0.867
curr.feedrate = 100 × 0.867 = 86.7 mm/s

// 重新计算各轴速度分量
axis_feedrate[X] = 69.2 × 0.867 = 60.0 mm/s
axis_feedrate[Y] = 69.2 × 0.867 = 60.0 mm/s
axis_feedrate[Z] = 13.84 × 0.867 = 12.0 mm/s   刚好等于限制

// 验证
(60² + 60² + 12²) = 86.7 mm/s 

结果: 由于Z轴限制12 mm/s整体速度从100降到86.7 mm/s

加速度的分量计算(完全相同的逻辑)

位置: GCodeProcessor.cpp:2834-2838

for (unsigned char a = X; a <= E; ++a) {
    float axis_max_acceleration = get_axis_max_acceleration(..., static_cast<Axis>(a));

    // 计算这个轴的加速度分量
    float axis_acceleration_component = acceleration × |delta_pos[a]| × inv_distance;

    if (axis_acceleration_component > axis_max_acceleration)
        // 降低整体加速度以满足这个轴的限制
        acceleration = axis_max_acceleration / (|delta_pos[a]| × inv_distance);
}

示例3: E轴加速度限制

场景: 高挤出率的打印移动

G1 X50 Y50 E25 F3000

参数:

delta_X = 50mm
delta_Y = 50mm
delta_E = 25mm
距离 = √(50² + 50² + 25²) = 75mm
速度 = 50 mm/s
初始加速度 = 20000 mm/s²
E轴最大加速度 = 5000 mm/s²

计算E轴加速度分量

inv_distance = 1/75 = 0.01333

// E轴加速度分量
E_accel_component = 20000 × 25 × 0.01333
                  = 20000 × 0.3333
                  = 6666.7 mm/s²

// 检查E轴限制
6666.7 > 5000  超限!

// 调整整体加速度
acceleration = 5000 / (25 × 0.01333)
             = 5000 / 0.3333
             = 15000 mm/s²

结果:

  • 初始加速度20000被降到15000
  • E轴分量刚好是5000 mm/s²
  • X、Y轴分量相应降低

可视化理解

速度矢量分解

对于 G1 X100 Y100 F6000 (100 mm/s)

         Y轴
         ↑
         │ 70.7 mm/s
         │
         │      合成速度
         │    100 mm/s
         │╱
    ─────┼──────────→ X轴
         │  70.7 mm/s
         │

合成速度 = √(Vx² + Vy²) = √(70.7² + 70.7²) = 100 mm/s

如果X轴限制为50 mm/s

原始:
Vx = 70.7 mm/s  > 50 ✗ 超限!

降速因子:
factor = 50 / 70.7 = 0.707

降速后:
Vx = 70.7 × 0.707 = 50 mm/s   ✓
Vy = 70.7 × 0.707 = 50 mm/s   ✓
合成 = √(50² + 50²) = 70.7 mm/s

         Y轴
         ↑
         │ 50 mm/s
         │
         │    70.7 mm/s (降速后)
         │╱
    ─────┼──────────→ X轴
         │ 50 mm/s

关键理解

1. 限制的是分量

轴向速度限制检查的是:

  • 每个轴的速度分量
  • 不是合成速度

例子:

G1 X100 Y100 F10000 (合成速度166.7 mm/s)

即使合成速度很高,但如果:
- X轴分量 = 118 mm/s < 500 (X轴限制)
- Y轴分量 = 118 mm/s < 500 (Y轴限制)

则不会降速!

2. 保持方向不变

降速时:

  • 所有轴按相同比例降速
  • 保持移动方向不变
  • 只改变速度大小
原始: (Vx, Vy, Vz) = (70.7, 70.7, 13.84)
降速: (Vx, Vy, Vz) = (60.0, 60.0, 12.0)  ← 都乘以0.867
方向: Vx:Vy:Vz = 70.7:70.7:13.84 = 60:60:12  ✓ 方向不变

3. 找最严格的限制

min_feedrate_factor = 1.0

for each axis:
    if (轴分量 > 轴限制)
        factor = 轴限制 / 轴分量
        min_feedrate_factor = min(min_feedrate_factor, factor)

// 使用最小的factor最严格的限制
速度 *= min_feedrate_factor

实际例子:打印一条线

G-code

G1 X0 Y0 Z0.2 E0
G1 X100 Y50 Z0.2 E5 F3000

第二条命令分析

移动参数:

delta_X = 100mm
delta_Y = 50mm
delta_Z = 0mm
delta_E = 5mm
距离 = √(100² + 50²) = 111.8mm
目标速度 = 3000 mm/min = 50 mm/s

速度分量:

inv_distance = 1/111.8 = 0.00894

Vx = 50 × 100 × 0.00894 = 44.7 mm/s
Vy = 50 × 50 × 0.00894 = 22.35 mm/s
Vz = 0 mm/s
Ve = 50 × 5 × 0.00894 = 2.24 mm/s

检查限制(假设标准配置):

Vx = 44.7 < 500 ✓
Vy = 22.35 < 500 ✓
Vz = 0 < 12 ✓
Ve = 2.24 < 120 ✓

所有轴都不超限保持50 mm/s

如果降低Z轴限制到1 mm/s(极端例子):

即使Vz = 0也不受影响因为没有Z移动
只有当有Z移动时Z轴限制才起作用

总结

关键点

  1. 限制的是分量,不是合成速度
  2. 分量 = 合成速度 × (轴移动量 / 总距离)
  3. 降速保持方向,所有轴同比例降速
  4. 最严格限制决定最终速度

计算公式

轴速度分量 = 合成速度 × (delta_轴 / 总距离)

如果 轴速度分量 > 轴限制:
    降速因子 = 轴限制 / 轴速度分量
    合成速度 *= 降速因子

同样适用于加速度!

物理意义

这个设计确保:

  • 每个轴的电机不超过物理限制
  • 移动方向始终正确
  • 在满足所有限制的前提下尽可能快

这就是为什么即使是斜向移动,各轴的速度/加速度限制仍然有效!