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
This commit is contained in:
xiaoyeliu
2025-12-09 10:39:27 +08:00
committed by GitHub
parent f32aa81f6a
commit b43cfaaaf9
13 changed files with 4256 additions and 39 deletions

View File

@@ -0,0 +1,539 @@
# 时间预估补充问题分析
> **文档版本**: v1.0
> **创建日期**: 2025-12-06
> **问题来源**: M109/M190时间预估修复方案的补充问题
---
## 问题1挤出最大加速度 vs E最大加速度的区别
### 1.1 配置参数定义
**位置**: `src/libslic3r/PrintConfig.cpp:3640-3682``3734-3744`
#### machine_max_acceleration_eE轴最大加速度
```cpp
// Line 3666: 通过循环自动生成 machine_max_acceleration_e
def = this->add("machine_max_acceleration_" + axis.name, coFloats);
// 对于E轴
// - 默认值:{ 5000., 5000. } mm/s²
// - 对应固件命令M201 E5000
// - 定义E轴电机的最大加速度
```
**说明**:
- **物理含义**: E轴挤出机电机的硬件物理限制
- **固件命令**: `M201 E5000` - 设置E轴最大加速度
- **作用范围**: 限制E轴电机本身的加速度无论是打印、回抽还是其他动作
- **默认值**: 5000 mm/s²非常高因为E轴质量小电机响应快
#### machine_max_acceleration_extruding挤出时最大加速度
```cpp
// Line 3734
def = this->add("machine_max_acceleration_extruding", coFloats);
def->full_label = L("Maximum acceleration for extruding");
def->tooltip = L("Maximum acceleration for extruding (M204 P)");
def->set_default_value(new ConfigOptionFloats{ 1500., 1250. });
```
**说明**:
- **物理含义**: 打印移动(挤出动作)时的最大加速度限制
- **固件命令**: `M204 P1500` - 设置打印时最大加速度
- **作用范围**: 仅限于打印移动extrusion moves即XYZ+E同时移动的情况
- **默认值**: 1500 mm/s²比E轴最大加速度低很多
### 1.2 核心区别
| 特性 | machine_max_acceleration_e | machine_max_acceleration_extruding |
|-----|---------------------------|-----------------------------------|
| **固件命令** | M201 E5000 | M204 P1500 |
| **作用对象** | E轴电机 | 打印移动XYZ+E |
| **物理含义** | 电机硬件限制 | 打印质量限制 |
| **默认值** | 5000 mm/s² | 1500 mm/s² |
| **影响范围** | E轴所有动作 | 仅打印时 |
| **限制原因** | 电机性能 | 打印质量、振动、层粘合 |
### 1.3 为什么extruding加速度更低
1. **打印质量考虑**
- 高加速度会导致振动ringing/ghosting
- 影响外壁质量和尺寸精度
- 可能导致层间粘合问题
2. **机械限制**
- XYZ轴移动的惯性更大
- 打印头/打印床的质量较大
- 需要考虑整机的刚性
3. **挤出一致性**
- 高加速度会导致挤出量不均匀
- 影响压力提前pressure advance效果
- 可能产生过挤/欠挤
### 1.4 在时间预估中的使用
**位置**: `src/libslic3r/GCode/GCodeProcessor.cpp`
```cpp
// Line 1002-1014: 加载配置
const ConfigOptionFloats* max_acceleration_extruding =
config.option<ConfigOptionFloats>("machine_max_acceleration_extruding");
if (max_acceleration_extruding != nullptr)
m_time_processor.machine_limits.machine_max_acceleration_extruding.values =
max_acceleration_extruding->values;
// E轴加速度通过循环加载Line 1028-1042中的类似代码
```
**使用场景**:
- **machine_max_acceleration_e**: 在jerk计算时限制E轴的加速度
- **machine_max_acceleration_extruding**: 在打印移动时作为加速度上限
---
## 问题2Jerk如何影响预估时间的计算
### 2.1 Jerk的定义
**Jerk加加速度**: 加速度的变化率,单位 mm/s
在3D打印中jerk实际上被用作**瞬时速度变化的限制**,而不是严格意义上的加加速度。
### 2.2 Jerk配置参数
**位置**: `src/libslic3r/PrintConfig.cpp:3684-3700`
```cpp
def = this->add("machine_max_jerk_" + axis.name, coFloats);
// 默认值:
// X轴10 mm/s
// Y轴10 mm/s
// Z轴0.2 mm/s很小因为Z轴移动慢
// E轴2.5 mm/s
```
**对应固件命令**: `M205 X10 Y10 Z0.2 E2.5`
### 2.3 Jerk在时间预估中的作用
**位置**: `src/libslic3r/GCode/GCodeProcessor.cpp:2845-2929`
#### 作用1: 限制安全速度Safe Feedrate
```cpp
// Line 2845-2849
for (unsigned char a = X; a <= E; ++a) {
float axis_max_jerk = get_axis_max_jerk(..., static_cast<Axis>(a));
if (curr.abs_axis_feedrate[a] > axis_max_jerk)
curr.safe_feedrate = std::min(curr.safe_feedrate, axis_max_jerk);
}
```
**含义**:
- 每个轴的移动速度不能超过该轴的jerk限制
- 如果某个轴的速度超过jerk降低整体移动的安全速度
- 这是**单轴独立限制**
#### 作用2: 计算连接速度Junction Velocity
```cpp
// Line 2873-2884: 计算XYZ轴的jerk向量
Vec3f entry_v = block.feedrate_profile.cruise * (curr.enter_direction);
Vec3f exit_v = prev.feedrate * (prev.exit_direction);
Vec3f jerk_v = entry_v - exit_v; // 速度变化向量
jerk_v = Vec3f(abs(jerk_v.x()), abs(jerk_v.y()), abs(jerk_v.z()));
Vec3f max_xyz_jerk_v = get_xyz_max_jerk(...);
// 检查是否超过jerk限制
for (size_t i = 0; i < 3; i++) {
if (jerk_v[i] > max_xyz_jerk_v[i]) {
v_factor *= max_xyz_jerk_v[i] / jerk_v[i]; // 计算降速系数
limited = true;
}
}
```
**含义**:
- 计算从上一个移动到当前移动的速度变化
- 如果速度变化超过jerk限制降低连接速度
- 这是**XYZ组合限制**
#### 作用3: E轴独立jerk计算
```cpp
// Line 2901-2921: 计算E轴的jerk
float jerk = (v_exit > v_entry) ?
(((v_entry > 0.0f) || (v_exit < 0.0f)) ?
(v_exit - v_entry) : // 同向减速
std::max(v_exit, -v_entry)) : // 反向
(((v_entry < 0.0f) || (v_exit > 0.0f)) ?
(v_entry - v_exit) : // 同向加速
std::max(-v_exit, v_entry)); // 反向
float axis_max_jerk = get_axis_max_jerk(..., static_cast<Axis>(a));
if (jerk > axis_max_jerk) {
v_factor *= axis_max_jerk / jerk; // 降速
limited = true;
}
```
**含义**:
- E轴的jerk单独计算
- 区分同向运动coasting和反向运动reversal
- 反向运动的jerk更严格
### 2.4 Jerk对时间的影响
**影响机制**:
1. **降低连接速度** → 增加加速/减速时间
```
示例:
- 无jerk限制连接速度100 mm/s
- 有jerk限制连接速度降至50 mm/s
- 结果:需要更长的加速/减速时间
```
2. **降低巡航速度** → 增加总移动时间
```
示例:
- 目标速度150 mm/s
- jerk限制导致入口速度30 mm/s
- 结果:加速段更长,可能无法达到目标速度
```
3. **影响梯形速度曲线**
```
无jerk限制
┌─────────┐ (平顶梯形)
│ │
│ │
└ └
有jerk限制
┌───┐ (尖顶三角形或低平顶)
└ └
```
### 2.5 实际计算示例
**场景**: 直角转弯90度
```
前一移动X方向 100 mm/s
当前移动Y方向 100 mm/s
X轴jerk限制10 mm/s
Y轴jerk限制10 mm/s
计算:
- X轴速度变化100 mm/s → 0 mm/s = 100 mm/s
- Y轴速度变化0 mm/s → 100 mm/s = 100 mm/s
- 超过jerk限制需要降速
降速系数:
- X轴10 / 100 = 0.1
- Y轴10 / 100 = 0.1
- 最终连接速度100 * 0.1 = 10 mm/s
时间影响:
- 如果没有jerk限制可能以50 mm/s通过转角
- 有jerk限制只能以10 mm/s通过转角
- 需要从100减速到10再从10加速到100
- 增加的时间:约 (90/加速度) 秒
```
---
## 问题3换料gcode中的M109指令是否会被统计
### 3.1 换料gcode的处理流程
**位置**: `src/libslic3r/GCode.cpp:903-918`
```cpp
if (line == "[change_filament_gcode]") {
// BBS
if (!m_single_extruder_multi_material) {
extruder_offset = m_extruder_offsets[tcr.new_tool].cast<float>();
// If the extruder offset changed, add an extra move
if (extruder_offset != m_extruder_offsets[tcr.initial_tool].cast<float>()) {
std::ostringstream oss;
oss << std::fixed << std::setprecision(3)
<< "G1 X" << transformed_pos.x() - extruder_offset.x()
<< " Y" << transformed_pos.y() - extruder_offset.y()
<< "\n";
gcode_out += oss.str();
}
}
}
```
**说明**:
- `[change_filament_gcode]`是一个特殊标记
- 在WipeTower中使用`src/libslic3r/GCode/WipeTower.cpp:1013`
- 标记换料gcode的插入位置
### 3.2 换料gcode的生成
**位置**: `src/libslic3r/GCode.cpp:6590-6597`
```cpp
// Process the custom change_filament_gcode.
const std::string& change_filament_gcode = m_config.change_filament_gcode.value;
//Orca: Ignore change_filament_gcode if is the first call for a tool change
// and manual_filament_change is enabled
if (!change_filament_gcode.empty() &&
!(m_config.manual_filament_change.value && m_toolchange_count == 1)) {
toolchange_gcode_parsed = placeholder_parser_process(
"change_filament_gcode", change_filament_gcode, extruder_id, &dyn_config);
}
```
**说明**:
- `change_filament_gcode`是用户配置的自定义换料脚本
- 通过`placeholder_parser_process`处理占位符如温度、喷头ID等
- 生成的gcode会被插入到最终的G-code文件中
### 3.3 M109是否会被统计
**答案:会被统计**
**原因**:
1. **换料gcode被完整插入到G-code文件中**
```cpp
// Line 507-597
toolchange_gcode_str = gcodegen.placeholder_parser_process(
"change_filament_gcode", change_filament_gcode, new_extruder_id, ...);
```
2. **GCodeProcessor会解析所有G-code行**
```cpp
// GCodeProcessor::process_gcode_line() 会处理所有行
// 包括change_filament_gcode中的M109
```
3. **M109会触发process_M109()函数**
- 位置:`GCodeProcessor.cpp:3640-3655`(当前实现)
- 如果应用修复方案,会计算等待时间并调用`simulate_st_synchronize()`
### 3.4 示例
**用户的换料gcode配置**:
```gcode
M109 S{new_filament_temp[next_extruder]} ; 等待新工具温度
G1 E10 F300 ; 挤出少量材料
```
**生成的实际gcode**假设温度220°C:
```gcode
M109 S220 ; 等待新工具温度 ⬅️ 这行会被GCodeProcessor处理
G1 E10 F300
```
**时间统计**:
- **当前实现**: M109不会添加等待时间bug
- **修复后**: M109会计算等待时间
- 如果有M104预热计算剩余等待时间可能0-20秒
- 如果无预热计算完整等待时间可能20-40秒
### 3.5 注意事项
⚠️ **重要**: 如果用户的换料gcode中有M109修复方案会统计这个时间
**建议**:
1. 检查U1的默认`change_filament_gcode`配置
2. 确认是否包含M109
3. 如果包含,修复后时间估算会更准确
4. 如果不包含,需要确认换料过程是否在其他地方等待温度
---
## 问题4GCode.cpp中的M400是否会被统计到时间如何计算
### 4.1 U1的M400使用场景
**位置**: `src/libslic3r/GCode.cpp:6377-6380`
```cpp
// Snapmaker U1
std::string printer_model = this->m_curr_print->m_config.printer_model.value;
if (printer_model == "Snapmaker U1" && toolchange) {
gcode += "M400\n"; // ⬅️ 注意:没有参数
}
```
**使用场景**:
- 工具切换时toolchange = true
- 仅限Snapmaker U1机型
- 添加一个无参数的M400命令
### 4.2 M400的含义
**固件行为**: M400表示"Finish all moves"(完成所有移动)
- 阻塞等待,直到运动缓冲区清空
- 确保所有G1/G0移动都已完成
- 类似于固件的`st_synchronize()`调用
### 4.3 M400的时间计算
**位置**: `src/libslic3r/GCode/GCodeProcessor.cpp:3883-3891`
```cpp
void GCodeProcessor::process_M400(const GCodeReader::GCodeLine& line)
{
float value_s = 0.0;
float value_p = 0.0;
if (line.has_value('S', value_s) || line.has_value('P', value_p)) {
value_s += value_p * 0.001; // P参数单位是毫秒
simulate_st_synchronize(value_s);
}
// ⚠️ 注意如果没有S或P参数不会调用simulate_st_synchronize()
}
```
**关键点**:
1. **有参数的M400**(如`M400 S1`或`M400 P100`
- 会调用`simulate_st_synchronize(value_s)`
- 添加额外的等待时间
- 示例:`M400 P100` → 添加0.1秒等待时间
2. **无参数的M400**(如`M400\n`
- **不会**调用`simulate_st_synchronize()`
- **不会**添加额外的等待时间
- 只会触发现有移动块的完成(但这部分时间已经在移动块计算中)
### 4.4 U1的M400时间统计
**答案U1的M400不会添加额外等待时间**
**原因**:
1. U1添加的是`M400\n`(无参数)
2. `process_M400()`检测到无S和P参数
3. 不会调用`simulate_st_synchronize()`
4. **只会同步现有移动,不会添加额外时间**
### 4.5 M400的实际作用
虽然不添加额外时间但M400仍然有重要作用
**在时间估算中**:
```cpp
void GCodeProcessor::process_M400(const GCodeReader::GCodeLine& line)
{
// ... 检查参数 ...
// 即使没有参数也会触发TimeMachine处理当前的移动块
// 确保所有pending的移动都被计算完成
}
```
**效果**:
- 确保M400之前的所有移动块都被处理完成
- 刷新时间估算的缓冲区
- **但不添加额外的等待时间**
### 4.6 对比:有参数 vs 无参数的M400
| M400命令 | 添加等待时间 | 代码位置 | 用途 |
|---------|------------|---------|------|
| `M400\n` (U1) | ❌ 否 | GCode.cpp:6379 | 同步移动缓冲区 |
| `M400 S1` | ✅ 是1秒 | - | 等待1秒 |
| `M400 P100` | ✅ 是0.1秒 | GCode.cpp扫描模型:行号未显示 | 等待0.1秒 |
### 4.7 GCode.cpp中其他M400的使用
**扫描模型场景**(搜索结果中发现):
```cpp
gcode += "M976 S1 P1 ; scan model before printing 2nd layer\n";
gcode += "M400 P100\n"; // ⬅️ 有P参数会添加0.1秒等待
```
**说明**:
- 这个M400有P参数
- **会添加0.1秒的等待时间**
- 用于扫描模型后的延迟
---
## 总结
### 问题1答案挤出加速度 vs E加速度
| 参数 | 作用 | 默认值 |
|-----|------|-------|
| `machine_max_acceleration_e` | E轴电机的物理限制 | 5000 mm/s² |
| `machine_max_acceleration_extruding` | 打印时的质量限制 | 1500 mm/s² |
**关键区别**: e是硬件限制extruding是打印质量限制
### 问题2答案Jerk的影响
**影响方式**:
1. 限制单轴的安全速度
2. 限制相邻移动的连接速度
3. 降低连接速度 → 增加加速/减速时间 → 增加总打印时间
**典型影响**: 直角转弯时jerk限制会将连接速度从50-100 mm/s降至10 mm/s
### 问题3答案换料gcode中的M109
**会被统计** ✅
- 换料gcode会被完整插入到G-code文件
- GCodeProcessor会解析所有行包括M109
- 修复方案会计算M109的等待时间考虑预热
### 问题4答案U1的M400时间计算
**不会添加额外时间** ❌
- U1添加的是`M400\n`(无参数)
- `process_M400()`只在有S或P参数时添加时间
- U1的M400只同步移动缓冲区不添加等待时间
**但其他M400可能会**:
- `M400 P100`扫描模型会添加0.1秒
---
## 建议
### 对于M109修复方案的建议
1. **确认U1的change_filament_gcode配置**
- 检查是否包含M109
- 如果包含,修复后会更准确
2. **M400不影响修复方案**
- U1的M400不添加时间
- 修复方案可以正常实施
3. **Jerk配置建议**
- 检查U1的jerk配置是否合理
- 如果时间估算仍有偏差可能是jerk配置问题
### 测试建议
1. **验证换料gcode中的M109**
```bash
# 检查生成的G-code中换料部分的M109
grep -A10 "T1" output.gcode | grep M109
```
2. **验证M400不影响时间**
```bash
# 检查M400是否有参数
grep "M400" output.gcode
```
3. **验证jerk影响**
```bash
# 对比不同jerk配置下的时间估算
```