对齐 LinuxCNC 解析器覆盖

This commit is contained in:
wangdequan
2026-05-23 17:28:41 +08:00
parent 7fe7ea6038
commit ed4e674d1e
40 changed files with 8881 additions and 313 deletions

View File

@@ -57,20 +57,28 @@ The first useful target is:
- 已有最小 LinuxCNC tooldata 初始化native runner 和 API 后端都能覆盖 `T... M6` 换刀路径。 - 已有最小 LinuxCNC tooldata 初始化native runner 和 API 后端都能覆盖 `T... M6` 换刀路径。
- 已有 LinuxCNC RS274 源码级链接 smoke本项目直接编译 23 个解释器 core 源文件,不再通过 `librs274` 取得解释器主体。 - 已有 LinuxCNC RS274 源码级链接 smoke本项目直接编译 23 个解释器 core 源文件,不再通过 `librs274` 取得解释器主体。
- 已有五轴 RTCP 第一版几何内核可根据编程刀尖点、A/B/C 姿态和刀长计算枢轴/主轴点补偿位置。 - 已有五轴 RTCP 第一版几何内核可根据编程刀尖点、A/B/C 姿态和刀长计算枢轴/主轴点补偿位置。
- 已有坐标系事件回归语料,覆盖 `G10 L2``G10 L20` 的 G5X/XY 旋转事件和 `G92.1` 清零事件。 - 已有坐标系事件回归语料,覆盖 `G10 L2``G10 L20``G10 P0``G54`-`G59.3` 全部工件坐标系选择、`G52``G92/G92.1/G92.2/G92.3` 的 G5X/G92/XY 旋转事件。
- 已有探针事件回归语料LinuxCNC `G38.3` 会输出独立 `probe` 事件,不再混作普通直线进给。 - 已有探针事件回归语料LinuxCNC `G38.2/G38.3/G38.4/G38.5` 会输出独立 `probe` 事件,不再混作普通直线进给`probe.reserved` 保留 LinuxCNC `probe_type``0=trip/error``1=trip/no-error``2=clear/error``3=clear/no-error`
- 已有主轴方向状态回归语料,`M3/M4/M5` 会通过 `set-spindle.reserved` 输出 `1=顺时针``2=逆时针``0=停止` - 已有主轴方向状态回归语料,`M3/M4/M5` 会通过 `set-spindle.reserved` 输出 `1=顺时针``2=逆时针``0=停止`
- 已有主轴速度模式回归语料,`G96/G97` 会通过 `comment.reserved` 临时输出 `960=CSS``970=constant RPM``feed` 暂存 LinuxCNC `SET_SPINDLE_MODE` 的 mode/max-RPM 值。
- 已有主轴定向回归语料,`M19 R... P... Q...` 会通过 `comment.reserved` 临时输出 `1901=orient spindle``1902=wait orient complete``feed` 暂存 R 角度,`arcTurns` 暂存 P 模式,`dwellSeconds` 暂存 Q 超时。
- 已有主轴同步进给和螺纹回归语料,`G33/G33.1/G76` 会通过 `comment.reserved` 临时输出 `3301=speed-feed sync start``3302=velocity sync start``3300=sync stop``feed` 暂存每转进给量。
- 已有车床直径/半径模式回归语料,`G7/G8` 会切换 X 轴输入缩放,`G76` 会在直径模式下同步缩放线程几何参数。
- 已有 LinuxCNC 常用只读命名参数回归语料,`#<_absolute>``#<_incremental>``#<_metric>``#<_imperial>``#<_lathe_diameter_mode>``#<_lathe_radius_mode>` 能在 O-word 条件里直接读取当前模态状态。
- 已有覆盖控制回归语料,`M48/M49/M50/M51/M52/M53` 会通过 `comment.reserved` 临时输出 `50=feed override``51=speed override``52=adaptive feed``53=feed hold``feed` 暂存启用状态,`tool` 对 speed override 暂存 spindle 号。
- 已有 I/O M-code 回归语料,`M62/M63/M64/M65/M66/M67/M68` 会通过 `comment.reserved` 临时输出对应 M 码号,`tool` 暂存 P/E 通道号,`feed` 暂存输出值或 M66 等待模式,`arcTurns` 暂存 M66 输入类型,`dwellSeconds` 暂存 M66 超时。
- 已有 modal state 回归语料,`M70/M71/M72` 在 smoke parser 中支持主程序级保存、失效、恢复,`M73` 支持 O-word 子程序返回自动恢复native/source 语料验证恢复后的距离模式、单位和 XY 平面运动。
- 已有注释事件行号回归语料LinuxCNC `COMMENT` 事件会保留当前 G-code 行号。 - 已有注释事件行号回归语料LinuxCNC `COMMENT` 事件会保留当前 G-code 行号。
- 已有当前刀号事件行号回归语料LinuxCNC `M61 Q...` 会输出带行号的 `tool-change` 事件。 - 已有当前刀号事件行号回归语料LinuxCNC `M61 Q...` 会输出带行号的 `tool-change` 事件。
- 已有停止类事件回归语料,`M0/M1/M60` 会通过 `program-end.reserved` 输出 `1=程序停``2=可选停``3=托盘交换` - 已有停止类事件回归语料,`M0/M1/M60` 会通过 `program-end.reserved` 输出 `1=程序停``2=可选停``3=托盘交换`
- 已有冷却液状态回归语料,`M7/M8/M9` 会通过 `comment.reserved` 临时输出 `10/11=mist off/on``20/21=flood off/on` - 已有冷却液状态回归语料,`M7/M8/M9` 会通过 `comment.reserved` 临时输出 `10/11=mist off/on``20/21=flood off/on`
- 已有进给模式回归语料,`G93/G94/G95` 会通过 `comment.reserved` 临时输出 `93/94/95`,并通过 `set-feed` 记录 Canon feed mode 回调。 - 已有进给模式回归语料,`G93/G94/G95` 会通过 `comment.reserved` 临时输出 `93/94/95`,并通过 `set-feed` 记录 Canon feed mode 回调。
- 已有运动控制模式回归语料,`G61/G61.1/G64` 会通过 `comment.reserved` 临时输出 `611/612/640``feed` 暂存 G64 tolerance。 - 已有运动控制模式回归语料,`G61/G61.1/G64` 会通过 `comment.reserved` 临时输出 `611/612/640``feed` 暂存 G64 tolerance。
- smoke parser 已有固定循环第一版展开,覆盖 `G73` 高速啄钻、`G81` 普通钻、`G82` 孔底暂停钻、`G83` 啄钻、`G85` 镗孔进给退刀、`G86` 镗孔停主轴快速退刀、`G89` 镗孔暂停后进给退刀,以及 `G80` 取消、`G98/G99` 返回模式和 `L` 重复次数。 - smoke parser 已有固定循环第一版展开,覆盖 `G73` 高速啄钻、`G74/G84` 攻丝、`G81` 普通钻、`G82` 孔底暂停钻、`G83` 啄钻、`G85` 镗孔进给退刀、`G86` 镗孔停主轴快速退刀、`G87` 背镗、`G88` 手动退刀镗孔、`G89` 镗孔暂停后进给退刀,以及 `G80` 取消、`G98/G99` 返回模式和 `L` 重复次数;这些循环已按 LinuxCNC `G17/G18/G19` 平面映射进刀轴,`G87` 会按平面重映射 `I/J/K`
- LinuxCNC native/source 对照已扩展到 `G82` 孔底暂停`G83` 啄钻关键事件,覆盖孔底 dwell、啄钻深度序列R 平面退刀。 - LinuxCNC native/source 对照已扩展到 `G82` 孔底暂停`G83` 啄钻`G18/G19` 固定循环平面关键事件,覆盖 `G74/G84/G86/G87/G88` 非 XY 平面序列、孔底 dwell、啄钻深度序列R 平面退刀、手动退刀停机和背镗偏置路径
- smoke parser 已有 Fanuc 风格 `M98 P... L...` / `M99` 子程序调用第一版,支持同文件 `O...` 子程序块和重复调用展开;未知子程序、裸 `M99` 和过深嵌套会返回明确错误。 - smoke parser 已有 Fanuc 风格 `M98 P... L...` / `M99` 子程序调用第一版,支持同文件 `O...` 子程序块和重复调用展开;未知子程序、裸 `M99` 和过深嵌套会返回明确错误。
- smoke parser 已有 LinuxCNC 风格 O-word 子程序第一版,覆盖数字 `O100 ...` 和命名 `O<name> ...``sub` / `call [args]` / `return` / `endsub`,支持简单数字实参、`#1 = ...` 编号参数赋值、`#<name> = ...` 命名参数赋值、`X#1` / `X#<name>` 参数引用、`+ - * /` 可嵌套方括号表达式,以及 `ABS[]``SQRT[]``EXP[]``LN[]`、角度制 `SIN[]` / `COS[]` / `TAN[]` / `ASIN[]` / `ACOS[]`、LinuxCNC 双参数 `ATAN[]/[]``FIX[]` / `FUP[]` / `ROUND[]`,并拒绝和 `M98/M99` 风格混用。 - smoke parser 已有 LinuxCNC 风格 O-word 子程序第一版,覆盖数字 `O100 ...` 和命名 `O<name> ...``sub` / `call [args]` / `return` / `endsub`,支持简单数字实参、`#1 = ...` 编号参数赋值、`#<name> = ...` 命名参数赋值、`X#1` / `X#<name>` 参数引用、`+ - * /` 可嵌套方括号表达式,以及 `ABS[]``SQRT[]``EXP[]``LN[]`、角度制 `SIN[]` / `COS[]` / `TAN[]` / `ASIN[]` / `ACOS[]`、LinuxCNC 双参数 `ATAN[]/[]``FIX[]` / `FUP[]` / `ROUND[]`,并拒绝和 `M98/M99` 风格混用。
- LinuxCNC native/source runner 已支持显式文件模式执行O-word 子程序语料会通过 LinuxCNC 自身 `open/read/execute` 路径验证,而不是逐行模拟。 - LinuxCNC native/source runner 已支持显式文件模式执行O-word 子程序语料会通过 LinuxCNC 自身 `open/read/execute` 路径验证,而不是逐行模拟native/source 回归现已同时覆盖数字 `O100` 和命名 `O<move_plus>` 子程序、实参传递、命名参数赋值、`return` 跳过体尾,以及 `if` / `elseif` / `else``while``repeat``do` / `while``break``continue` 控制流
- LinuxCNC Canon bridge 会把当前解释行号补到没有自带 `lineno` 的回调事件上,方便 Web 端诊断和源码高亮。 - LinuxCNC Canon bridge 会把当前解释行号补到没有自带 `lineno` 的回调事件上,方便 Web 端诊断和源码高亮。
- 下一步是继续替换源码级链接中残留的 Python、INI/HAL、文件系统和动态加载依赖并把 RTCP 内核接入 canon 事件流和机型配置。 - 下一步是继续替换源码级链接中残留的 Python、INI/HAL、文件系统和动态加载依赖并把 RTCP 内核接入 canon 事件流和机型配置。
@@ -97,11 +105,11 @@ The first useful target is:
- `M7` / `M8` / `M9` 冷却液状态回归 - `M7` / `M8` / `M9` 冷却液状态回归
- `G93` / `G94` / `G95` 进给模式回归 - `G93` / `G94` / `G95` 进给模式回归
- `G61` / `G61.1` / `G64` 运动控制模式回归 - `G61` / `G61.1` / `G64` 运动控制模式回归
- smoke parser `G73` / `G81` / `G82` / `G83` / `G85` / `G86` / `G89` / `G80` / `G98` / `G99` / `L` 固定循环展开回归 - smoke parser `G73` / `G74` / `G81` / `G82` / `G83` / `G84` / `G85` / `G86` / `G87` / `G88` / `G89` / `G80` / `G98` / `G99` / `L` 固定循环展开回归,以及 `G18/G19` 平面进刀轴和 `G87 I/J/K` 平面映射回归
- LinuxCNC native/source `G82` / `G83` 固定循环对照回归 - LinuxCNC native/source `G74` / `G82` / `G83` / `G84` / `G86` / `G87` / `G88` / `G18` / `G19` 固定循环对照回归
- smoke parser `M98 P... L...` / `M99` 子程序调用回归 - smoke parser `M98 P... L...` / `M99` 子程序调用回归
- smoke parser LinuxCNC 风格 `O... sub/call/return/endsub` 子程序调用回归 - smoke parser LinuxCNC 风格 `O... sub/call/return/endsub` 子程序调用回归
- `G10 L2` / `G10 L20` / `G92.1` 坐标系事件回归 - `G10 L2` / `G10 L20` / `G10 P0` / `G54`-`G59.3` / `G92.1` 坐标系事件回归
- `G38.3` 探针事件回归 - `G38.3` 探针事件回归
## 后端选择 ## 后端选择
@@ -170,7 +178,7 @@ Canon bridge 已不再丢弃坐标系相关回调,会输出:
- `set-xy-rotation`:来自 `SET_XY_ROTATION``feed` 暂存旋转角度。 - `set-xy-rotation`:来自 `SET_XY_ROTATION``feed` 暂存旋转角度。
这些事件先保证 LinuxCNC Canon 层信息完整进入 Web/core。具体 G-code`G10``G92`、坐标旋转)是否触发这些回调,还要继续按 LinuxCNC 解释器参数路径逐项补回归语料。 这些事件先保证 LinuxCNC Canon 层信息完整进入 Web/core。具体 G-code`G10``G92`、坐标旋转)是否触发这些回调,还要继续按 LinuxCNC 解释器参数路径逐项补回归语料。
目前已有组回归语料:`tests/gcode/linuxcnc_coordinate_offsets.ngc` 覆盖 `G10 L2 P1 X... Y... Z... R...` 触发 `set-g5x-offset` / `set-xy-rotation`,以及 `G92.1` 触发 `set-g92-offset` 清零;`tests/gcode/linuxcnc_coordinate_l20.ngc` 覆盖 `G10 L20 P2` 按当前位置和目标工件坐标计算 G55 偏置。测试脚本会在坐标系语料之间重置参数文件,避免 LinuxCNC 持久参数互相污染。后续继续扩展到更多坐标系 P 号、持久参数文件读写策略和旋转叠加运动路径。 目前已有组回归语料:`tests/gcode/linuxcnc_coordinate_offsets.ngc` 覆盖 `G10 L2 P1 X... Y... Z... R...` 触发 `set-g5x-offset` / `set-xy-rotation`,以及 `G92.1` 触发 `set-g92-offset` 清零;`tests/gcode/linuxcnc_coordinate_l20.ngc` 覆盖 `G10 L20 P2` 按当前位置和目标工件坐标计算 G55 偏置`tests/gcode/linuxcnc_coordinate_p0.ngc` 覆盖 `G10 L2 P0` 指向当前活动坐标系;`tests/gcode/linuxcnc_coordinate_select_all.ngc` 覆盖 `G54`-`G59.3` 选择时的 G5X index 和偏置载入。测试脚本会在坐标系语料之间重置参数文件,避免 LinuxCNC 持久参数互相污染。后续继续扩展持久参数文件读写策略和旋转叠加运动路径。
LinuxCNC 中部分 Canon 函数不携带行号参数bridge 会在调用解释器 `read/execute` 前记录当前输入行,并用它填充这类事件的 `line` 字段。 LinuxCNC 中部分 Canon 函数不携带行号参数bridge 会在调用解释器 `read/execute` 前记录当前输入行,并用它填充这类事件的 `line` 字段。
## CMake native LinuxCNC 后端 ## CMake native LinuxCNC 后端

View File

@@ -6,12 +6,22 @@ void CanonEventSink::reset() {
position_ = {}; position_ = {};
plane_ = 17; plane_ = 17;
unit_scale_ = 1.0; unit_scale_ = 1.0;
traverse_rate_ = 0.0;
feed_ = 0.0; feed_ = 0.0;
spindle_ = 0.0; spindle_ = 0.0;
spindle_direction_ = 0; spindle_direction_ = 0;
selected_tool_ = 0; selected_tool_ = 0;
probe_position_ = {};
probe_tripped_ = false;
tool_length_offset_ = {};
callback_status_ = 0; callback_status_ = 0;
kinematics_type_ = 1; kinematics_type_ = 1;
feed_override_ = false;
speed_override_ = false;
adaptive_feed_ = false;
feed_hold_ = false;
mist_on_ = false;
flood_on_ = false;
} }
void CanonEventSink::set_callback(CncSimEventCallback callback, void *user_data) { void CanonEventSink::set_callback(CncSimEventCallback callback, void *user_data) {
@@ -48,6 +58,10 @@ void CanonEventSink::set_tool_length(int h_code, double tool_length) {
} }
} }
void CanonEventSink::set_tool_length_offset(const CncSimPose &offset) {
tool_length_offset_ = offset;
}
void CanonEventSink::set_rtcp_state(bool enabled, int h_code, int line) { void CanonEventSink::set_rtcp_state(bool enabled, int h_code, int line) {
rtcp_enabled_ = enabled; rtcp_enabled_ = enabled;
rtcp_h_code_ = enabled ? h_code : 0; rtcp_h_code_ = enabled ? h_code : 0;
@@ -104,6 +118,10 @@ void CanonEventSink::select_plane(int plane, int line) {
emit(event); emit(event);
} }
void CanonEventSink::set_traverse_rate(double rate) {
traverse_rate_ = rate;
}
void CanonEventSink::set_feed_rate(double feed, int line) { void CanonEventSink::set_feed_rate(double feed, int line) {
feed_ = feed; feed_ = feed;
CncSimEvent event = base_event(CNC_SIM_EVENT_SET_FEED, line); CncSimEvent event = base_event(CNC_SIM_EVENT_SET_FEED, line);
@@ -111,9 +129,10 @@ void CanonEventSink::set_feed_rate(double feed, int line) {
emit(event); emit(event);
} }
void CanonEventSink::set_feed_mode(int mode, int line) { void CanonEventSink::set_feed_mode(int spindle, int mode, int line) {
CncSimEvent event = base_event(CNC_SIM_EVENT_SET_FEED, line); CncSimEvent event = base_event(CNC_SIM_EVENT_SET_FEED, line);
event.feed = feed_; event.feed = feed_;
event.tool = spindle;
event.reserved = mode; event.reserved = mode;
emit(event); emit(event);
} }
@@ -126,6 +145,89 @@ void CanonEventSink::set_spindle_speed(double spindle, int line) {
emit(event); emit(event);
} }
void CanonEventSink::set_spindle_mode(int spindle, double mode, int line) {
CncSimEvent event = base_event(CNC_SIM_EVENT_COMMENT, line);
event.tool = spindle;
event.feed = mode;
event.reserved = mode == 0.0 ? 970 : 960;
emit(event);
}
void CanonEventSink::set_speed_feed_sync(int spindle, double feed_per_revolution, bool velocity_mode, bool enabled, int line) {
CncSimEvent event = base_event(CNC_SIM_EVENT_COMMENT, line);
event.tool = spindle;
event.feed = feed_per_revolution;
event.reserved = enabled ? (velocity_mode ? 3302 : 3301) : 3300;
emit(event);
}
void CanonEventSink::orient_spindle(int spindle, double orientation, int mode, int line) {
CncSimEvent event = base_event(CNC_SIM_EVENT_COMMENT, line);
event.tool = spindle;
event.feed = orientation;
event.arc_turns = mode;
event.reserved = 1901;
emit(event);
}
void CanonEventSink::wait_spindle_orient_complete(int spindle, double timeout, int line) {
CncSimEvent event = base_event(CNC_SIM_EVENT_COMMENT, line);
event.tool = spindle;
event.dwell_seconds = timeout;
event.reserved = 1902;
emit(event);
}
void CanonEventSink::set_digital_output(int index, bool enabled, bool motion_synchronized, int line) {
CncSimEvent event = base_event(CNC_SIM_EVENT_COMMENT, line);
event.tool = index;
event.feed = enabled ? 1.0 : 0.0;
event.reserved = motion_synchronized ? (enabled ? 62 : 63) : (enabled ? 64 : 65);
emit(event);
}
void CanonEventSink::set_analog_output(int index, double value, bool motion_synchronized, int line) {
CncSimEvent event = base_event(CNC_SIM_EVENT_COMMENT, line);
event.tool = index;
event.feed = value;
event.reserved = motion_synchronized ? 67 : 68;
emit(event);
}
void CanonEventSink::wait_input(int index, int input_type, int wait_type, double timeout, int line) {
CncSimEvent event = base_event(CNC_SIM_EVENT_COMMENT, line);
event.tool = index;
event.feed = wait_type;
event.dwell_seconds = timeout;
event.arc_turns = input_type;
event.reserved = 66;
emit(event);
}
void CanonEventSink::set_override_control(int control, bool enabled, int spindle, int line) {
switch (control) {
case 50:
feed_override_ = enabled;
break;
case 51:
speed_override_ = enabled;
break;
case 52:
adaptive_feed_ = enabled;
break;
case 53:
feed_hold_ = enabled;
break;
default:
break;
}
CncSimEvent event = base_event(CNC_SIM_EVENT_COMMENT, line);
event.tool = spindle;
event.feed = enabled ? 1.0 : 0.0;
event.reserved = control;
emit(event);
}
void CanonEventSink::start_spindle(int direction, int line) { void CanonEventSink::start_spindle(int direction, int line) {
spindle_direction_ = direction < 0 ? 2 : 1; spindle_direction_ = direction < 0 ? 2 : 1;
CncSimEvent event = base_event(CNC_SIM_EVENT_SET_SPINDLE, line); CncSimEvent event = base_event(CNC_SIM_EVENT_SET_SPINDLE, line);
@@ -181,11 +283,14 @@ void CanonEventSink::arc_feed(int line, const CncSimPose &end, const CncSimPose
position_ = end; position_ = end;
} }
void CanonEventSink::straight_probe(int line, const CncSimPose &end) { void CanonEventSink::straight_probe(int line, const CncSimPose &end, int probe_type) {
CncSimEvent event = base_event(CNC_SIM_EVENT_PROBE, line); CncSimEvent event = base_event(CNC_SIM_EVENT_PROBE, line);
event.start = position_; event.start = position_;
event.end = end; event.end = end;
event.reserved = probe_type;
emit(event); emit(event);
probe_position_ = end;
probe_tripped_ = (probe_type & 2) == 0;
position_ = end; position_ = end;
} }
@@ -224,6 +329,10 @@ double CanonEventSink::unit_scale() const {
return unit_scale_; return unit_scale_;
} }
double CanonEventSink::traverse_rate() const {
return traverse_rate_;
}
double CanonEventSink::feed_rate() const { double CanonEventSink::feed_rate() const {
return feed_; return feed_;
} }
@@ -236,6 +345,18 @@ int CanonEventSink::spindle_direction() const {
return spindle_direction_; return spindle_direction_;
} }
const CncSimPose &CanonEventSink::tool_length_offset() const {
return tool_length_offset_;
}
const CncSimPose &CanonEventSink::probe_position() const {
return probe_position_;
}
bool CanonEventSink::probe_tripped() const {
return probe_tripped_;
}
int CanonEventSink::selected_tool() const { int CanonEventSink::selected_tool() const {
return selected_tool_; return selected_tool_;
} }
@@ -252,6 +373,38 @@ double CanonEventSink::rtcp_tool_length() const {
return rtcp_tool_length_; return rtcp_tool_length_;
} }
bool CanonEventSink::feed_override() const {
return feed_override_;
}
bool CanonEventSink::speed_override() const {
return speed_override_;
}
bool CanonEventSink::adaptive_feed() const {
return adaptive_feed_;
}
bool CanonEventSink::feed_hold() const {
return feed_hold_;
}
bool CanonEventSink::mist_on() const {
return mist_on_;
}
bool CanonEventSink::flood_on() const {
return flood_on_;
}
void CanonEventSink::set_mist_on(bool enabled) {
mist_on_ = enabled;
}
void CanonEventSink::set_flood_on(bool enabled) {
flood_on_ = enabled;
}
void CanonEventSink::emit(CncSimEvent event) { void CanonEventSink::emit(CncSimEvent event) {
if (callback_ && callback_status_ == 0) { if (callback_ && callback_status_ == 0) {
callback_status_ = callback_(&event, user_data_); callback_status_ = callback_(&event, user_data_);

View File

@@ -12,6 +12,7 @@ public:
bool callback_aborted() const; bool callback_aborted() const;
void configure_rtcp(bool enabled, double tool_length); void configure_rtcp(bool enabled, double tool_length);
void set_tool_length(int h_code, double tool_length); void set_tool_length(int h_code, double tool_length);
void set_tool_length_offset(const CncSimPose &offset);
void set_rtcp_state(bool enabled, int h_code, int line); void set_rtcp_state(bool enabled, int h_code, int line);
void switch_kinematics(int kinematics_type, bool rtcp_enabled, int line); void switch_kinematics(int kinematics_type, bool rtcp_enabled, int line);
void set_g5x_offset(int index, const CncSimPose &offset, int line); void set_g5x_offset(int index, const CncSimPose &offset, int line);
@@ -20,9 +21,18 @@ public:
void use_length_units(double scale, int line); void use_length_units(double scale, int line);
void select_plane(int plane, int line); void select_plane(int plane, int line);
void set_traverse_rate(double rate);
void set_feed_rate(double feed, int line); void set_feed_rate(double feed, int line);
void set_feed_mode(int mode, int line); void set_feed_mode(int spindle, int mode, int line);
void set_spindle_speed(double spindle, int line); void set_spindle_speed(double spindle, int line);
void set_spindle_mode(int spindle, double mode, int line);
void set_speed_feed_sync(int spindle, double feed_per_revolution, bool velocity_mode, bool enabled, int line);
void orient_spindle(int spindle, double orientation, int mode, int line);
void wait_spindle_orient_complete(int spindle, double timeout, int line);
void set_digital_output(int index, bool enabled, bool motion_synchronized, int line);
void set_analog_output(int index, double value, bool motion_synchronized, int line);
void wait_input(int index, int input_type, int wait_type, double timeout, int line);
void set_override_control(int control, bool enabled, int spindle, int line);
void start_spindle(int direction, int line); void start_spindle(int direction, int line);
void stop_spindle(int line); void stop_spindle(int line);
void select_tool(int tool); void select_tool(int tool);
@@ -30,7 +40,7 @@ public:
void straight_traverse(int line, const CncSimPose &end); void straight_traverse(int line, const CncSimPose &end);
void straight_feed(int line, const CncSimPose &end); void straight_feed(int line, const CncSimPose &end);
void arc_feed(int line, const CncSimPose &end, const CncSimPose &center, int turns); void arc_feed(int line, const CncSimPose &end, const CncSimPose &center, int turns);
void straight_probe(int line, const CncSimPose &end); void straight_probe(int line, const CncSimPose &end, int probe_type = 0);
void dwell(double seconds, int line); void dwell(double seconds, int line);
void program_end(int line); void program_end(int line);
void program_stop(int line, int kind); void program_stop(int line, int kind);
@@ -39,13 +49,25 @@ public:
const CncSimPose &position() const; const CncSimPose &position() const;
int plane() const; int plane() const;
double unit_scale() const; double unit_scale() const;
double traverse_rate() const;
double feed_rate() const; double feed_rate() const;
double spindle_speed() const; double spindle_speed() const;
int spindle_direction() const; int spindle_direction() const;
const CncSimPose &tool_length_offset() const;
const CncSimPose &probe_position() const;
bool probe_tripped() const;
int selected_tool() const; int selected_tool() const;
int kinematics_type() const; int kinematics_type() const;
bool rtcp_enabled() const; bool rtcp_enabled() const;
double rtcp_tool_length() const; double rtcp_tool_length() const;
bool feed_override() const;
bool speed_override() const;
bool adaptive_feed() const;
bool feed_hold() const;
bool mist_on() const;
bool flood_on() const;
void set_mist_on(bool enabled);
void set_flood_on(bool enabled);
private: private:
void emit(CncSimEvent event); void emit(CncSimEvent event);
@@ -58,14 +80,24 @@ private:
CncSimPose position_{}; CncSimPose position_{};
int plane_ = 17; int plane_ = 17;
double unit_scale_ = 1.0; double unit_scale_ = 1.0;
double traverse_rate_ = 0.0;
double feed_ = 0.0; double feed_ = 0.0;
double spindle_ = 0.0; double spindle_ = 0.0;
int spindle_direction_ = 0; int spindle_direction_ = 0;
int selected_tool_ = 0; int selected_tool_ = 0;
CncSimPose probe_position_{};
bool probe_tripped_ = false;
bool rtcp_enabled_ = false; bool rtcp_enabled_ = false;
double default_rtcp_tool_length_ = 0.0; double default_rtcp_tool_length_ = 0.0;
double rtcp_tool_length_ = 0.0; double rtcp_tool_length_ = 0.0;
int rtcp_h_code_ = 0; int rtcp_h_code_ = 0;
CncSimPose tool_length_offset_{};
int kinematics_type_ = 1; int kinematics_type_ = 1;
bool feed_override_ = false;
bool speed_override_ = false;
bool adaptive_feed_ = false;
bool feed_hold_ = false;
bool mist_on_ = false;
bool flood_on_ = false;
std::unordered_map<int, double> tool_lengths_; std::unordered_map<int, double> tool_lengths_;
}; };

View File

@@ -19,6 +19,11 @@ CanonEventSink *active_sink = nullptr;
int active_line = 0; int active_line = 0;
bool flood_on = false; bool flood_on = false;
bool mist_on = false; bool mist_on = false;
bool block_delete = false;
bool optional_program_stop = false;
CANON_MOTION_MODE motion_control_mode = CANON_EXACT_STOP;
double motion_control_tolerance = 0.0;
double naivecam_tolerance = 0.0;
std::string parameter_file_name = "rs274ngc.var"; std::string parameter_file_name = "rs274ngc.var";
CncSimPose make_pose(double x, double y, double z, CncSimPose make_pose(double x, double y, double z,
@@ -102,14 +107,23 @@ void emit_state_event(CncSimEventType type, int reserved) {
active_sink->emit_raw(event); active_sink->emit_raw(event);
} }
void reset_bridge_state() {
flood_on = false;
mist_on = false;
block_delete = false;
optional_program_stop = false;
motion_control_mode = CANON_EXACT_STOP;
motion_control_tolerance = 0.0;
naivecam_tolerance = 0.0;
}
} // namespace } // namespace
void cnc_sim_linuxcnc_set_canon_sink(CanonEventSink *sink) { void cnc_sim_linuxcnc_set_canon_sink(CanonEventSink *sink) {
trace_call("cnc_sim_linuxcnc_set_canon_sink"); trace_call("cnc_sim_linuxcnc_set_canon_sink");
active_sink = sink; active_sink = sink;
active_line = 0; active_line = 0;
flood_on = false; reset_bridge_state();
mist_on = false;
} }
CanonEventSink *cnc_sim_linuxcnc_get_canon_sink() { CanonEventSink *cnc_sim_linuxcnc_get_canon_sink() {
@@ -125,8 +139,7 @@ void INIT_CANON() {
if (active_sink) { if (active_sink) {
active_sink->reset(); active_sink->reset();
} }
flood_on = false; reset_bridge_state();
mist_on = false;
} }
void USE_LENGTH_UNITS(CANON_UNITS units) { void USE_LENGTH_UNITS(CANON_UNITS units) {
@@ -291,19 +304,24 @@ void CANON_UPDATE_END_POINT(double x, double y, double z,
} }
} }
void SET_TRAVERSE_RATE(double) { void SET_TRAVERSE_RATE(double rate) {
if (active_sink) {
active_sink->set_traverse_rate(rate);
}
} }
void SET_FEED_REFERENCE(CANON_FEED_REFERENCE) { void SET_FEED_REFERENCE(CANON_FEED_REFERENCE) {
} }
void SET_FEED_MODE(int, int) { void SET_FEED_MODE(int spindle, int mode) {
if (active_sink) { if (active_sink) {
active_sink->set_feed_mode(0, event_line()); active_sink->set_feed_mode(spindle, mode, event_line());
} }
} }
void SET_MOTION_CONTROL_MODE(CANON_MOTION_MODE mode, double tolerance) { void SET_MOTION_CONTROL_MODE(CANON_MOTION_MODE mode, double tolerance) {
motion_control_mode = mode;
motion_control_tolerance = tolerance;
int reserved = 0; int reserved = 0;
switch (mode) { switch (mode) {
case CANON_EXACT_PATH: case CANON_EXACT_PATH:
@@ -330,7 +348,8 @@ void SET_MOTION_CONTROL_MODE(CANON_MOTION_MODE mode, double tolerance) {
} }
} }
void SET_NAIVECAM_TOLERANCE(double) { void SET_NAIVECAM_TOLERANCE(double tolerance) {
naivecam_tolerance = tolerance;
} }
void SET_CUTTER_RADIUS_COMPENSATION(double) { void SET_CUTTER_RADIUS_COMPENSATION(double) {
@@ -342,10 +361,16 @@ void START_CUTTER_RADIUS_COMPENSATION(int) {
void STOP_CUTTER_RADIUS_COMPENSATION() { void STOP_CUTTER_RADIUS_COMPENSATION() {
} }
void START_SPEED_FEED_SYNCH(int, double, bool) { void START_SPEED_FEED_SYNCH(int spindle, double feed_per_revolution, bool velocity_mode) {
if (active_sink) {
active_sink->set_speed_feed_sync(spindle, feed_per_revolution, velocity_mode, true, event_line());
}
} }
void STOP_SPEED_FEED_SYNCH() { void STOP_SPEED_FEED_SYNCH() {
if (active_sink) {
active_sink->set_speed_feed_sync(0, 0.0, false, false, event_line());
}
} }
void NURBS_G5_FEED(int lineno, const std::vector<NURBS_CONTROL_POINT> &points, unsigned int, CANON_PLANE) { void NURBS_G5_FEED(int lineno, const std::vector<NURBS_CONTROL_POINT> &points, unsigned int, CANON_PLANE) {
@@ -378,7 +403,7 @@ void RIGID_TAP(int lineno, double x, double y, double z, double) {
end.x = x; end.x = x;
end.y = y; end.y = y;
end.z = z; end.z = z;
active_sink->straight_feed(lineno, end); active_sink->straight_feed(event_line(lineno), end);
} }
} }
@@ -386,16 +411,21 @@ void STRAIGHT_PROBE(int lineno,
double x, double y, double z, double x, double y, double z,
double a, double b, double c, double a, double b, double c,
double u, double v, double w, double u, double v, double w,
unsigned char) { unsigned char probe_type) {
if (active_sink) { if (active_sink) {
active_sink->straight_probe(event_line(lineno), make_pose(x, y, z, a, b, c, u, v, w)); active_sink->straight_probe(event_line(lineno),
make_pose(x, y, z, a, b, c, u, v, w),
probe_type);
} }
} }
void STOP() { void STOP() {
} }
void SET_SPINDLE_MODE(int, double) { void SET_SPINDLE_MODE(int spindle, double mode) {
if (active_sink) {
active_sink->set_spindle_mode(spindle, mode, event_line());
}
} }
void SPINDLE_RETRACT_TRAVERSE() { void SPINDLE_RETRACT_TRAVERSE() {
@@ -422,10 +452,16 @@ void STOP_SPINDLE_TURNING(int) {
void SPINDLE_RETRACT() { void SPINDLE_RETRACT() {
} }
void ORIENT_SPINDLE(int, double, int) { void ORIENT_SPINDLE(int spindle, double orientation, int mode) {
if (active_sink) {
active_sink->orient_spindle(spindle, orientation, mode, event_line());
}
} }
void WAIT_SPINDLE_ORIENT_COMPLETE(int, double) { void WAIT_SPINDLE_ORIENT_COMPLETE(int spindle, double timeout) {
if (active_sink) {
active_sink->wait_spindle_orient_complete(spindle, timeout, event_line());
}
} }
void LOCK_SPINDLE_Z() { void LOCK_SPINDLE_Z() {
@@ -444,14 +480,16 @@ void USE_TOOL_LENGTH_OFFSET(const EmcPose &offset) {
if (!active_sink) { if (!active_sink) {
return; return;
} }
const CncSimPose tool_offset = make_pose(offset.tran.x, offset.tran.y, offset.tran.z,
offset.a, offset.b, offset.c,
offset.u, offset.v, offset.w);
active_sink->set_tool_length_offset(tool_offset);
CncSimEvent event{}; CncSimEvent event{};
event.version = 1; event.version = 1;
event.type = CNC_SIM_EVENT_COMMENT; event.type = CNC_SIM_EVENT_COMMENT;
event.line = event_line(); event.line = event_line();
event.reserved = 430; event.reserved = 430;
event.start = make_pose(offset.tran.x, offset.tran.y, offset.tran.z, event.start = tool_offset;
offset.a, offset.b, offset.c,
offset.u, offset.v, offset.w);
active_sink->emit_raw(event); active_sink->emit_raw(event);
} }
@@ -482,36 +520,66 @@ void COMMENT(const char *message) {
} }
void DISABLE_ADAPTIVE_FEED() { void DISABLE_ADAPTIVE_FEED() {
if (active_sink) {
active_sink->set_override_control(52, false, 0, event_line());
}
} }
void ENABLE_ADAPTIVE_FEED() { void ENABLE_ADAPTIVE_FEED() {
if (active_sink) {
active_sink->set_override_control(52, true, 0, event_line());
}
} }
void DISABLE_FEED_OVERRIDE() { void DISABLE_FEED_OVERRIDE() {
if (active_sink) {
active_sink->set_override_control(50, false, 0, event_line());
}
} }
void ENABLE_FEED_OVERRIDE() { void ENABLE_FEED_OVERRIDE() {
if (active_sink) {
active_sink->set_override_control(50, true, 0, event_line());
}
} }
void DISABLE_SPEED_OVERRIDE(int) { void DISABLE_SPEED_OVERRIDE(int spindle) {
if (active_sink) {
active_sink->set_override_control(51, false, spindle, event_line());
}
} }
void ENABLE_SPEED_OVERRIDE(int) { void ENABLE_SPEED_OVERRIDE(int spindle) {
if (active_sink) {
active_sink->set_override_control(51, true, spindle, event_line());
}
} }
void DISABLE_FEED_HOLD() { void DISABLE_FEED_HOLD() {
if (active_sink) {
active_sink->set_override_control(53, false, 0, event_line());
}
} }
void ENABLE_FEED_HOLD() { void ENABLE_FEED_HOLD() {
if (active_sink) {
active_sink->set_override_control(53, true, 0, event_line());
}
} }
void FLOOD_OFF() { void FLOOD_OFF() {
flood_on = false; flood_on = false;
if (active_sink) {
active_sink->set_flood_on(false);
}
emit_state_event(CNC_SIM_EVENT_COMMENT, 20); emit_state_event(CNC_SIM_EVENT_COMMENT, 20);
} }
void FLOOD_ON() { void FLOOD_ON() {
flood_on = true; flood_on = true;
if (active_sink) {
active_sink->set_flood_on(true);
}
emit_state_event(CNC_SIM_EVENT_COMMENT, 21); emit_state_event(CNC_SIM_EVENT_COMMENT, 21);
} }
@@ -532,11 +600,17 @@ void LOGCLOSE() {
void MIST_OFF() { void MIST_OFF() {
mist_on = false; mist_on = false;
if (active_sink) {
active_sink->set_mist_on(false);
}
emit_state_event(CNC_SIM_EVENT_COMMENT, 10); emit_state_event(CNC_SIM_EVENT_COMMENT, 10);
} }
void MIST_ON() { void MIST_ON() {
mist_on = true; mist_on = true;
if (active_sink) {
active_sink->set_mist_on(true);
}
emit_state_event(CNC_SIM_EVENT_COMMENT, 11); emit_state_event(CNC_SIM_EVENT_COMMENT, 11);
} }
@@ -564,11 +638,12 @@ void NURB_CONTROL_POINT(int, double, double, double, double) {
void NURB_FEED(double, double) { void NURB_FEED(double, double) {
} }
void SET_BLOCK_DELETE(bool) { void SET_BLOCK_DELETE(bool enabled) {
block_delete = enabled;
} }
bool GET_BLOCK_DELETE(void) { bool GET_BLOCK_DELETE(void) {
return false; return block_delete;
} }
void OPTIONAL_PROGRAM_STOP() { void OPTIONAL_PROGRAM_STOP() {
@@ -577,11 +652,12 @@ void OPTIONAL_PROGRAM_STOP() {
} }
} }
void SET_OPTIONAL_PROGRAM_STOP(bool) { void SET_OPTIONAL_PROGRAM_STOP(bool state) {
optional_program_stop = state;
} }
bool GET_OPTIONAL_PROGRAM_STOP() { bool GET_OPTIONAL_PROGRAM_STOP() {
return false; return optional_program_stop;
} }
void PROGRAM_STOP() { void PROGRAM_STOP() {
@@ -590,25 +666,46 @@ void PROGRAM_STOP() {
} }
} }
void SET_MOTION_OUTPUT_BIT(int) { void SET_MOTION_OUTPUT_BIT(int index) {
if (active_sink) {
active_sink->set_digital_output(index, true, true, event_line());
}
} }
void CLEAR_MOTION_OUTPUT_BIT(int) { void CLEAR_MOTION_OUTPUT_BIT(int index) {
if (active_sink) {
active_sink->set_digital_output(index, false, true, event_line());
}
} }
void SET_AUX_OUTPUT_BIT(int) { void SET_AUX_OUTPUT_BIT(int index) {
if (active_sink) {
active_sink->set_digital_output(index, true, false, event_line());
}
} }
void CLEAR_AUX_OUTPUT_BIT(int) { void CLEAR_AUX_OUTPUT_BIT(int index) {
if (active_sink) {
active_sink->set_digital_output(index, false, false, event_line());
}
} }
void SET_MOTION_OUTPUT_VALUE(int, double) { void SET_MOTION_OUTPUT_VALUE(int index, double value) {
if (active_sink) {
active_sink->set_analog_output(index, value, true, event_line());
}
} }
void SET_AUX_OUTPUT_VALUE(int, double) { void SET_AUX_OUTPUT_VALUE(int index, double value) {
if (active_sink) {
active_sink->set_analog_output(index, value, false, event_line());
}
} }
int WAIT(int, int, int wait_type, double) { int WAIT(int index, int input_type, int wait_type, double timeout) {
if (active_sink) {
active_sink->wait_input(index, input_type, wait_type, timeout, event_line());
}
return wait_type; return wait_type;
} }
@@ -645,15 +742,15 @@ int GET_EXTERNAL_MIST() {
} }
CANON_MOTION_MODE GET_EXTERNAL_MOTION_CONTROL_MODE() { CANON_MOTION_MODE GET_EXTERNAL_MOTION_CONTROL_MODE() {
return CANON_EXACT_STOP; return motion_control_mode;
} }
double GET_EXTERNAL_MOTION_CONTROL_TOLERANCE() { double GET_EXTERNAL_MOTION_CONTROL_TOLERANCE() {
return 0.0; return motion_control_tolerance;
} }
double GET_EXTERNAL_MOTION_CONTROL_NAIVECAM_TOLERANCE() { double GET_EXTERNAL_MOTION_CONTROL_NAIVECAM_TOLERANCE() {
return 0.0; return naivecam_tolerance;
} }
void GET_EXTERNAL_PARAMETER_FILE_NAME(char *filename, int max_size) { void GET_EXTERNAL_PARAMETER_FILE_NAME(char *filename, int max_size) {
@@ -680,22 +777,22 @@ double GET_EXTERNAL_POSITION_U() { return current_position().u; }
double GET_EXTERNAL_POSITION_V() { return current_position().v; } double GET_EXTERNAL_POSITION_V() { return current_position().v; }
double GET_EXTERNAL_POSITION_W() { return current_position().w; } double GET_EXTERNAL_POSITION_W() { return current_position().w; }
double GET_EXTERNAL_PROBE_POSITION_A() { return current_position().a; } double GET_EXTERNAL_PROBE_POSITION_A() { return active_sink ? active_sink->probe_position().a : 0.0; }
double GET_EXTERNAL_PROBE_POSITION_B() { return current_position().b; } double GET_EXTERNAL_PROBE_POSITION_B() { return active_sink ? active_sink->probe_position().b : 0.0; }
double GET_EXTERNAL_PROBE_POSITION_C() { return current_position().c; } double GET_EXTERNAL_PROBE_POSITION_C() { return active_sink ? active_sink->probe_position().c : 0.0; }
double GET_EXTERNAL_PROBE_POSITION_X() { return current_position().x; } double GET_EXTERNAL_PROBE_POSITION_X() { return active_sink ? active_sink->probe_position().x : 0.0; }
double GET_EXTERNAL_PROBE_POSITION_Y() { return current_position().y; } double GET_EXTERNAL_PROBE_POSITION_Y() { return active_sink ? active_sink->probe_position().y : 0.0; }
double GET_EXTERNAL_PROBE_POSITION_Z() { return current_position().z; } double GET_EXTERNAL_PROBE_POSITION_Z() { return active_sink ? active_sink->probe_position().z : 0.0; }
double GET_EXTERNAL_PROBE_POSITION_U() { return current_position().u; } double GET_EXTERNAL_PROBE_POSITION_U() { return active_sink ? active_sink->probe_position().u : 0.0; }
double GET_EXTERNAL_PROBE_POSITION_V() { return current_position().v; } double GET_EXTERNAL_PROBE_POSITION_V() { return active_sink ? active_sink->probe_position().v : 0.0; }
double GET_EXTERNAL_PROBE_POSITION_W() { return current_position().w; } double GET_EXTERNAL_PROBE_POSITION_W() { return active_sink ? active_sink->probe_position().w : 0.0; }
double GET_EXTERNAL_PROBE_VALUE() { double GET_EXTERNAL_PROBE_VALUE() {
return 0.0; return 0.0;
} }
int GET_EXTERNAL_PROBE_TRIPPED_VALUE() { int GET_EXTERNAL_PROBE_TRIPPED_VALUE() {
return 0; return active_sink && active_sink->probe_tripped() ? 1 : 0;
} }
int GET_EXTERNAL_QUEUE_EMPTY() { int GET_EXTERNAL_QUEUE_EMPTY() {
@@ -719,15 +816,15 @@ CANON_DIRECTION GET_EXTERNAL_SPINDLE(int) {
return CANON_STOPPED; return CANON_STOPPED;
} }
double GET_EXTERNAL_TOOL_LENGTH_XOFFSET() { return 0.0; } double GET_EXTERNAL_TOOL_LENGTH_XOFFSET() { return active_sink ? active_sink->tool_length_offset().x : 0.0; }
double GET_EXTERNAL_TOOL_LENGTH_YOFFSET() { return 0.0; } double GET_EXTERNAL_TOOL_LENGTH_YOFFSET() { return active_sink ? active_sink->tool_length_offset().y : 0.0; }
double GET_EXTERNAL_TOOL_LENGTH_ZOFFSET() { return 0.0; } double GET_EXTERNAL_TOOL_LENGTH_ZOFFSET() { return active_sink ? active_sink->tool_length_offset().z : 0.0; }
double GET_EXTERNAL_TOOL_LENGTH_AOFFSET() { return 0.0; } double GET_EXTERNAL_TOOL_LENGTH_AOFFSET() { return active_sink ? active_sink->tool_length_offset().a : 0.0; }
double GET_EXTERNAL_TOOL_LENGTH_BOFFSET() { return 0.0; } double GET_EXTERNAL_TOOL_LENGTH_BOFFSET() { return active_sink ? active_sink->tool_length_offset().b : 0.0; }
double GET_EXTERNAL_TOOL_LENGTH_COFFSET() { return 0.0; } double GET_EXTERNAL_TOOL_LENGTH_COFFSET() { return active_sink ? active_sink->tool_length_offset().c : 0.0; }
double GET_EXTERNAL_TOOL_LENGTH_UOFFSET() { return 0.0; } double GET_EXTERNAL_TOOL_LENGTH_UOFFSET() { return active_sink ? active_sink->tool_length_offset().u : 0.0; }
double GET_EXTERNAL_TOOL_LENGTH_VOFFSET() { return 0.0; } double GET_EXTERNAL_TOOL_LENGTH_VOFFSET() { return active_sink ? active_sink->tool_length_offset().v : 0.0; }
double GET_EXTERNAL_TOOL_LENGTH_WOFFSET() { return 0.0; } double GET_EXTERNAL_TOOL_LENGTH_WOFFSET() { return active_sink ? active_sink->tool_length_offset().w : 0.0; }
int GET_EXTERNAL_TOOL_SLOT() { int GET_EXTERNAL_TOOL_SLOT() {
return active_sink ? active_sink->selected_tool() : 0; return active_sink ? active_sink->selected_tool() : 0;
@@ -755,23 +852,23 @@ int GET_EXTERNAL_TC_REASON() {
} }
double GET_EXTERNAL_TRAVERSE_RATE() { double GET_EXTERNAL_TRAVERSE_RATE() {
return 0.0; return active_sink ? active_sink->traverse_rate() : 0.0;
} }
int GET_EXTERNAL_FEED_OVERRIDE_ENABLE() { int GET_EXTERNAL_FEED_OVERRIDE_ENABLE() {
return 1; return active_sink ? (active_sink->feed_override() ? 1 : 0) : 1;
} }
int GET_EXTERNAL_SPINDLE_OVERRIDE_ENABLE(int) { int GET_EXTERNAL_SPINDLE_OVERRIDE_ENABLE(int) {
return 1; return active_sink ? (active_sink->speed_override() ? 1 : 0) : 1;
} }
int GET_EXTERNAL_ADAPTIVE_FEED_ENABLE() { int GET_EXTERNAL_ADAPTIVE_FEED_ENABLE() {
return 1; return active_sink ? (active_sink->adaptive_feed() ? 1 : 0) : 1;
} }
int GET_EXTERNAL_FEED_HOLD_ENABLE() { int GET_EXTERNAL_FEED_HOLD_ENABLE() {
return 1; return active_sink ? (active_sink->feed_hold() ? 1 : 0) : 1;
} }
int GET_EXTERNAL_DIGITAL_INPUT(int, int def) { int GET_EXTERNAL_DIGITAL_INPUT(int, int def) {

File diff suppressed because it is too large Load Diff

View File

@@ -14,6 +14,10 @@ public:
private: private:
CanonEventSink &sink_; CanonEventSink &sink_;
bool absolute_ = true; bool absolute_ = true;
bool arc_absolute_ = false;
bool lathe_diameter_mode_ = false;
bool cutter_comp_on_ = false;
int feed_mode_ = 0;
int canned_cycle_ = 0; int canned_cycle_ = 0;
bool canned_return_to_initial_ = false; bool canned_return_to_initial_ = false;
bool canned_has_r_ = false; bool canned_has_r_ = false;
@@ -21,9 +25,17 @@ private:
bool canned_has_p_ = false; bool canned_has_p_ = false;
bool canned_has_q_ = false; bool canned_has_q_ = false;
bool canned_has_d_ = false; bool canned_has_d_ = false;
bool canned_has_i_ = false;
bool canned_has_j_ = false;
bool canned_has_k_ = false;
double canned_r_ = 0.0; double canned_r_ = 0.0;
double canned_z_ = 0.0; double canned_z_ = 0.0;
double canned_p_ = 0.0; double canned_p_ = 0.0;
double canned_q_ = 0.0; double canned_q_ = 0.0;
double canned_d_ = 1.0; double canned_d_ = 1.0;
double canned_i_ = 0.0;
double canned_j_ = 0.0;
double canned_k_ = 0.0;
double oword_return_value_ = 0.0;
bool oword_value_returned_ = false;
}; };

View File

@@ -30,6 +30,27 @@ bool near(double lhs, double rhs) {
return std::fabs(lhs - rhs) < 0.000001; return std::fabs(lhs - rhs) < 0.000001;
} }
bool saw_comment_state(const std::vector<CncSimEvent> &events,
int line,
int reserved,
int tool,
double feed,
int arc_turns = 0,
double dwell_seconds = 0.0) {
for (const auto &event : events) {
if (event.type == CNC_SIM_EVENT_COMMENT &&
event.line == line &&
event.reserved == reserved &&
event.tool == tool &&
near(event.feed, feed) &&
event.arc_turns == arc_turns &&
near(event.dwell_seconds, dwell_seconds)) {
return true;
}
}
return false;
}
} // namespace } // namespace
int main() { int main() {
@@ -73,14 +94,30 @@ int main() {
bool saw_g5x_offset = false; bool saw_g5x_offset = false;
bool saw_xy_rotation = false; bool saw_xy_rotation = false;
bool saw_g92_clear = false; bool saw_g92_clear = false;
bool saw_g92_suspend = false;
bool saw_g92_restore = false;
bool saw_g92_restore_after_clear = false;
bool saw_g52_initial = false;
bool saw_g52_sticky_axis = false;
bool saw_g52_suspend = false;
bool saw_g52_restore = false;
bool saw_g52_end_line = false;
bool saw_coordinate_end_line = false; bool saw_coordinate_end_line = false;
bool saw_l20_g55_offset = false; bool saw_l20_g55_offset = false;
bool saw_l20_end_line = false; bool saw_l20_end_line = false;
bool saw_g10_p0_g55 = false;
bool saw_g10_p0_end_line = false;
bool saw_probe = false; bool saw_probe = false;
bool saw_probe_error_variant = false;
bool saw_probe_no_error_variant = false;
bool saw_probe_clear_error_variant = false;
bool saw_probe_clear_no_error_variant = false;
bool saw_probe_as_feed = false; bool saw_probe_as_feed = false;
bool saw_spindle_cw = false; bool saw_spindle_cw = false;
bool saw_spindle_ccw = false; bool saw_spindle_ccw = false;
bool saw_spindle_stop = false; bool saw_spindle_stop = false;
bool saw_spindle_orient = false;
bool saw_spindle_orient_wait = false;
bool saw_comment_line = false; bool saw_comment_line = false;
bool saw_tool_number_line = false; bool saw_tool_number_line = false;
bool saw_program_stop = false; bool saw_program_stop = false;
@@ -96,9 +133,33 @@ int main() {
bool saw_g95_mode = false; bool saw_g95_mode = false;
bool saw_g94_feed_mode = false; bool saw_g94_feed_mode = false;
bool saw_g95_feed_mode = false; bool saw_g95_feed_mode = false;
bool saw_g96_mode = false;
bool saw_g97_mode = false;
bool saw_g33_sync_start = false;
bool saw_g33_sync_stop = false;
bool saw_g33_thread_line = false;
bool saw_g331_sync_start = false;
bool saw_g331_sync_stop = false;
bool saw_g331_rigid_tap_line = false;
bool saw_g61_mode = false; bool saw_g61_mode = false;
bool saw_g611_mode = false; bool saw_g611_mode = false;
bool saw_g64_mode = false; bool saw_g64_mode = false;
bool saw_g18_arc = false;
bool saw_g19_arc = false;
bool saw_g911_arc = false;
bool saw_g901_arc = false;
bool saw_g911_restored_arc = false;
bool saw_g28_waypoint = false;
bool saw_g28_home_axis = false;
bool saw_g30_waypoint = false;
bool saw_g30_home_all_axes = false;
bool saw_g53_rapid = false;
bool saw_g53_modal_rapid = false;
bool saw_g53_feed = false;
bool saw_g431_tool_length = false;
bool saw_g432_tool_length = false;
bool saw_g432_h_tool_length = false;
bool saw_g49_dynamic_tool_length_clear = false;
bool saw_tool_length = false; bool saw_tool_length = false;
bool saw_tool_length_clear = false; bool saw_tool_length_clear = false;
bool saw_cutter_left_first = false; bool saw_cutter_left_first = false;
@@ -159,6 +220,229 @@ int main() {
ok &= expect(saw_g49, "expected LinuxCNC G49 RTCP off state"); ok &= expect(saw_g49, "expected LinuxCNC G49 RTCP off state");
ok &= expect(saw_g434, "expected LinuxCNC G43.4 RTCP on state with H code"); ok &= expect(saw_g434, "expected LinuxCNC G43.4 RTCP on state with H code");
const char arc_planes_program[] =
"G21 G90 G17\n"
"G0 X0 Y0 Z0\n"
"F100\n"
"G18\n"
"G2 X10 Z0 I5 K0\n"
"G0 X0 Y0 Z0\n"
"G19\n"
"G3 Y10 Z0 J5 K0\n"
"M30\n";
events.clear();
ok &= expect(cnc_sim_parse_program(sim, arc_planes_program, sizeof(arc_planes_program) - 1) == 0,
cnc_sim_last_error(sim));
for (const auto &event : events) {
saw_g18_arc = saw_g18_arc ||
(event.type == CNC_SIM_EVENT_ARC_FEED &&
event.line == 5 &&
event.plane == 18 &&
event.start.x == 0.0 &&
event.start.z == 0.0 &&
event.end.x == 10.0 &&
event.end.z == 0.0 &&
event.center.x == 5.0 &&
event.center.z == 0.0 &&
event.arc_turns == -1);
saw_g19_arc = saw_g19_arc ||
(event.type == CNC_SIM_EVENT_ARC_FEED &&
event.line == 8 &&
event.plane == 19 &&
event.start.y == 0.0 &&
event.start.z == 0.0 &&
event.end.y == 10.0 &&
event.end.z == 0.0 &&
event.center.y == 5.0 &&
event.center.z == 0.0 &&
event.arc_turns == 1);
}
ok &= expect(saw_g18_arc, "expected LinuxCNC G18 XZ arc center mapping");
ok &= expect(saw_g19_arc, "expected LinuxCNC G19 YZ arc center mapping");
const char arc_distance_program[] =
"G21 G90 G17\n"
"G0 X0 Y0 Z0\n"
"F100\n"
"G91.1\n"
"G3 X10 Y0 I5 J0\n"
"G90.1\n"
"G3 X20 Y0 I15 J0\n"
"G91.1\n"
"G3 X30 Y0 I5 J0\n"
"M30\n";
events.clear();
ok &= expect(cnc_sim_parse_program(sim, arc_distance_program, sizeof(arc_distance_program) - 1) == 0,
cnc_sim_last_error(sim));
for (const auto &event : events) {
saw_g911_arc = saw_g911_arc ||
(event.type == CNC_SIM_EVENT_ARC_FEED &&
event.line == 5 &&
event.center.x == 5.0 &&
event.center.y == 0.0);
saw_g901_arc = saw_g901_arc ||
(event.type == CNC_SIM_EVENT_ARC_FEED &&
event.line == 7 &&
event.center.x == 15.0 &&
event.center.y == 0.0);
saw_g911_restored_arc = saw_g911_restored_arc ||
(event.type == CNC_SIM_EVENT_ARC_FEED &&
event.line == 9 &&
event.center.x == 25.0 &&
event.center.y == 0.0);
}
ok &= expect(saw_g911_arc, "expected LinuxCNC G91.1 incremental IJK arc center");
ok &= expect(saw_g901_arc, "expected LinuxCNC G90.1 absolute IJK arc center");
ok &= expect(saw_g911_restored_arc, "expected LinuxCNC G91.1 restored incremental IJK arc center");
const char predefined_position_program[] =
"G21 G90 G17\n"
"G0 X1 Y2 Z3\n"
"G28.1\n"
"G0 X10 Y20 Z30\n"
"G28 Z5\n"
"G0 X4 Y5 Z6\n"
"G30.1\n"
"G0 X40 Y50 Z60\n"
"G30\n"
"M30\n";
events.clear();
ok &= expect(cnc_sim_parse_program(sim,
predefined_position_program,
sizeof(predefined_position_program) - 1) == 0,
cnc_sim_last_error(sim));
for (const auto &event : events) {
saw_g28_waypoint = saw_g28_waypoint ||
(event.type == CNC_SIM_EVENT_RAPID &&
event.line == 5 &&
event.start.x == 10.0 &&
event.start.y == 20.0 &&
event.start.z == 30.0 &&
event.end.x == 10.0 &&
event.end.y == 20.0 &&
event.end.z == 5.0);
saw_g28_home_axis = saw_g28_home_axis ||
(event.type == CNC_SIM_EVENT_RAPID &&
event.line == 5 &&
event.start.x == 10.0 &&
event.start.y == 20.0 &&
event.start.z == 5.0 &&
event.end.x == 10.0 &&
event.end.y == 20.0 &&
event.end.z == 3.0);
saw_g30_home_all_axes = saw_g30_home_all_axes ||
(event.type == CNC_SIM_EVENT_RAPID &&
event.line == 9 &&
event.start.x == 40.0 &&
event.start.y == 50.0 &&
event.start.z == 60.0 &&
event.end.x == 4.0 &&
event.end.y == 5.0 &&
event.end.z == 6.0);
saw_g30_waypoint = saw_g30_waypoint ||
(event.type == CNC_SIM_EVENT_RAPID &&
event.line == 9 &&
event.start.x == 40.0 &&
event.start.y == 50.0 &&
event.start.z == 60.0 &&
event.end.x == 40.0 &&
event.end.y == 50.0 &&
event.end.z == 60.0);
}
ok &= expect(saw_g28_waypoint, "expected LinuxCNC G28 waypoint rapid");
ok &= expect(saw_g28_home_axis, "expected LinuxCNC G28 selected-axis home rapid");
ok &= expect(saw_g30_waypoint, "expected LinuxCNC G30 waypoint rapid");
ok &= expect(saw_g30_home_all_axes, "expected LinuxCNC G30 all-axis home rapid");
const char machine_coordinate_program[] =
"G21 G90 G17\n"
"G0 X5 Y6 Z7\n"
"G53 G0 X0 Z1\n"
"G53 X2\n"
"G1 F100\n"
"G53 G1 Y3\n"
"M30\n";
events.clear();
ok &= expect(cnc_sim_parse_program(sim,
machine_coordinate_program,
sizeof(machine_coordinate_program) - 1) == 0,
cnc_sim_last_error(sim));
for (const auto &event : events) {
saw_g53_rapid = saw_g53_rapid ||
(event.type == CNC_SIM_EVENT_RAPID &&
event.line == 3 &&
event.start.x == 5.0 &&
event.start.y == 6.0 &&
event.start.z == 7.0 &&
event.end.x == 0.0 &&
event.end.y == 6.0 &&
event.end.z == 1.0);
saw_g53_modal_rapid = saw_g53_modal_rapid ||
(event.type == CNC_SIM_EVENT_RAPID &&
event.line == 4 &&
event.start.x == 0.0 &&
event.start.y == 6.0 &&
event.start.z == 1.0 &&
event.end.x == 2.0 &&
event.end.y == 6.0 &&
event.end.z == 1.0);
saw_g53_feed = saw_g53_feed ||
(event.type == CNC_SIM_EVENT_LINEAR_FEED &&
event.line == 6 &&
event.start.x == 2.0 &&
event.start.y == 6.0 &&
event.start.z == 1.0 &&
event.end.x == 2.0 &&
event.end.y == 3.0 &&
event.end.z == 1.0);
}
ok &= expect(saw_g53_rapid, "expected LinuxCNC G53 explicit rapid move");
ok &= expect(saw_g53_modal_rapid, "expected LinuxCNC G53 modal rapid move");
ok &= expect(saw_g53_feed, "expected LinuxCNC G53 feed move");
const char dynamic_tool_length_program[] =
"G21 G90 G17\n"
"G43.1 X1 Z2\n"
"G43.2 X0.25 Z0.5\n"
"G43.2 H1\n"
"G49\n"
"M30\n";
events.clear();
ok &= expect(cnc_sim_parse_program(sim,
dynamic_tool_length_program,
sizeof(dynamic_tool_length_program) - 1) == 0,
cnc_sim_last_error(sim));
for (const auto &event : events) {
saw_g431_tool_length = saw_g431_tool_length ||
(event.type == CNC_SIM_EVENT_COMMENT &&
event.line == 2 &&
event.reserved == 430 &&
event.start.x == 1.0 &&
event.start.z == 2.0);
saw_g432_tool_length = saw_g432_tool_length ||
(event.type == CNC_SIM_EVENT_COMMENT &&
event.line == 3 &&
event.reserved == 430 &&
event.start.x == 1.25 &&
event.start.z == 2.5);
saw_g49_dynamic_tool_length_clear = saw_g49_dynamic_tool_length_clear ||
(event.type == CNC_SIM_EVENT_COMMENT &&
event.line == 5 &&
event.reserved == 430 &&
event.start.x == 0.0 &&
event.start.z == 0.0);
saw_g432_h_tool_length = saw_g432_h_tool_length ||
(event.type == CNC_SIM_EVENT_COMMENT &&
event.line == 4 &&
event.reserved == 430 &&
event.start.x == 1.25 &&
event.start.z == 15.0);
}
ok &= expect(saw_g431_tool_length, "expected LinuxCNC G43.1 dynamic tool length event");
ok &= expect(saw_g432_tool_length, "expected LinuxCNC G43.2 additive tool length event");
ok &= expect(saw_g432_h_tool_length, "expected LinuxCNC G43.2 H tool-table additive event");
ok &= expect(saw_g49_dynamic_tool_length_clear, "expected LinuxCNC G49 dynamic tool length clear event");
const char spindle_program[] = const char spindle_program[] =
"G21 G90 G17\n" "G21 G90 G17\n"
"S1200 M3\n" "S1200 M3\n"
@@ -189,6 +473,249 @@ int main() {
ok &= expect(saw_spindle_ccw, "expected LinuxCNC M4 counterclockwise spindle state"); ok &= expect(saw_spindle_ccw, "expected LinuxCNC M4 counterclockwise spindle state");
ok &= expect(saw_spindle_stop, "expected LinuxCNC M5 stopped spindle state"); ok &= expect(saw_spindle_stop, "expected LinuxCNC M5 stopped spindle state");
const char spindle_mode_program[] =
"G21 G90 G17\n"
"G97 S1000\n"
"G96 S120 D2500\n"
"G97 S900\n"
"M30\n";
events.clear();
ok &= expect(cnc_sim_parse_program(sim, spindle_mode_program, sizeof(spindle_mode_program) - 1) == 0,
cnc_sim_last_error(sim));
for (const auto &event : events) {
saw_g97_mode = saw_g97_mode ||
(event.type == CNC_SIM_EVENT_COMMENT &&
event.line == 2 &&
event.reserved == 970 &&
event.feed == 0.0);
saw_g96_mode = saw_g96_mode ||
(event.type == CNC_SIM_EVENT_COMMENT &&
event.line == 3 &&
event.reserved == 960 &&
event.feed == 2500.0);
}
ok &= expect(saw_g97_mode, "expected LinuxCNC G97 constant-RPM spindle mode state");
ok &= expect(saw_g96_mode, "expected LinuxCNC G96 CSS spindle mode state");
const char spindle_orient_program[] =
"G21 G90 G17\n"
"M19 R45 P1 Q2\n"
"M30\n";
events.clear();
ok &= expect(cnc_sim_parse_program(sim, spindle_orient_program, sizeof(spindle_orient_program) - 1) == 0,
cnc_sim_last_error(sim));
for (const auto &event : events) {
saw_spindle_orient = saw_spindle_orient ||
(event.type == CNC_SIM_EVENT_COMMENT &&
event.line == 2 &&
event.reserved == 1901 &&
event.tool == 0 &&
event.feed == 45.0 &&
event.arc_turns == 1);
saw_spindle_orient_wait = saw_spindle_orient_wait ||
(event.type == CNC_SIM_EVENT_COMMENT &&
event.line == 2 &&
event.reserved == 1902 &&
event.tool == 0 &&
event.dwell_seconds == 2.0);
}
ok &= expect(saw_spindle_orient, "expected LinuxCNC M19 spindle orient state");
ok &= expect(saw_spindle_orient_wait, "expected LinuxCNC M19 spindle orient wait state");
const char io_controls_program[] =
"G21 G90 G17\n"
"M62 P1\n"
"M63 P1\n"
"M64 P2\n"
"M65 P2\n"
"M66 P0 L3 Q5\n"
"M66 E1 L0\n"
"M67 E0 Q1.25\n"
"M68 E1 Q2.5\n"
"M30\n";
events.clear();
ok &= expect(cnc_sim_parse_program(sim, io_controls_program, sizeof(io_controls_program) - 1) == 0,
cnc_sim_last_error(sim));
bool saw_m62 = false;
bool saw_m63 = false;
bool saw_m64 = false;
bool saw_m65 = false;
bool saw_m66_digital = false;
bool saw_m66_analog = false;
bool saw_m67 = false;
bool saw_m68 = false;
for (const auto &event : events) {
saw_m62 = saw_m62 || (event.type == CNC_SIM_EVENT_COMMENT &&
event.line == 2 &&
event.reserved == 62 &&
event.tool == 1 &&
event.feed == 1.0);
saw_m63 = saw_m63 || (event.type == CNC_SIM_EVENT_COMMENT &&
event.line == 3 &&
event.reserved == 63 &&
event.tool == 1 &&
event.feed == 0.0);
saw_m64 = saw_m64 || (event.type == CNC_SIM_EVENT_COMMENT &&
event.line == 4 &&
event.reserved == 64 &&
event.tool == 2 &&
event.feed == 1.0);
saw_m65 = saw_m65 || (event.type == CNC_SIM_EVENT_COMMENT &&
event.line == 5 &&
event.reserved == 65 &&
event.tool == 2 &&
event.feed == 0.0);
saw_m66_digital = saw_m66_digital || (event.type == CNC_SIM_EVENT_COMMENT &&
event.line == 6 &&
event.reserved == 66 &&
event.tool == 0 &&
event.arc_turns == 1 &&
event.feed == 3.0 &&
event.dwell_seconds == 5.0);
saw_m66_analog = saw_m66_analog || (event.type == CNC_SIM_EVENT_COMMENT &&
event.line == 7 &&
event.reserved == 66 &&
event.tool == 1 &&
event.arc_turns == 0 &&
event.feed == 0.0 &&
event.dwell_seconds == 0.0);
saw_m67 = saw_m67 || (event.type == CNC_SIM_EVENT_COMMENT &&
event.line == 8 &&
event.reserved == 67 &&
event.tool == 0 &&
event.feed == 1.25);
saw_m68 = saw_m68 || (event.type == CNC_SIM_EVENT_COMMENT &&
event.line == 9 &&
event.reserved == 68 &&
event.tool == 1 &&
event.feed == 2.5);
}
ok &= expect(saw_m62, "expected LinuxCNC M62 motion digital output on state");
ok &= expect(saw_m63, "expected LinuxCNC M63 motion digital output off state");
ok &= expect(saw_m64, "expected LinuxCNC M64 auxiliary digital output on state");
ok &= expect(saw_m65, "expected LinuxCNC M65 auxiliary digital output off state");
ok &= expect(saw_m66_digital, "expected LinuxCNC M66 digital input wait state");
ok &= expect(saw_m66_analog, "expected LinuxCNC M66 analog input wait state");
ok &= expect(saw_m67, "expected LinuxCNC M67 motion analog output state");
ok &= expect(saw_m68, "expected LinuxCNC M68 auxiliary analog output state");
const char override_controls_program[] =
"G21 G90 G17\n"
"M48\n"
"M49\n"
"M50 P1\n"
"M50 P0\n"
"M51 P1\n"
"M51 P0\n"
"M52 P1\n"
"M52 P0\n"
"M53 P1\n"
"M53 P0\n"
"M30\n";
events.clear();
ok &= expect(cnc_sim_parse_program(sim, override_controls_program, sizeof(override_controls_program) - 1) == 0,
cnc_sim_last_error(sim));
ok &= expect(saw_comment_state(events, 2, 50, 0, 1.0), "expected LinuxCNC M48 feed override enable state");
ok &= expect(saw_comment_state(events, 2, 51, 0, 1.0), "expected LinuxCNC M48 speed override enable state");
ok &= expect(saw_comment_state(events, 3, 50, 0, 0.0), "expected LinuxCNC M49 feed override disable state");
ok &= expect(saw_comment_state(events, 3, 51, 0, 0.0), "expected LinuxCNC M49 speed override disable state");
ok &= expect(saw_comment_state(events, 4, 50, 0, 1.0), "expected LinuxCNC M50 feed override enable state");
ok &= expect(saw_comment_state(events, 5, 50, 0, 0.0), "expected LinuxCNC M50 feed override disable state");
ok &= expect(saw_comment_state(events, 6, 51, 0, 1.0), "expected LinuxCNC M51 speed override enable state");
ok &= expect(saw_comment_state(events, 7, 51, 0, 0.0), "expected LinuxCNC M51 speed override disable state");
ok &= expect(saw_comment_state(events, 8, 52, 0, 1.0), "expected LinuxCNC M52 adaptive feed enable state");
ok &= expect(saw_comment_state(events, 9, 52, 0, 0.0), "expected LinuxCNC M52 adaptive feed disable state");
ok &= expect(saw_comment_state(events, 10, 53, 0, 1.0), "expected LinuxCNC M53 feed hold enable state");
ok &= expect(saw_comment_state(events, 11, 53, 0, 0.0), "expected LinuxCNC M53 feed hold disable state");
const char modal_state_program[] =
"G21 G90 G17\n"
"G0 X0 Y0 Z0\n"
"M70\n"
"G91 G18 G20\n"
"G0 X1 Z1\n"
"M72\n"
"G0 X2 Y0 Z2\n"
"F100 G2 X4 Y0 I1 J0\n"
"M30\n";
events.clear();
ok &= expect(cnc_sim_parse_program(sim, modal_state_program, sizeof(modal_state_program) - 1) == 0,
cnc_sim_last_error(sim));
bool saw_modal_restored_absolute_mm = false;
bool saw_modal_restored_xy_arc = false;
for (const auto &event : events) {
saw_modal_restored_absolute_mm = saw_modal_restored_absolute_mm ||
(event.type == CNC_SIM_EVENT_RAPID &&
event.line == 7 &&
near(event.end.x, 2.0) &&
near(event.end.y, 0.0) &&
near(event.end.z, 2.0));
saw_modal_restored_xy_arc = saw_modal_restored_xy_arc ||
(event.type == CNC_SIM_EVENT_ARC_FEED &&
event.line == 8 &&
event.plane == 17 &&
near(event.end.x, 4.0) &&
near(event.end.y, 0.0));
}
ok &= expect(saw_modal_restored_absolute_mm, "expected LinuxCNC M72 restored absolute millimeter move");
ok &= expect(saw_modal_restored_xy_arc, "expected LinuxCNC M72 restored XY plane arc");
const char modal_invalidate_program[] =
"G21 G90 G17\n"
"M70\n"
"M71\n"
"M72\n"
"M30\n";
events.clear();
ok &= expect(cnc_sim_parse_program(sim, modal_invalidate_program, sizeof(modal_invalidate_program) - 1) != 0,
"expected LinuxCNC M71 invalidated modal state to reject M72 restore");
const char threading_sync_program[] =
"G21 G90 G17\n"
"S500 M3\n"
"G0 Z5\n"
"G33 Z0 K1\n"
"G0 Z5\n"
"G33.1 Z0 K1\n"
"M30\n";
events.clear();
ok &= expect(cnc_sim_parse_program(sim, threading_sync_program, sizeof(threading_sync_program) - 1) == 0,
cnc_sim_last_error(sim));
for (const auto &event : events) {
saw_g33_sync_start = saw_g33_sync_start ||
(event.type == CNC_SIM_EVENT_COMMENT &&
event.line == 4 &&
event.reserved == 3301 &&
event.feed == 1.0);
saw_g33_sync_stop = saw_g33_sync_stop ||
(event.type == CNC_SIM_EVENT_COMMENT &&
event.line == 4 &&
event.reserved == 3300);
saw_g33_thread_line = saw_g33_thread_line ||
(event.type == CNC_SIM_EVENT_LINEAR_FEED &&
event.line == 4 &&
event.end.z == 0.0);
saw_g331_sync_start = saw_g331_sync_start ||
(event.type == CNC_SIM_EVENT_COMMENT &&
event.line == 6 &&
event.reserved == 3301 &&
event.feed == 1.0);
saw_g331_sync_stop = saw_g331_sync_stop ||
(event.type == CNC_SIM_EVENT_COMMENT &&
event.line == 6 &&
event.reserved == 3300);
saw_g331_rigid_tap_line = saw_g331_rigid_tap_line ||
(event.type == CNC_SIM_EVENT_LINEAR_FEED &&
event.line == 6 &&
event.end.z == 0.0);
}
ok &= expect(saw_g33_sync_start, "expected LinuxCNC G33 speed-feed sync start");
ok &= expect(saw_g33_sync_stop, "expected LinuxCNC G33 speed-feed sync stop");
ok &= expect(saw_g33_thread_line, "expected LinuxCNC G33 threading feed line");
ok &= expect(saw_g331_sync_start, "expected LinuxCNC G33.1 speed-feed sync start");
ok &= expect(saw_g331_sync_stop, "expected LinuxCNC G33.1 speed-feed sync stop");
ok &= expect(saw_g331_rigid_tap_line, "expected LinuxCNC G33.1 rigid tap line number");
const char tool_number_program[] = const char tool_number_program[] =
"G21 G90 G17\n" "G21 G90 G17\n"
"M61 Q1\n" "M61 Q1\n"
@@ -297,7 +824,7 @@ int main() {
saw_g95_feed_mode = saw_g95_feed_mode || saw_g95_feed_mode = saw_g95_feed_mode ||
(event.type == CNC_SIM_EVENT_SET_FEED && (event.type == CNC_SIM_EVENT_SET_FEED &&
event.line == 4 && event.line == 4 &&
event.reserved == 0); event.reserved == 1);
} }
ok &= expect(saw_g93_mode, "expected LinuxCNC G93 feed mode state"); ok &= expect(saw_g93_mode, "expected LinuxCNC G93 feed mode state");
ok &= expect(saw_g94_mode, "expected LinuxCNC G94 feed mode state"); ok &= expect(saw_g94_mode, "expected LinuxCNC G94 feed mode state");
@@ -464,7 +991,13 @@ int main() {
"G21 G90 G17\n" "G21 G90 G17\n"
"G0 X0 Y0 Z5\n" "G0 X0 Y0 Z5\n"
"F100\n" "F100\n"
"G38.3 Z0\n" "G38.2 Z4\n"
"G0 Z5\n"
"G38.3 Z3\n"
"G0 Z5\n"
"G38.4 Z2\n"
"G0 Z5\n"
"G38.5 Z1\n"
"M30\n"; "M30\n";
events.clear(); events.clear();
ok &= expect(cnc_sim_parse_program(sim, probe_program, sizeof(probe_program) - 1) == 0, ok &= expect(cnc_sim_parse_program(sim, probe_program, sizeof(probe_program) - 1) == 0,
@@ -472,16 +1005,47 @@ int main() {
for (const auto &event : events) { for (const auto &event : events) {
saw_probe = saw_probe || saw_probe = saw_probe ||
(event.type == CNC_SIM_EVENT_PROBE && (event.type == CNC_SIM_EVENT_PROBE &&
event.line == 4 && event.line == 6 &&
event.feed == 100.0 && event.feed == 100.0 &&
event.start.z == 5.0 && event.start.z == 5.0 &&
event.end.z == 0.0); event.end.z == 3.0);
saw_probe_error_variant = saw_probe_error_variant ||
(event.type == CNC_SIM_EVENT_PROBE &&
event.line == 4 &&
event.reserved == 0 &&
event.start.z == 5.0 &&
event.end.z == 4.0);
saw_probe_no_error_variant = saw_probe_no_error_variant ||
(event.type == CNC_SIM_EVENT_PROBE &&
event.line == 6 &&
event.reserved == 1 &&
event.start.z == 5.0 &&
event.end.z == 3.0);
saw_probe_clear_error_variant = saw_probe_clear_error_variant ||
(event.type == CNC_SIM_EVENT_PROBE &&
event.line == 8 &&
event.reserved == 2 &&
event.start.z == 5.0 &&
event.end.z == 2.0);
saw_probe_clear_no_error_variant = saw_probe_clear_no_error_variant ||
(event.type == CNC_SIM_EVENT_PROBE &&
event.line == 10 &&
event.reserved == 3 &&
event.start.z == 5.0 &&
event.end.z == 1.0);
saw_probe_as_feed = saw_probe_as_feed || saw_probe_as_feed = saw_probe_as_feed ||
(event.type == CNC_SIM_EVENT_LINEAR_FEED && (event.type == CNC_SIM_EVENT_LINEAR_FEED &&
event.line == 4); (event.line == 4 ||
event.line == 6 ||
event.line == 8 ||
event.line == 10));
} }
ok &= expect(saw_probe, "expected LinuxCNC G38.3 probe event"); ok &= expect(saw_probe, "expected LinuxCNC G38.3 probe event");
ok &= expect(!saw_probe_as_feed, "expected LinuxCNC G38.3 to avoid linear-feed event"); ok &= expect(saw_probe_error_variant, "expected LinuxCNC G38.2 probe event");
ok &= expect(saw_probe_no_error_variant, "expected LinuxCNC G38.3 probe event with probe type");
ok &= expect(saw_probe_clear_error_variant, "expected LinuxCNC G38.4 probe-clear event");
ok &= expect(saw_probe_clear_no_error_variant, "expected LinuxCNC G38.5 probe-clear no-error event");
ok &= expect(!saw_probe_as_feed, "expected LinuxCNC G38 probe moves to avoid linear-feed events");
const char l20_program[] = const char l20_program[] =
"G21 G90 G17\n" "G21 G90 G17\n"
@@ -507,11 +1071,37 @@ int main() {
ok &= expect(saw_l20_g55_offset, "expected LinuxCNC G10 L20 P2 offset after G55 selection"); ok &= expect(saw_l20_g55_offset, "expected LinuxCNC G10 L20 P2 offset after G55 selection");
ok &= expect(saw_l20_end_line, "expected LinuxCNC G10 L20 program end line number"); ok &= expect(saw_l20_end_line, "expected LinuxCNC G10 L20 program end line number");
const char p0_coordinate_program[] =
"G21 G90 G17\n"
"G55\n"
"G10 L2 P0 X7 Y8 Z9\n"
"M30\n";
events.clear();
ok &= expect(cnc_sim_parse_program(sim, p0_coordinate_program, sizeof(p0_coordinate_program) - 1) == 0,
cnc_sim_last_error(sim));
for (const auto &event : events) {
saw_g10_p0_g55 = saw_g10_p0_g55 ||
(event.type == CNC_SIM_EVENT_SET_G5X_OFFSET &&
event.line == 3 &&
event.tool == 2 &&
event.start.x == 7.0 &&
event.start.y == 8.0 &&
event.start.z == 9.0);
saw_g10_p0_end_line = saw_g10_p0_end_line ||
(event.type == CNC_SIM_EVENT_PROGRAM_END &&
event.line == 4);
}
ok &= expect(saw_g10_p0_g55, "expected LinuxCNC G10 L2 P0 to target active G55");
ok &= expect(saw_g10_p0_end_line, "expected LinuxCNC G10 P0 program end line number");
const char coordinate_program[] = const char coordinate_program[] =
"G21 G90 G17\n" "G21 G90 G17\n"
"G10 L2 P1 X12.5 Y-3 Z4 R30\n" "G10 L2 P1 X12.5 Y-3 Z4 R30\n"
"G92 X1 Y2 Z3\n" "G92 X1 Y2 Z3\n"
"G92.2\n"
"G92.3\n"
"G92.1\n" "G92.1\n"
"G92.3\n"
"M30\n"; "M30\n";
events.clear(); events.clear();
ok &= expect(cnc_sim_parse_program(sim, coordinate_program, sizeof(coordinate_program) - 1) == 0, ok &= expect(cnc_sim_parse_program(sim, coordinate_program, sizeof(coordinate_program) - 1) == 0,
@@ -529,20 +1119,87 @@ int main() {
event.line == 2 && event.line == 2 &&
event.feed == 30.0); event.feed == 30.0);
saw_g92_clear = saw_g92_clear || saw_g92_clear = saw_g92_clear ||
(event.type == CNC_SIM_EVENT_SET_G92_OFFSET &&
event.line == 6 &&
event.start.x == 0.0 &&
event.start.y == 0.0 &&
event.start.z == 0.0);
saw_g92_suspend = saw_g92_suspend ||
(event.type == CNC_SIM_EVENT_SET_G92_OFFSET && (event.type == CNC_SIM_EVENT_SET_G92_OFFSET &&
event.line == 4 && event.line == 4 &&
event.start.x == 0.0 && event.start.x == 0.0 &&
event.start.y == 0.0 && event.start.y == 0.0 &&
event.start.z == 0.0); event.start.z == 0.0);
saw_g92_restore = saw_g92_restore ||
(event.type == CNC_SIM_EVENT_SET_G92_OFFSET &&
event.line == 5 &&
near(event.start.x, -10.325317547305483) &&
near(event.start.y, 6.848076211353316) &&
event.start.z == -7.0);
saw_g92_restore_after_clear = saw_g92_restore_after_clear ||
(event.type == CNC_SIM_EVENT_SET_G92_OFFSET &&
event.line == 7 &&
event.start.x == 0.0 &&
event.start.y == 0.0 &&
event.start.z == 0.0);
saw_coordinate_end_line = saw_coordinate_end_line || saw_coordinate_end_line = saw_coordinate_end_line ||
(event.type == CNC_SIM_EVENT_PROGRAM_END && (event.type == CNC_SIM_EVENT_PROGRAM_END &&
event.line == 5); event.line == 8);
} }
ok &= expect(saw_g5x_offset, "expected LinuxCNC G10 L2 G5X offset event"); ok &= expect(saw_g5x_offset, "expected LinuxCNC G10 L2 G5X offset event");
ok &= expect(saw_xy_rotation, "expected LinuxCNC G10 L2 XY rotation event"); ok &= expect(saw_xy_rotation, "expected LinuxCNC G10 L2 XY rotation event");
ok &= expect(saw_g92_suspend, "expected LinuxCNC G92.2 suspend offset event");
ok &= expect(saw_g92_restore, "expected LinuxCNC G92.3 restore suspended rotated-offset event");
ok &= expect(saw_g92_clear, "expected LinuxCNC G92.1 clear offset event"); ok &= expect(saw_g92_clear, "expected LinuxCNC G92.1 clear offset event");
ok &= expect(saw_g92_restore_after_clear, "expected LinuxCNC G92.3 to restore zero after G92.1");
ok &= expect(saw_coordinate_end_line, "expected LinuxCNC coordinate program end line number"); ok &= expect(saw_coordinate_end_line, "expected LinuxCNC coordinate program end line number");
const char g52_program[] =
"G21 G90 G17\n"
"G52 X1 Y2\n"
"G52 Y3\n"
"G92.2\n"
"G92.3\n"
"G92.1\n"
"M30\n";
events.clear();
ok &= expect(cnc_sim_parse_program(sim, g52_program, sizeof(g52_program) - 1) == 0,
cnc_sim_last_error(sim));
for (const auto &event : events) {
saw_g52_initial = saw_g52_initial ||
(event.type == CNC_SIM_EVENT_SET_G92_OFFSET &&
event.line == 2 &&
event.start.x == 1.0 &&
event.start.y == 2.0 &&
event.start.z == 0.0);
saw_g52_sticky_axis = saw_g52_sticky_axis ||
(event.type == CNC_SIM_EVENT_SET_G92_OFFSET &&
event.line == 3 &&
event.start.x == 1.0 &&
event.start.y == 3.0 &&
event.start.z == 0.0);
saw_g52_suspend = saw_g52_suspend ||
(event.type == CNC_SIM_EVENT_SET_G92_OFFSET &&
event.line == 4 &&
event.start.x == 0.0 &&
event.start.y == 0.0 &&
event.start.z == 0.0);
saw_g52_restore = saw_g52_restore ||
(event.type == CNC_SIM_EVENT_SET_G92_OFFSET &&
event.line == 5 &&
event.start.x == 1.0 &&
event.start.y == 3.0 &&
event.start.z == 0.0);
saw_g52_end_line = saw_g52_end_line ||
(event.type == CNC_SIM_EVENT_PROGRAM_END &&
event.line == 7);
}
ok &= expect(saw_g52_initial, "expected LinuxCNC G52 initial local offset event");
ok &= expect(saw_g52_sticky_axis, "expected LinuxCNC G52 to retain omitted axes");
ok &= expect(saw_g52_suspend, "expected LinuxCNC G52/G92 shared offset to suspend with G92.2");
ok &= expect(saw_g52_restore, "expected LinuxCNC G52/G92 shared offset to restore with G92.3");
ok &= expect(saw_g52_end_line, "expected LinuxCNC G52 program end line number");
cnc_sim_destroy(sim); cnc_sim_destroy(sim);
int abort_count = 0; int abort_count = 0;

File diff suppressed because it is too large Load Diff

View File

@@ -33,11 +33,61 @@ int main() {
INIT_CANON(); INIT_CANON();
USE_LENGTH_UNITS(CANON_UNITS_MM); USE_LENGTH_UNITS(CANON_UNITS_MM);
SELECT_PLANE(CANON_PLANE::XY); SELECT_PLANE(CANON_PLANE::XY);
SET_TRAVERSE_RATE(9000.0);
const bool external_traverse_rate = GET_EXTERNAL_TRAVERSE_RATE() == 9000.0;
SET_FEED_RATE(500.0); SET_FEED_RATE(500.0);
SET_FEED_MODE(2, 1);
SET_SPINDLE_SPEED(0, 1200.0); SET_SPINDLE_SPEED(0, 1200.0);
START_SPINDLE_CLOCKWISE(0, 0); START_SPINDLE_CLOCKWISE(0, 0);
START_SPINDLE_COUNTERCLOCKWISE(0, 0); START_SPINDLE_COUNTERCLOCKWISE(0, 0);
STOP_SPINDLE_TURNING(0); STOP_SPINDLE_TURNING(0);
SET_SPINDLE_MODE(0, 2500.0);
cnc_sim_linuxcnc_set_current_line(27);
ORIENT_SPINDLE(0, 45.0, 1);
WAIT_SPINDLE_ORIENT_COMPLETE(0, 2.5);
cnc_sim_linuxcnc_set_current_line(28);
SET_MOTION_OUTPUT_BIT(1);
CLEAR_MOTION_OUTPUT_BIT(1);
SET_AUX_OUTPUT_BIT(2);
CLEAR_AUX_OUTPUT_BIT(2);
WAIT(0, DIGITAL_INPUT, WAIT_MODE_HIGH, 5.0);
WAIT(1, ANALOG_INPUT, WAIT_MODE_IMMEDIATE, 0.0);
SET_MOTION_OUTPUT_VALUE(0, 1.25);
SET_AUX_OUTPUT_VALUE(1, 2.5);
cnc_sim_linuxcnc_set_current_line(29);
ENABLE_FEED_OVERRIDE();
const bool external_feed_override_on = GET_EXTERNAL_FEED_OVERRIDE_ENABLE() == 1;
DISABLE_FEED_OVERRIDE();
const bool external_feed_override_off = GET_EXTERNAL_FEED_OVERRIDE_ENABLE() == 0;
ENABLE_SPEED_OVERRIDE(0);
const bool external_speed_override_on = GET_EXTERNAL_SPINDLE_OVERRIDE_ENABLE(0) == 1;
DISABLE_SPEED_OVERRIDE(0);
const bool external_speed_override_off = GET_EXTERNAL_SPINDLE_OVERRIDE_ENABLE(0) == 0;
ENABLE_ADAPTIVE_FEED();
const bool external_adaptive_feed_on = GET_EXTERNAL_ADAPTIVE_FEED_ENABLE() == 1;
DISABLE_ADAPTIVE_FEED();
const bool external_adaptive_feed_off = GET_EXTERNAL_ADAPTIVE_FEED_ENABLE() == 0;
ENABLE_FEED_HOLD();
const bool external_feed_hold_on = GET_EXTERNAL_FEED_HOLD_ENABLE() == 1;
DISABLE_FEED_HOLD();
const bool external_feed_hold_off = GET_EXTERNAL_FEED_HOLD_ENABLE() == 0;
cnc_sim_linuxcnc_set_current_line(30);
SET_MOTION_CONTROL_MODE(CANON_CONTINUOUS, 0.125);
SET_NAIVECAM_TOLERANCE(0.025);
const bool external_motion_mode = GET_EXTERNAL_MOTION_CONTROL_MODE() == CANON_CONTINUOUS;
const bool external_motion_tolerance = GET_EXTERNAL_MOTION_CONTROL_TOLERANCE() == 0.125;
const bool external_naivecam_tolerance = GET_EXTERNAL_MOTION_CONTROL_NAIVECAM_TOLERANCE() == 0.025;
SET_BLOCK_DELETE(true);
const bool external_block_delete_on = GET_BLOCK_DELETE();
SET_BLOCK_DELETE(false);
const bool external_block_delete_off = !GET_BLOCK_DELETE();
SET_OPTIONAL_PROGRAM_STOP(true);
const bool external_optional_stop_on = GET_OPTIONAL_PROGRAM_STOP();
SET_OPTIONAL_PROGRAM_STOP(false);
const bool external_optional_stop_off = !GET_OPTIONAL_PROGRAM_STOP();
cnc_sim_linuxcnc_set_current_line(0);
START_SPEED_FEED_SYNCH(0, 1.25, false);
STOP_SPEED_FEED_SYNCH();
SELECT_TOOL(7); SELECT_TOOL(7);
CHANGE_TOOL(); CHANGE_TOOL();
cnc_sim_linuxcnc_set_current_line(8); cnc_sim_linuxcnc_set_current_line(8);
@@ -45,7 +95,10 @@ int main() {
STRAIGHT_TRAVERSE(10, 0.0, 0.0, 5.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0); STRAIGHT_TRAVERSE(10, 0.0, 0.0, 5.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0);
STRAIGHT_FEED(11, 10.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0); STRAIGHT_FEED(11, 10.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0);
ARC_FEED(12, 10.0, 10.0, 10.0, 5.0, 1, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0); ARC_FEED(12, 10.0, 10.0, 10.0, 5.0, 1, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0);
STRAIGHT_PROBE(13, 10.0, 10.0, -1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0); STRAIGHT_PROBE(13, 10.0, 10.0, -1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 3);
STRAIGHT_PROBE(14, 10.0, 10.0, -2.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1);
const bool external_probe_position = GET_EXTERNAL_PROBE_POSITION_Z() == -2.0;
const bool external_probe_tripped = GET_EXTERNAL_PROBE_TRIPPED_VALUE() == 1;
SET_G5X_OFFSET(1, 10.0, 20.0, 30.0, 1.0, 2.0, 3.0, 0.0, 0.0, 0.0); SET_G5X_OFFSET(1, 10.0, 20.0, 30.0, 1.0, 2.0, 3.0, 0.0, 0.0, 0.0);
SET_G92_OFFSET(1.0, 2.0, 3.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0); SET_G92_OFFSET(1.0, 2.0, 3.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0);
SET_XY_ROTATION(15.0); SET_XY_ROTATION(15.0);
@@ -53,6 +106,7 @@ int main() {
tool_offset.tran.z = 12.5; tool_offset.tran.z = 12.5;
cnc_sim_linuxcnc_set_current_line(19); cnc_sim_linuxcnc_set_current_line(19);
USE_TOOL_LENGTH_OFFSET(tool_offset); USE_TOOL_LENGTH_OFFSET(tool_offset);
const bool external_tool_length_z = GET_EXTERNAL_TOOL_LENGTH_ZOFFSET() == 12.5;
cnc_sim_linuxcnc_set_current_line(20); cnc_sim_linuxcnc_set_current_line(20);
COMMENT("bridge comment"); COMMENT("bridge comment");
cnc_sim_linuxcnc_set_current_line(24); cnc_sim_linuxcnc_set_current_line(24);
@@ -74,6 +128,7 @@ int main() {
ok &= expect(events.size() >= 8, "expected bridge events"); ok &= expect(events.size() >= 8, "expected bridge events");
ok &= expect(events[0].type == CNC_SIM_EVENT_SET_UNITS, "expected units event"); ok &= expect(events[0].type == CNC_SIM_EVENT_SET_UNITS, "expected units event");
ok &= expect(events[1].type == CNC_SIM_EVENT_SET_PLANE, "expected plane event"); ok &= expect(events[1].type == CNC_SIM_EVENT_SET_PLANE, "expected plane event");
ok &= expect(external_traverse_rate, "expected external traverse rate query to reflect SET_TRAVERSE_RATE");
bool saw_tool = false; bool saw_tool = false;
bool saw_tool_number = false; bool saw_tool_number = false;
@@ -82,6 +137,28 @@ int main() {
bool saw_spindle_cw = false; bool saw_spindle_cw = false;
bool saw_spindle_ccw = false; bool saw_spindle_ccw = false;
bool saw_spindle_stop = false; bool saw_spindle_stop = false;
bool saw_spindle_mode = false;
bool saw_feed_mode = false;
bool saw_spindle_orient = false;
bool saw_spindle_orient_wait = false;
bool saw_motion_digital_on = false;
bool saw_motion_digital_off = false;
bool saw_aux_digital_on = false;
bool saw_aux_digital_off = false;
bool saw_wait_digital = false;
bool saw_wait_analog = false;
bool saw_motion_analog = false;
bool saw_aux_analog = false;
bool saw_feed_override_on = false;
bool saw_feed_override_off = false;
bool saw_speed_override_on = false;
bool saw_speed_override_off = false;
bool saw_adaptive_feed_on = false;
bool saw_adaptive_feed_off = false;
bool saw_feed_hold_on = false;
bool saw_feed_hold_off = false;
bool saw_speed_feed_sync_start = false;
bool saw_speed_feed_sync_stop = false;
bool saw_arc = false; bool saw_arc = false;
bool saw_probe = false; bool saw_probe = false;
bool saw_g5x = false; bool saw_g5x = false;
@@ -111,6 +188,110 @@ int main() {
saw_spindle_stop = saw_spindle_stop || (event.type == CNC_SIM_EVENT_SET_SPINDLE && saw_spindle_stop = saw_spindle_stop || (event.type == CNC_SIM_EVENT_SET_SPINDLE &&
event.spindle == 0.0 && event.spindle == 0.0 &&
event.reserved == 0); event.reserved == 0);
saw_spindle_mode = saw_spindle_mode || (event.type == CNC_SIM_EVENT_COMMENT &&
event.reserved == 960 &&
event.feed == 2500.0 &&
event.tool == 0);
saw_feed_mode = saw_feed_mode || (event.type == CNC_SIM_EVENT_SET_FEED &&
event.reserved == 1 &&
event.tool == 2);
saw_spindle_orient = saw_spindle_orient || (event.type == CNC_SIM_EVENT_COMMENT &&
event.line == 27 &&
event.reserved == 1901 &&
event.tool == 0 &&
event.feed == 45.0 &&
event.arc_turns == 1);
saw_spindle_orient_wait = saw_spindle_orient_wait || (event.type == CNC_SIM_EVENT_COMMENT &&
event.line == 27 &&
event.reserved == 1902 &&
event.tool == 0 &&
event.dwell_seconds == 2.5);
saw_motion_digital_on = saw_motion_digital_on || (event.type == CNC_SIM_EVENT_COMMENT &&
event.line == 28 &&
event.reserved == 62 &&
event.tool == 1 &&
event.feed == 1.0);
saw_motion_digital_off = saw_motion_digital_off || (event.type == CNC_SIM_EVENT_COMMENT &&
event.line == 28 &&
event.reserved == 63 &&
event.tool == 1 &&
event.feed == 0.0);
saw_aux_digital_on = saw_aux_digital_on || (event.type == CNC_SIM_EVENT_COMMENT &&
event.line == 28 &&
event.reserved == 64 &&
event.tool == 2 &&
event.feed == 1.0);
saw_aux_digital_off = saw_aux_digital_off || (event.type == CNC_SIM_EVENT_COMMENT &&
event.line == 28 &&
event.reserved == 65 &&
event.tool == 2 &&
event.feed == 0.0);
saw_wait_digital = saw_wait_digital || (event.type == CNC_SIM_EVENT_COMMENT &&
event.line == 28 &&
event.reserved == 66 &&
event.tool == 0 &&
event.arc_turns == DIGITAL_INPUT &&
event.feed == WAIT_MODE_HIGH &&
event.dwell_seconds == 5.0);
saw_wait_analog = saw_wait_analog || (event.type == CNC_SIM_EVENT_COMMENT &&
event.line == 28 &&
event.reserved == 66 &&
event.tool == 1 &&
event.arc_turns == ANALOG_INPUT &&
event.feed == WAIT_MODE_IMMEDIATE &&
event.dwell_seconds == 0.0);
saw_motion_analog = saw_motion_analog || (event.type == CNC_SIM_EVENT_COMMENT &&
event.line == 28 &&
event.reserved == 67 &&
event.tool == 0 &&
event.feed == 1.25);
saw_aux_analog = saw_aux_analog || (event.type == CNC_SIM_EVENT_COMMENT &&
event.line == 28 &&
event.reserved == 68 &&
event.tool == 1 &&
event.feed == 2.5);
saw_feed_override_on = saw_feed_override_on || (event.type == CNC_SIM_EVENT_COMMENT &&
event.line == 29 &&
event.reserved == 50 &&
event.feed == 1.0);
saw_feed_override_off = saw_feed_override_off || (event.type == CNC_SIM_EVENT_COMMENT &&
event.line == 29 &&
event.reserved == 50 &&
event.feed == 0.0);
saw_speed_override_on = saw_speed_override_on || (event.type == CNC_SIM_EVENT_COMMENT &&
event.line == 29 &&
event.reserved == 51 &&
event.tool == 0 &&
event.feed == 1.0);
saw_speed_override_off = saw_speed_override_off || (event.type == CNC_SIM_EVENT_COMMENT &&
event.line == 29 &&
event.reserved == 51 &&
event.tool == 0 &&
event.feed == 0.0);
saw_adaptive_feed_on = saw_adaptive_feed_on || (event.type == CNC_SIM_EVENT_COMMENT &&
event.line == 29 &&
event.reserved == 52 &&
event.feed == 1.0);
saw_adaptive_feed_off = saw_adaptive_feed_off || (event.type == CNC_SIM_EVENT_COMMENT &&
event.line == 29 &&
event.reserved == 52 &&
event.feed == 0.0);
saw_feed_hold_on = saw_feed_hold_on || (event.type == CNC_SIM_EVENT_COMMENT &&
event.line == 29 &&
event.reserved == 53 &&
event.feed == 1.0);
saw_feed_hold_off = saw_feed_hold_off || (event.type == CNC_SIM_EVENT_COMMENT &&
event.line == 29 &&
event.reserved == 53 &&
event.feed == 0.0);
saw_speed_feed_sync_start = saw_speed_feed_sync_start || (event.type == CNC_SIM_EVENT_COMMENT &&
event.reserved == 3301 &&
event.feed == 1.25 &&
event.tool == 0);
saw_speed_feed_sync_stop = saw_speed_feed_sync_stop || (event.type == CNC_SIM_EVENT_COMMENT &&
event.reserved == 3300 &&
event.feed == 0.0 &&
event.tool == 0);
saw_rapid = saw_rapid || (event.type == CNC_SIM_EVENT_RAPID && event.end.z == 5.0); saw_rapid = saw_rapid || (event.type == CNC_SIM_EVENT_RAPID && event.end.z == 5.0);
saw_feed = saw_feed || (event.type == CNC_SIM_EVENT_LINEAR_FEED && event.end.x == 10.0); saw_feed = saw_feed || (event.type == CNC_SIM_EVENT_LINEAR_FEED && event.end.x == 10.0);
saw_arc = saw_arc || (event.type == CNC_SIM_EVENT_ARC_FEED && saw_arc = saw_arc || (event.type == CNC_SIM_EVENT_ARC_FEED &&
@@ -119,6 +300,7 @@ int main() {
event.center.y == 5.0); event.center.y == 5.0);
saw_probe = saw_probe || (event.type == CNC_SIM_EVENT_PROBE && saw_probe = saw_probe || (event.type == CNC_SIM_EVENT_PROBE &&
event.line == 13 && event.line == 13 &&
event.reserved == 3 &&
event.start.x == 10.0 && event.start.x == 10.0 &&
event.start.y == 10.0 && event.start.y == 10.0 &&
event.end.z == -1.0); event.end.z == -1.0);
@@ -171,14 +353,54 @@ int main() {
ok &= expect(saw_spindle_cw, "expected clockwise spindle state"); ok &= expect(saw_spindle_cw, "expected clockwise spindle state");
ok &= expect(saw_spindle_ccw, "expected counterclockwise spindle state"); ok &= expect(saw_spindle_ccw, "expected counterclockwise spindle state");
ok &= expect(saw_spindle_stop, "expected stopped spindle state"); ok &= expect(saw_spindle_stop, "expected stopped spindle state");
ok &= expect(saw_spindle_mode, "expected spindle mode state");
ok &= expect(saw_feed_mode, "expected feed mode state to preserve spindle and mode arguments");
ok &= expect(saw_spindle_orient, "expected spindle orient state");
ok &= expect(saw_spindle_orient_wait, "expected spindle orient wait state");
ok &= expect(saw_motion_digital_on, "expected motion digital output on state");
ok &= expect(saw_motion_digital_off, "expected motion digital output off state");
ok &= expect(saw_aux_digital_on, "expected auxiliary digital output on state");
ok &= expect(saw_aux_digital_off, "expected auxiliary digital output off state");
ok &= expect(saw_wait_digital, "expected digital input wait state");
ok &= expect(saw_wait_analog, "expected analog input wait state");
ok &= expect(saw_motion_analog, "expected motion analog output state");
ok &= expect(saw_aux_analog, "expected auxiliary analog output state");
ok &= expect(saw_feed_override_on, "expected feed override enable state");
ok &= expect(saw_feed_override_off, "expected feed override disable state");
ok &= expect(saw_speed_override_on, "expected speed override enable state");
ok &= expect(saw_speed_override_off, "expected speed override disable state");
ok &= expect(saw_adaptive_feed_on, "expected adaptive feed enable state");
ok &= expect(saw_adaptive_feed_off, "expected adaptive feed disable state");
ok &= expect(saw_feed_hold_on, "expected feed hold enable state");
ok &= expect(saw_feed_hold_off, "expected feed hold disable state");
ok &= expect(external_feed_override_on, "expected external feed override query to reflect enable");
ok &= expect(external_feed_override_off, "expected external feed override query to reflect disable");
ok &= expect(external_speed_override_on, "expected external speed override query to reflect enable");
ok &= expect(external_speed_override_off, "expected external speed override query to reflect disable");
ok &= expect(external_adaptive_feed_on, "expected external adaptive feed query to reflect enable");
ok &= expect(external_adaptive_feed_off, "expected external adaptive feed query to reflect disable");
ok &= expect(external_feed_hold_on, "expected external feed hold query to reflect enable");
ok &= expect(external_feed_hold_off, "expected external feed hold query to reflect disable");
ok &= expect(external_motion_mode, "expected external motion-control mode query to reflect SET_MOTION_CONTROL_MODE");
ok &= expect(external_motion_tolerance, "expected external motion-control tolerance query to reflect SET_MOTION_CONTROL_MODE");
ok &= expect(external_naivecam_tolerance, "expected external naivecam tolerance query to reflect SET_NAIVECAM_TOLERANCE");
ok &= expect(external_block_delete_on, "expected block-delete query to reflect enable");
ok &= expect(external_block_delete_off, "expected block-delete query to reflect disable");
ok &= expect(external_optional_stop_on, "expected optional-stop query to reflect enable");
ok &= expect(external_optional_stop_off, "expected optional-stop query to reflect disable");
ok &= expect(saw_speed_feed_sync_start, "expected speed-feed sync start state");
ok &= expect(saw_speed_feed_sync_stop, "expected speed-feed sync stop state");
ok &= expect(saw_rapid, "expected rapid move"); ok &= expect(saw_rapid, "expected rapid move");
ok &= expect(saw_feed, "expected linear feed"); ok &= expect(saw_feed, "expected linear feed");
ok &= expect(saw_arc, "expected arc feed"); ok &= expect(saw_arc, "expected arc feed");
ok &= expect(saw_probe, "expected probe event"); ok &= expect(saw_probe, "expected probe event");
ok &= expect(external_probe_position, "expected external probe position query to reflect last STRAIGHT_PROBE");
ok &= expect(external_probe_tripped, "expected external probe tripped query to reflect trip-seeking STRAIGHT_PROBE");
ok &= expect(saw_g5x, "expected G5X offset event"); ok &= expect(saw_g5x, "expected G5X offset event");
ok &= expect(saw_g92, "expected G92 offset event"); ok &= expect(saw_g92, "expected G92 offset event");
ok &= expect(saw_rotation, "expected XY rotation event"); ok &= expect(saw_rotation, "expected XY rotation event");
ok &= expect(saw_tool_length, "expected tool length offset event"); ok &= expect(saw_tool_length, "expected tool length offset event");
ok &= expect(external_tool_length_z, "expected external tool length Z query to reflect USE_TOOL_LENGTH_OFFSET");
ok &= expect(saw_comment, "expected comment event line"); ok &= expect(saw_comment, "expected comment event line");
ok &= expect(saw_mist_on, "expected mist on state"); ok &= expect(saw_mist_on, "expected mist on state");
ok &= expect(saw_flood_on, "expected flood on state"); ok &= expect(saw_flood_on, "expected flood on state");

View File

@@ -24,15 +24,20 @@ This parser only exists to test the ABI and UI before Emscripten and LinuxCNC ar
- multiple G/M words on one line - multiple G/M words on one line
- `G0`, `G1`, `G2`, `G3` - `G0`, `G1`, `G2`, `G3`
- `G17`, `G18`, `G19` - `G17`, `G18`, `G19`
- `G90.1`, `G91.1` arc IJK distance mode
- `G20`, `G21`, `G70`, `G71` - `G20`, `G21`, `G70`, `G71`
- `G7`, `G8` lathe diameter/radius mode for X-axis input
- `G90`, `G91` - `G90`, `G91`
- `G4 P...` - `G4 P...`
- `G38.2`, `G38.3`, `G38.4`, `G38.5`
- `F`, `S`, `T`, `M3`, `M4`, `M5`, `M6`, `M2`, `M30` - `F`, `S`, `T`, `M3`, `M4`, `M5`, `M6`, `M2`, `M30`
- spindle modes `G96`, `G97`
- IJK and R arcs - IJK and R arcs
- numbered and named parameter assignment/reference such as `#1 = ...`, `#<name> = ...`, `X#1`, and nested expressions like `X[[#<name> + 2] * 3]` - numbered and named parameter assignment/reference such as `#1 = ...`, `#<name> = ...`, `X#1`, and nested expressions like `X[[#<name> + 2] * 3]`
- expression functions `ABS[]`, `SQRT[]`, `EXP[]`, `LN[]`, degree-based `SIN[]`/`COS[]`/`TAN[]`/`ASIN[]`/`ACOS[]`, LinuxCNC-style `ATAN[]/[]`, and `FIX[]`/`FUP[]`/`ROUND[]` - expression functions `ABS[]`, `SQRT[]`, `EXP[]`, `LN[]`, degree-based `SIN[]`/`COS[]`/`TAN[]`/`ASIN[]`/`ACOS[]`, LinuxCNC-style `ATAN[]/[]`, and `FIX[]`/`FUP[]`/`ROUND[]`
- numeric and named O-word subprograms such as `O100 call` and `O<name> call` - numeric and named O-word subprograms such as `O100 call` and `O<name> call`
- canned cycles `G73`, `G81`, `G82`, `G83`, `G85`, `G86`, `G89` with `G80`, `G98`, `G99`, `L` - canned cycles `G73`, `G74`, `G81`, `G82`, `G83`, `G84`, `G85`, `G86`, `G87`, `G88`, `G89` with `G80`, `G98`, `G99`, `L`
- coordinate offset events for `G10 L2`, `G10 L20`, `G54`-`G59.3`, `G52`, `G92`, `G92.1`, `G92.2`, and `G92.3`
It is not the production interpreter. It is not the production interpreter.
@@ -186,17 +191,27 @@ This matrix tracks LinuxCNC feature coverage for the web/WASM simulator. A featu
| Area | Status | Regression | | Area | Status | Regression |
| --- | --- | --- | | --- | --- | --- |
| Basic modal motion `G0/G1/G2/G3` | covered | `tests/gcode/linuxcnc_basic_motion.ngc`, `tests/gcode/basic_mill.ngc` | | Basic modal motion `G0/G1/G2/G3` | covered, including `G18`/`G19` arc plane mapping and `G90.1`/`G91.1` IJK modes | `tests/gcode/linuxcnc_basic_motion.ngc`, `tests/gcode/basic_mill.ngc`, `tests/gcode/linuxcnc_arc_planes.ngc`, `tests/gcode/linuxcnc_arc_distance_modes.ngc` |
| Predefined position moves `G28/G28.1`, `G30/G30.1` | covered for stored position, waypoint, selected-axis return, and all-axis return | `tests/gcode/linuxcnc_predefined_positions.ngc` |
| Machine-coordinate move `G53` | covered for explicit/modal `G0`, `G1`, and incremental-mode rejection in smoke parser | `tests/gcode/linuxcnc_machine_coordinates.ngc` |
| Tool select/change `T... M6` | covered with minimal native tooldata | `tests/gcode/basic_mill.ngc` | | Tool select/change `T... M6` | covered with minimal native tooldata | `tests/gcode/basic_mill.ngc` |
| Tool length offset `G43/G49` | covered with nonzero tool-table offset through LinuxCNC native/source backends | `tests/gcode/linuxcnc_tool_length.ngc` | | Tool length offset `G43/G43.1/G43.2/G49` | covered with nonzero tool-table offset, dynamic replacement, additive axis offsets, `G43.2 H...`, and clear through LinuxCNC native/source backends | `tests/gcode/linuxcnc_tool_length.ngc`, `tests/gcode/linuxcnc_dynamic_tool_length.ngc` |
| RTCP controls `G43.4/G43.5/G49` | covered as simulator-owned control lines | `tests/gcode/linuxcnc_rtcp_controls.ngc` | | RTCP controls `G43.4/G43.5/G49` | covered as simulator-owned control lines | `tests/gcode/linuxcnc_rtcp_controls.ngc` |
| Kinematics switch `M428/M429/M430` | covered as simulator-owned control lines | `tests/gcode/linuxcnc_rtcp_controls.ngc` | | Kinematics switch `M428/M429/M430` | covered as simulator-owned control lines | `tests/gcode/linuxcnc_rtcp_controls.ngc` |
| Spindle, coolant, program stops, and current tool number `M3/M4/M5`, `M7/M8/M9`, `M0/M1/M60/M30`, `M61 Q...` | covered through LinuxCNC native/source backends | `tests/gcode/linuxcnc_spindle_direction.ngc`, `tests/gcode/linuxcnc_coolant.ngc`, `tests/gcode/linuxcnc_program_stops.ngc`, `tests/gcode/linuxcnc_tool_number.ngc` | | Spindle, coolant, program stops, and current tool number `M3/M4/M5`, `M7/M8/M9`, `M0/M1/M60/M30`, `M61 Q...` | covered through LinuxCNC native/source backends | `tests/gcode/linuxcnc_spindle_direction.ngc`, `tests/gcode/linuxcnc_coolant.ngc`, `tests/gcode/linuxcnc_program_stops.ngc`, `tests/gcode/linuxcnc_tool_number.ngc` |
| Spindle speed mode `G96/G97` | covered with Canon `SET_SPINDLE_MODE` preserved as mode state events, including `G96 D...` max-RPM value | `tests/gcode/linuxcnc_spindle_modes.ngc` |
| Spindle orientation `M19 R... P... Q...` | covered with Canon `ORIENT_SPINDLE` and `WAIT_SPINDLE_ORIENT_COMPLETE` preserved as temporary mode state events | `tests/gcode/linuxcnc_spindle_orient.ngc` |
| Spindle-synchronized feed and threading `G33/G33.1/G76` | covered through smoke, LinuxCNC native, and source-linked paths with Canon `START_SPEED_FEED_SYNCH`/`STOP_SPEED_FEED_SYNCH` preserved, rigid-tap line numbers normalized, and G76 multi-pass threading smoke-covered | `tests/gcode/linuxcnc_threading_sync.ngc`, `tests/gcode/linuxcnc_threading_cycle.ngc`, smoke API regression |
| Lathe diameter/radius mode `G7/G8` | covered in smoke parser for X-axis diameter/radius scaling, including interaction with G76 threading geometry; native/source backends use LinuxCNC interpreter state directly | smoke API regression |
| Digital/analog I/O `M62`-`M68` | covered with Canon digital output, analog output, and input wait callbacks preserved as temporary state events | `tests/gcode/linuxcnc_io_controls.ngc` |
| Override controls `M48`-`M53` | covered with Canon feed override, spindle speed override, adaptive feed, and feed hold callbacks preserved as temporary state events | `tests/gcode/linuxcnc_override_controls.ngc` |
| Modal state save/restore `M70`-`M73` | covered for main-program save/invalidate/restore plus O-word subroutine autorestore in smoke parser, with native/source regressions checking restored distance mode, units, and XY plane motion | `tests/gcode/linuxcnc_modal_state.ngc`, `tests/gcode/linuxcnc_modal_autorestore.ngc` |
| LinuxCNC read-only named parameters | partially covered in smoke parser for common modal state reads used by O-word macros: `#<_absolute>`, `#<_incremental>`, `#<_metric>`, `#<_imperial>`, `#<_feed>`, `#<_rpm>`, `#<_spindle_on>`, `#<_spindle_cw>`, `#<_lathe_diameter_mode>`, and `#<_lathe_radius_mode>` | smoke API regression |
| Feed and motion control modes `G93/G94/G95`, `G61/G61.1/G64` | covered through LinuxCNC native/source backends | `tests/gcode/linuxcnc_feed_modes.ngc`, `tests/gcode/linuxcnc_motion_modes.ngc` | | Feed and motion control modes `G93/G94/G95`, `G61/G61.1/G64` | covered through LinuxCNC native/source backends | `tests/gcode/linuxcnc_feed_modes.ngc`, `tests/gcode/linuxcnc_motion_modes.ngc` |
| Canned cycle `G81/G80` | covered for drilling expand-to-canon path | `tests/gcode/linuxcnc_canned_cycle.ngc` | | Canned cycle `G81/G80` | covered for drilling expand-to-canon path, including `G18/G19` plane-specific depth-axis mapping for representative drilling/boring cycles | `tests/gcode/linuxcnc_canned_cycle.ngc`, `tests/gcode/linuxcnc_canned_cycle_planes.ngc` |
| Coordinate offset Canon events `G10 L2`, `G10 L20`, `G92/G92.1` | covered through LinuxCNC native/source backends | `tests/gcode/linuxcnc_coordinate_offsets.ngc`, `tests/gcode/linuxcnc_coordinate_l20.ngc` | | Coordinate offset Canon events `G10 L2`, `G10 L20`, `G10 P0 active-system targeting`, `G54`-`G59.3` selection, `G52`, `G92/G92.1/G92.2/G92.3` | covered through LinuxCNC native/source backends, including all nine G5X indices | `tests/gcode/linuxcnc_coordinate_offsets.ngc`, `tests/gcode/linuxcnc_coordinate_l20.ngc`, `tests/gcode/linuxcnc_coordinate_p0.ngc`, `tests/gcode/linuxcnc_coordinate_select_all.ngc`, `tests/gcode/linuxcnc_g92_restore.ngc`, `tests/gcode/linuxcnc_g52_offset.ngc` |
| Cutter compensation | covered for tool-table `G41/G42 D...` and explicit-radius `G41.1/G42.1/G40` through LinuxCNC native/source backends | `tests/gcode/linuxcnc_cutter_comp.ngc` | | Cutter compensation | covered for tool-table `G41/G42 D...` and explicit-radius `G41.1/G42.1/G40` through LinuxCNC native/source backends | `tests/gcode/linuxcnc_cutter_comp.ngc` |
| Probe move `G38.3` | covered as a distinct probe event through LinuxCNC native/source backends | `tests/gcode/linuxcnc_probe_no_error.ngc` | | Probe moves `G38.2/G38.3/G38.4/G38.5` | covered as distinct probe events with LinuxCNC `probe_type` preserved through smoke, native, and source-linked paths | `tests/gcode/linuxcnc_probe_no_error.ngc` |
| O-word subroutines and calls | covered for numeric `O... sub/call/return/endsub` through LinuxCNC file mode; smoke parser also covers named `O<name>` sub/call/return/endsub | `tests/gcode/smoke_oword_subprogram.ngc` | | O-word subroutines, calls, and control flow | covered for numeric and named `O... sub/call/return/endsub` plus `if`/`elseif`/`else`, `while`, `repeat`, `do`/`while`, `break`, and `continue` through LinuxCNC file mode; smoke parser also covers named `O<name>` sub/call/return/endsub and loop-control forms | `tests/gcode/smoke_oword_subprogram.ngc`, `tests/gcode/linuxcnc_named_oword_subprogram.ngc`, `tests/gcode/linuxcnc_oword_control_flow.ngc` |
| Broader canned cycles `G73`, `G82`-`G89` | partially covered: `G73`, `G82`, `G83`, `G85`, `G86`, `G89` | `tests/gcode/linuxcnc_canned_cycles_extended.ngc`, smoke API regression | | Broader canned cycles `G73`, `G74`, `G82`-`G89` | partially covered: `G73`, `G74`, `G82`, `G83`, `G84`, `G85`, `G86`, `G87`, `G88`, `G89`; smoke parser maps supported cycles across `G17/G18/G19`, including LinuxCNC's special non-XY `G74/G84` tapping argument order and `G87` plane-specific `I/J/K` mapping; native/source regressions now check non-XY `G74/G84/G86/G87/G88` sequences | `tests/gcode/linuxcnc_canned_cycles_extended.ngc`, `tests/gcode/linuxcnc_canned_cycle_planes.ngc`, smoke API regression |
| Full source-level wasm build | pending | replace Python/HAL/INI/tooldata support dependencies | | Full source-level wasm build | pending | replace Python/HAL/INI/tooldata support dependencies |

View File

@@ -9,6 +9,7 @@ build_dir=${TMPDIR:-/tmp}/cnc_sim_native
mkdir -p "$build_dir" mkdir -p "$build_dir"
var_file="$build_dir/rs274ngc.var" var_file="$build_dir/rs274ngc.var"
base_var_file="$build_dir/rs274ngc-base.var" base_var_file="$build_dir/rs274ngc-base.var"
ini_named_parameter_file="$(pwd)/tests/gcode/linuxcnc_ini_named_parameter.ini"
cp "$linuxcnc_root/tests/halui/jogging/sim.var" "$base_var_file" cp "$linuxcnc_root/tests/halui/jogging/sim.var" "$base_var_file"
cp "$base_var_file" "$var_file" cp "$base_var_file" "$var_file"
@@ -39,22 +40,54 @@ CNC_SIM_RS274_VAR="$var_file" "$build_dir/linuxcnc_rs274_dump" tests/gcode/linux
CNC_SIM_RS274_VAR="$var_file" "$build_dir/linuxcnc_rs274_dump" tests/gcode/basic_mill.ngc >/tmp/cnc_sim_linuxcnc_basic_mill.json CNC_SIM_RS274_VAR="$var_file" "$build_dir/linuxcnc_rs274_dump" tests/gcode/basic_mill.ngc >/tmp/cnc_sim_linuxcnc_basic_mill.json
CNC_SIM_RS274_VAR="$var_file" "$build_dir/linuxcnc_rs274_dump" tests/gcode/linuxcnc_rtcp_controls.ngc >/tmp/cnc_sim_linuxcnc_rtcp_controls.json CNC_SIM_RS274_VAR="$var_file" "$build_dir/linuxcnc_rs274_dump" tests/gcode/linuxcnc_rtcp_controls.ngc >/tmp/cnc_sim_linuxcnc_rtcp_controls.json
CNC_SIM_RS274_VAR="$var_file" "$build_dir/linuxcnc_rs274_dump" tests/gcode/linuxcnc_spindle_direction.ngc >/tmp/cnc_sim_linuxcnc_spindle_direction.json CNC_SIM_RS274_VAR="$var_file" "$build_dir/linuxcnc_rs274_dump" tests/gcode/linuxcnc_spindle_direction.ngc >/tmp/cnc_sim_linuxcnc_spindle_direction.json
CNC_SIM_RS274_VAR="$var_file" "$build_dir/linuxcnc_rs274_dump" tests/gcode/linuxcnc_spindle_modes.ngc >/tmp/cnc_sim_linuxcnc_spindle_modes.json
CNC_SIM_RS274_VAR="$var_file" "$build_dir/linuxcnc_rs274_dump" tests/gcode/linuxcnc_spindle_orient.ngc >/tmp/cnc_sim_linuxcnc_spindle_orient.json
CNC_SIM_RS274_VAR="$var_file" "$build_dir/linuxcnc_rs274_dump" tests/gcode/linuxcnc_io_controls.ngc >/tmp/cnc_sim_linuxcnc_io_controls.json
CNC_SIM_RS274_VAR="$var_file" "$build_dir/linuxcnc_rs274_dump" tests/gcode/linuxcnc_override_controls.ngc >/tmp/cnc_sim_linuxcnc_override_controls.json
CNC_SIM_RS274_VAR="$var_file" "$build_dir/linuxcnc_rs274_dump" tests/gcode/linuxcnc_modal_state.ngc >/tmp/cnc_sim_linuxcnc_modal_state.json
CNC_SIM_RS274_FILE_MODE=1 CNC_SIM_RS274_VAR="$var_file" "$build_dir/linuxcnc_rs274_dump" tests/gcode/linuxcnc_modal_autorestore.ngc >/tmp/cnc_sim_linuxcnc_modal_autorestore.json
if CNC_SIM_RS274_VAR="$var_file" "$build_dir/linuxcnc_rs274_dump" tests/gcode/linuxcnc_modal_invalidate.ngc >/tmp/cnc_sim_linuxcnc_modal_invalidate.json 2>/tmp/cnc_sim_linuxcnc_modal_invalidate.err; then
echo "expected linuxcnc_modal_invalidate.ngc to fail" >&2
exit 1
fi
CNC_SIM_RS274_VAR="$var_file" "$build_dir/linuxcnc_rs274_dump" tests/gcode/linuxcnc_threading_sync.ngc >/tmp/cnc_sim_linuxcnc_threading_sync.json
CNC_SIM_RS274_VAR="$var_file" "$build_dir/linuxcnc_rs274_dump" tests/gcode/linuxcnc_threading_cycle.ngc >/tmp/cnc_sim_linuxcnc_threading_cycle.json
CNC_SIM_RS274_VAR="$var_file" "$build_dir/linuxcnc_rs274_dump" tests/gcode/linuxcnc_tool_number.ngc >/tmp/cnc_sim_linuxcnc_tool_number.json CNC_SIM_RS274_VAR="$var_file" "$build_dir/linuxcnc_rs274_dump" tests/gcode/linuxcnc_tool_number.ngc >/tmp/cnc_sim_linuxcnc_tool_number.json
CNC_SIM_RS274_VAR="$var_file" "$build_dir/linuxcnc_rs274_dump" tests/gcode/linuxcnc_program_stops.ngc >/tmp/cnc_sim_linuxcnc_program_stops.json CNC_SIM_RS274_VAR="$var_file" "$build_dir/linuxcnc_rs274_dump" tests/gcode/linuxcnc_program_stops.ngc >/tmp/cnc_sim_linuxcnc_program_stops.json
CNC_SIM_RS274_VAR="$var_file" "$build_dir/linuxcnc_rs274_dump" tests/gcode/linuxcnc_coolant.ngc >/tmp/cnc_sim_linuxcnc_coolant.json CNC_SIM_RS274_VAR="$var_file" "$build_dir/linuxcnc_rs274_dump" tests/gcode/linuxcnc_coolant.ngc >/tmp/cnc_sim_linuxcnc_coolant.json
CNC_SIM_RS274_VAR="$var_file" "$build_dir/linuxcnc_rs274_dump" tests/gcode/linuxcnc_feed_modes.ngc >/tmp/cnc_sim_linuxcnc_feed_modes.json CNC_SIM_RS274_VAR="$var_file" "$build_dir/linuxcnc_rs274_dump" tests/gcode/linuxcnc_feed_modes.ngc >/tmp/cnc_sim_linuxcnc_feed_modes.json
CNC_SIM_RS274_VAR="$var_file" "$build_dir/linuxcnc_rs274_dump" tests/gcode/linuxcnc_motion_modes.ngc >/tmp/cnc_sim_linuxcnc_motion_modes.json CNC_SIM_RS274_VAR="$var_file" "$build_dir/linuxcnc_rs274_dump" tests/gcode/linuxcnc_motion_modes.ngc >/tmp/cnc_sim_linuxcnc_motion_modes.json
CNC_SIM_RS274_VAR="$var_file" "$build_dir/linuxcnc_rs274_dump" tests/gcode/linuxcnc_tool_length.ngc >/tmp/cnc_sim_linuxcnc_tool_length.json CNC_SIM_RS274_VAR="$var_file" "$build_dir/linuxcnc_rs274_dump" tests/gcode/linuxcnc_tool_length.ngc >/tmp/cnc_sim_linuxcnc_tool_length.json
CNC_SIM_RS274_VAR="$var_file" "$build_dir/linuxcnc_rs274_dump" tests/gcode/linuxcnc_dynamic_tool_length.ngc >/tmp/cnc_sim_linuxcnc_dynamic_tool_length.json
CNC_SIM_RS274_VAR="$var_file" "$build_dir/linuxcnc_rs274_dump" tests/gcode/linuxcnc_canned_cycle.ngc >/tmp/cnc_sim_linuxcnc_canned_cycle.json CNC_SIM_RS274_VAR="$var_file" "$build_dir/linuxcnc_rs274_dump" tests/gcode/linuxcnc_canned_cycle.ngc >/tmp/cnc_sim_linuxcnc_canned_cycle.json
CNC_SIM_RS274_VAR="$var_file" "$build_dir/linuxcnc_rs274_dump" tests/gcode/linuxcnc_canned_cycles_extended.ngc >/tmp/cnc_sim_linuxcnc_canned_cycles_extended.json CNC_SIM_RS274_VAR="$var_file" "$build_dir/linuxcnc_rs274_dump" tests/gcode/linuxcnc_canned_cycles_extended.ngc >/tmp/cnc_sim_linuxcnc_canned_cycles_extended.json
CNC_SIM_RS274_VAR="$var_file" "$build_dir/linuxcnc_rs274_dump" tests/gcode/linuxcnc_canned_cycle_planes.ngc >/tmp/cnc_sim_linuxcnc_canned_cycle_planes.json
CNC_SIM_RS274_VAR="$var_file" "$build_dir/linuxcnc_rs274_dump" tests/gcode/linuxcnc_arc_planes.ngc >/tmp/cnc_sim_linuxcnc_arc_planes.json
CNC_SIM_RS274_VAR="$var_file" "$build_dir/linuxcnc_rs274_dump" tests/gcode/linuxcnc_arc_distance_modes.ngc >/tmp/cnc_sim_linuxcnc_arc_distance_modes.json
CNC_SIM_RS274_VAR="$var_file" "$build_dir/linuxcnc_rs274_dump" tests/gcode/linuxcnc_predefined_positions.ngc >/tmp/cnc_sim_linuxcnc_predefined_positions.json
CNC_SIM_RS274_VAR="$var_file" "$build_dir/linuxcnc_rs274_dump" tests/gcode/linuxcnc_machine_coordinates.ngc >/tmp/cnc_sim_linuxcnc_machine_coordinates.json
CNC_SIM_RS274_VAR="$var_file" "$build_dir/linuxcnc_rs274_dump" tests/gcode/linuxcnc_cutter_comp.ngc >/tmp/cnc_sim_linuxcnc_cutter_comp.json CNC_SIM_RS274_VAR="$var_file" "$build_dir/linuxcnc_rs274_dump" tests/gcode/linuxcnc_cutter_comp.ngc >/tmp/cnc_sim_linuxcnc_cutter_comp.json
CNC_SIM_RS274_VAR="$var_file" "$build_dir/linuxcnc_rs274_dump" tests/gcode/linuxcnc_comments.ngc >/tmp/cnc_sim_linuxcnc_comments.json CNC_SIM_RS274_VAR="$var_file" "$build_dir/linuxcnc_rs274_dump" tests/gcode/linuxcnc_comments.ngc >/tmp/cnc_sim_linuxcnc_comments.json
CNC_SIM_RS274_VAR="$var_file" "$build_dir/linuxcnc_rs274_dump" tests/gcode/linuxcnc_probe_no_error.ngc >/tmp/cnc_sim_linuxcnc_probe_no_error.json CNC_SIM_RS274_VAR="$var_file" "$build_dir/linuxcnc_rs274_dump" tests/gcode/linuxcnc_probe_no_error.ngc >/tmp/cnc_sim_linuxcnc_probe_no_error.json
CNC_SIM_RS274_FILE_MODE=1 CNC_SIM_RS274_VAR="$var_file" "$build_dir/linuxcnc_rs274_dump" tests/gcode/smoke_oword_subprogram.ngc >/tmp/cnc_sim_linuxcnc_oword_subprogram.json CNC_SIM_RS274_FILE_MODE=1 CNC_SIM_RS274_VAR="$var_file" "$build_dir/linuxcnc_rs274_dump" tests/gcode/smoke_oword_subprogram.ngc >/tmp/cnc_sim_linuxcnc_oword_subprogram.json
CNC_SIM_RS274_FILE_MODE=1 CNC_SIM_RS274_VAR="$var_file" "$build_dir/linuxcnc_rs274_dump" tests/gcode/linuxcnc_named_oword_subprogram.ngc >/tmp/cnc_sim_linuxcnc_named_oword_subprogram.json
CNC_SIM_RS274_FILE_MODE=1 CNC_SIM_RS274_VAR="$var_file" "$build_dir/linuxcnc_rs274_dump" tests/gcode/linuxcnc_oword_control_flow.ngc >/tmp/cnc_sim_linuxcnc_oword_control_flow.json
CNC_SIM_RS274_FILE_MODE=1 CNC_SIM_RS274_VAR="$var_file" "$build_dir/linuxcnc_rs274_dump" tests/gcode/linuxcnc_named_parameter_exists.ngc >/tmp/cnc_sim_linuxcnc_named_parameter_exists.json
CNC_SIM_RS274_FILE_MODE=1 CNC_SIM_RS274_VAR="$var_file" "$build_dir/linuxcnc_rs274_dump" tests/gcode/linuxcnc_indexed_parameters.ngc >/tmp/cnc_sim_linuxcnc_indexed_parameters.json
CNC_SIM_RS274_FILE_MODE=1 CNC_SIM_RS274_VAR="$var_file" "$build_dir/linuxcnc_rs274_dump" tests/gcode/linuxcnc_named_parameter_normalization.ngc >/tmp/cnc_sim_linuxcnc_named_parameter_normalization.json
INI_FILE_NAME="$ini_named_parameter_file" CNC_SIM_RS274_FILE_MODE=1 CNC_SIM_RS274_VAR="$var_file" "$build_dir/linuxcnc_rs274_dump" tests/gcode/linuxcnc_ini_named_parameter.ngc >/tmp/cnc_sim_linuxcnc_ini_named_parameter.json
cp "$base_var_file" "$var_file" cp "$base_var_file" "$var_file"
CNC_SIM_RS274_VAR="$var_file" "$build_dir/linuxcnc_rs274_dump" tests/gcode/linuxcnc_coordinate_offsets.ngc >/tmp/cnc_sim_linuxcnc_coordinate_offsets.json CNC_SIM_RS274_VAR="$var_file" "$build_dir/linuxcnc_rs274_dump" tests/gcode/linuxcnc_coordinate_offsets.ngc >/tmp/cnc_sim_linuxcnc_coordinate_offsets.json
cp "$base_var_file" "$var_file" cp "$base_var_file" "$var_file"
CNC_SIM_RS274_VAR="$var_file" "$build_dir/linuxcnc_rs274_dump" tests/gcode/linuxcnc_coordinate_l20.ngc >/tmp/cnc_sim_linuxcnc_coordinate_l20.json CNC_SIM_RS274_VAR="$var_file" "$build_dir/linuxcnc_rs274_dump" tests/gcode/linuxcnc_coordinate_l20.ngc >/tmp/cnc_sim_linuxcnc_coordinate_l20.json
cp "$base_var_file" "$var_file"
CNC_SIM_RS274_VAR="$var_file" "$build_dir/linuxcnc_rs274_dump" tests/gcode/linuxcnc_coordinate_p0.ngc >/tmp/cnc_sim_linuxcnc_coordinate_p0.json
cp "$base_var_file" "$var_file"
CNC_SIM_RS274_VAR="$var_file" "$build_dir/linuxcnc_rs274_dump" tests/gcode/linuxcnc_coordinate_select_all.ngc >/tmp/cnc_sim_linuxcnc_coordinate_select_all.json
cp "$base_var_file" "$var_file"
CNC_SIM_RS274_VAR="$var_file" "$build_dir/linuxcnc_rs274_dump" tests/gcode/linuxcnc_g92_restore.ngc >/tmp/cnc_sim_linuxcnc_g92_restore.json
cp "$base_var_file" "$var_file"
CNC_SIM_RS274_VAR="$var_file" "$build_dir/linuxcnc_rs274_dump" tests/gcode/linuxcnc_g52_offset.ngc >/tmp/cnc_sim_linuxcnc_g52_offset.json
python3 - <<'PY' python3 - <<'PY'
import json import json
from pathlib import Path from pathlib import Path
@@ -95,6 +128,160 @@ if (3, 1200, 2) not in spindle_states:
if (4, 0, 0) not in spindle_states: if (4, 0, 0) not in spindle_states:
raise SystemExit("missing M5 stopped spindle state") raise SystemExit("missing M5 stopped spindle state")
spindle_modes = json.loads(Path("/tmp/cnc_sim_linuxcnc_spindle_modes.json").read_text())
spindle_mode_states = [
(event["line"], event["reserved"], event["feed"], event["tool"])
for event in spindle_modes
if event["type"] == "comment" and event["line"] in {2, 3, 4} and event["reserved"] in {960, 970}
]
expected_spindle_mode_states = [
(2, 970, 0, 0),
(3, 960, 2500, 0),
(4, 970, 0, 0),
]
if spindle_mode_states != expected_spindle_mode_states:
raise SystemExit(f"unexpected G96/G97 spindle mode states: {spindle_mode_states!r}")
spindle_orient = json.loads(Path("/tmp/cnc_sim_linuxcnc_spindle_orient.json").read_text())
if not any(
event["type"] == "comment" and
event["line"] == 2 and
event["reserved"] == 1901 and
event["tool"] == 0 and
event["feed"] == 45 and
event["arcTurns"] == 1
for event in spindle_orient
):
raise SystemExit("missing M19 spindle orient state")
if not any(
event["type"] == "comment" and
event["line"] == 2 and
event["reserved"] == 1902 and
event["tool"] == 0 and
event["dwellSeconds"] == 2
for event in spindle_orient
):
raise SystemExit("missing M19 spindle orient wait state")
io_controls = json.loads(Path("/tmp/cnc_sim_linuxcnc_io_controls.json").read_text())
io_states = [
(event["line"], event["reserved"], event["tool"], event["feed"], event["arcTurns"], event["dwellSeconds"])
for event in io_controls
if event["type"] == "comment" and event["reserved"] in {62, 63, 64, 65, 66, 67, 68}
]
expected_io_states = [
(2, 62, 1, 1, 0, 0),
(3, 63, 1, 0, 0, 0),
(4, 64, 2, 1, 0, 0),
(5, 65, 2, 0, 0, 0),
(6, 66, 0, 3, 1, 5),
(7, 66, 1, 0, 0, 0),
(8, 67, 0, 1.25, 0, 0),
(9, 68, 1, 2.5, 0, 0),
]
if io_states != expected_io_states:
raise SystemExit(f"unexpected M62-M68 I/O states: {io_states!r}")
override_controls = json.loads(Path("/tmp/cnc_sim_linuxcnc_override_controls.json").read_text())
override_states = [
(event["line"], event["reserved"], event["tool"], event["feed"])
for event in override_controls
if event["type"] == "comment" and event["reserved"] in {50, 51, 52, 53}
]
expected_override_states = [
(2, 50, 0, 1),
(2, 51, 0, 1),
(3, 50, 0, 0),
(3, 51, 0, 0),
(4, 50, 0, 1),
(5, 50, 0, 0),
(6, 51, 0, 1),
(7, 51, 0, 0),
(8, 52, 0, 1),
(9, 52, 0, 0),
(10, 53, 0, 1),
(11, 53, 0, 0),
(12, 50, 0, 1),
]
if override_states != expected_override_states:
raise SystemExit(f"unexpected M48-M53 override states: {override_states!r}")
modal_state = json.loads(Path("/tmp/cnc_sim_linuxcnc_modal_state.json").read_text())
if not any(
event["type"] == "rapid" and
event["line"] == 7 and
event["end"]["x"] == 2 and
event["end"]["y"] == 0 and
event["end"]["z"] == 2
for event in modal_state
):
raise SystemExit("missing M72 restored absolute millimeter move")
if not any(
event["type"] == "arc-feed" and
event["line"] == 8 and
event["plane"] == 17 and
event["end"]["x"] == 4 and
event["end"]["y"] == 0
for event in modal_state
):
raise SystemExit("missing M72 restored XY plane arc")
modal_autorestore = json.loads(Path("/tmp/cnc_sim_linuxcnc_modal_autorestore.json").read_text())
if not any(
event["type"] == "rapid" and
event["line"] == 9 and
event["end"]["x"] == 10
for event in modal_autorestore
):
raise SystemExit("missing M73 subroutine changed modal state move")
if not any(
event["type"] == "rapid" and
event["line"] == 4 and
event["start"]["x"] == 10 and
event["end"]["x"] == 12
for event in modal_autorestore
):
raise SystemExit("missing M73 autorestored incremental caller move")
threading_sync = json.loads(Path("/tmp/cnc_sim_linuxcnc_threading_sync.json").read_text())
sync_states = [
(event["line"], event["reserved"], event["feed"], event["tool"])
for event in threading_sync
if event["type"] == "comment" and event["reserved"] in {3300, 3301, 3302}
]
expected_sync_states = [
(4, 3301, 1, 0),
(4, 3300, 0, 0),
(6, 3301, 1, 0),
(6, 3300, 0, 0),
]
if sync_states != expected_sync_states:
raise SystemExit(f"unexpected G33/G33.1 sync states: {sync_states!r}")
if not any(
event["type"] == "linear-feed" and event["line"] == 6 and event["end"]["z"] == 0
for event in threading_sync
):
raise SystemExit("missing G33.1 rigid tap motion line")
threading_cycle = json.loads(Path("/tmp/cnc_sim_linuxcnc_threading_cycle.json").read_text())
if not any(
event["type"] == "comment" and
event["line"] == 4 and
event["reserved"] == 3301 and
event["feed"] == 0.05
for event in threading_cycle
):
raise SystemExit("missing G76 threading sync start")
if not any(event["type"] == "comment" and event["line"] == 4 and event["reserved"] == 3300 for event in threading_cycle):
raise SystemExit("missing G76 threading sync stop")
if not any(
event["type"] == "linear-feed" and event["line"] == 4 and event["end"]["z"] == -1
for event in threading_cycle
):
raise SystemExit("missing G76 final threading pass")
if not any(event["type"] == "program-end" and event["line"] == 5 for event in threading_cycle):
raise SystemExit("missing G76 program end line number")
tool_number = json.loads(Path("/tmp/cnc_sim_linuxcnc_tool_number.json").read_text()) tool_number = json.loads(Path("/tmp/cnc_sim_linuxcnc_tool_number.json").read_text())
if not any( if not any(
event["type"] == "tool-change" and event["type"] == "tool-change" and
@@ -170,6 +357,16 @@ if not any(
): ):
raise SystemExit("missing G49 tool length clear event") raise SystemExit("missing G49 tool length clear event")
dynamic_tool_length = json.loads(Path("/tmp/cnc_sim_linuxcnc_dynamic_tool_length.json").read_text())
dynamic_offsets = [
(event["line"], event["start"]["x"], event["start"]["z"])
for event in dynamic_tool_length
if event["type"] == "comment" and event["reserved"] == 430
]
expected_dynamic_offsets = [(2, 1, 2), (3, 1.25, 2.5), (4, 1.25, 15), (5, 0, 0)]
if dynamic_offsets != expected_dynamic_offsets:
raise SystemExit(f"unexpected G43.1/G43.2 tool length offsets: {dynamic_offsets!r}")
cycle = json.loads(Path("/tmp/cnc_sim_linuxcnc_canned_cycle.json").read_text()) cycle = json.loads(Path("/tmp/cnc_sim_linuxcnc_canned_cycle.json").read_text())
motions = [event for event in cycle if event["type"] in {"rapid", "linear-feed"}] motions = [event for event in cycle if event["type"] in {"rapid", "linear-feed"}]
expected_cycle = [ expected_cycle = [
@@ -183,6 +380,152 @@ actual_cycle = [(event["type"], event["end"]["x"], event["end"]["y"], event["end
if actual_cycle != expected_cycle: if actual_cycle != expected_cycle:
raise SystemExit(f"unexpected G81/G80 expansion: {actual_cycle!r}") raise SystemExit(f"unexpected G81/G80 expansion: {actual_cycle!r}")
cycle_planes = json.loads(Path("/tmp/cnc_sim_linuxcnc_canned_cycle_planes.json").read_text())
if not any(
event["type"] == "linear-feed" and
event["line"] == 4 and
event["end"]["x"] == 1 and
event["end"]["y"] == -2 and
event["end"]["z"] == 4
for event in cycle_planes
):
raise SystemExit("missing G18 G81 feed along Y depth axis")
if not any(
event["type"] == "rapid" and
event["line"] == 4 and
event["end"]["x"] == 1 and
event["end"]["y"] == 3 and
event["end"]["z"] == 4
for event in cycle_planes
):
raise SystemExit("missing G18 G81 retract to Y R plane")
if not any(
event["type"] == "linear-feed" and
event["line"] == 7 and
event["end"]["x"] == -2 and
event["end"]["y"] == 3 and
event["end"]["z"] == 4
for event in cycle_planes
):
raise SystemExit("missing G19 G82 feed along X depth axis")
if not any(
event["type"] == "dwell" and
event["line"] == 7 and
event["dwellSeconds"] == 0.2
for event in cycle_planes
):
raise SystemExit("missing G19 G82 dwell at bottom")
if not any(
event["type"] == "rapid" and
event["line"] == 7 and
event["end"]["x"] == 2 and
event["end"]["y"] == 3 and
event["end"]["z"] == 4
for event in cycle_planes
):
raise SystemExit("missing G19 G82 retract to X R plane")
def plane_cycle_signature(event):
if event["type"] in {"rapid", "linear-feed"}:
return (event["type"], event["end"]["x"], event["end"]["y"], event["end"]["z"])
if event["type"] == "set-spindle":
return ("set-spindle", event["spindle"], event["reserved"])
if event["type"] == "dwell":
return ("dwell", event["dwellSeconds"])
if event["type"] == "program-end":
return ("program-end", event["reserved"])
return None
plane_g84_sequence = [
plane_cycle_signature(event)
for event in cycle_planes
if event["line"] == 11 and event["type"] in {"rapid", "linear-feed", "set-spindle", "dwell"}
]
expected_plane_g84_sequence = [
("rapid", 1, 5, 4),
("rapid", 1, 3, 4),
("linear-feed", -2, 4, 1),
("set-spindle", 0, 0),
("set-spindle", 600, 2),
("dwell", 0.05),
("linear-feed", 3, 4, 1),
("set-spindle", 0, 0),
("set-spindle", 600, 1),
]
if plane_g84_sequence != expected_plane_g84_sequence:
raise SystemExit(f"unexpected G18 G84 plane sequence: {plane_g84_sequence!r}")
plane_g74_sequence = [
plane_cycle_signature(event)
for event in cycle_planes
if event["line"] == 15 and event["type"] in {"rapid", "linear-feed", "set-spindle", "dwell"}
]
expected_plane_g74_sequence = [
("rapid", 5, 3, 4),
("rapid", 2, 3, 4),
("linear-feed", 4, -2, 3),
("set-spindle", 0, 0),
("set-spindle", 500, 1),
("dwell", 0.04),
("linear-feed", 4, 2, 3),
("set-spindle", 0, 0),
("set-spindle", 500, 2),
]
if plane_g74_sequence != expected_plane_g74_sequence:
raise SystemExit(f"unexpected G19 G74 plane sequence: {plane_g74_sequence!r}")
plane_g86_sequence = [
plane_cycle_signature(event)
for event in cycle_planes
if event["line"] == 19 and event["type"] in {"rapid", "linear-feed", "set-spindle", "dwell"}
]
expected_plane_g86_sequence = [
("rapid", 1, 5, 4),
("rapid", 1, 3, 4),
("linear-feed", 1, -2, 4),
("dwell", 0.1),
("set-spindle", 0, 0),
("rapid", 1, 3, 4),
("set-spindle", 900, 1),
]
if plane_g86_sequence != expected_plane_g86_sequence:
raise SystemExit(f"unexpected G18 G86 plane sequence: {plane_g86_sequence!r}")
plane_g88_sequence = [
plane_cycle_signature(event)
for event in cycle_planes
if event["line"] == 23 and event["type"] in {"rapid", "linear-feed", "set-spindle", "dwell", "program-end"}
]
expected_plane_g88_sequence = [
("rapid", 5, 3, 4),
("rapid", 2, 3, 4),
("linear-feed", -2, 3, 4),
("dwell", 0.07),
("set-spindle", 0, 0),
("program-end", 1),
("set-spindle", 700, 1),
]
if plane_g88_sequence != expected_plane_g88_sequence:
raise SystemExit(f"unexpected G19 G88 plane sequence: {plane_g88_sequence!r}")
plane_g87_sequence = [
plane_cycle_signature(event)
for event in cycle_planes
if event["line"] == 27 and event["type"] in {"rapid", "linear-feed", "set-spindle"}
]
expected_plane_g87_sequence = [
("rapid", 5, 1, 2),
("rapid", 2, 1, 2),
("rapid", 2, 1.2, 2.3),
("set-spindle", 0, 0),
("rapid", -4, 1.2, 2.3),
("rapid", -4, 1, 2),
("set-spindle", 800, 1),
("linear-feed", -2, 1, 2),
("linear-feed", -4, 1, 2),
("set-spindle", 0, 0),
("rapid", -4, 1.2, 2.3),
("rapid", 2, 1.2, 2.3),
("rapid", 2, 1, 2),
("set-spindle", 800, 1),
]
if plane_g87_sequence != expected_plane_g87_sequence:
raise SystemExit(f"unexpected G19 G87 plane sequence: {plane_g87_sequence!r}")
extended_cycle = json.loads(Path("/tmp/cnc_sim_linuxcnc_canned_cycles_extended.json").read_text()) extended_cycle = json.loads(Path("/tmp/cnc_sim_linuxcnc_canned_cycles_extended.json").read_text())
if not any( if not any(
event["type"] == "linear-feed" and event["type"] == "linear-feed" and
@@ -214,6 +557,178 @@ if not any(
for event in extended_cycle for event in extended_cycle
): ):
raise SystemExit("missing G83 final retract to R plane") raise SystemExit("missing G83 final retract to R plane")
def g84_signature(event):
if event["type"] == "linear-feed":
return ("linear-feed", event["end"]["x"], event["end"]["z"])
if event["type"] == "set-spindle":
return ("set-spindle", event["spindle"], event["reserved"])
if event["type"] == "dwell":
return ("dwell", event["dwellSeconds"])
if event["type"] == "program-end":
return ("program-end", event["reserved"])
return None
g84_sequence = [
g84_signature(event)
for event in extended_cycle
if event["line"] == 7 and event["type"] in {"linear-feed", "set-spindle", "dwell"}
]
expected_g84_sequence = [
("linear-feed", 30, -2),
("set-spindle", 0, 0),
("set-spindle", 600, 2),
("dwell", 0.05),
("linear-feed", 30, 2),
("set-spindle", 0, 0),
("set-spindle", 600, 1),
]
if g84_sequence != expected_g84_sequence:
raise SystemExit(f"unexpected G84 tapping sequence: {g84_sequence!r}")
g74_sequence = [
g84_signature(event)
for event in extended_cycle
if event["line"] == 9 and event["type"] in {"linear-feed", "set-spindle", "dwell"}
]
expected_g74_sequence = [
("linear-feed", 40, -2),
("set-spindle", 0, 0),
("set-spindle", 500, 1),
("dwell", 0.04),
("linear-feed", 40, 2),
("set-spindle", 0, 0),
("set-spindle", 500, 2),
]
if g74_sequence != expected_g74_sequence:
raise SystemExit(f"unexpected G74 tapping sequence: {g74_sequence!r}")
g88_sequence = [
g84_signature(event)
for event in extended_cycle
if event["line"] == 11 and event["type"] in {"linear-feed", "set-spindle", "dwell", "program-end"}
]
expected_g88_sequence = [
("linear-feed", 50, -2),
("dwell", 0.07),
("set-spindle", 0, 0),
("program-end", 1),
("set-spindle", 700, 1),
]
if g88_sequence != expected_g88_sequence:
raise SystemExit(f"unexpected G88 manual-out sequence: {g88_sequence!r}")
if any(
event["type"] == "rapid" and
event["line"] == 11 and
event["start"]["x"] == 50 and
event["start"]["z"] == -2 and
event["end"]["x"] == 50 and
event["end"]["z"] == 2
for event in extended_cycle
):
raise SystemExit("unexpected G88 automatic retract")
def g87_signature(event):
if event["type"] in {"rapid", "linear-feed"}:
return (event["type"], event["end"]["x"], event["end"]["y"], event["end"]["z"])
if event["type"] == "set-spindle":
return ("set-spindle", event["spindle"], event["reserved"])
return None
g87_sequence = [
g87_signature(event)
for event in extended_cycle
if event["line"] == 14 and event["type"] in {"rapid", "linear-feed", "set-spindle"}
]
expected_g87_sequence = [
("rapid", 60, 0, 5),
("rapid", 60, 0, 2),
("rapid", 60.2, 0.3, 2),
("set-spindle", 0, 0),
("rapid", 60.2, 0.3, -4),
("rapid", 60, 0, -4),
("set-spindle", 800, 1),
("linear-feed", 60, 0, -2),
("linear-feed", 60, 0, -4),
("set-spindle", 0, 0),
("rapid", 60.2, 0.3, -4),
("rapid", 60.2, 0.3, 2),
("rapid", 60, 0, 2),
("set-spindle", 800, 1),
]
if g87_sequence != expected_g87_sequence:
raise SystemExit(f"unexpected G87 back-boring sequence: {g87_sequence!r}")
arc_planes = json.loads(Path("/tmp/cnc_sim_linuxcnc_arc_planes.json").read_text())
if not any(
event["type"] == "arc-feed" and
event["line"] == 5 and
event["plane"] == 18 and
event["start"]["x"] == 0 and
event["start"]["z"] == 0 and
event["end"]["x"] == 10 and
event["end"]["z"] == 0 and
event["center"]["x"] == 5 and
event["center"]["z"] == 0 and
event["arcTurns"] == -1
for event in arc_planes
):
raise SystemExit("missing G18 XZ plane arc-feed mapping")
if not any(
event["type"] == "arc-feed" and
event["line"] == 8 and
event["plane"] == 19 and
event["start"]["y"] == 0 and
event["start"]["z"] == 0 and
event["end"]["y"] == 10 and
event["end"]["z"] == 0 and
event["center"]["y"] == 5 and
event["center"]["z"] == 0 and
event["arcTurns"] == 1
for event in arc_planes
):
raise SystemExit("missing G19 YZ plane arc-feed mapping")
arc_distance = json.loads(Path("/tmp/cnc_sim_linuxcnc_arc_distance_modes.json").read_text())
arc_centers = [
(event["line"], event["center"]["x"], event["center"]["y"])
for event in arc_distance
if event["type"] == "arc-feed"
]
expected_arc_centers = [(5, 5, 0), (7, 15, 0), (9, 25, 0)]
if arc_centers != expected_arc_centers:
raise SystemExit(f"unexpected G90.1/G91.1 arc centers: {arc_centers!r}")
predefined = json.loads(Path("/tmp/cnc_sim_linuxcnc_predefined_positions.json").read_text())
predefined_rapids = [
(
event["line"],
event["start"]["x"], event["start"]["y"], event["start"]["z"],
event["end"]["x"], event["end"]["y"], event["end"]["z"],
)
for event in predefined
if event["type"] == "rapid" and event["line"] in {5, 9}
]
expected_predefined_rapids = [
(5, 10, 20, 30, 10, 20, 5),
(5, 10, 20, 5, 10, 20, 3),
(9, 40, 50, 60, 40, 50, 60),
(9, 40, 50, 60, 4, 5, 6),
]
if predefined_rapids != expected_predefined_rapids:
raise SystemExit(f"unexpected G28/G30 rapid sequence: {predefined_rapids!r}")
machine_coords = json.loads(Path("/tmp/cnc_sim_linuxcnc_machine_coordinates.json").read_text())
machine_moves = [
(
event["type"], event["line"],
event["start"]["x"], event["start"]["y"], event["start"]["z"],
event["end"]["x"], event["end"]["y"], event["end"]["z"],
)
for event in machine_coords
if event["type"] in {"rapid", "linear-feed"} and event["line"] in {3, 4, 6}
]
expected_machine_moves = [
("rapid", 3, 5, 6, 7, 0, 6, 1),
("rapid", 4, 0, 6, 1, 2, 6, 1),
("linear-feed", 6, 2, 6, 1, 2, 3, 1),
]
if machine_moves != expected_machine_moves:
raise SystemExit(f"unexpected G53 machine-coordinate moves: {machine_moves!r}")
cutter_comp = json.loads(Path("/tmp/cnc_sim_linuxcnc_cutter_comp.json").read_text()) cutter_comp = json.loads(Path("/tmp/cnc_sim_linuxcnc_cutter_comp.json").read_text())
cutter_comp_motions = [ cutter_comp_motions = [
@@ -248,17 +763,29 @@ if not any(event["type"] == "comment" and event["line"] == 2 for event in commen
raise SystemExit("missing LinuxCNC comment line event") raise SystemExit("missing LinuxCNC comment line event")
probe = json.loads(Path("/tmp/cnc_sim_linuxcnc_probe_no_error.json").read_text()) probe = json.loads(Path("/tmp/cnc_sim_linuxcnc_probe_no_error.json").read_text())
probe_events = [
(event["line"], event["reserved"], event["start"]["z"], event["end"]["z"])
for event in probe
if event["type"] == "probe"
]
expected_probe_events = [
(4, 0, 5, 4),
(6, 1, 5, 3),
(8, 2, 5, 2),
(10, 3, 5, 1),
(12, 1, 5, 0),
]
if probe_events != expected_probe_events:
raise SystemExit(f"unexpected G38 probe variants: {probe_events!r}")
if any(event["type"] == "linear-feed" and event["line"] in {4, 6, 8, 10, 12} for event in probe):
raise SystemExit("G38 probe moves should not be emitted as linear-feed")
if not any( if not any(
event["type"] == "probe" and event["type"] == "linear-feed" and
event["line"] == 4 and event["line"] == 14 and
event["feed"] == 100 and event["end"]["x"] == 1
event["start"]["z"] == 5 and
event["end"]["z"] == 0
for event in probe for event in probe
): ):
raise SystemExit("missing G38.3 probe event") raise SystemExit("missing #5070 probe-tripped conditional motion")
if any(event["type"] == "linear-feed" and event["line"] == 4 for event in probe):
raise SystemExit("G38.3 probe should not be emitted as linear-feed")
oword = json.loads(Path("/tmp/cnc_sim_linuxcnc_oword_subprogram.json").read_text()) oword = json.loads(Path("/tmp/cnc_sim_linuxcnc_oword_subprogram.json").read_text())
if not any( if not any(
@@ -285,6 +812,161 @@ if any(
): ):
raise SystemExit("LinuxCNC O-word return should skip remaining subprogram body") raise SystemExit("LinuxCNC O-word return should skip remaining subprogram body")
named_oword = json.loads(Path("/tmp/cnc_sim_linuxcnc_named_oword_subprogram.json").read_text())
if not any(
event["type"] == "linear-feed" and
event["line"] == 9 and
event["start"]["x"] == 0 and
event["end"]["x"] == 10
for event in named_oword
):
raise SystemExit("missing LinuxCNC named O-word expression motion")
if not any(
event["type"] == "linear-feed" and
event["line"] == 10 and
event["start"]["y"] == 0 and
event["end"]["y"] == 6
for event in named_oword
):
raise SystemExit("missing LinuxCNC named O-word #2 argument motion")
if not any(
event["type"] == "linear-feed" and
event["line"] == 5 and
event["start"]["x"] == 10 and
event["end"]["x"] == 20
for event in named_oword
):
raise SystemExit("missing LinuxCNC named O-word return-to-caller motion")
if any(
event["type"] == "linear-feed" and
event["line"] == 12 and
event["end"]["x"] == 99
for event in named_oword
):
raise SystemExit("LinuxCNC named O-word return should skip remaining subprogram body")
oword_flow = json.loads(Path("/tmp/cnc_sim_linuxcnc_oword_control_flow.json").read_text())
if not any(event["type"] == "linear-feed" and event["line"] == 7 and event["end"]["x"] == 2 for event in oword_flow):
raise SystemExit("missing LinuxCNC O-word elseif branch motion")
if any(
event["type"] == "linear-feed" and event["line"] in {5, 9} and event["end"]["x"] in {98, 99}
for event in oword_flow
):
raise SystemExit("LinuxCNC O-word conditional should skip inactive branches")
while_values = [
event["end"]["y"]
for event in oword_flow
if event["type"] == "linear-feed" and event["line"] == 13
]
if while_values != [0, 1, 2]:
raise SystemExit(f"unexpected LinuxCNC O-word while values: {while_values!r}")
repeat_values = [
event["end"]["z"]
for event in oword_flow
if event["type"] == "linear-feed" and event["line"] == 19
]
if repeat_values != [1, 2, 3]:
raise SystemExit(f"unexpected LinuxCNC O-word repeat values: {repeat_values!r}")
do_values = [
event["end"]["a"]
for event in oword_flow
if event["type"] == "linear-feed" and event["line"] == 24
]
if do_values != [1, 2, 3]:
raise SystemExit(f"unexpected LinuxCNC O-word do/while values: {do_values!r}")
break_values = [
event["end"]["b"]
for event in oword_flow
if event["type"] == "linear-feed" and event["line"] == 32
]
if break_values != [1]:
raise SystemExit(f"unexpected LinuxCNC O-word do/break body values: {break_values!r}")
if not any(
event["type"] == "linear-feed" and
event["line"] == 34 and
event["end"]["c"] == 2
for event in oword_flow
):
raise SystemExit("missing LinuxCNC O-word do/break final loop counter motion")
continue_values = [
event["end"]["u"]
for event in oword_flow
if event["type"] == "linear-feed" and event["line"] == 43
]
if continue_values != [2, 3]:
raise SystemExit(f"unexpected LinuxCNC O-word do/continue body values: {continue_values!r}")
if not any(
event["type"] == "linear-feed" and
event["line"] == 45 and
event["end"]["v"] == 3
for event in oword_flow
):
raise SystemExit("missing LinuxCNC O-word do/continue final loop counter motion")
if not any(
event["type"] == "linear-feed" and
event["line"] == 46 and
event["end"]["w"] == 2
for event in oword_flow
):
raise SystemExit("missing LinuxCNC O-word do/continue skipped-body counter motion")
exists = json.loads(Path("/tmp/cnc_sim_linuxcnc_named_parameter_exists.json").read_text())
exists_moves = [
(event["line"], event["end"]["x"], event["end"]["y"])
for event in exists
if event["type"] == "linear-feed"
]
expected_exists_moves = [(5, 1, 0), (8, 1, 1)]
if exists_moves != expected_exists_moves:
raise SystemExit(f"unexpected LinuxCNC EXISTS named parameter branch motions: {exists_moves!r}")
indexed = json.loads(Path("/tmp/cnc_sim_linuxcnc_indexed_parameters.json").read_text())
indexed_moves = [
(
event["line"],
event["end"]["x"], event["end"]["y"], event["end"]["z"],
event["end"]["a"], event["end"]["b"], event["end"]["c"],
event["end"]["u"], event["end"]["v"], event["end"]["w"],
)
for event in indexed
if event["type"] == "linear-feed"
]
expected_indexed_moves = [
(7, 17, 0, 0, 0, 0, 0, 0, 0, 0),
(8, 17, 22, 0, 0, 0, 0, 0, 0, 0),
(10, 17, 22, 1, 0, 0, 0, 0, 0, 0),
(13, 17, 22, 1, 21, 0, 0, 0, 0, 0),
(14, 17, 22, 1, 21, 9, 0, 0, 0, 0),
(16, 17, 22, 1, 21, 9, 9, 2, 0, 0),
(17, 17, 22, 1, 21, 9, 9, 2, 4, 9),
(18, 4, 22, 1, 21, 9, 9, 2, 4, 9),
(19, 4, 12, 4, 21, 9, 9, 2, 4, 9),
(20, 4, 12, 4, 12, 9, 9, 2, 4, 9),
(21, 4, 12, 4, 12, 14, 9, 2, 4, 9),
]
if indexed_moves != expected_indexed_moves:
raise SystemExit(f"unexpected LinuxCNC indexed/indirect parameter motions: {indexed_moves!r}")
normalized = json.loads(Path("/tmp/cnc_sim_linuxcnc_named_parameter_normalization.json").read_text())
normalized_moves = [
(event["line"], event["end"]["x"], event["end"]["y"])
for event in normalized
if event["type"] == "linear-feed"
]
expected_normalized_moves = [(4, 12, 0), (6, 12, 1)]
if normalized_moves != expected_normalized_moves:
raise SystemExit(f"unexpected LinuxCNC normalized named parameter motions: {normalized_moves!r}")
ini_named = json.loads(Path("/tmp/cnc_sim_linuxcnc_ini_named_parameter.json").read_text())
ini_named_moves = [
(event["line"], event["end"]["x"], event["end"]["y"])
for event in ini_named
if event["type"] == "linear-feed"
]
expected_ini_named_moves = [(3, 3.25, 0), (5, 3.25, 1)]
if ini_named_moves != expected_ini_named_moves:
raise SystemExit(f"unexpected LinuxCNC INI named parameter motions: {ini_named_moves!r}")
coords = json.loads(Path("/tmp/cnc_sim_linuxcnc_coordinate_offsets.json").read_text()) coords = json.loads(Path("/tmp/cnc_sim_linuxcnc_coordinate_offsets.json").read_text())
g5x = [event for event in coords if event["type"] == "set-g5x-offset"] g5x = [event for event in coords if event["type"] == "set-g5x-offset"]
g92 = [event for event in coords if event["type"] == "set-g92-offset"] g92 = [event for event in coords if event["type"] == "set-g92-offset"]
@@ -324,6 +1006,76 @@ if not any(
raise SystemExit("missing G10 L20 P2 offset event after G55 selection") raise SystemExit("missing G10 L20 P2 offset event after G55 selection")
if not any(event["type"] == "program-end" and event["line"] == 5 for event in l20): if not any(event["type"] == "program-end" and event["line"] == 5 for event in l20):
raise SystemExit("missing G10 L20 program end line number") raise SystemExit("missing G10 L20 program end line number")
p0 = json.loads(Path("/tmp/cnc_sim_linuxcnc_coordinate_p0.json").read_text())
if not any(
event["type"] == "set-g5x-offset" and
event["line"] == 3 and
event["tool"] == 2 and
event["start"]["x"] == 7 and
event["start"]["y"] == 8 and
event["start"]["z"] == 9
for event in p0
):
raise SystemExit("missing G10 L2 P0 active G55 offset event")
if not any(event["type"] == "program-end" and event["line"] == 4 for event in p0):
raise SystemExit("missing G10 P0 program end line number")
select_all = json.loads(Path("/tmp/cnc_sim_linuxcnc_coordinate_select_all.json").read_text())
select_events = [
(event["line"], event["tool"], event["start"]["x"])
for event in select_all
if event["type"] == "set-g5x-offset" and event["line"] in set(range(11, 20))
]
expected_select_events = [
(11, 2, 2),
(12, 1, 1),
(13, 3, 3),
(14, 4, 4),
(15, 5, 5),
(16, 6, 6),
(17, 7, 7),
(18, 8, 8),
(19, 9, 9),
]
if select_events != expected_select_events:
raise SystemExit(f"unexpected G54-G59.3 selection events: {select_events!r}")
g92_restore = json.loads(Path("/tmp/cnc_sim_linuxcnc_g92_restore.json").read_text())
g92_states = [
(event["line"], event["start"]["x"], event["start"]["y"], event["start"]["z"])
for event in g92_restore
if event["type"] == "set-g92-offset" and event["line"] > 0
]
expected_g92_states = [
(2, -1, -2, -3),
(3, 0, 0, 0),
(4, -1, -2, -3),
(5, 0, 0, 0),
(6, 0, 0, 0),
]
if g92_states != expected_g92_states:
raise SystemExit(f"unexpected G92.2/G92.3 restore sequence: {g92_states!r}")
if not any(event["type"] == "program-end" and event["line"] == 7 for event in g92_restore):
raise SystemExit("missing G92 restore program end line number")
g52_offset = json.loads(Path("/tmp/cnc_sim_linuxcnc_g52_offset.json").read_text())
g52_states = [
(event["line"], event["start"]["x"], event["start"]["y"], event["start"]["z"])
for event in g52_offset
if event["type"] == "set-g92-offset" and event["line"] > 0
]
expected_g52_states = [
(2, 1, 2, 0),
(3, 1, 3, 0),
(4, 0, 0, 0),
(5, 1, 3, 0),
(6, 0, 0, 0),
]
if g52_states != expected_g52_states:
raise SystemExit(f"unexpected G52 shared offset sequence: {g52_states!r}")
if not any(event["type"] == "program-end" and event["line"] == 7 for event in g52_offset):
raise SystemExit("missing G52 offset program end line number")
PY PY
echo "linuxcnc rs274 native smoke passed" echo "linuxcnc rs274 native smoke passed"
@@ -331,17 +1083,41 @@ echo "dumped /tmp/cnc_sim_linuxcnc_basic_motion.json"
echo "dumped /tmp/cnc_sim_linuxcnc_basic_mill.json" echo "dumped /tmp/cnc_sim_linuxcnc_basic_mill.json"
echo "dumped /tmp/cnc_sim_linuxcnc_rtcp_controls.json" echo "dumped /tmp/cnc_sim_linuxcnc_rtcp_controls.json"
echo "dumped /tmp/cnc_sim_linuxcnc_spindle_direction.json" echo "dumped /tmp/cnc_sim_linuxcnc_spindle_direction.json"
echo "dumped /tmp/cnc_sim_linuxcnc_spindle_modes.json"
echo "dumped /tmp/cnc_sim_linuxcnc_spindle_orient.json"
echo "dumped /tmp/cnc_sim_linuxcnc_io_controls.json"
echo "dumped /tmp/cnc_sim_linuxcnc_override_controls.json"
echo "dumped /tmp/cnc_sim_linuxcnc_modal_state.json"
echo "dumped /tmp/cnc_sim_linuxcnc_modal_autorestore.json"
echo "dumped /tmp/cnc_sim_linuxcnc_threading_sync.json"
echo "dumped /tmp/cnc_sim_linuxcnc_threading_cycle.json"
echo "dumped /tmp/cnc_sim_linuxcnc_tool_number.json" echo "dumped /tmp/cnc_sim_linuxcnc_tool_number.json"
echo "dumped /tmp/cnc_sim_linuxcnc_program_stops.json" echo "dumped /tmp/cnc_sim_linuxcnc_program_stops.json"
echo "dumped /tmp/cnc_sim_linuxcnc_coolant.json" echo "dumped /tmp/cnc_sim_linuxcnc_coolant.json"
echo "dumped /tmp/cnc_sim_linuxcnc_feed_modes.json" echo "dumped /tmp/cnc_sim_linuxcnc_feed_modes.json"
echo "dumped /tmp/cnc_sim_linuxcnc_motion_modes.json" echo "dumped /tmp/cnc_sim_linuxcnc_motion_modes.json"
echo "dumped /tmp/cnc_sim_linuxcnc_tool_length.json" echo "dumped /tmp/cnc_sim_linuxcnc_tool_length.json"
echo "dumped /tmp/cnc_sim_linuxcnc_dynamic_tool_length.json"
echo "dumped /tmp/cnc_sim_linuxcnc_canned_cycle.json" echo "dumped /tmp/cnc_sim_linuxcnc_canned_cycle.json"
echo "dumped /tmp/cnc_sim_linuxcnc_canned_cycles_extended.json" echo "dumped /tmp/cnc_sim_linuxcnc_canned_cycles_extended.json"
echo "dumped /tmp/cnc_sim_linuxcnc_canned_cycle_planes.json"
echo "dumped /tmp/cnc_sim_linuxcnc_arc_planes.json"
echo "dumped /tmp/cnc_sim_linuxcnc_arc_distance_modes.json"
echo "dumped /tmp/cnc_sim_linuxcnc_predefined_positions.json"
echo "dumped /tmp/cnc_sim_linuxcnc_machine_coordinates.json"
echo "dumped /tmp/cnc_sim_linuxcnc_cutter_comp.json" echo "dumped /tmp/cnc_sim_linuxcnc_cutter_comp.json"
echo "dumped /tmp/cnc_sim_linuxcnc_comments.json" echo "dumped /tmp/cnc_sim_linuxcnc_comments.json"
echo "dumped /tmp/cnc_sim_linuxcnc_probe_no_error.json" echo "dumped /tmp/cnc_sim_linuxcnc_probe_no_error.json"
echo "dumped /tmp/cnc_sim_linuxcnc_oword_subprogram.json" echo "dumped /tmp/cnc_sim_linuxcnc_oword_subprogram.json"
echo "dumped /tmp/cnc_sim_linuxcnc_named_oword_subprogram.json"
echo "dumped /tmp/cnc_sim_linuxcnc_oword_control_flow.json"
echo "dumped /tmp/cnc_sim_linuxcnc_named_parameter_exists.json"
echo "dumped /tmp/cnc_sim_linuxcnc_indexed_parameters.json"
echo "dumped /tmp/cnc_sim_linuxcnc_named_parameter_normalization.json"
echo "dumped /tmp/cnc_sim_linuxcnc_ini_named_parameter.json"
echo "dumped /tmp/cnc_sim_linuxcnc_coordinate_offsets.json" echo "dumped /tmp/cnc_sim_linuxcnc_coordinate_offsets.json"
echo "dumped /tmp/cnc_sim_linuxcnc_coordinate_l20.json" echo "dumped /tmp/cnc_sim_linuxcnc_coordinate_l20.json"
echo "dumped /tmp/cnc_sim_linuxcnc_coordinate_p0.json"
echo "dumped /tmp/cnc_sim_linuxcnc_coordinate_select_all.json"
echo "dumped /tmp/cnc_sim_linuxcnc_g92_restore.json"
echo "dumped /tmp/cnc_sim_linuxcnc_g52_offset.json"

View File

@@ -94,6 +94,7 @@ done
var_file="$build_dir/rs274ngc-source.var" var_file="$build_dir/rs274ngc-source.var"
base_var_file="$build_dir/rs274ngc-source-base.var" base_var_file="$build_dir/rs274ngc-source-base.var"
ini_named_parameter_file="$(pwd)/tests/gcode/linuxcnc_ini_named_parameter.ini"
cp "$linuxcnc_root/tests/halui/jogging/sim.var" "$base_var_file" cp "$linuxcnc_root/tests/halui/jogging/sim.var" "$base_var_file"
cp "$base_var_file" "$var_file" cp "$base_var_file" "$var_file"
@@ -106,6 +107,36 @@ CNC_SIM_RS274_VAR="$var_file" \
CNC_SIM_RS274_VAR="$var_file" \ CNC_SIM_RS274_VAR="$var_file" \
"$build_dir/linuxcnc_rs274_source_dump" tests/gcode/linuxcnc_spindle_direction.ngc \ "$build_dir/linuxcnc_rs274_source_dump" tests/gcode/linuxcnc_spindle_direction.ngc \
>/tmp/cnc_sim_linuxcnc_source_spindle_direction.json >/tmp/cnc_sim_linuxcnc_source_spindle_direction.json
CNC_SIM_RS274_VAR="$var_file" \
"$build_dir/linuxcnc_rs274_source_dump" tests/gcode/linuxcnc_spindle_modes.ngc \
>/tmp/cnc_sim_linuxcnc_source_spindle_modes.json
CNC_SIM_RS274_VAR="$var_file" \
"$build_dir/linuxcnc_rs274_source_dump" tests/gcode/linuxcnc_spindle_orient.ngc \
>/tmp/cnc_sim_linuxcnc_source_spindle_orient.json
CNC_SIM_RS274_VAR="$var_file" \
"$build_dir/linuxcnc_rs274_source_dump" tests/gcode/linuxcnc_io_controls.ngc \
>/tmp/cnc_sim_linuxcnc_source_io_controls.json
CNC_SIM_RS274_VAR="$var_file" \
"$build_dir/linuxcnc_rs274_source_dump" tests/gcode/linuxcnc_override_controls.ngc \
>/tmp/cnc_sim_linuxcnc_source_override_controls.json
CNC_SIM_RS274_VAR="$var_file" \
"$build_dir/linuxcnc_rs274_source_dump" tests/gcode/linuxcnc_modal_state.ngc \
>/tmp/cnc_sim_linuxcnc_source_modal_state.json
CNC_SIM_RS274_FILE_MODE=1 CNC_SIM_RS274_VAR="$var_file" \
"$build_dir/linuxcnc_rs274_source_dump" tests/gcode/linuxcnc_modal_autorestore.ngc \
>/tmp/cnc_sim_linuxcnc_source_modal_autorestore.json
if CNC_SIM_RS274_VAR="$var_file" \
"$build_dir/linuxcnc_rs274_source_dump" tests/gcode/linuxcnc_modal_invalidate.ngc \
>/tmp/cnc_sim_linuxcnc_source_modal_invalidate.json 2>/tmp/cnc_sim_linuxcnc_source_modal_invalidate.err; then
echo "expected linuxcnc_modal_invalidate.ngc to fail" >&2
exit 1
fi
CNC_SIM_RS274_VAR="$var_file" \
"$build_dir/linuxcnc_rs274_source_dump" tests/gcode/linuxcnc_threading_sync.ngc \
>/tmp/cnc_sim_linuxcnc_source_threading_sync.json
CNC_SIM_RS274_VAR="$var_file" \
"$build_dir/linuxcnc_rs274_source_dump" tests/gcode/linuxcnc_threading_cycle.ngc \
>/tmp/cnc_sim_linuxcnc_source_threading_cycle.json
CNC_SIM_RS274_VAR="$var_file" \ CNC_SIM_RS274_VAR="$var_file" \
"$build_dir/linuxcnc_rs274_source_dump" tests/gcode/linuxcnc_tool_number.ngc \ "$build_dir/linuxcnc_rs274_source_dump" tests/gcode/linuxcnc_tool_number.ngc \
>/tmp/cnc_sim_linuxcnc_source_tool_number.json >/tmp/cnc_sim_linuxcnc_source_tool_number.json
@@ -124,12 +155,30 @@ CNC_SIM_RS274_VAR="$var_file" \
CNC_SIM_RS274_VAR="$var_file" \ CNC_SIM_RS274_VAR="$var_file" \
"$build_dir/linuxcnc_rs274_source_dump" tests/gcode/linuxcnc_tool_length.ngc \ "$build_dir/linuxcnc_rs274_source_dump" tests/gcode/linuxcnc_tool_length.ngc \
>/tmp/cnc_sim_linuxcnc_source_tool_length.json >/tmp/cnc_sim_linuxcnc_source_tool_length.json
CNC_SIM_RS274_VAR="$var_file" \
"$build_dir/linuxcnc_rs274_source_dump" tests/gcode/linuxcnc_dynamic_tool_length.ngc \
>/tmp/cnc_sim_linuxcnc_source_dynamic_tool_length.json
CNC_SIM_RS274_VAR="$var_file" \ CNC_SIM_RS274_VAR="$var_file" \
"$build_dir/linuxcnc_rs274_source_dump" tests/gcode/linuxcnc_canned_cycle.ngc \ "$build_dir/linuxcnc_rs274_source_dump" tests/gcode/linuxcnc_canned_cycle.ngc \
>/tmp/cnc_sim_linuxcnc_source_canned_cycle.json >/tmp/cnc_sim_linuxcnc_source_canned_cycle.json
CNC_SIM_RS274_VAR="$var_file" \ CNC_SIM_RS274_VAR="$var_file" \
"$build_dir/linuxcnc_rs274_source_dump" tests/gcode/linuxcnc_canned_cycles_extended.ngc \ "$build_dir/linuxcnc_rs274_source_dump" tests/gcode/linuxcnc_canned_cycles_extended.ngc \
>/tmp/cnc_sim_linuxcnc_source_canned_cycles_extended.json >/tmp/cnc_sim_linuxcnc_source_canned_cycles_extended.json
CNC_SIM_RS274_VAR="$var_file" \
"$build_dir/linuxcnc_rs274_source_dump" tests/gcode/linuxcnc_canned_cycle_planes.ngc \
>/tmp/cnc_sim_linuxcnc_source_canned_cycle_planes.json
CNC_SIM_RS274_VAR="$var_file" \
"$build_dir/linuxcnc_rs274_source_dump" tests/gcode/linuxcnc_arc_planes.ngc \
>/tmp/cnc_sim_linuxcnc_source_arc_planes.json
CNC_SIM_RS274_VAR="$var_file" \
"$build_dir/linuxcnc_rs274_source_dump" tests/gcode/linuxcnc_arc_distance_modes.ngc \
>/tmp/cnc_sim_linuxcnc_source_arc_distance_modes.json
CNC_SIM_RS274_VAR="$var_file" \
"$build_dir/linuxcnc_rs274_source_dump" tests/gcode/linuxcnc_predefined_positions.ngc \
>/tmp/cnc_sim_linuxcnc_source_predefined_positions.json
CNC_SIM_RS274_VAR="$var_file" \
"$build_dir/linuxcnc_rs274_source_dump" tests/gcode/linuxcnc_machine_coordinates.ngc \
>/tmp/cnc_sim_linuxcnc_source_machine_coordinates.json
CNC_SIM_RS274_VAR="$var_file" \ CNC_SIM_RS274_VAR="$var_file" \
"$build_dir/linuxcnc_rs274_source_dump" tests/gcode/linuxcnc_cutter_comp.ngc \ "$build_dir/linuxcnc_rs274_source_dump" tests/gcode/linuxcnc_cutter_comp.ngc \
>/tmp/cnc_sim_linuxcnc_source_cutter_comp.json >/tmp/cnc_sim_linuxcnc_source_cutter_comp.json
@@ -139,6 +188,24 @@ CNC_SIM_RS274_VAR="$var_file" \
CNC_SIM_RS274_FILE_MODE=1 CNC_SIM_RS274_VAR="$var_file" \ CNC_SIM_RS274_FILE_MODE=1 CNC_SIM_RS274_VAR="$var_file" \
"$build_dir/linuxcnc_rs274_source_dump" tests/gcode/smoke_oword_subprogram.ngc \ "$build_dir/linuxcnc_rs274_source_dump" tests/gcode/smoke_oword_subprogram.ngc \
>/tmp/cnc_sim_linuxcnc_source_oword_subprogram.json >/tmp/cnc_sim_linuxcnc_source_oword_subprogram.json
CNC_SIM_RS274_FILE_MODE=1 CNC_SIM_RS274_VAR="$var_file" \
"$build_dir/linuxcnc_rs274_source_dump" tests/gcode/linuxcnc_named_oword_subprogram.ngc \
>/tmp/cnc_sim_linuxcnc_source_named_oword_subprogram.json
CNC_SIM_RS274_FILE_MODE=1 CNC_SIM_RS274_VAR="$var_file" \
"$build_dir/linuxcnc_rs274_source_dump" tests/gcode/linuxcnc_oword_control_flow.ngc \
>/tmp/cnc_sim_linuxcnc_source_oword_control_flow.json
CNC_SIM_RS274_FILE_MODE=1 CNC_SIM_RS274_VAR="$var_file" \
"$build_dir/linuxcnc_rs274_source_dump" tests/gcode/linuxcnc_named_parameter_exists.ngc \
>/tmp/cnc_sim_linuxcnc_source_named_parameter_exists.json
CNC_SIM_RS274_FILE_MODE=1 CNC_SIM_RS274_VAR="$var_file" \
"$build_dir/linuxcnc_rs274_source_dump" tests/gcode/linuxcnc_indexed_parameters.ngc \
>/tmp/cnc_sim_linuxcnc_source_indexed_parameters.json
CNC_SIM_RS274_FILE_MODE=1 CNC_SIM_RS274_VAR="$var_file" \
"$build_dir/linuxcnc_rs274_source_dump" tests/gcode/linuxcnc_named_parameter_normalization.ngc \
>/tmp/cnc_sim_linuxcnc_source_named_parameter_normalization.json
INI_FILE_NAME="$ini_named_parameter_file" CNC_SIM_RS274_FILE_MODE=1 CNC_SIM_RS274_VAR="$var_file" \
"$build_dir/linuxcnc_rs274_source_dump" tests/gcode/linuxcnc_ini_named_parameter.ngc \
>/tmp/cnc_sim_linuxcnc_source_ini_named_parameter.json
cp "$base_var_file" "$var_file" cp "$base_var_file" "$var_file"
CNC_SIM_RS274_VAR="$var_file" \ CNC_SIM_RS274_VAR="$var_file" \
"$build_dir/linuxcnc_rs274_source_dump" tests/gcode/linuxcnc_coordinate_offsets.ngc \ "$build_dir/linuxcnc_rs274_source_dump" tests/gcode/linuxcnc_coordinate_offsets.ngc \
@@ -147,6 +214,22 @@ cp "$base_var_file" "$var_file"
CNC_SIM_RS274_VAR="$var_file" \ CNC_SIM_RS274_VAR="$var_file" \
"$build_dir/linuxcnc_rs274_source_dump" tests/gcode/linuxcnc_coordinate_l20.ngc \ "$build_dir/linuxcnc_rs274_source_dump" tests/gcode/linuxcnc_coordinate_l20.ngc \
>/tmp/cnc_sim_linuxcnc_source_coordinate_l20.json >/tmp/cnc_sim_linuxcnc_source_coordinate_l20.json
cp "$base_var_file" "$var_file"
CNC_SIM_RS274_VAR="$var_file" \
"$build_dir/linuxcnc_rs274_source_dump" tests/gcode/linuxcnc_coordinate_p0.ngc \
>/tmp/cnc_sim_linuxcnc_source_coordinate_p0.json
cp "$base_var_file" "$var_file"
CNC_SIM_RS274_VAR="$var_file" \
"$build_dir/linuxcnc_rs274_source_dump" tests/gcode/linuxcnc_coordinate_select_all.ngc \
>/tmp/cnc_sim_linuxcnc_source_coordinate_select_all.json
cp "$base_var_file" "$var_file"
CNC_SIM_RS274_VAR="$var_file" \
"$build_dir/linuxcnc_rs274_source_dump" tests/gcode/linuxcnc_g92_restore.ngc \
>/tmp/cnc_sim_linuxcnc_source_g92_restore.json
cp "$base_var_file" "$var_file"
CNC_SIM_RS274_VAR="$var_file" \
"$build_dir/linuxcnc_rs274_source_dump" tests/gcode/linuxcnc_g52_offset.ngc \
>/tmp/cnc_sim_linuxcnc_source_g52_offset.json
python3 - <<'PY' python3 - <<'PY'
import json import json
@@ -194,6 +277,160 @@ if (3, 1200, 2) not in spindle_states:
if (4, 0, 0) not in spindle_states: if (4, 0, 0) not in spindle_states:
raise SystemExit("missing source-linked M5 stopped spindle state") raise SystemExit("missing source-linked M5 stopped spindle state")
spindle_modes = json.loads(Path("/tmp/cnc_sim_linuxcnc_source_spindle_modes.json").read_text())
spindle_mode_states = [
(event["line"], event["reserved"], event["feed"], event["tool"])
for event in spindle_modes
if event["type"] == "comment" and event["line"] in {2, 3, 4} and event["reserved"] in {960, 970}
]
expected_spindle_mode_states = [
(2, 970, 0, 0),
(3, 960, 2500, 0),
(4, 970, 0, 0),
]
if spindle_mode_states != expected_spindle_mode_states:
raise SystemExit(f"unexpected source-linked G96/G97 spindle mode states: {spindle_mode_states!r}")
spindle_orient = json.loads(Path("/tmp/cnc_sim_linuxcnc_source_spindle_orient.json").read_text())
if not any(
event["type"] == "comment" and
event["line"] == 2 and
event["reserved"] == 1901 and
event["tool"] == 0 and
event["feed"] == 45 and
event["arcTurns"] == 1
for event in spindle_orient
):
raise SystemExit("missing source-linked M19 spindle orient state")
if not any(
event["type"] == "comment" and
event["line"] == 2 and
event["reserved"] == 1902 and
event["tool"] == 0 and
event["dwellSeconds"] == 2
for event in spindle_orient
):
raise SystemExit("missing source-linked M19 spindle orient wait state")
io_controls = json.loads(Path("/tmp/cnc_sim_linuxcnc_source_io_controls.json").read_text())
io_states = [
(event["line"], event["reserved"], event["tool"], event["feed"], event["arcTurns"], event["dwellSeconds"])
for event in io_controls
if event["type"] == "comment" and event["reserved"] in {62, 63, 64, 65, 66, 67, 68}
]
expected_io_states = [
(2, 62, 1, 1, 0, 0),
(3, 63, 1, 0, 0, 0),
(4, 64, 2, 1, 0, 0),
(5, 65, 2, 0, 0, 0),
(6, 66, 0, 3, 1, 5),
(7, 66, 1, 0, 0, 0),
(8, 67, 0, 1.25, 0, 0),
(9, 68, 1, 2.5, 0, 0),
]
if io_states != expected_io_states:
raise SystemExit(f"unexpected source-linked M62-M68 I/O states: {io_states!r}")
override_controls = json.loads(Path("/tmp/cnc_sim_linuxcnc_source_override_controls.json").read_text())
override_states = [
(event["line"], event["reserved"], event["tool"], event["feed"])
for event in override_controls
if event["type"] == "comment" and event["reserved"] in {50, 51, 52, 53}
]
expected_override_states = [
(2, 50, 0, 1),
(2, 51, 0, 1),
(3, 50, 0, 0),
(3, 51, 0, 0),
(4, 50, 0, 1),
(5, 50, 0, 0),
(6, 51, 0, 1),
(7, 51, 0, 0),
(8, 52, 0, 1),
(9, 52, 0, 0),
(10, 53, 0, 1),
(11, 53, 0, 0),
(12, 50, 0, 1),
]
if override_states != expected_override_states:
raise SystemExit(f"unexpected source-linked M48-M53 override states: {override_states!r}")
modal_state = json.loads(Path("/tmp/cnc_sim_linuxcnc_source_modal_state.json").read_text())
if not any(
event["type"] == "rapid" and
event["line"] == 7 and
event["end"]["x"] == 2 and
event["end"]["y"] == 0 and
event["end"]["z"] == 2
for event in modal_state
):
raise SystemExit("missing source-linked M72 restored absolute millimeter move")
if not any(
event["type"] == "arc-feed" and
event["line"] == 8 and
event["plane"] == 17 and
event["end"]["x"] == 4 and
event["end"]["y"] == 0
for event in modal_state
):
raise SystemExit("missing source-linked M72 restored XY plane arc")
modal_autorestore = json.loads(Path("/tmp/cnc_sim_linuxcnc_source_modal_autorestore.json").read_text())
if not any(
event["type"] == "rapid" and
event["line"] == 9 and
event["end"]["x"] == 10
for event in modal_autorestore
):
raise SystemExit("missing source-linked M73 subroutine changed modal state move")
if not any(
event["type"] == "rapid" and
event["line"] == 4 and
event["start"]["x"] == 10 and
event["end"]["x"] == 12
for event in modal_autorestore
):
raise SystemExit("missing source-linked M73 autorestored incremental caller move")
threading_sync = json.loads(Path("/tmp/cnc_sim_linuxcnc_source_threading_sync.json").read_text())
sync_states = [
(event["line"], event["reserved"], event["feed"], event["tool"])
for event in threading_sync
if event["type"] == "comment" and event["reserved"] in {3300, 3301, 3302}
]
expected_sync_states = [
(4, 3301, 1, 0),
(4, 3300, 0, 0),
(6, 3301, 1, 0),
(6, 3300, 0, 0),
]
if sync_states != expected_sync_states:
raise SystemExit(f"unexpected source-linked G33/G33.1 sync states: {sync_states!r}")
if not any(
event["type"] == "linear-feed" and event["line"] == 6 and event["end"]["z"] == 0
for event in threading_sync
):
raise SystemExit("missing source-linked G33.1 rigid tap motion line")
threading_cycle = json.loads(Path("/tmp/cnc_sim_linuxcnc_source_threading_cycle.json").read_text())
if not any(
event["type"] == "comment" and
event["line"] == 4 and
event["reserved"] == 3301 and
event["feed"] == 0.05
for event in threading_cycle
):
raise SystemExit("missing source-linked G76 threading sync start")
if not any(event["type"] == "comment" and event["line"] == 4 and event["reserved"] == 3300 for event in threading_cycle):
raise SystemExit("missing source-linked G76 threading sync stop")
if not any(
event["type"] == "linear-feed" and event["line"] == 4 and event["end"]["z"] == -1
for event in threading_cycle
):
raise SystemExit("missing source-linked G76 final threading pass")
if not any(event["type"] == "program-end" and event["line"] == 5 for event in threading_cycle):
raise SystemExit("missing source-linked G76 program end line number")
tool_number = json.loads(Path("/tmp/cnc_sim_linuxcnc_source_tool_number.json").read_text()) tool_number = json.loads(Path("/tmp/cnc_sim_linuxcnc_source_tool_number.json").read_text())
if not any( if not any(
event["type"] == "tool-change" and event["type"] == "tool-change" and
@@ -269,6 +506,16 @@ if not any(
): ):
raise SystemExit("missing source-linked G49 tool length clear event") raise SystemExit("missing source-linked G49 tool length clear event")
dynamic_tool_length = json.loads(Path("/tmp/cnc_sim_linuxcnc_source_dynamic_tool_length.json").read_text())
dynamic_offsets = [
(event["line"], event["start"]["x"], event["start"]["z"])
for event in dynamic_tool_length
if event["type"] == "comment" and event["reserved"] == 430
]
expected_dynamic_offsets = [(2, 1, 2), (3, 1.25, 2.5), (4, 1.25, 15), (5, 0, 0)]
if dynamic_offsets != expected_dynamic_offsets:
raise SystemExit(f"unexpected source-linked G43.1/G43.2 tool length offsets: {dynamic_offsets!r}")
cycle = json.loads(Path("/tmp/cnc_sim_linuxcnc_source_canned_cycle.json").read_text()) cycle = json.loads(Path("/tmp/cnc_sim_linuxcnc_source_canned_cycle.json").read_text())
motions = [event for event in cycle if event["type"] in {"rapid", "linear-feed"}] motions = [event for event in cycle if event["type"] in {"rapid", "linear-feed"}]
expected_cycle = [ expected_cycle = [
@@ -282,6 +529,152 @@ actual_cycle = [(event["type"], event["end"]["x"], event["end"]["y"], event["end
if actual_cycle != expected_cycle: if actual_cycle != expected_cycle:
raise SystemExit(f"unexpected source-linked G81/G80 expansion: {actual_cycle!r}") raise SystemExit(f"unexpected source-linked G81/G80 expansion: {actual_cycle!r}")
cycle_planes = json.loads(Path("/tmp/cnc_sim_linuxcnc_source_canned_cycle_planes.json").read_text())
if not any(
event["type"] == "linear-feed" and
event["line"] == 4 and
event["end"]["x"] == 1 and
event["end"]["y"] == -2 and
event["end"]["z"] == 4
for event in cycle_planes
):
raise SystemExit("missing source-linked G18 G81 feed along Y depth axis")
if not any(
event["type"] == "rapid" and
event["line"] == 4 and
event["end"]["x"] == 1 and
event["end"]["y"] == 3 and
event["end"]["z"] == 4
for event in cycle_planes
):
raise SystemExit("missing source-linked G18 G81 retract to Y R plane")
if not any(
event["type"] == "linear-feed" and
event["line"] == 7 and
event["end"]["x"] == -2 and
event["end"]["y"] == 3 and
event["end"]["z"] == 4
for event in cycle_planes
):
raise SystemExit("missing source-linked G19 G82 feed along X depth axis")
if not any(
event["type"] == "dwell" and
event["line"] == 7 and
event["dwellSeconds"] == 0.2
for event in cycle_planes
):
raise SystemExit("missing source-linked G19 G82 dwell at bottom")
if not any(
event["type"] == "rapid" and
event["line"] == 7 and
event["end"]["x"] == 2 and
event["end"]["y"] == 3 and
event["end"]["z"] == 4
for event in cycle_planes
):
raise SystemExit("missing source-linked G19 G82 retract to X R plane")
def plane_cycle_signature(event):
if event["type"] in {"rapid", "linear-feed"}:
return (event["type"], event["end"]["x"], event["end"]["y"], event["end"]["z"])
if event["type"] == "set-spindle":
return ("set-spindle", event["spindle"], event["reserved"])
if event["type"] == "dwell":
return ("dwell", event["dwellSeconds"])
if event["type"] == "program-end":
return ("program-end", event["reserved"])
return None
plane_g84_sequence = [
plane_cycle_signature(event)
for event in cycle_planes
if event["line"] == 11 and event["type"] in {"rapid", "linear-feed", "set-spindle", "dwell"}
]
expected_plane_g84_sequence = [
("rapid", 1, 5, 4),
("rapid", 1, 3, 4),
("linear-feed", -2, 4, 1),
("set-spindle", 0, 0),
("set-spindle", 600, 2),
("dwell", 0.05),
("linear-feed", 3, 4, 1),
("set-spindle", 0, 0),
("set-spindle", 600, 1),
]
if plane_g84_sequence != expected_plane_g84_sequence:
raise SystemExit(f"unexpected source-linked G18 G84 plane sequence: {plane_g84_sequence!r}")
plane_g74_sequence = [
plane_cycle_signature(event)
for event in cycle_planes
if event["line"] == 15 and event["type"] in {"rapid", "linear-feed", "set-spindle", "dwell"}
]
expected_plane_g74_sequence = [
("rapid", 5, 3, 4),
("rapid", 2, 3, 4),
("linear-feed", 4, -2, 3),
("set-spindle", 0, 0),
("set-spindle", 500, 1),
("dwell", 0.04),
("linear-feed", 4, 2, 3),
("set-spindle", 0, 0),
("set-spindle", 500, 2),
]
if plane_g74_sequence != expected_plane_g74_sequence:
raise SystemExit(f"unexpected source-linked G19 G74 plane sequence: {plane_g74_sequence!r}")
plane_g86_sequence = [
plane_cycle_signature(event)
for event in cycle_planes
if event["line"] == 19 and event["type"] in {"rapid", "linear-feed", "set-spindle", "dwell"}
]
expected_plane_g86_sequence = [
("rapid", 1, 5, 4),
("rapid", 1, 3, 4),
("linear-feed", 1, -2, 4),
("dwell", 0.1),
("set-spindle", 0, 0),
("rapid", 1, 3, 4),
("set-spindle", 900, 1),
]
if plane_g86_sequence != expected_plane_g86_sequence:
raise SystemExit(f"unexpected source-linked G18 G86 plane sequence: {plane_g86_sequence!r}")
plane_g88_sequence = [
plane_cycle_signature(event)
for event in cycle_planes
if event["line"] == 23 and event["type"] in {"rapid", "linear-feed", "set-spindle", "dwell", "program-end"}
]
expected_plane_g88_sequence = [
("rapid", 5, 3, 4),
("rapid", 2, 3, 4),
("linear-feed", -2, 3, 4),
("dwell", 0.07),
("set-spindle", 0, 0),
("program-end", 1),
("set-spindle", 700, 1),
]
if plane_g88_sequence != expected_plane_g88_sequence:
raise SystemExit(f"unexpected source-linked G19 G88 plane sequence: {plane_g88_sequence!r}")
plane_g87_sequence = [
plane_cycle_signature(event)
for event in cycle_planes
if event["line"] == 27 and event["type"] in {"rapid", "linear-feed", "set-spindle"}
]
expected_plane_g87_sequence = [
("rapid", 5, 1, 2),
("rapid", 2, 1, 2),
("rapid", 2, 1.2, 2.3),
("set-spindle", 0, 0),
("rapid", -4, 1.2, 2.3),
("rapid", -4, 1, 2),
("set-spindle", 800, 1),
("linear-feed", -2, 1, 2),
("linear-feed", -4, 1, 2),
("set-spindle", 0, 0),
("rapid", -4, 1.2, 2.3),
("rapid", 2, 1.2, 2.3),
("rapid", 2, 1, 2),
("set-spindle", 800, 1),
]
if plane_g87_sequence != expected_plane_g87_sequence:
raise SystemExit(f"unexpected source-linked G19 G87 plane sequence: {plane_g87_sequence!r}")
extended_cycle = json.loads(Path("/tmp/cnc_sim_linuxcnc_source_canned_cycles_extended.json").read_text()) extended_cycle = json.loads(Path("/tmp/cnc_sim_linuxcnc_source_canned_cycles_extended.json").read_text())
if not any( if not any(
event["type"] == "linear-feed" and event["type"] == "linear-feed" and
@@ -313,6 +706,178 @@ if not any(
for event in extended_cycle for event in extended_cycle
): ):
raise SystemExit("missing source-linked G83 final retract to R plane") raise SystemExit("missing source-linked G83 final retract to R plane")
def g84_signature(event):
if event["type"] == "linear-feed":
return ("linear-feed", event["end"]["x"], event["end"]["z"])
if event["type"] == "set-spindle":
return ("set-spindle", event["spindle"], event["reserved"])
if event["type"] == "dwell":
return ("dwell", event["dwellSeconds"])
if event["type"] == "program-end":
return ("program-end", event["reserved"])
return None
g84_sequence = [
g84_signature(event)
for event in extended_cycle
if event["line"] == 7 and event["type"] in {"linear-feed", "set-spindle", "dwell"}
]
expected_g84_sequence = [
("linear-feed", 30, -2),
("set-spindle", 0, 0),
("set-spindle", 600, 2),
("dwell", 0.05),
("linear-feed", 30, 2),
("set-spindle", 0, 0),
("set-spindle", 600, 1),
]
if g84_sequence != expected_g84_sequence:
raise SystemExit(f"unexpected source-linked G84 tapping sequence: {g84_sequence!r}")
g74_sequence = [
g84_signature(event)
for event in extended_cycle
if event["line"] == 9 and event["type"] in {"linear-feed", "set-spindle", "dwell"}
]
expected_g74_sequence = [
("linear-feed", 40, -2),
("set-spindle", 0, 0),
("set-spindle", 500, 1),
("dwell", 0.04),
("linear-feed", 40, 2),
("set-spindle", 0, 0),
("set-spindle", 500, 2),
]
if g74_sequence != expected_g74_sequence:
raise SystemExit(f"unexpected source-linked G74 tapping sequence: {g74_sequence!r}")
g88_sequence = [
g84_signature(event)
for event in extended_cycle
if event["line"] == 11 and event["type"] in {"linear-feed", "set-spindle", "dwell", "program-end"}
]
expected_g88_sequence = [
("linear-feed", 50, -2),
("dwell", 0.07),
("set-spindle", 0, 0),
("program-end", 1),
("set-spindle", 700, 1),
]
if g88_sequence != expected_g88_sequence:
raise SystemExit(f"unexpected source-linked G88 manual-out sequence: {g88_sequence!r}")
if any(
event["type"] == "rapid" and
event["line"] == 11 and
event["start"]["x"] == 50 and
event["start"]["z"] == -2 and
event["end"]["x"] == 50 and
event["end"]["z"] == 2
for event in extended_cycle
):
raise SystemExit("unexpected source-linked G88 automatic retract")
def g87_signature(event):
if event["type"] in {"rapid", "linear-feed"}:
return (event["type"], event["end"]["x"], event["end"]["y"], event["end"]["z"])
if event["type"] == "set-spindle":
return ("set-spindle", event["spindle"], event["reserved"])
return None
g87_sequence = [
g87_signature(event)
for event in extended_cycle
if event["line"] == 14 and event["type"] in {"rapid", "linear-feed", "set-spindle"}
]
expected_g87_sequence = [
("rapid", 60, 0, 5),
("rapid", 60, 0, 2),
("rapid", 60.2, 0.3, 2),
("set-spindle", 0, 0),
("rapid", 60.2, 0.3, -4),
("rapid", 60, 0, -4),
("set-spindle", 800, 1),
("linear-feed", 60, 0, -2),
("linear-feed", 60, 0, -4),
("set-spindle", 0, 0),
("rapid", 60.2, 0.3, -4),
("rapid", 60.2, 0.3, 2),
("rapid", 60, 0, 2),
("set-spindle", 800, 1),
]
if g87_sequence != expected_g87_sequence:
raise SystemExit(f"unexpected source-linked G87 back-boring sequence: {g87_sequence!r}")
arc_planes = json.loads(Path("/tmp/cnc_sim_linuxcnc_source_arc_planes.json").read_text())
if not any(
event["type"] == "arc-feed" and
event["line"] == 5 and
event["plane"] == 18 and
event["start"]["x"] == 0 and
event["start"]["z"] == 0 and
event["end"]["x"] == 10 and
event["end"]["z"] == 0 and
event["center"]["x"] == 5 and
event["center"]["z"] == 0 and
event["arcTurns"] == -1
for event in arc_planes
):
raise SystemExit("missing source-linked G18 XZ plane arc-feed mapping")
if not any(
event["type"] == "arc-feed" and
event["line"] == 8 and
event["plane"] == 19 and
event["start"]["y"] == 0 and
event["start"]["z"] == 0 and
event["end"]["y"] == 10 and
event["end"]["z"] == 0 and
event["center"]["y"] == 5 and
event["center"]["z"] == 0 and
event["arcTurns"] == 1
for event in arc_planes
):
raise SystemExit("missing source-linked G19 YZ plane arc-feed mapping")
arc_distance = json.loads(Path("/tmp/cnc_sim_linuxcnc_source_arc_distance_modes.json").read_text())
arc_centers = [
(event["line"], event["center"]["x"], event["center"]["y"])
for event in arc_distance
if event["type"] == "arc-feed"
]
expected_arc_centers = [(5, 5, 0), (7, 15, 0), (9, 25, 0)]
if arc_centers != expected_arc_centers:
raise SystemExit(f"unexpected source-linked G90.1/G91.1 arc centers: {arc_centers!r}")
predefined = json.loads(Path("/tmp/cnc_sim_linuxcnc_source_predefined_positions.json").read_text())
predefined_rapids = [
(
event["line"],
event["start"]["x"], event["start"]["y"], event["start"]["z"],
event["end"]["x"], event["end"]["y"], event["end"]["z"],
)
for event in predefined
if event["type"] == "rapid" and event["line"] in {5, 9}
]
expected_predefined_rapids = [
(5, 10, 20, 30, 10, 20, 5),
(5, 10, 20, 5, 10, 20, 3),
(9, 40, 50, 60, 40, 50, 60),
(9, 40, 50, 60, 4, 5, 6),
]
if predefined_rapids != expected_predefined_rapids:
raise SystemExit(f"unexpected source-linked G28/G30 rapid sequence: {predefined_rapids!r}")
machine_coords = json.loads(Path("/tmp/cnc_sim_linuxcnc_source_machine_coordinates.json").read_text())
machine_moves = [
(
event["type"], event["line"],
event["start"]["x"], event["start"]["y"], event["start"]["z"],
event["end"]["x"], event["end"]["y"], event["end"]["z"],
)
for event in machine_coords
if event["type"] in {"rapid", "linear-feed"} and event["line"] in {3, 4, 6}
]
expected_machine_moves = [
("rapid", 3, 5, 6, 7, 0, 6, 1),
("rapid", 4, 0, 6, 1, 2, 6, 1),
("linear-feed", 6, 2, 6, 1, 2, 3, 1),
]
if machine_moves != expected_machine_moves:
raise SystemExit(f"unexpected source-linked G53 machine-coordinate moves: {machine_moves!r}")
cutter_comp = json.loads(Path("/tmp/cnc_sim_linuxcnc_source_cutter_comp.json").read_text()) cutter_comp = json.loads(Path("/tmp/cnc_sim_linuxcnc_source_cutter_comp.json").read_text())
cutter_comp_motions = [ cutter_comp_motions = [
@@ -343,17 +908,29 @@ if actual_cutter_comp != expected_cutter_comp:
raise SystemExit(f"unexpected source-linked cutter compensation path: {actual_cutter_comp!r}") raise SystemExit(f"unexpected source-linked cutter compensation path: {actual_cutter_comp!r}")
probe = json.loads(Path("/tmp/cnc_sim_linuxcnc_source_probe_no_error.json").read_text()) probe = json.loads(Path("/tmp/cnc_sim_linuxcnc_source_probe_no_error.json").read_text())
probe_events = [
(event["line"], event["reserved"], event["start"]["z"], event["end"]["z"])
for event in probe
if event["type"] == "probe"
]
expected_probe_events = [
(4, 0, 5, 4),
(6, 1, 5, 3),
(8, 2, 5, 2),
(10, 3, 5, 1),
(12, 1, 5, 0),
]
if probe_events != expected_probe_events:
raise SystemExit(f"unexpected source-linked G38 probe variants: {probe_events!r}")
if any(event["type"] == "linear-feed" and event["line"] in {4, 6, 8, 10, 12} for event in probe):
raise SystemExit("source-linked G38 probe moves should not be emitted as linear-feed")
if not any( if not any(
event["type"] == "probe" and event["type"] == "linear-feed" and
event["line"] == 4 and event["line"] == 14 and
event["feed"] == 100 and event["end"]["x"] == 1
event["start"]["z"] == 5 and
event["end"]["z"] == 0
for event in probe for event in probe
): ):
raise SystemExit("missing source-linked G38.3 probe event") raise SystemExit("missing source-linked #5070 probe-tripped conditional motion")
if any(event["type"] == "linear-feed" and event["line"] == 4 for event in probe):
raise SystemExit("source-linked G38.3 probe should not be emitted as linear-feed")
oword = json.loads(Path("/tmp/cnc_sim_linuxcnc_source_oword_subprogram.json").read_text()) oword = json.loads(Path("/tmp/cnc_sim_linuxcnc_source_oword_subprogram.json").read_text())
if not any( if not any(
@@ -380,6 +957,161 @@ if any(
): ):
raise SystemExit("source-linked O-word return should skip remaining subprogram body") raise SystemExit("source-linked O-word return should skip remaining subprogram body")
named_oword = json.loads(Path("/tmp/cnc_sim_linuxcnc_source_named_oword_subprogram.json").read_text())
if not any(
event["type"] == "linear-feed" and
event["line"] == 9 and
event["start"]["x"] == 0 and
event["end"]["x"] == 10
for event in named_oword
):
raise SystemExit("missing source-linked named O-word expression motion")
if not any(
event["type"] == "linear-feed" and
event["line"] == 10 and
event["start"]["y"] == 0 and
event["end"]["y"] == 6
for event in named_oword
):
raise SystemExit("missing source-linked named O-word #2 argument motion")
if not any(
event["type"] == "linear-feed" and
event["line"] == 5 and
event["start"]["x"] == 10 and
event["end"]["x"] == 20
for event in named_oword
):
raise SystemExit("missing source-linked named O-word return-to-caller motion")
if any(
event["type"] == "linear-feed" and
event["line"] == 12 and
event["end"]["x"] == 99
for event in named_oword
):
raise SystemExit("source-linked named O-word return should skip remaining subprogram body")
oword_flow = json.loads(Path("/tmp/cnc_sim_linuxcnc_source_oword_control_flow.json").read_text())
if not any(event["type"] == "linear-feed" and event["line"] == 7 and event["end"]["x"] == 2 for event in oword_flow):
raise SystemExit("missing source-linked O-word elseif branch motion")
if any(
event["type"] == "linear-feed" and event["line"] in {5, 9} and event["end"]["x"] in {98, 99}
for event in oword_flow
):
raise SystemExit("source-linked O-word conditional should skip inactive branches")
while_values = [
event["end"]["y"]
for event in oword_flow
if event["type"] == "linear-feed" and event["line"] == 13
]
if while_values != [0, 1, 2]:
raise SystemExit(f"unexpected source-linked O-word while values: {while_values!r}")
repeat_values = [
event["end"]["z"]
for event in oword_flow
if event["type"] == "linear-feed" and event["line"] == 19
]
if repeat_values != [1, 2, 3]:
raise SystemExit(f"unexpected source-linked O-word repeat values: {repeat_values!r}")
do_values = [
event["end"]["a"]
for event in oword_flow
if event["type"] == "linear-feed" and event["line"] == 24
]
if do_values != [1, 2, 3]:
raise SystemExit(f"unexpected source-linked O-word do/while values: {do_values!r}")
break_values = [
event["end"]["b"]
for event in oword_flow
if event["type"] == "linear-feed" and event["line"] == 32
]
if break_values != [1]:
raise SystemExit(f"unexpected source-linked O-word do/break body values: {break_values!r}")
if not any(
event["type"] == "linear-feed" and
event["line"] == 34 and
event["end"]["c"] == 2
for event in oword_flow
):
raise SystemExit("missing source-linked O-word do/break final loop counter motion")
continue_values = [
event["end"]["u"]
for event in oword_flow
if event["type"] == "linear-feed" and event["line"] == 43
]
if continue_values != [2, 3]:
raise SystemExit(f"unexpected source-linked O-word do/continue body values: {continue_values!r}")
if not any(
event["type"] == "linear-feed" and
event["line"] == 45 and
event["end"]["v"] == 3
for event in oword_flow
):
raise SystemExit("missing source-linked O-word do/continue final loop counter motion")
if not any(
event["type"] == "linear-feed" and
event["line"] == 46 and
event["end"]["w"] == 2
for event in oword_flow
):
raise SystemExit("missing source-linked O-word do/continue skipped-body counter motion")
exists = json.loads(Path("/tmp/cnc_sim_linuxcnc_source_named_parameter_exists.json").read_text())
exists_moves = [
(event["line"], event["end"]["x"], event["end"]["y"])
for event in exists
if event["type"] == "linear-feed"
]
expected_exists_moves = [(5, 1, 0), (8, 1, 1)]
if exists_moves != expected_exists_moves:
raise SystemExit(f"unexpected source-linked EXISTS named parameter branch motions: {exists_moves!r}")
indexed = json.loads(Path("/tmp/cnc_sim_linuxcnc_source_indexed_parameters.json").read_text())
indexed_moves = [
(
event["line"],
event["end"]["x"], event["end"]["y"], event["end"]["z"],
event["end"]["a"], event["end"]["b"], event["end"]["c"],
event["end"]["u"], event["end"]["v"], event["end"]["w"],
)
for event in indexed
if event["type"] == "linear-feed"
]
expected_indexed_moves = [
(7, 17, 0, 0, 0, 0, 0, 0, 0, 0),
(8, 17, 22, 0, 0, 0, 0, 0, 0, 0),
(10, 17, 22, 1, 0, 0, 0, 0, 0, 0),
(13, 17, 22, 1, 21, 0, 0, 0, 0, 0),
(14, 17, 22, 1, 21, 9, 0, 0, 0, 0),
(16, 17, 22, 1, 21, 9, 9, 2, 0, 0),
(17, 17, 22, 1, 21, 9, 9, 2, 4, 9),
(18, 4, 22, 1, 21, 9, 9, 2, 4, 9),
(19, 4, 12, 4, 21, 9, 9, 2, 4, 9),
(20, 4, 12, 4, 12, 9, 9, 2, 4, 9),
(21, 4, 12, 4, 12, 14, 9, 2, 4, 9),
]
if indexed_moves != expected_indexed_moves:
raise SystemExit(f"unexpected source-linked indexed/indirect parameter motions: {indexed_moves!r}")
normalized = json.loads(Path("/tmp/cnc_sim_linuxcnc_source_named_parameter_normalization.json").read_text())
normalized_moves = [
(event["line"], event["end"]["x"], event["end"]["y"])
for event in normalized
if event["type"] == "linear-feed"
]
expected_normalized_moves = [(4, 12, 0), (6, 12, 1)]
if normalized_moves != expected_normalized_moves:
raise SystemExit(f"unexpected source-linked normalized named parameter motions: {normalized_moves!r}")
ini_named = json.loads(Path("/tmp/cnc_sim_linuxcnc_source_ini_named_parameter.json").read_text())
ini_named_moves = [
(event["line"], event["end"]["x"], event["end"]["y"])
for event in ini_named
if event["type"] == "linear-feed"
]
expected_ini_named_moves = [(3, 3.25, 0), (5, 3.25, 1)]
if ini_named_moves != expected_ini_named_moves:
raise SystemExit(f"unexpected source-linked INI named parameter motions: {ini_named_moves!r}")
coords = json.loads(Path("/tmp/cnc_sim_linuxcnc_source_coordinate_offsets.json").read_text()) coords = json.loads(Path("/tmp/cnc_sim_linuxcnc_source_coordinate_offsets.json").read_text())
g5x = [event for event in coords if event["type"] == "set-g5x-offset"] g5x = [event for event in coords if event["type"] == "set-g5x-offset"]
g92 = [event for event in coords if event["type"] == "set-g92-offset"] g92 = [event for event in coords if event["type"] == "set-g92-offset"]
@@ -419,22 +1151,116 @@ if not any(
raise SystemExit("missing source-linked G10 L20 P2 offset event after G55 selection") raise SystemExit("missing source-linked G10 L20 P2 offset event after G55 selection")
if not any(event["type"] == "program-end" and event["line"] == 5 for event in l20): if not any(event["type"] == "program-end" and event["line"] == 5 for event in l20):
raise SystemExit("missing source-linked G10 L20 program end line number") raise SystemExit("missing source-linked G10 L20 program end line number")
p0 = json.loads(Path("/tmp/cnc_sim_linuxcnc_source_coordinate_p0.json").read_text())
if not any(
event["type"] == "set-g5x-offset" and
event["line"] == 3 and
event["tool"] == 2 and
event["start"]["x"] == 7 and
event["start"]["y"] == 8 and
event["start"]["z"] == 9
for event in p0
):
raise SystemExit("missing source-linked G10 L2 P0 active G55 offset event")
if not any(event["type"] == "program-end" and event["line"] == 4 for event in p0):
raise SystemExit("missing source-linked G10 P0 program end line number")
select_all = json.loads(Path("/tmp/cnc_sim_linuxcnc_source_coordinate_select_all.json").read_text())
select_events = [
(event["line"], event["tool"], event["start"]["x"])
for event in select_all
if event["type"] == "set-g5x-offset" and event["line"] in set(range(11, 20))
]
expected_select_events = [
(11, 2, 2),
(12, 1, 1),
(13, 3, 3),
(14, 4, 4),
(15, 5, 5),
(16, 6, 6),
(17, 7, 7),
(18, 8, 8),
(19, 9, 9),
]
if select_events != expected_select_events:
raise SystemExit(f"unexpected source-linked G54-G59.3 selection events: {select_events!r}")
g92_restore = json.loads(Path("/tmp/cnc_sim_linuxcnc_source_g92_restore.json").read_text())
g92_states = [
(event["line"], event["start"]["x"], event["start"]["y"], event["start"]["z"])
for event in g92_restore
if event["type"] == "set-g92-offset" and event["line"] > 0
]
expected_g92_states = [
(2, -1, -2, -3),
(3, 0, 0, 0),
(4, -1, -2, -3),
(5, 0, 0, 0),
(6, 0, 0, 0),
]
if g92_states != expected_g92_states:
raise SystemExit(f"unexpected source-linked G92.2/G92.3 restore sequence: {g92_states!r}")
if not any(event["type"] == "program-end" and event["line"] == 7 for event in g92_restore):
raise SystemExit("missing source-linked G92 restore program end line number")
g52_offset = json.loads(Path("/tmp/cnc_sim_linuxcnc_source_g52_offset.json").read_text())
g52_states = [
(event["line"], event["start"]["x"], event["start"]["y"], event["start"]["z"])
for event in g52_offset
if event["type"] == "set-g92-offset" and event["line"] > 0
]
expected_g52_states = [
(2, 1, 2, 0),
(3, 1, 3, 0),
(4, 0, 0, 0),
(5, 1, 3, 0),
(6, 0, 0, 0),
]
if g52_states != expected_g52_states:
raise SystemExit(f"unexpected source-linked G52 shared offset sequence: {g52_states!r}")
if not any(event["type"] == "program-end" and event["line"] == 7 for event in g52_offset):
raise SystemExit("missing source-linked G52 offset program end line number")
PY PY
echo "linuxcnc rs274 source link smoke passed (${#objects[@]} local objects)" echo "linuxcnc rs274 source link smoke passed (${#objects[@]} local objects)"
echo "dumped /tmp/cnc_sim_linuxcnc_source_basic_mill.json" echo "dumped /tmp/cnc_sim_linuxcnc_source_basic_mill.json"
echo "dumped /tmp/cnc_sim_linuxcnc_source_rtcp_controls.json" echo "dumped /tmp/cnc_sim_linuxcnc_source_rtcp_controls.json"
echo "dumped /tmp/cnc_sim_linuxcnc_source_spindle_direction.json" echo "dumped /tmp/cnc_sim_linuxcnc_source_spindle_direction.json"
echo "dumped /tmp/cnc_sim_linuxcnc_source_spindle_modes.json"
echo "dumped /tmp/cnc_sim_linuxcnc_source_spindle_orient.json"
echo "dumped /tmp/cnc_sim_linuxcnc_source_io_controls.json"
echo "dumped /tmp/cnc_sim_linuxcnc_source_override_controls.json"
echo "dumped /tmp/cnc_sim_linuxcnc_source_modal_state.json"
echo "dumped /tmp/cnc_sim_linuxcnc_source_modal_autorestore.json"
echo "dumped /tmp/cnc_sim_linuxcnc_source_threading_sync.json"
echo "dumped /tmp/cnc_sim_linuxcnc_source_threading_cycle.json"
echo "dumped /tmp/cnc_sim_linuxcnc_source_tool_number.json" echo "dumped /tmp/cnc_sim_linuxcnc_source_tool_number.json"
echo "dumped /tmp/cnc_sim_linuxcnc_source_program_stops.json" echo "dumped /tmp/cnc_sim_linuxcnc_source_program_stops.json"
echo "dumped /tmp/cnc_sim_linuxcnc_source_coolant.json" echo "dumped /tmp/cnc_sim_linuxcnc_source_coolant.json"
echo "dumped /tmp/cnc_sim_linuxcnc_source_feed_modes.json" echo "dumped /tmp/cnc_sim_linuxcnc_source_feed_modes.json"
echo "dumped /tmp/cnc_sim_linuxcnc_source_motion_modes.json" echo "dumped /tmp/cnc_sim_linuxcnc_source_motion_modes.json"
echo "dumped /tmp/cnc_sim_linuxcnc_source_tool_length.json" echo "dumped /tmp/cnc_sim_linuxcnc_source_tool_length.json"
echo "dumped /tmp/cnc_sim_linuxcnc_source_dynamic_tool_length.json"
echo "dumped /tmp/cnc_sim_linuxcnc_source_canned_cycle.json" echo "dumped /tmp/cnc_sim_linuxcnc_source_canned_cycle.json"
echo "dumped /tmp/cnc_sim_linuxcnc_source_canned_cycles_extended.json" echo "dumped /tmp/cnc_sim_linuxcnc_source_canned_cycles_extended.json"
echo "dumped /tmp/cnc_sim_linuxcnc_source_canned_cycle_planes.json"
echo "dumped /tmp/cnc_sim_linuxcnc_source_arc_planes.json"
echo "dumped /tmp/cnc_sim_linuxcnc_source_arc_distance_modes.json"
echo "dumped /tmp/cnc_sim_linuxcnc_source_predefined_positions.json"
echo "dumped /tmp/cnc_sim_linuxcnc_source_machine_coordinates.json"
echo "dumped /tmp/cnc_sim_linuxcnc_source_cutter_comp.json" echo "dumped /tmp/cnc_sim_linuxcnc_source_cutter_comp.json"
echo "dumped /tmp/cnc_sim_linuxcnc_source_probe_no_error.json" echo "dumped /tmp/cnc_sim_linuxcnc_source_probe_no_error.json"
echo "dumped /tmp/cnc_sim_linuxcnc_source_oword_subprogram.json" echo "dumped /tmp/cnc_sim_linuxcnc_source_oword_subprogram.json"
echo "dumped /tmp/cnc_sim_linuxcnc_source_named_oword_subprogram.json"
echo "dumped /tmp/cnc_sim_linuxcnc_source_oword_control_flow.json"
echo "dumped /tmp/cnc_sim_linuxcnc_source_named_parameter_exists.json"
echo "dumped /tmp/cnc_sim_linuxcnc_source_indexed_parameters.json"
echo "dumped /tmp/cnc_sim_linuxcnc_source_named_parameter_normalization.json"
echo "dumped /tmp/cnc_sim_linuxcnc_source_ini_named_parameter.json"
echo "dumped /tmp/cnc_sim_linuxcnc_source_coordinate_offsets.json" echo "dumped /tmp/cnc_sim_linuxcnc_source_coordinate_offsets.json"
echo "dumped /tmp/cnc_sim_linuxcnc_source_coordinate_l20.json" echo "dumped /tmp/cnc_sim_linuxcnc_source_coordinate_l20.json"
echo "dumped /tmp/cnc_sim_linuxcnc_source_coordinate_p0.json"
echo "dumped /tmp/cnc_sim_linuxcnc_source_coordinate_select_all.json"
echo "dumped /tmp/cnc_sim_linuxcnc_source_g92_restore.json"
echo "dumped /tmp/cnc_sim_linuxcnc_source_g52_offset.json"

View File

@@ -0,0 +1,10 @@
G21 G90 G17
G0 X0 Y0 Z0
F100
G91.1
G3 X10 Y0 I5 J0
G90.1
G3 X20 Y0 I15 J0
G91.1
G3 X30 Y0 I5 J0
M30

View File

@@ -0,0 +1,9 @@
G21 G90 G17
G0 X0 Y0 Z0
F100
G18
G2 X10 Z0 I5 K0
G0 X0 Y0 Z0
G19
G3 Y10 Z0 J5 K0
M30

View File

@@ -0,0 +1,28 @@
G21 G90
G18
G0 X0 Y5 Z0
G99 G81 X1 Y-2 Z4 R3 F100
G19
G0 X5 Y0 Z0
G99 G82 X-2 Y3 Z4 R2 P0.2 F100
G18
S600 M3
G0 X0 Y5 Z0
G99 G84 X1 Y-2 Z4 R3 P0.05 F60
G19
S500 M4
G0 X5 Y0 Z0
G99 G74 X-2 Y3 Z4 R2 P0.04 F50
G18
S900 M3
G0 X0 Y5 Z0
G99 G86 X1 Y-2 Z4 R3 P0.1 F80
G19
S700 M3
G0 X5 Y0 Z0
G99 G88 X-2 Y3 Z4 R2 P0.07 F70
G19
S800 M3
G0 X5 Y0 Z0
G99 G87 X-4 Y1 Z2 R2 I-2 J0.2 K0.3 F80
M30

View File

@@ -3,4 +3,13 @@ G0 X0 Y0 Z10
G99 G82 X10 Y0 Z-2 R3 P0.25 F100 G99 G82 X10 Y0 Z-2 R3 P0.25 F100
G83 X20 Y0 Z-3 R2 Q1 G83 X20 Y0 Z-3 R2 Q1
G80 G80
S600 M3
G99 G84 X30 Y0 Z-2 R2 P0.05 F60
S500 M4
G99 G74 X40 Y0 Z-2 R2 P0.04 F50
S700 M3
G99 G88 X50 Y0 Z-2 R2 P0.07 F70
G0 X0 Y0 Z5
S800 M3
G99 G87 X60 Y0 Z-4 R2 I0.2 J0.3 K-2 F80
M30 M30

View File

@@ -0,0 +1,4 @@
G21 G90 G17
G55
G10 L2 P0 X7 Y8 Z9
M30

View File

@@ -0,0 +1,20 @@
G21 G90
G10 L2 P1 X1
G10 L2 P2 X2
G10 L2 P3 X3
G10 L2 P4 X4
G10 L2 P5 X5
G10 L2 P6 X6
G10 L2 P7 X7
G10 L2 P8 X8
G10 L2 P9 X9
G55
G54
G56
G57
G58
G59
G59.1
G59.2
G59.3
M30

View File

@@ -0,0 +1,6 @@
G21 G90 G17
G43.1 X1 Z2
G43.2 X0.25 Z0.5
G43.2 H1
G49
M30

View File

@@ -0,0 +1,7 @@
G21 G90 G17
G52 X1 Y2
G52 Y3
G92.2
G92.3
G92.1
M30

View File

@@ -0,0 +1,7 @@
G21 G90 G17
G92 X1 Y2 Z3
G92.2
G92.3
G92.1
G92.3
M30

View File

@@ -0,0 +1,22 @@
G21 G90
F100
#2 = 3
#3 = 11
#4 = [#[1 + 2] + ##2]
#[1 + 2] = 17
G1 X#[1 + 2]
G1 Y#4
O10 if [##2 EQ 17]
G1 Z1
O10 endif
#5 = 21
#5 = 9 G1 A#5
G1 B#5
#6 = 2
#5 = 4 #6 = #5 G1 C#5 U#6
G1 V#5 W#6
G1 X#5 #5 = 12 #6 = #5
G1 Y#5 Z#6
#5 = 13 #5 = 14 G1 A#5
G1 B#5
M30

View File

@@ -0,0 +1,2 @@
[SETUP]
XPOS = 3.25

View File

@@ -0,0 +1,7 @@
G21 G90
F100
G1 X#<_ini[setup]xpos>
O10 if [EXISTS[#<_ini[SETUP]XPOS>]]
G1 Y1
O10 endif
M30

View File

@@ -0,0 +1,10 @@
G21 G90 G17
M62 P1
M63 P1
M64 P2
M65 P2
M66 P0 L3 Q5
M66 E1 L0
M67 E0 Q1.25
M68 E1 Q2.5
M30

View File

@@ -0,0 +1,7 @@
G21 G90 G17
G0 X5 Y6 Z7
G53 G0 X0 Z1
G53 X2
G1 F100
G53 G1 Y3
M30

View File

@@ -0,0 +1,10 @@
G21 G91 G17
G0 X0 Y0 Z0
O100 call
G0 X2
M30
O100 sub
M73
G90
G0 X10
O100 endsub

View File

@@ -0,0 +1,5 @@
G21 G90 G17
M70
M71
M72
M30

View File

@@ -0,0 +1,9 @@
G21 G90 G17
G0 X0 Y0 Z0
M70
G91 G18 G20
G0 X1 Z1
M72
G0 X2 Y0 Z2
F100 G2 X4 Y0 I1 J0
M30

View File

@@ -0,0 +1,13 @@
G21 G90
G0 X0 Y0 Z0
F100
O<move_plus> call [4] [6]
G1 X20
M30
O<move_plus> sub
#<sum> = [#1 + #2]
G1 X#<sum>
G1 Y#2
O<move_plus> return
G1 X99
O<move_plus> endsub

View File

@@ -0,0 +1,10 @@
G21 G90
F100
#<present> = 7
O10 if [EXISTS[#<present>]]
G1 X1
O10 endif
O20 if [EXISTS[#<missing>] EQ 0]
G1 Y1
O20 endif
M30

View File

@@ -0,0 +1,8 @@
G21 G90
F100
#<P a R am> = 12
G1 X#<param>
O10 if [EXISTS[#<P A R A M>]]
G1 Y1
O10 endif
M30

View File

@@ -0,0 +1,12 @@
G21 G90 G17
M48
M49
M50 P1
M50 P0
M51 P1
M51 P0
M52 P1
M52 P0
M53 P1
M53 P0
M30

View File

@@ -0,0 +1,47 @@
G21 G90
F100
#1 = 2
O100 if [#1 EQ 1]
G1 X99
O100 elseif [#1 EQ 2]
G1 X2
O100 else
G1 X98
O100 endif
#2 = 0
O200 while [#2 LT 3]
G1 Y#2
#2 = [#2 + 1]
O200 endwhile
#3 = 0
O300 repeat [3]
#3 = [#3 + 1]
G1 Z#3
O300 endrepeat
#4 = 0
O400 do
#4 = [#4 + 1]
G1 A#4
O400 while [#4 LT 3]
#5 = 0
O410 do
#5 = [#5 + 1]
O411 if [#5 GE 2]
O410 break
O411 endif
G1 B#5
O410 while [#5 LT 4]
G1 C#5
#6 = 0
#7 = 0
O420 do
#6 = [#6 + 1]
O421 if [#6 EQ 1]
O420 continue
O421 endif
#7 = [#7 + 1]
G1 U#6
O420 while [#6 LT 3]
G1 V#6
G1 W#7
M30

View File

@@ -0,0 +1,10 @@
G21 G90 G17
G0 X1 Y2 Z3
G28.1
G0 X10 Y20 Z30
G28 Z5
G0 X4 Y5 Z6
G30.1
G0 X40 Y50 Z60
G30
M30

View File

@@ -1,5 +1,16 @@
G21 G90 G17 G21 G90 G17
G0 X0 Y0 Z5 G0 X0 Y0 Z5
F100 F100
G38.2 Z4
G0 Z5
G38.3 Z3
G0 Z5
G38.4 Z2
G0 Z5
G38.5 Z1
G0 Z5
G38.3 Z0 G38.3 Z0
O10 if [#5070 EQ 1]
G1 X1
O10 endif
M30 M30

View File

@@ -0,0 +1,5 @@
G21 G90 G17
G97 S1000
G96 S120 D2500
G97 S900
M30

View File

@@ -0,0 +1,3 @@
G21 G90 G17
M19 R45 P1 Q2
M30

View File

@@ -0,0 +1,5 @@
G20 G90 G18
S500 M3
G0 X1 Z0.1
G76 P0.05 Z-1 I-.075 J0.008 K0.045 Q29.5 L2 E0.045
M30

View File

@@ -0,0 +1,7 @@
G21 G90 G17
S500 M3
G0 Z5
G33 Z0 K1
G0 Z5
G33.1 Z0 K1
M30