# gmoccapy_XYZAB.ini 执行过程与界面通信分析 分析对象: `/home/mes123456/cnc_wams/linuxcnc/configs/sim/gmoccapy/gmoccapy_XYZAB.ini` 结论先行:这个配置不是一个单独程序,而是一套 LinuxCNC 运行配置。`linuxcnc ` 先启动 LinuxCNC 后台进程、实时运动模块和 HAL 网络,再启动 `gmoccapy` GTK 界面。界面与后台的主要通信不是 HTTP/TCP API,而是 LinuxCNC 的三类本地机制: 1. NML 命令/状态/错误通道:`linuxcnc.command()` 发命令,`linuxcnc.stat()` 读状态,`linuxcnc.error_channel()` 读错误。 2. HAL 共享内存引脚/信号网络:`gmoccapy` 自己注册 HAL component 和引脚,`POSTGUI_HALFILE` 把界面引脚接入实时/用户空间 HAL 网络。 3. 解释器 Python REMAP:`[PYTHON]` 和 `[RS274NGC] REMAP` 在 `milltask` 内部影响 G-code 解释/换刀流程,不是 GUI 主通信链路。 ## 1. 配置角色 `gmoccapy_XYZAB.ini` 定义一台五轴仿真机: - GUI:`[DISPLAY] DISPLAY = gmoccapy`。 - 轮询周期:`[DISPLAY] CYCLE_TIME = 100`,即界面约每 100 ms 轮询一次 LinuxCNC 状态。 - 任务进程:`[TASK] TASK = milltask`。 - 实时运动模块:`[EMCMOT] EMCMOT = motmod`。 - 运动周期:`BASE_PERIOD = 100000` ns,`SERVO_PERIOD = 1000000` ns。 - 坐标:`[TRAJ] COORDINATES = X Y Z A B`。 - 运动学:`[KINS] KINEMATICS = trivkins coordinates=xyzab`,`JOINTS = 5`。 - 主 HAL 文件: - `core_sim_XYZAB.hal` - `spindle_sim.hal` - `simulated_home.hal` - GUI 创建完成后执行的 HAL 文件: - `gmoccapy_postgui.hal` - HAL 用户接口: - `[HAL] HALUI = halui` ## 2. LinuxCNC 启动顺序 入口通常是: ```bash linuxcnc /home/mes123456/cnc_wams/linuxcnc/configs/sim/gmoccapy/gmoccapy_XYZAB.ini ``` 启动脚本路径: `/home/mes123456/cnc_wams/linuxcnc/scripts/linuxcnc` 关键过程如下。 ### 2.1 解析 INI 和导出环境 启动脚本先检查 INI,然后设置: - `CONFIG_DIR=` - `INI_FILE_NAME=` - `PATH=$CONFIG_DIR/bin:$PATH` 后续的 Python 模块、HAL 文件解析和 `gmoccapy.getiniinfo` 都依赖这些环境变量。 脚本从 INI 读取: - `[EMCMOT] EMCMOT` -> `motmod` - `[TASK] TASK` -> `milltask` - `[HAL] HALUI` -> `halui` - `[DISPLAY] DISPLAY` -> `gmoccapy` ### 2.2 启动后台和实时系统 脚本执行的后台启动顺序是: 1. 启动 `linuxcncsvr -ini `。脚本注释说明该进程默认持有/创建 NML buffers。 2. 启动 realtime/RTAPI/HAL。 3. 加载 `tpmod`、`homemod`。 4. 启动任务进程: ```bash halcmd loadusr -Wn inihal milltask -ini ``` 5. 启动 HALUI: ```bash halcmd loadusr -Wn halui halui -ini ``` 6. 依次执行 `[HAL] HALFILE`: ```bash halcmd -i -f core_sim_XYZAB.hal halcmd -i -f spindle_sim.hal halcmd -i -f simulated_home.hal ``` 7. `halcmd start` 启动实时线程。 8. 最后以前台方式启动显示程序: ```bash gmoccapy -ini ``` 实际运行文件是: `/home/mes123456/cnc_wams/linuxcnc/bin/gmoccapy` 它与源码副本 `/home/mes123456/cnc_wams/linuxcnc/src/emc/usr_intf/gmoccapy/gmoccapy.py` 只有 shebang Python 版本不同,主体逻辑一致。 ## 3. HAL 文件执行过程 ### 3.1 core_sim_XYZAB.hal 该文件建立五轴仿真运动核心: - `loadrt [KINS]KINEMATICS` 加载 `trivkins coordinates=xyzab`。 - `loadrt [EMCMOT]EMCMOT ... num_joints=[KINS]JOINTS unlock_joints_mask=16` 加载 `motmod`。 - 把 `motion-command-handler` 和 `motion-controller` 加入 `servo-thread`。 - 将仿真轴命令位置直接回环到反馈: ```hal net Xpos joint.0.motor-pos-cmd => joint.0.motor-pos-fb ddt_x.in net Ypos joint.1.motor-pos-cmd => joint.1.motor-pos-fb ddt_y.in net Zpos joint.2.motor-pos-cmd => joint.2.motor-pos-fb ddt_z.in net Apos joint.3.motor-pos-cmd => joint.3.motor-pos-fb net Bpos joint.4.motor-pos-cmd => joint.4.motor-pos-fb ``` 这说明该配置没有真实伺服驱动,运动命令立即变成反馈,用于仿真。 同时它还建立: - 急停回环: ```hal net estop-loop iocontrol.0.user-enable-out iocontrol.0.emc-enable-in ``` - 换刀准备/完成回环: ```hal net tool-prep-loop iocontrol.0.tool-prepare iocontrol.0.tool-prepared net tool-change-loop iocontrol.0.tool-change iocontrol.0.tool-changed ``` - 主轴方向、冷却液信号: ```hal net spindle-fwd spindle.0.forward net spindle-rev spindle.0.reverse net flood iocontrol.0.coolant-flood net mist iocontrol.0.coolant-mist ``` ### 3.2 spindle_sim.hal 该文件模拟主轴: - `spindle.0.speed-out` 进入 `limit2`,模拟转速斜坡。 - `sim_encoder` 生成 A/B/Z 相。 - `encoder` 将脉冲转为 `spindle.0.revs` 和 `spindle.0.speed-in`。 - `near` 比较命令转速和反馈转速,输出 `spindle.0.at-speed`。 核心链路: ```hal spindle.0.speed-out -> limit2 -> sim_encoder -> encoder -> spindle.0.speed-in near_speed.out -> spindle.0.at-speed ``` ### 3.3 simulated_home.hal 该文件用 `comp` 比较轴位置,模拟 X/Y/Z 回零开关: - X 回零位置设为 1。 - Y 回零位置设为 0.5。 - Z 回零位置设为 2。 当仿真位置达到比较点附近时,对应 `joint.N.home-sw-in` 被置位。 ### 3.4 gmoccapy_postgui.hal 该文件必须等 GUI 启动并创建 `gmoccapy.*` HAL pins 后才能执行。`gmoccapy` 主程序在 `halcomp.ready()` 后读取 `[HAL] POSTGUI_HALFILE` 并执行: ```bash halcmd -i -f gmoccapy_postgui.hal ``` 本配置中的 postgui 连接: ```hal net spindle-speed-limited => abs_spindle_feedback.in net spindle-abs abs_spindle_feedback.out => gmoccapy.spindle_feedback_bar net spindle-at-speed gmoccapy.spindle_at_speed_led net tooloffset-x gmoccapy.tooloffset-x <= motion.tooloffset.x net tooloffset-z gmoccapy.tooloffset-z <= motion.tooloffset.z ``` 含义: - 主轴模拟反馈值经过 `abs` 后驱动界面的主轴反馈条。 - `spindle-at-speed` 驱动界面的主轴到速 LED。 - `motion.tooloffset.x/z` 驱动界面的刀补显示引脚。 该文件中手动换刀 GUI 引脚连接被注释掉,所以这个仿真配置实际仍使用 `iocontrol.0.tool-change -> iocontrol.0.tool-changed` 的回环换刀,而不是弹出 gmoccapy 手动换刀确认流程。 ## 4. gmoccapy GUI 初始化过程 `gmoccapy` 启动后主要执行: 1. 创建 HAL component: ```python self.halcomp = hal.component("gmoccapy") ``` 2. 创建 LinuxCNC NML 通信对象: ```python self.command = linuxcnc.command() self.stat = linuxcnc.stat() self.error_channel = linuxcnc.error_channel() self.stat.poll() self.error_channel.poll() ``` 3. 用 `Gtk.Builder` 加载界面: ```python self.builder.add_from_file(XMLNAME) ``` 其中 `XMLNAME` 指向: `/home/mes123456/cnc_wams/linuxcnc/share/gmoccapy/gmoccapy.glade` 4. 读取 INI: ```python self._get_ini_data() ``` 该逻辑由: `/home/mes123456/cnc_wams/linuxcnc/src/emc/usr_intf/gmoccapy/getiniinfo.py` 通过 `os.environ["INI_FILE_NAME"]` 和 `linuxcnc.ini()` 完成。 5. 根据 INI 动态生成 DRO、回零按钮、点动按钮、宏按钮等。 6. 调用 `_make_hal_pins()` 创建 gmoccapy 自己的 HAL pins。 7. 用 `gladevcp.makepins.GladePanel(...)` 为 glade 中的 HAL widget 创建/更新 HAL pins。 8. 调用: ```python self.halcomp.ready() ``` 此时 `gmoccapy.*` pins 对外可见。 9. 建立周期定时器: ```python GLib.timeout_add(cycle_time, self._periodic) GLib.timeout_add(1000, self._periodic_1s) ``` 10. 构造完成后执行 `[HAL] POSTGUI_HALFILE`,然后进入: ```python Gtk.main() ``` ## 5. 界面与后台如何通信 ### 5.1 NML:界面命令到 milltask `linuxcnc.command()` 是 GUI 发控制命令的主入口。常见命令包括: - 急停/复位/上电: ```python self.command.state(linuxcnc.STATE_ESTOP) self.command.state(linuxcnc.STATE_ESTOP_RESET) self.command.state(linuxcnc.STATE_ON) self.command.state(linuxcnc.STATE_OFF) ``` - 模式切换: ```python self.command.mode(linuxcnc.MODE_MANUAL) self.command.mode(linuxcnc.MODE_MDI) self.command.mode(linuxcnc.MODE_AUTO) ``` - 点动: ```python self.command.jog(linuxcnc.JOG_CONTINUOUS, ...) self.command.jog(linuxcnc.JOG_INCREMENT, ...) self.command.jog(linuxcnc.JOG_STOP, ...) ``` - 回零: ```python self.command.home(-1) self.command.home(joint_or_axis) self.command.unhome(joint) ``` - 主轴/冷却/倍率: ```python self.command.spindle(...) self.command.spindleoverride(...) self.command.flood(...) self.command.mist(...) self.command.feedrate(...) self.command.rapidrate(...) ``` - MDI 和自动运行: ```python self.command.mdi("...") self.command.auto(linuxcnc.AUTO_RUN, self.start_line) self.command.auto(linuxcnc.AUTO_PAUSE) self.command.auto(linuxcnc.AUTO_RESUME) self.command.abort() ``` 这些命令写入 NML command buffer。`milltask` 后台循环中读取 command buffer,然后执行规划、解释器、IO 和 motion 同步。 `milltask` 初始化时打开三类 NML channel: - `emcCommand`:GUI/halui 等写命令,`milltask` 读。 - `emcStatus`:`milltask` 写综合状态,GUI 读。 - `emcError`:后台写错误/提示,GUI 读。 `milltask` 主循环的关键节奏是: 1. `emcCommandBuffer->read()` 读取新命令。 2. `emcTaskPlan()` 做解释/规划。 3. `emcTaskExecute()` 执行任务。 4. `emcMotionUpdate(&emcStatus->motion)` 更新运动状态。 5. `emcTaskUpdate(&emcStatus->task)` 更新任务状态。 6. `emcStatusBuffer->write(emcStatus)` 写回状态。 所以 GUI 的控制命令不是直接调用 `motmod`,而是经 NML 发给 `milltask`,再由 `milltask` 协调解释器、IO、motion 和 HAL。 ### 5.2 NML:后台状态到界面 `gmoccapy` 通过 100 ms 定时器调用 `_periodic()`: ```python self.stat.poll() error = self.error_channel.poll() ``` 然后根据 `self.stat` 更新: - 当前 G-code/M-code。 - 速度、进给、主轴、冷却状态。 - HALUI 相关 pin 状态。 - 主轴 Vc。 - UI 时间、进度等。 如果 `error_channel.poll()` 读到错误或提示,`gmoccapy` 会显示通知,并通过自己的 HAL pin `gmoccapy.error` 输出错误状态。 ### 5.3 HAL:界面引脚与实时/用户空间 HAL 网络 `gmoccapy` 自己注册了一个 HAL component,名字固定为: ```text gmoccapy ``` 动态创建的典型 HAL pins 有: - 硬按钮输入: - `gmoccapy.h-button.button-0` 到 `button-9` - `gmoccapy.v-button.button-0` 到 `button-6` - 轴点动输入: - `gmoccapy.jog.axis.jog-x-plus` - `gmoccapy.jog.axis.jog-x-minus` - 对 Y/Z/A/B 等轴同理 - 点动增量: - `gmoccapy.jog.jog-inc-N` - `gmoccapy.jog.jog-increment` - 倍率/速度编码器输入: - `gmoccapy.feed.feed-override.counts` - `gmoccapy.spindle.spindle-override.counts` - `gmoccapy.jog.jog-velocity.counts` - `gmoccapy.rapid.rapid-override.counts` - 模拟直控输入: - `gmoccapy.feed.feed-override.direct-value` - `gmoccapy.spindle.spindle-override.direct-value` - `gmoccapy.jog.jog-velocity.direct-value` - `gmoccapy.rapid.rapid-override.direct-value` - 工具/刀补相关: - `gmoccapy.tooloffset-x` - `gmoccapy.tooloffset-z` - `gmoccapy.tool-diameter` - `gmoccapy.toolchange-change` - `gmoccapy.toolchange-changed` - `gmoccapy.toolchange-number` - 程序进度: - `gmoccapy.program.length` - `gmoccapy.program.current-line` - `gmoccapy.program.progress` - 错误和消息: - `gmoccapy.error` - `gmoccapy.delete-message` 这些 pins 的变化由 `hal_glib.GPin` 包装。`GPin` 每 100 ms 轮询一次 HAL pin,如果值变化,就发出 `value_changed` 信号,触发 gmoccapy 回调。例如: - `gmoccapy.jog.axis.jog-x-plus` 变为 true: 1. `GPin` 检测到变化。 2. 调用 `_on_pin_jog_changed(...)`。 3. 再调用 `_on_btn_jog_pressed(...)`。 4. 最终调用 `self.command.jog(...)` 发 NML 点动命令。 因此 HAL 输入通常不是直接驱动 motion,而是先进入 GUI 回调,再由 GUI 通过 NML command 发给 `milltask`。也可以有纯 HAL 路径,例如 postgui 中的主轴反馈条和 LED 是 HAL 信号直接驱动 gmoccapy HAL widget。 ### 5.4 HALUI 的角色 本配置启用了: ```ini [HAL] HALUI = halui ``` `halui` 是另一个用户空间 HAL component,它把 LinuxCNC 常用命令/状态暴露为 HAL pins。它自己也使用 LinuxCNC command/stat 通道与 `milltask` 交互。 本 INI 的 `[HALUI]` section 没有定义 MDI_COMMAND,因此这里的 `halui` 主要提供默认 HALUI pins,便于外部硬件按钮或 HAL 逻辑直接控制 LinuxCNC。`gmoccapy` 的主控制链路仍是自己的 `linuxcnc.command/stat/error_channel`,不是通过 `halui` 间接通信。 ## 6. 典型操作链路 ### 6.1 界面上电 用户点击界面上电按钮: ```text GTK toggle button -> gmoccapy.on_tbtn_on_toggled() -> linuxcnc.command().state(STATE_ON) -> NML emcCommand -> milltask -> iocontrol/motion 状态改变 -> emcStatus -> gmoccapy self.stat.poll() -> 界面按钮、DRO、状态区刷新 ``` 本仿真中急停链路由 HAL 回环: ```hal iocontrol.0.user-enable-out -> iocontrol.0.emc-enable-in ``` 所以没有真实外部急停硬件。 ### 6.2 界面点动 X+ 用户按住 X+: ```text GTK jog button pressed -> _on_btn_jog_pressed("x+") -> self.command.jog(JOG_CONTINUOUS, ...) -> NML emcCommand -> milltask/motion -> motmod 输出 joint.0.motor-pos-cmd -> core_sim_XYZAB.hal 回环到 joint.0.motor-pos-fb -> emcStatus 位置更新 -> gmoccapy stat.poll() -> DRO/预览刷新 ``` 松开按钮时: ```text GTK jog button released -> _on_btn_jog_released("x+") -> self.command.jog(JOG_STOP, ...) ``` 如果来自外部 HAL 按钮: ```text HAL signal -> gmoccapy.jog.axis.jog-x-plus -> GPin value_changed -> _on_pin_jog_changed() -> 同上 NML 点动链路 ``` ### 6.3 主轴启动和反馈 用户点击主轴正转: ```text GTK spindle forward -> _set_spindle("forward") -> self.command.spindle(1, rpm) -> NML emcCommand -> milltask/motion -> spindle.0.forward / spindle.0.speed-out HAL pins -> spindle_sim.hal 模拟编码器和速度反馈 -> spindle.0.speed-in / spindle.0.at-speed -> gmoccapy_postgui.hal -> gmoccapy.spindle_feedback_bar / gmoccapy.spindle_at_speed_led -> 界面显示主轴反馈和到速状态 ``` 同时 gmoccapy 的 `_periodic()` 也会从 `stat.spindle` 和 HAL 的 `spindle.0.speed-out` 读取状态刷新按钮/文字。 ### 6.4 冷却液 用户点击 flood/mist: ```text GTK coolant button -> self.command.flood(FLOOD_ON/OFF) 或 self.command.mist(MIST_ON/OFF) -> NML emcCommand -> milltask/iocontrol -> iocontrol.0.coolant-flood / iocontrol.0.coolant-mist HAL pins -> core_sim_XYZAB.hal 中 flood/mist 信号 -> stat.poll() 回读状态并刷新按钮 ``` ### 6.5 MDI、自动运行和 REMAP MDI 和自动运行也走 NML: ```text GUI -> command.mode(MODE_MDI) / command.mdi(...) -> 或 command.mode(MODE_AUTO) / command.auto(AUTO_RUN, line) -> milltask 解释器/任务队列 -> motion + io + status ``` INI 中的: ```ini REMAP=M6 modalgroup=6 prolog=change_prolog ngc=change_g43 epilog=change_epilog REMAP=M61 modalgroup=6 prolog=settool_prolog ngc=settool_g43 epilog=settool_epilog [PYTHON] PATH_PREPEND = ./python TOPLEVEL = ./python/toplevel.py ``` 表示 `milltask` 的解释器在执行 M6/M61 时加载 `./python/toplevel.py`,再导入 `remap.py` 和 `stdglue.py`。这些逻辑运行在解释器/任务侧,用于换刀 prolog/epilog 和工具参数处理,不是 gmoccapy 界面轮询的一部分。 ## 7. 通信结构图 ```text +---------------------+ | gmoccapy | | GTK UI + HAL comp | +----------+----------+ | +---------------+----------------+ | | v v linuxcnc.command/stat/error_channel HAL pins | | v v NML buffers HAL shared memory emcCommand / emcStatus / emcError | | | v v linuxcncsvr halui / iocontrol / | motmod / sim_encoder / v gmoccapy_postgui.hal milltask | interpreter + task + IO | | | v | motmod <----------------------------+ realtime motion ``` 更精确地说: - GUI 控制类动作:`gmoccapy -> NML command -> milltask -> motion/io/HAL`。 - GUI 状态显示:`milltask -> NML status/error -> gmoccapy stat/error poll`。 - GUI HAL 控件:`HAL network <-> gmoccapy.* pins`。 - postgui 连接:`HAL network -> gmoccapy.* pins`,必须在 `gmoccapy.halcomp.ready()` 后执行。 ## 8. 需要注意的细节 1. `gmoccapy_postgui.hal` 不能放到普通 `HALFILE` 中执行,因为普通 HALFILE 执行时 `gmoccapy.*` pins 还不存在。 2. 本配置是仿真机,轴反馈是命令位置回环,不代表真实驱动闭环。 3. `core_sim_XYZAB.hal` 和 `gmoccapy_postgui.hal` 都处理了 tool-change loop。postgui 中先 `unlinkp`,再重新建立 `iocontrol.0.tool-change -> iocontrol.0.tool-changed`,目的是避免仿真环境中的连接冲突并继续自动完成换刀。 4. `HALUI = halui` 提供额外 HAL 控制入口,但 gmoccapy 的主要 GUI 交互直接使用 `linuxcnc.command/stat/error_channel`。 5. `gmoccapy` 源码中非 identity kinematics 的 joint minus pin 回调参数看起来写成了 `"{0}+"`,即 plus/minus 都传 plus。对本 `trivkins` 仿真配置通常不影响主轴向点动,但如果改成非平凡运动学并启用 joint jogging,需要复查这一处。 ## 9. G 代码执行条件和状态互锁 本节分析的是 `gmoccapy_XYZAB.ini` 当前配置的实际逻辑。关键前提是: ```ini [TRAJ] NO_FORCE_HOMING = 0 ``` 因此本配置要求先完成全轴回零,才允许进入 MDI/Auto 等会执行解释器命令的模式。如果改成 `NO_FORCE_HOMING = 1`,gmoccapy 会绕过这部分回零互锁。 ### 9.1 三层保护 G 代码是否能执行,不只由一个按钮决定,而是三层共同约束: 1. GUI 页面和按钮敏感状态:gmoccapy 根据 `state-*`、`mode-*`、`interp-*`、`all-homed` 等状态事件启停按钮。 2. gladevcp Action 对象:例如暂停、单步、重载文件按钮绑定到 `EMC_ToggleAction_Pause`、`EMC_Action_Step`、`EMC_Action_Reload`,这些对象也会检查 machine on、解释器状态和模式。 3. LinuxCNC 后台校验:最终的 `command.mode()`、`command.mdi()`、`command.auto()`、`command.jog()` 等命令会进入 NML,`milltask`/motion 会再次按任务状态、模式、限位、回零、解释器状态拒绝非法命令。 所以界面按钮不可点是第一道互锁,后台拒绝非法命令是最后一道互锁。 ### 9.2 自动运行 G 代码的正常链路 从冷启动到自动运行一个文件,正常条件链如下: ```text 启动 linuxcnc -> linuxcncsvr / milltask / motmod / HAL / halui 启动 -> gmoccapy 创建 linuxcnc.command/stat/error_channel 和 gmoccapy HAL component -> gmoccapy_postgui.hal 连接界面 HAL pins -> F1 急停状态或默认急停状态 -> 解除急停:command.state(STATE_ESTOP_RESET) -> 上电:command.state(STATE_ON) -> 回零:command.home(-1) 或逐轴 command.home(joint) -> 收到 all-homed 状态,MDI/Auto/Touch/Tool 相关按钮变为可用 -> 加载程序:EMC_Action_Open.load_file(path) 或 reload -> 切换 Auto:command.mode(MODE_AUTO) -> Cycle Start:command.auto(AUTO_RUN, start_line) -> milltask 解释 RS274NGC,必要时执行 REMAP,例如 M6/M61 -> motion/io/HAL 运动和 IO 状态变化 -> gmoccapy stat.poll()/GStat 信号刷新界面 ``` 从界面角度,自动运行前应满足: - LinuxCNC 后台进程和 HAL 网络已启动,gmoccapy 已完成 `halcomp.ready()`。 - 急停已复位,即不在 `STATE_ESTOP`。 - 机床已上电,即 `task_state == STATE_ON`。 - 全轴已回零,即收到 `all-homed`;本配置 `NO_FORCE_HOMING = 0`,不能跳过。 - 解释器空闲,即 `INTERP_IDLE`。运行中不能切换 Manual/MDI/Auto,也不能加载/编辑程序。 - 已处于 Auto 模式,或按钮/Action 会先 `ensure_mode(... MODE_AUTO)`。 - 应加载了有效程序文件。gmoccapy 的快捷键逻辑会用 `btn_use_current` 是否敏感判断文件已加载;`btn_run` 回调本身直接发送 `AUTO_RUN`,如果无文件或状态不合法,最终由 LinuxCNC 后台报错。 - 未处于设置页、编辑页、文件选择页、偏置编辑页等会临时禁止模式切换的页面。 - 硬限位没有阻止运动;若限位触发,只能在允许的状态下通过 `override_limits()` 临时忽略限位后退出限位。 ### 9.3 MDI 和宏的执行条件 MDI 的入口包括 MDI 历史输入框、宏按钮、Touch Off、工具补偿、坐标系切换等内部 MDI 命令。 ```text MDI 输入框 Enter -> EMC_MDIHistory.submit() -> ensure_mode(MODE_MDI) -> command.mdi(cmd) -> milltask interpreter ``` 宏按钮来自 INI `[MACROS]`: ```ini MACRO = i_am_lost MACRO = halo_world MACRO = jog_around MACRO = increment xinc yinc MACRO = go_to_position X-pos Y-pos Z-pos ``` 点击宏按钮后,gmoccapy 生成: ```text O call [param1] [param2] ... ``` 然后调用 `command.mdi(command)`。宏运行期间会禁用宏按钮,键盘按钮在非 onboard 模式下变成中断宏的按钮,点击会 `command.abort()`。 MDI 的互锁要点: - `rbt_mdi` 只有在上电且全轴回零后才被启用。 - 进入 MDI 前如果按钮不敏感,gmoccapy 会立即 `command.abort()`,切回 Manual,并提示当前不能进入 MDI。 - MDI 运行中 gmoccapy 允许继续添加 MDI 命令,但会禁用 Manual/Auto/Setup/Load/Edit 等容易破坏解释器状态的入口。 - Touch Off、工具 Touch Off、坐标系切换等内部命令会临时切到 `MODE_MDI`,发送 G/M 代码,再切回 `MODE_MANUAL`。 ### 9.4 任务状态互锁 LinuxCNC 这里最重要的任务状态是 `STATE_ESTOP`、`STATE_ESTOP_RESET`、`STATE_OFF`、`STATE_ON`。 | 状态 | 触发/来源 | gmoccapy 界面动作 | 允许的主要操作 | 禁止或限制 | | --- | --- | --- | --- | --- | | `STATE_ESTOP` 急停 | F1、急停按钮置位、退出时最终置位 | 急停按钮显示按下,上电按钮不敏感且关闭,强制 `MODE_MANUAL` | 只能复位急停;Esc 仍可 abort | 上电、回零、点动、MDI、Auto、主轴、冷却、进给覆盖等全部禁用 | | `STATE_ESTOP_RESET` 急停复位 | 急停按钮释放后 `command.state(STATE_ESTOP_RESET)` | 上电按钮变为可用;点动页外框可见,但具体点动/速度控件仍受上电限制 | 可以点击上电;如果有限位,可显示 ignore limits | 机床未上电,仍不能运动、不能执行 MDI/Auto | | `STATE_OFF` 下电 | 上电按钮释放或启动/异常进入 OFF | 关闭 Manual/MDI/Auto、回零、Touch、Tool、Jog、Spindle、Coolant、Feed/Rapid 控件;退出按钮可用 | 可以退出或重新上电 | 不能回零、点动、执行程序、主轴冷却 | | `STATE_ON` 上电 | 上电按钮置位后 `command.state(STATE_ON)` 成功 | Manual、回零、Jog、Feed/Rapid、Spindle、Coolant 基本控件启用;退出按钮禁用 | 可回零、点动、主轴冷却、调覆盖率 | 未回零时 MDI/Auto/Touch/Tool 仍被禁用 | 上电按钮的处理有额外保护: - 如果当前仍是 `STATE_ESTOP`,点击上电会立即撤销按钮状态,不发送上电。 - 发送 `STATE_ON` 后会 `wait_complete()` 并 `stat.poll()`;如果后台没有进入 `STATE_ON`,界面会撤销上电按钮并报错。 - 下电时发送 `STATE_OFF`,并统一 `_update_widgets(False)` 禁用可运动控件。 ### 9.5 模式互锁 任务模式是 `MODE_MANUAL`、`MODE_MDI`、`MODE_AUTO`。 | 模式 | 进入方式 | 页面切换 | 允许的典型动作 | 互锁 | | --- | --- | --- | --- | --- | | Manual | `rbt_manual` 或状态回调强制 | 主页面、Manual 按钮页、Jog 页 | 回零、点动、Touch Off、Tool 页面、主轴冷却、覆盖率 | 运行中不能切换;设置页/编辑页会临时禁用模式按钮 | | MDI | `rbt_mdi`、MDI 输入框、内部 Touch/Tool 命令 | MDI 按钮页,输入框获得焦点 | 单条 MDI、宏、内部 `G10/G43/M61/Tn M6` 等 | 未上电/未回零不能进入;按钮不敏感时会 abort 并切回 Manual | | Auto | `rbt_auto`、Run/Step Action 可确保 Auto | Auto 按钮页,G-code 预览获得焦点 | `AUTO_RUN`、`AUTO_STEP`、Pause/Resume、Stop、Reload、From Line | 未上电/未回零不能进入;解释器运行中禁止切模式 | 键盘快捷键也遵守互锁: - F1:任何时候发送 `STATE_ESTOP`。 - Esc:任何时候 `command.abort()`。 - F2:不在急停时切换上电。 - F3/F5:只有解释器空闲时才允许切 Manual/MDI。 - Auto 模式下,`R` 运行、`Ctrl+R` 重载、`P` 暂停、`S` 继续;但要求当前不是编辑页,并且已有程序加载。 - 键盘点动只在 Manual 且主页面时处理。 ### 9.6 回零与运动模式互锁 本配置 `NO_FORCE_HOMING = 0`,回零状态直接控制解释器相关入口: ```text not-all-homed -> all_homed = False -> 禁用 rbt_mdi / rbt_auto / btn_tool / btn_touch / tbtn_switch_mode -> teleop_enable(0),进入 joint mode all-homed -> all_homed = True -> 启用 rbt_mdi / rbt_auto / btn_tool / btn_touch / tbtn_switch_mode -> teleop_enable(1),进入 world/teleop mode ``` 回零按钮逻辑: - `btn_homing` 只切到回零按钮页。 - `ref_all` 调用 `command.home(-1)`。 - 单轴/单关节回零先检查是否已有 joint 正在 homing;若有则拒绝新回零命令。 - 回零前会 `teleop_enable(0)` 进入 joint mode。 - `unref_all` 或 unhome 信号会 `command.unhome(-1/joint)`,并把 `all_homed` 置 False。 非 identity kinematics 时,joint/world 模式还会影响 MDI/Auto 的敏感状态:joint mode 下 `rbt_mdi`、`rbt_auto` 会被禁用,防止在关节模式下执行笛卡尔程序。本配置使用 `trivkins coordinates=xyzab`,轴和 joint 一一对应,但 gmoccapy 仍保留这套通用逻辑。 ### 9.7 解释器状态互锁 解释器状态主要由 `interp-idle` 和 `interp-run` 信号驱动界面: | 解释器状态 | gmoccapy 处理 | 结果 | | --- | --- | --- | | `INTERP_IDLE` | 重新启用 Jog、G-code view、冷却、主轴、Load、Edit、Optional Blocks、Reload;若已上电且已回零,启用 MDI/Auto/Tool/Touch;`btn_run=True`、`btn_stop=False` | 空闲,可准备运行或编辑 | | `INTERP_READING` / `INTERP_WAITING` / 运行中 | 禁用 Manual/MDI/Auto、Setup、Tool、Load、Edit、Optional Blocks、部分主轴按钮、Touch、Reload;`btn_run=False`、`btn_stop=True` | 正在执行,防止模式/文件/工具状态被改坏 | | Pause | gladevcp pause toggle 会保持暂停按钮激活;gmoccapy 额外允许主轴方向按钮和 G-code view 敏感 | 暂停时可查看代码并调整部分主轴控制 | 停止按钮有两条链路: ```text btn_stop related-action hal_action_stop -> command.abort() btn_stop clicked handler -> command.abort(), start_line=0, gcode line=0, pause=False ``` 因此 Stop 既让 LinuxCNC abort,也清理 gmoccapy 的从行运行和暂停显示状态。 ### 9.8 限位与忽略限位 限位状态通过 `hard-limits-tripped` 信号进入界面: - 有限位触发时,`chk_ignore_limits` 变为可用,`ntb_jog` 也会保持可用,便于退出限位。 - 点击 `chk_ignore_limits` 时调用 `command.override_limits()`。 - 外部 HAL pin `gmoccapy.ignore-limits` 也可驱动这个复选框。 - 限位解除后,ignore limits 自动取消选中并变为不敏感。 是否允许上电、是否允许运动最终仍由 motion/task 判断。gmoccapy 的职责是暴露 override 控件并避免在明显非法状态下发运动命令。 ### 9.9 特殊页面互锁 gmoccapy 有几个“临时工作页”,它们会有意禁用模式切换: - 设置页 `tbtn_setup`:进入时强制 `MODE_MANUAL`,记录原模式,禁用 Manual/MDI/Auto/User Tabs。是否允许进入由偏好设置决定:不加锁、输入解锁码、或 HAL pin `unlock-settings`。退出时按急停/上电/回零状态恢复模式按钮,并尝试恢复原模式。 - 文件选择页 `btn_load`:切到文件页和全屏预览,刷新文件列表,禁用 Manual/MDI/Setup。选择文件后调用 `hal_action_open.load_file(path)`,回到 Auto 页并恢复模式按钮。 - 编辑页 `btn_edit`:使 G-code view 可编辑,隐藏/调整预览和 DRO,禁用 Manual/MDI/Setup。退出时如有未保存修改会询问是否丢弃,并触发 reload 以恢复解释器看到的文件。 - 偏置编辑 `tbtn_edit_offsets`:编辑坐标偏置时禁用 Jog、MDI、Auto、Setup 和 User Tabs;退出编辑时强制回 Manual。 - Tool 编辑页:如果工具表有未保存修改,离开或换刀前会询问是否丢弃;不能删除当前主轴内的工具。 这些页面互锁的共同目的,是避免一边编辑文件/设置/偏置/工具表,一边让解释器执行旧文件或半修改状态。 ## 10. 界面按钮和控制逻辑 ### 10.1 顶部电源和模式按钮 | 控件 | 回调/绑定 | 实际命令 | 控制逻辑 | | --- | --- | --- | --- | | `tbtn_estop` | `on_tbtn_estop_toggled` | `command.state(STATE_ESTOP)` 或 `STATE_ESTOP_RESET` | 按下进入急停;释放复位急停。复位失败会重新置位急停按钮并提示。 | | `tbtn_on` | `on_tbtn_on_toggled` | `command.state(STATE_ON/OFF)` | 急停中不能上电;上电失败会撤销按钮;下电后禁用运动和执行控件。 | | `rbt_manual` | pressed | `command.mode(MODE_MANUAL)` | 只发模式命令;具体页面由 `mode-manual` 状态回调切换。 | | `rbt_mdi` | pressed | `command.mode(MODE_MDI)` | 未满足条件时状态回调会 abort 并切回 Manual。 | | `rbt_auto` | pressed | `command.mode(MODE_AUTO)` | 未满足条件时状态回调会 abort 并切回 Manual。 | | `tbtn_setup` | `on_tbtn_setup_toggled` | 必要时 `MODE_MANUAL` | 解锁后进入设置页,禁用模式切换;退出后恢复。 | | `tbtn_user_tabs` | `on_tbtn_user_tabs_toggled` | 无 NML 命令 | 仅切换用户页显示;设置页激活时不允许自由切换。 | ### 10.2 手动页、回零和点动 | 控件/入口 | 实际命令 | 控制逻辑 | | --- | --- | --- | | `btn_homing` | 无,切页面 | 显示动态生成的回零按钮。 | | `ref_all` | `command.home(-1)` | 全轴回零,先切 joint mode。 | | 单轴/单 joint 回零 | `command.home(joint)` | 如果已有 joint 在 homing,则拒绝。 | | `unref_all` | `command.unhome(-1)` | 取消回零状态,切 joint mode,Auto/MDI 随后被禁用。 | | `tbtn_switch_mode` | `command.teleop_enable(0/1)` | 在 joint/world mode 间切换;非 identity kinematics 下 joint mode 禁用 Auto/MDI。 | | 屏幕点动按钮 | `command.jog(...)` | 只在 `stat.enabled` 且 `MODE_MANUAL` 时有效;连续点动松开时 `JOG_STOP`,增量点动松开不停止。 | | 点动增量按钮 | `command.jog(JOG_STOP, ...)` 后更新距离 | 切换增量前先停止当前点动,避免速度/距离状态混乱。 | | 键盘点动 | `command.jog(...)` | 只在 Manual 主页面,偏置页/工具页/编辑输入框不抢键。 | | 窗口失焦 | `command.jog(JOG_STOP, ...)` | 如果 Manual 中仍有速度,停止所有非 homing joint 的点动。 | 外部 HAL 点动 pin 走同一套按钮函数: ```text gmoccapy.jog.axis.x-plus / x-minus / ... -> _on_pin_jog_changed() -> _on_btn_jog_pressed/released() -> command.jog(...) ``` ### 10.3 Touch Off 和偏置按钮 | 控件 | 实际命令 | 控制逻辑 | | --- | --- | --- | | `btn_touch` | 无,切页面 | 显示坐标偏置/Touch Off 页面。 | | 轴 Touch Off 动态按钮 | `G10 L20 P0 ` | 必须 `STATE_ON` 且已回零;临时切 MDI,执行后 reload,再回 Manual。 | | DRO 轴点击 | 同轴 Touch Off | 点击 DRO 也会进入 `_on_btn_set_value_clicked()`。 | | `btn_zero_g92` | `G92.1` | 清 G92,之后回 Manual 并刷新 Touch 页。 | | `btn_set_selected` | `G54` 到 `G59.3` | 只能选择有效坐标系;临时 MDI 后回 Manual。 | | `tbtn_edit_offsets` | offsetpage 内部编辑 | 编辑时禁用 Jog、MDI、Auto、Setup、User Tabs;退出回 Manual。 | | Block Height | `G10 L2 P0 Z` | 结合探针设置写入 blockheight/probeheight HAL pins,并设置 Z 原点。 | ### 10.4 自动页和文件执行按钮 | 控件 | 回调/绑定 | 实际命令 | 控制逻辑 | | --- | --- | --- | --- | | `btn_load` | `on_btn_load_clicked` | 无,进入文件页 | 刷新 `IconFileSelection1`,禁用 Manual/MDI/Setup。 | | 文件选择确认 | `on_IconFileSelection1_selected` | `hal_action_open.load_file(path)` | 加载文件,返回 Auto 页,恢复模式按钮。 | | `btn_reload` | `hal_action_reload` | `_load_file(stat.file)` | 解释器运行中 Action 会禁用;空闲时重载当前文件。 | | `btn_run` | `on_btn_run_clicked` | `command.auto(AUTO_RUN, start_line)` | 直接按 `start_line` 启动。状态和文件合法性主要靠按钮敏感状态、快捷键判断和 LinuxCNC 后台校验。 | | `btn_stop` | `hal_action_stop` + `on_btn_stop_clicked` | `command.abort()` | 同时清 `start_line`、G-code 行号和暂停按钮。 | | `tbtn_pause` | `hal_tgl_pause` + `on_tbtn_pause_toggled` | 激活 `AUTO_PAUSE`,取消激活 `AUTO_RESUME` | 只有 Auto 运行/等待状态有效;gmoccapy 额外切换图标并允许部分主轴/G-code 控件。 | | `btn_step` | `hal_action_step` | `ensure_mode(MODE_AUTO)` 后 `AUTO_STEP` | 上电且解释器空闲时可用。 | | `btn_from_line` | `restart_dialog` | 只设置 `start_line` | 选择行号后不立即运行;下一次 `btn_run` 从该行启动。该功能不会检查前序 G 代码上下文,界面 tooltip 已标为危险。 | | `tbtn_optional_blocks` | `on_tbtn_optional_blocks_toggled` | `command.set_block_delete(state)` 后 reload | 控制跳过 `/` 可选段;状态写入偏好设置。 | | `btn_edit` | `on_btn_edit_clicked` | 无,进入编辑页 | 使 G-code view 可编辑,禁用 Manual/MDI/Setup。 | ### 10.5 MDI、宏和虚拟键盘按钮 | 控件 | 实际命令 | 控制逻辑 | | --- | --- | --- | | `hal_mdihistory` 输入框 | `ensure_mode(MODE_MDI)` 后 `command.mdi(cmd)` | Enter 或图标提交;`HALMETER`、`STATUS`、`HALSHOW` 是特殊工具命令,不作为 MDI 发给解释器。 | | MDI 删除历史 | 无 NML 命令 | 只清当前会话列表,不删除历史文件。 | | 宏按钮 | `O call [params...]` | 参数由对话框输入;发送后清 live plotter,禁用宏按钮直到空闲。 | | 计算器按钮 | 无 NML 命令 | 将计算值插入 MDI 输入框或编辑器。 | | 键盘按钮 | 可能 `command.abort()` | MDI 宏运行时可作为中断按钮;其他时候切换虚拟键盘显示。 | ### 10.6 工具和换刀按钮 | 控件 | 实际命令 | 控制逻辑 | | --- | --- | --- | | `btn_tool` | 无,切页面 | 显示工具表编辑页。 | | 添加/删除工具 | tool editor 本地表操作 | 删除当前主轴工具被禁止;修改后标记 `edited=True`。 | | 重载工具表 | `tooledit.reload()` | 有未保存修改时先询问是否丢弃。 | | 保存工具表 | `tooledit.save()` | 保存后清 edited 标记。 | | `btn_select_tool_by_no` | `Tn M6` | 输入工具号;若等于当前主轴工具则拒绝;发送前切 MDI。 | | `btn_change_tool` | `Tn M6` | 对工具表选中工具执行换刀;发送后再发一个短 `G4 P...`,避免状态信号丢失。 | | `btn_index_tool` | `M61 Qn` | 只改变当前工具号,不执行 M6 换刀流程;同样用 MDI 发送。 | | 工具 Touch Off X/Z | `G10 L10 P X/Z` | 必须选中工具就是主轴工具;G41/G42 刀补开启时拒绝;如果原来有 G43,写入后重新 `G43`。 | | HAL tool-change | 对话框确认后置 `toolchange-changed` | `toolchange-change` pin 触发手动换刀对话框;确认 pin 可由外部 HAL 按钮关闭对话框;取消时 abort 并保留旧工具。 | 本仿真配置中 `gmoccapy_postgui.hal` 把 `iocontrol.0.tool-change` 和 `iocontrol.0.tool-changed` 重新接成自动完成回路,所以多数 M6 在仿真里不会真正等待人工换刀。 ### 10.7 主轴、冷却和覆盖率 | 控件/HAL pin | 实际命令 | 控制逻辑 | | --- | --- | --- | | `rbt_forward` | `command.spindle(1, rpm)` | 急停中直接返回;Auto/MDI 解释器 reading/waiting 时不允许手动改主轴,避免覆盖 G-code 主轴命令。 | | `rbt_reverse` | `command.spindle(-1, rpm)` | 同上,且按 min/max spindle rpm 修正输出。 | | `rbt_stop` | `command.spindle(0)` | 停主轴,显示转速清 0。 | | `spc_spindle` | `command.spindleoverride(value)` | 按实际 speed-out、min/max spindle rpm 反算覆盖率,避免超限。 | | `btn_spindle_100` | 设置 `spc_spindle=100` | 通过 slider 回调发送 override。 | | `tbtn_flood` | `command.flood(FLOOD_ON/OFF)` | 如果界面状态已等于 stat 状态,不重复发送。 | | `tbtn_mist` | `command.mist(MIST_ON/OFF)` | 同 flood。 | | `spc_feed` | `command.feedrate(value)` | 百分比转 0..n 倍率后发送。 | | `btn_feed_100` | 设置 `spc_feed=100` | 通过 slider 回调发送 feed override。 | | `spc_rapid` | `command.rapidrate(value)` | 设置快速倍率。 | | reset override HAL pins | `rapidrate(1.0)` 或点击 100% 按钮 | 外部硬件可复位 feed/spindle/rapid override。 | 覆盖率和点动速度也可以由 HAL counts 或 analog direct-value 驱动。`*_count-enable` 或 `*_analog-enable` 置位后,gmoccapy 会隐藏对应屏幕按钮或按外部输入更新 slider。 ### 10.8 硬件按钮和 HAL 输入 gmoccapy 创建了一组硬件按钮输入 pin: ```text gmoccapy.h-button.button-0 ... button-9 gmoccapy.v-button.button-0 ... button-6 ``` 输入 pin 变高时: ```text _button_pin_changed() -> 判断 h-button 还是 v-button -> 找当前页面对应位置的可见按钮 -> 如果按钮不敏感则忽略 -> ToggleButton 反转 active -> RadioButton set_active(True) 并 emit("pressed") -> 普通 Button emit("clicked") ``` 这意味着硬件按钮不是固定绑定某个功能,而是绑定“当前界面底部/右侧第 N 个按钮”。同一个硬件按钮在 Manual、MDI、Auto、Tool、File、Edit 页会触发不同软件按钮。它继承软件按钮的敏感状态,因此同样受急停、上电、回零、解释器运行等互锁限制。 其他关键 HAL 输入/输出: - `gmoccapy.jog.axis.*`:外部点动输入,走同一套 jog 逻辑。 - `gmoccapy.jog.jog-increment.*`:外部选择点动增量。 - `gmoccapy.unlock-settings`:设置页 HAL 解锁。 - `gmoccapy.ignore-limits`:外部驱动 ignore limits。 - `gmoccapy.optional-stop`、`gmoccapy.blockdelete`:源码注释写作 optional stop 和 block delete,但当前回调实际是交叉的:`optional-stop` pin 会驱动界面的 `tbtn_optional_blocks`,也就是 `set_block_delete()`;`blockdelete` pin 会调用 `set_optional_stop()`。 - `gmoccapy.delete-message`、`gmoccapy.warning-confirm`:外部清消息或确认弹窗。 - `gmoccapy.toolchange-number/change/changed/confirm`:手动换刀对话框和 iocontrol/remap 之间的握手。 - `gmoccapy.program.length/current-line/progress`:把程序长度、当前行、进度输出给 HAL。 - `gmoccapy.error`:存在报警通知时输出 True。 ### 10.9 设置页和数据类按钮 设置页多数按钮不直接控制运动,而是改 gmoccapy 偏好设置或 HAL 参数: - DRO 位数、DRO 显示切换、G-code 字体、消息弹窗位置和字体:写入 prefs,刷新界面属性。 - 运行从某行开始设置:写入 `run_from_line` prefs,决定 Auto 页是否显示/启用 `btn_from_line`。 - Reload tool、tool measurement、probe height/search velocity/probe velocity/block height:写入 prefs 和 `gmoccapy.probeheight/searchvel/probevel/blockheight/toolmeasurement` HAL pins。 - Turtle jog:改变 jog slider 的 min/max 和当前值,也可由 `gmoccapy.jog.turtle-jog` HAL pin 驱动。 - 音频、虚拟键盘、主题、图标、屏幕布局:只影响界面行为或视觉,不直接向 LinuxCNC 后台发运动命令。 设置页入口本身有锁。进入后会禁用模式按钮,退出时根据 `STATE_ESTOP`、`STATE_ON`、`all_homed`、`NO_FORCE_HOMING` 恢复 Manual/MDI/Auto 的可用状态。 ### 10.10 控制逻辑总图 ```text 用户点击/键盘/HAL button -> GTK signal 或 HAL pin callback -> gmoccapy 回调检查当前 state/mode/interp/all_homed/page -> 需要时切换 LinuxCNC mode -> linuxcnc.command 发 state/mode/jog/mdi/auto/spindle/coolant/override -> NML emcCommand -> linuxcncsvr / milltask / motion / iocontrol -> HAL pins 和 realtime motion 变化 -> emcStatus/emcError -> linuxcnc.stat/error_channel + GStat 信号 -> gmoccapy 刷新按钮敏感状态、DRO、G-code 行、进度、报警 ``` 最重要的互锁可以压缩为一句话: ```text 急停复位 + 机床上电 + 全轴回零 + 解释器空闲 + 合法模式 + 非特殊编辑/设置页 -> 才应该允许执行 MDI 或 Auto G 代码 ``` 其中 `btn_run` 是一个需要特别注意的例外:它的回调本身只做 `AUTO_RUN`,不重复检查所有前置条件。因此若要在二次开发中增加外部 Cycle Start、远程运行、或新的运行按钮,应复用上面的完整条件,而不能只调用 `command.auto(AUTO_RUN, 0)`。 ## 11. 按钮逐项核对清单 本节按源码重新核对按钮。范围包括: - `gmoccapy.glade` 中的 7 个 gladevcp Action 对象和 126 个静态可点击控件:`GtkButton`、`GtkToggleButton`、`GtkRadioButton`、`GtkCheckButton`、`GtkFileChooserButton`、`GtkColorButton`、`GtkFontButton`。 - `gmoccapy` 运行时按 INI 动态生成的按钮:回零、Touch Off、点动、MDI 宏、点动增量、OffsetPage/ToolEdit 内嵌按钮。 - 数值滑块、SpinButton、ComboBox 不是“按钮”,前文已按功能说明;本节只在它们由按钮/复选框联动时提到。 本 XYZAB 配置的实际动态条件: - 轴列表为 `X Y Z A B`,joint 数为 5。 - `[TRAJ] NO_FORCE_HOMING = 0`,所以回零互锁启用。 - 未定义 `[TOOLSENSOR]`,所以 Touch Off 页不会出现 `Block Height` 按钮,自动测刀复选框默认不可用。 - `[MACROS]` 定义 5 个宏按钮:`i_am_lost`、`halo_world`、`jog_around`、`increment xinc yinc`、`go_to_position X-pos Y-pos Z-pos`。 ### 11.1 gladevcp Action 对象 这些不是直接显示的按钮,而是 Glade 中供按钮 `related-action` 绑定或由 gmoccapy 代码调用的动作对象。 | 对象 | 被谁使用 | 功能 | | --- | --- | --- | | `hal_action_open` | 文件选择确认、启动自动加载文件 | 通过 FileChooser/`load_file(path)` 打开 G-code 文件,解释器运行中禁用。 | | `hal_action_reload` | `btn_reload`、`btn_reload_edit`、Touch/Offset 后刷新 | 重载 `stat.file` 当前文件。 | | `hal_action_step` | `btn_step` | 确保 Auto 模式后发送 `AUTO_STEP`。 | | `hal_action_stop` | `btn_stop` | 发送 `command.abort()` 并等待完成。 | | `hal_tgl_pause` | `tbtn_pause` | Toggle 激活时 `AUTO_PAUSE`,取消激活时 `AUTO_RESUME`。 | | `hal_action_save` | `btn_save` | 保存当前 G-code 文件。 | | `hal_action_saveas` | `btn_save_as` | 另存当前 G-code 文件。 | ### 11.2 顶部状态和模式按钮 | 按钮 | 回调 | 功能 | 后台命令/影响 | | --- | --- | --- | --- | | `tbtn_estop` | `on_tbtn_estop_toggled` | 急停/复位急停 | 按下发 `STATE_ESTOP`;释放发 `STATE_ESTOP_RESET`,失败时按钮回到急停状态。 | | `tbtn_on` | `on_tbtn_on_toggled` | 机床上电/下电 | 上电发 `STATE_ON`,下电发 `STATE_OFF`;急停未复位时不能上电。 | | `rbt_manual` | `on_rbt_manual_pressed`、`on_rbt_manual_toggled` | 切 Manual 模式,图标亮灭 | 发 `MODE_MANUAL`;页面切换由状态回调完成。 | | `rbt_mdi` | `on_rbt_mdi_pressed`、`on_rbt_mdi_toggled` | 切 MDI 模式,图标亮灭 | 发 `MODE_MDI`;未上电/未回零时会被禁用或切回 Manual。 | | `rbt_auto` | `on_rbt_auto_pressed`、`on_rbt_auto_toggled` | 切 Auto 模式,图标亮灭 | 发 `MODE_AUTO`;未上电/未回零时会被禁用或切回 Manual。 | | `tbtn_user_tabs` | `on_tbtn_user_tabs_toggled` | 显示/隐藏用户页 | 只切 UI 页,不发 NML 运动命令。 | | `tbtn_setup` | `on_tbtn_setup_toggled` | 进入/退出设置页 | 进入时强制 Manual、禁用模式按钮;需按设置的解锁方式通过。 | ### 11.3 预览和视图按钮 | 按钮 | 回调 | 功能 | | --- | --- | --- | | `rbt_view_p` | `on_rbt_view_p_toggled` | Gremlin 预览切透视视图 `p`。 | | `rbt_view_x` | `on_rbt_view_x_toggled` | 预览切 X 方向视图。 | | `rbt_view_y` | `on_rbt_view_y_toggled` | 预览切 Y 方向视图。 | | `rbt_view_y2` | `on_rbt_view_y2_toggled` | 预览切 Y2 视图,主要用于后置刀架车床显示。 | | `rbt_view_z` | `on_rbt_view_z_toggled` | 预览切 Z 方向视图。 | | `btn_zoom_in` | `on_btn_zoom_in_clicked` | 放大 G-code 预览。 | | `btn_zoom_out` | `on_btn_zoom_out_clicked` | 缩小 G-code 预览。 | | `tbtn_view_dimension` | `on_tbtn_view_dimension_toggled` | 显示/隐藏程序外形尺寸。 | | `tbtn_view_tool_path` | `on_tbtn_view_tool_path_toggled` | 显示/隐藏实时刀路。 | | `btn_delete_view` | `on_btn_delete_view_clicked` | 清空实时刀路轨迹。 | | `tbtn_fullsize_preview0` | `on_tbtn_fullsize_preview_toggled` | Manual 页预览最大化/恢复。 | | `tbtn_fullsize_preview1` | `on_tbtn_fullsize_preview_toggled` | Auto 页预览最大化/恢复。 | | `chk_show_dro` | `on_chk_show_dro_toggled` | 设置预览区是否显示 DRO。 | | `chk_show_offsets` | `on_chk_show_offsets_toggled` | 设置预览区是否显示偏置。 | | `chk_show_dtg` | `on_chk_show_dtg_toggled` | 设置预览区是否显示 DTG。 | ### 11.4 手动页、回零、点动按钮 | 按钮 | 回调 | 功能 | 后台命令/影响 | | --- | --- | --- | --- | | `btn_homing` | `on_btn_homing_clicked` | 打开回零按钮页 | 只切按钮页。 | | `btn_touch` | `on_btn_touch_clicked` | 打开 Touch Off/偏置页 | 显示 OffsetPage,是否显示预览由设置决定。 | | `btn_tool` | `on_btn_tool_clicked` | 打开工具表页 | 显示 ToolEdit。 | | `tbtn_switch_mode` | `on_tbtn_switch_mode_toggled` | Joint/World motion mode 切换 | `teleop_enable(0/1)`;非 identity kinematics 下影响 MDI/Auto 可用性。 | | `btn_exit` | `on_btn_exit_clicked` | 退出 gmoccapy | 销毁窗口;销毁回调会 `STATE_OFF` 后 `STATE_ESTOP`。 | | `tbtn_turtle_jog` | `on_tbtn_turtle_jog_toggled` | 低速/普通点动速度档切换 | 改变 jog velocity slider 范围和值。 | | `chk_ignore_limits` | `on_chk_ignore_limits_toggled` | 忽略限位以便退限位 | 选中时调用 `command.override_limits()`。 | 动态回零按钮: | 动态按钮 | 本 XYZAB 是否出现 | 功能 | | --- | --- | --- | | `ref_all` | 出现 | 全部回零,调用 `command.home(-1)`。 | | `home_axis_x/y/z/a/b` | 出现 | 对应轴回零;先检查是否已有 joint 正在 homing。 | | `home_joint_0..4` | 在 joint 显示模式下可能使用 | 对应 joint 回零。 | | `unref_all` | 出现 | 全部 unhome,调用 `command.unhome(-1)`。 | | `home_back` | 出现 | 返回 Manual 主按钮页。 | | `previous_button` / `next_button` | 本配置不需要 | 轴数超过 7 时分页显示回零按钮。 | 动态点动按钮: | 动态按钮 | 本 XYZAB 是否出现 | 功能 | | --- | --- | --- | | `x+ x- y+ y- z+ z- a+ a- b+ b-` | 出现 | 轴点动;Manual 且 `stat.enabled` 时才发 `command.jog()`。 | | `0+ 0- ... 4+ 4-` | 非全回零或 joint mode 时使用 | joint 点动;同样走 `command.jog()`。 | | `rbt_0` | 出现 | 连续点动。 | | `rbt_1..5` | 出现 | 对应 INI `INCREMENTS`:`1.000 mm`、`0.100 mm`、`0.010 mm`、`0.001 mm`、`1.2345 in`。 | ### 11.5 Touch Off 和 OffsetPage 内部按钮 | 按钮 | 来源 | 功能 | 后台命令/影响 | | --- | --- | --- | --- | | `touch_x/y/z/a/b` | 动态生成 | 对对应轴 Touch Off | 要求 `STATE_ON` 且已回零;执行 `G10 L20 P0 `。 | | `touch_back` | 动态生成 | 返回 Manual 主按钮页 | 不发运动命令。 | | `block_height` | 动态生成 | 设置测刀块高度 | 本 XYZAB 未定义 `[TOOLSENSOR]`,实际不出现;出现时会设置 blockheight 并用 `G10 L2 P0 Z...`。 | | `previous_button` / `next_button` | 动态生成 | Touch Off 轴按钮分页 | 本配置 5 轴,不需要分页。 | | `Edit Offsets` | OffsetPage 动态改造 | 进入/退出偏置表编辑 | 编辑时禁用 Jog/MDI/Auto/Setup;编辑单元格时可能发 `G10/G92/G43.1` 等 MDI。 | | `Zero G92/G52` | OffsetPage 动态改造 | 清 G92/G52 偏置 | 发 `G92.1`,回 Manual。 | | `Set Selected` | OffsetPage 动态改造 | 把选中的坐标系设为当前坐标系 | 对有效 `G54` 到 `G59.3` 发对应 MDI。 | | OffsetPage `Calculator` | OffsetPage 动态改造 | 编辑偏置数值时弹计算器 | 只辅助输入;最终由编辑逻辑发 MDI。 | | `rbtn_show_preview` | 设置页 | Touch 页默认显示预览 | 写 prefs `show_preview_on_offset=True`。 | | `rbtn_show_offsets` | 设置页 | Touch 页默认显示偏置表 | 与 `rbtn_show_preview` 成组,无独立回调;通过另一按钮状态体现。 | ### 11.6 Auto 页和程序执行按钮 | 按钮 | 回调/Action | 功能 | 后台命令/影响 | | --- | --- | --- | --- | | `btn_load` | `on_btn_load_clicked` | 进入文件选择页 | 刷新目录,禁用 Manual/MDI/Setup。 | | `btn_reload` | `hal_action_reload` | 重载当前程序 | 调 gladevcp reload action。 | | `btn_run` | `on_btn_run_clicked` | 运行已加载程序 | `command.auto(AUTO_RUN, start_line)`。 | | `btn_stop` | `hal_action_stop` + `on_btn_stop_clicked` | 停止运行程序 | `command.abort()`,清 `start_line`、行号、暂停状态。 | | `tbtn_pause` | `hal_tgl_pause` + `on_tbtn_pause_toggled` | 暂停/继续程序 | Action 发 `AUTO_PAUSE/AUTO_RESUME`;回调更新图标和部分控件敏感状态。 | | `btn_step` | `hal_action_step` | 单步执行程序 | `AUTO_STEP`。 | | `btn_from_line` | `on_btn_from_line_clicked` | 设置从某行开始运行 | 只打开 restart dialog 并设置 `start_line`;后续 Run 才执行。 | | `tbtn_optional_blocks` | `on_tbtn_optional_blocks_toggled` | 跳过/不跳过 `/` 可选段 | `command.set_block_delete(state)`,保存 prefs 并 reload。 | | `btn_edit` | `on_btn_edit_clicked` | 进入 G-code 编辑页 | 使 G-code view 可编辑,禁用 Manual/MDI/Setup。 | ### 11.7 MDI 页和宏按钮 | 按钮 | 来源 | 功能 | 后台命令/影响 | | --- | --- | --- | --- | | `btn_delete` | Glade | 清空当前会话 MDI 历史列表 | 不删除历史文件,不发 LinuxCNC 命令。 | | `macro_0` | 动态生成 | 运行 `i_am_lost` | 发 `O call`。 | | `macro_1` | 动态生成 | 运行 `halo_world` | 发 `O call`。 | | `macro_2` | 动态生成 | 运行 `jog_around` | 发 `O call`。 | | `macro_3` | 动态生成 | 运行 `increment xinc yinc` | 先弹参数输入,再发 `O call [xinc] [yinc]`。 | | `macro_4` | 动态生成 | 运行 `go_to_position X-pos Y-pos Z-pos` | 先弹 3 个参数,再发 `O call [...]`。 | | Macro `previous_button` / `next_button` | 动态生成 | 宏按钮分页 | 本配置 5 个宏,不需要分页显示。 | | Macro `calculator` | 动态生成 | 显示计算器 | 向 MDI 输入框插入计算值。 | | Macro `keyboard` | 动态生成 | 显示键盘或中断运行宏 | 宏运行中可 `command.abort()`。 | | MDI 输入框 Enter | `EMC_MDIHistory.submit` | 提交手写 MDI | `ensure_mode(MODE_MDI)` 后 `command.mdi(cmd)`。 | ### 11.8 编辑页按钮 | 按钮 | 回调/Action | 功能 | | --- | --- | --- | | `btn_search_forward` | `on_btn_search_forward_clicked` | 在 G-code 编辑器中向下搜索。 | | `btn_search_back` | `on_btn_search_back_clicked` | 在 G-code 编辑器中向上搜索。 | | `btn_undo` | `on_btn_undo_clicked` | 撤销编辑。 | | `btn_redo` | `on_btn_redo_clicked` | 重做编辑。 | | `chk_ignore_case` | 无独立回调 | 搜索/替换时忽略大小写。 | | `chk_replace_all` | 无独立回调 | 替换时执行全部替换。 | | `btn_replace` | `on_btn_replace_clicked` | 执行搜索替换。 | | `btn_comment` | `on_btn_toggle_comment_clicked` | 对选中 G-code 行切换注释。 | | `tbtn_split_view` | `on_tbtn_split_view_toggled` | 编辑时显示/隐藏分屏预览。 | | `btn_reload_edit` | `hal_action_reload` | 重载当前 G-code 文件。 | | `btn_save` | `hal_action_save` | 保存当前文件。 | | `btn_save_as` | `hal_action_saveas` | 当前文件另存为。 | | `btn_new` | `on_btn_new_clicked` | 创建临时新文件,内容为 startup code + `M2`。 | | `btn_calc` | `on_btn_show_calc_clicked` | 在编辑器插入计算值。 | | `btn_keyb` | `on_btn_show_kbd_clicked` | 显示/隐藏虚拟键盘。 | | `btn_back_edit` | `on_btn_back_clicked` | 退出编辑页;有未保存修改时询问是否丢弃。 | ### 11.9 工具页和换刀按钮 | 按钮 | 来源 | 功能 | 后台命令/影响 | | --- | --- | --- | --- | | `btn_select_tool_by_no` | Glade | 输入工具号并换刀 | 发 `Tn M6`。 | | `btn_index_tool` | Glade | 只登记当前工具号 | 发 `M61 Qn`,不做机械换刀移动。 | | `btn_change_tool` | Glade | 对工具表选中工具执行换刀 | 发 `Tn M6`。 | | `btn_tool_touchoff_x` | Glade | 当前主轴工具 X 方向 Touch Off | 发 `G10 L10 P X`,必要时恢复 `G43`。 | | `btn_tool_touchoff_z` | Glade | 当前主轴工具 Z 方向 Touch Off | 发 `G10 L10 P Z`,必要时恢复 `G43`。 | | `btn_back_tool` | Glade | 退出工具页 | 如工具表未保存会询问。 | | ToolEdit `delete` | ToolEdit 内部按钮,gmoccapy 重连回调 | 删除选中工具 | 当前主轴工具不能删除;修改后标记工具表已编辑。 | | ToolEdit `add` | ToolEdit 内部按钮,gmoccapy 重连回调 | 添加新工具行 | 标记工具表已编辑。 | | ToolEdit `reload` | ToolEdit 内部按钮,gmoccapy 重连回调 | 从文件重载工具表 | 有未保存修改时先询问。 | | ToolEdit `apply` | ToolEdit 内部按钮,gmoccapy 重连回调 | 保存工具表到文件 | 清除 edited 标记。 | | ToolEdit `Calculator` | ToolEdit 动态追加 | 用计算器编辑工具表数值 | 只辅助输入,编辑后标记工具表已编辑。 | ### 11.10 文件选择页按钮 | 按钮 | 回调 | 功能 | | --- | --- | --- | | `btn_home` | `on_btn_home_clicked` | 让 `IconFileSelection1` 跳到 home 目录。 | | `btn_jump_to` | `on_btn_jump_to_clicked` | 跳到设置里保存的用户目录。 | | `btn_dir_up` | `on_btn_dir_up_clicked` | 上一级目录。 | | `btn_reload_dir` | `on_btn_refresh_dir_clicked` | 刷新当前目录文件列表。 | | `btn_sel_prev` | `on_btn_sel_prev_clicked` | 选择上一个文件。 | | `btn_sel_next` | `on_btn_sel_next_clicked` | 选择下一个文件。 | | `tbtn_sort` | `on_tbtn_sort_toggled` | 按日期排序/恢复普通排序。 | | `btn_select` | `on_btn_select_clicked` | 选择当前高亮文件;后续 `on_IconFileSelection1_selected` 加载。 | | `btn_back_file_load` | `on_btn_back_clicked` | 退出文件选择页,不返回文件。 | ### 11.11 主轴、冷却、覆盖率按钮 | 按钮 | 回调 | 功能 | 后台命令/影响 | | --- | --- | --- | --- | | `btn_feed_100` | `on_btn_feed_100_clicked` | 进给倍率回 100% | 设置 feed slider,随后 `command.feedrate(1.0)`。 | | `tbtn_flood` | `on_tbtn_flood_toggled` | 冷却液 flood 开/关 | `command.flood(FLOOD_ON/OFF)`。 | | `tbtn_mist` | `on_tbtn_mist_toggled` | 雾冷 mist 开/关 | `command.mist(MIST_ON/OFF)`。 | | `btn_spindle_100` | `on_btn_spindle_100_clicked` | 主轴倍率回 100% | 设置 spindle override slider。 | | `rbt_reverse` | `on_rbt_reverse_clicked/released` | 主轴反转 | `_set_spindle("reverse")` 后 `command.spindle(-1, rpm)`。 | | `rbt_stop` | `on_rbt_stop_clicked` | 主轴停止 | `command.spindle(0)`。 | | `rbt_forward` | `on_rbt_forward_clicked/released` | 主轴正转 | `_set_spindle("forward")` 后 `command.spindle(1, rpm)`。 | ### 11.12 系统/诊断按钮 | 按钮 | 回调 | 功能 | | --- | --- | --- | | `btn_classicladder` | `on_btn_classicladder_clicked` | 如果 `classicladder_rt` 存在,启动 ClassicLadder;否则弹提示。 | | `btn_hal_scope` | `on_btn_hal_scope_clicked` | 启动 `halscope`。 | | `btn_status` | `on_btn_status_clicked` | 启动 `linuxcnctop`。 | | `btn_hal_meter` | `on_btn_hal_meter_clicked` | 启动 `halmeter`。 | | `btn_calibration` | `on_btn_calibration_clicked` | 启动 `emccalib.tcl -- -ini `。 | | `btn_show_hal` | `on_btn_show_hal_clicked` | 启动 `halshow.tcl`。 | 这些按钮通过 `os.popen(...)` 启动外部诊断/调试工具,不直接发运动命令。 ### 11.13 设置页按钮和可点控件 | 控件 | 回调 | 功能 | | --- | --- | --- | | `rbtn_fullscreen` | `on_rbtn_fullscreen_toggled` | 设置启动/当前窗口为全屏。 | | `rbtn_maximized` | `on_rbtn_maximized_toggled` | 设置启动/当前窗口为最大化,并联动标题栏选项。 | | `rbtn_window` | `on_rbtn_window_toggled` | 设置窗口模式,允许调整位置和大小。 | | `chkbtn_hide_titlebar` | `on_chkbtn_hide_titlebar_toggled` | 隐藏/显示窗口标题栏。 | | `chk_hide_cursor` | `on_chk_hide_cursor_toggled` | 隐藏/显示鼠标光标。 | | `chk_hide_tooltips` | `on_chk_hide_tooltips_toggled` | 全局隐藏/显示工具提示。 | | `chk_turtle_jog` | `on_chk_turtle_jog_toggled` | 隐藏/显示 turtle jog 按钮。 | | `rel_colorbutton` | `on_rel_colorbutton_color_set` | 设置 DRO 相对坐标颜色。 | | `abs_colorbutton` | `on_abs_colorbutton_color_set` | 设置 DRO 绝对坐标颜色。 | | `dtg_colorbutton` | `on_dtg_colorbutton_color_set` | 设置 DRO DTG 颜色。 | | `homed_colorbtn` | `on_homed_colorbtn_color_set` | 设置已回零轴显示颜色。 | | `unhomed_colorbtn` | `on_unhomed_colorbtn_color_set` | 设置未回零轴显示颜色。 | | `chk_toggle_readout` | `on_chk_toggle_readout_toggled` | 允许点击 DRO 切换读数模式。 | | `fontbutton_popup` | `on_fontbutton_popup_font_set` | 设置消息弹窗字体。 | | `chk_use_frames` | `on_chk_use_frames_toggled` | 设置消息是否带边框。 | | `btn_launch_test_message` | `on_btn_launch_test_message_pressed` | 生成一条测试消息。 | | `fontbutton_gcodeview` | `on_fontbutton_gcodeview_font_set` | 设置 G-code 视图字体。 | | `chk_font_monospace` | `on_chk_font_monospace_toggled` | 过滤/选择等宽字体。 | | `chk_font_regular` | `on_chk_font_regular_toggled` | 过滤/选择 Regular/Medium 字体。 | | `chk_en_audio` | `on_chk_en_audio_toggled` | 启用/关闭提示音。 | | `audio_alert_chooser` | `on_change_sound` | 选择提示音文件。 | | `audio_error_chooser` | `on_change_sound` | 选择错误提示音文件。 | | `chk_use_kb_on_offset` | `on_chk_use_kb_on_offset_toggled` | Offset 页自动显示键盘。 | | `chk_use_kb_on_tooledit` | `on_chk_use_kb_on_tooledit_toggled` | ToolEdit 页自动显示键盘。 | | `chk_use_kb_on_mdi` | `on_chk_use_kb_on_mdi_toggled` | MDI 页自动显示键盘。 | | `chk_use_kb_on_edit` | `on_chk_use_kb_on_edit_toggled` | 编辑页自动显示键盘。 | | `chk_use_kb_on_file_selection` | `on_chk_use_kb_on_file_selection_toggled` | 文件选择页自动显示键盘。 | | `chk_kbd_set_height` | `on_chk_kb_set_height_toggled` | 固定/取消固定虚拟键盘高度。 | | `chk_kbd_set_width` | `on_chk_kb_set_width_toggled` | 固定/取消固定虚拟键盘宽度。 | | `rbtn_no_run_from_line` | `on_rbtn_run_from_line_toggled` | 禁用 Auto 页从行运行按钮。 | | `rbtn_run_from_line` | `on_rbtn_run_from_line_toggled` | 启用 Auto 页从行运行按钮。 | | `chk_use_kb_shortcuts` | `on_chk_use_kb_shortcuts_toggled` | 启用/禁用 F1/F2/F3/F5/R/P/S 等键盘快捷键。 | | `file_to_load_chooser` | `on_file_to_load_chooser_file_set` | 设置启动时自动加载的文件。 | | `btn_use_current` | `on_btn_use_current_clicked` | 把当前已加载程序保存为启动自动加载文件。 | | `btn_none` | `on_btn_none_clicked` | 清空启动自动加载文件。 | | `jump_to_dir_chooser` | `on_jump_to_dir_chooser_file_set` | 设置文件选择页 Jump To 目录。 | | `rbt_use_unlock` | `on_rbt_unlock_toggled` | 设置设置页使用密码解锁。 | | `rbt_no_unlock` | `on_rbt_unlock_toggled` | 设置设置页不需要解锁。 | | `rbt_hal_unlock` | `on_rbt_unlock_toggled` | 设置设置页由 HAL pin `unlock-settings` 解锁。 | | `chk_use_tool_measurement` | `on_chk_use_tool_measurement_toggled` | 启用自动测刀,并设置相关 HAL pins;本配置缺少 `[TOOLSENSOR]`,默认不可用。 | | `chk_reload_tool` | `on_chk_reload_tool_toggled` | 启动 GUI 时重新加载上次主轴工具和长度补偿。 | ### 11.14 硬件按钮映射 | HAL 输入 | 功能 | | --- | --- | | `gmoccapy.h-button.button-0..9` | 触发当前底部按钮栏对应位置的软件按钮。 | | `gmoccapy.v-button.button-0..6` | 触发当前右侧按钮栏对应位置的软件按钮。 | 硬件按钮不固定绑定某个功能,而是按当前页面位置映射。若对应软件按钮不敏感,硬件输入会被忽略;若对应软件按钮是 ToggleButton/RadioButton/Button,会分别执行切换、选中并 pressed、或 clicked。 ## 12. 关键源文件索引 - INI: - `/home/mes123456/cnc_wams/linuxcnc/configs/sim/gmoccapy/gmoccapy_XYZAB.ini` - 启动脚本: - `/home/mes123456/cnc_wams/linuxcnc/scripts/linuxcnc` - 实际 gmoccapy 可执行文件: - `/home/mes123456/cnc_wams/linuxcnc/bin/gmoccapy` - gmoccapy Glade 界面定义: - `/home/mes123456/cnc_wams/linuxcnc/share/gmoccapy/gmoccapy.glade` - gmoccapy INI 读取: - `/home/mes123456/cnc_wams/linuxcnc/src/emc/usr_intf/gmoccapy/getiniinfo.py` - gmoccapy 对话框: - `/home/mes123456/cnc_wams/linuxcnc/src/emc/usr_intf/gmoccapy/dialogs.py` - gladevcp HAL pin 生成: - `/home/mes123456/cnc_wams/linuxcnc/lib/python/gladevcp/makepins.py` - `/home/mes123456/cnc_wams/linuxcnc/lib/python/common/hal_glib.py` - gladevcp LinuxCNC Action 和 MDI/File 控件: - `/home/mes123456/cnc_wams/linuxcnc/lib/python/gladevcp/hal_actions.py` - `/home/mes123456/cnc_wams/linuxcnc/lib/python/gladevcp/hal_filechooser.py` - `/home/mes123456/cnc_wams/linuxcnc/lib/python/gladevcp/hal_mdihistory.py` - LinuxCNC task/NML 主循环: - `/home/mes123456/cnc_wams/linuxcnc/src/emc/task/emctaskmain.cc` - HAL: - `/home/mes123456/cnc_wams/linuxcnc/configs/sim/gmoccapy/core_sim_XYZAB.hal` - `/home/mes123456/cnc_wams/linuxcnc/configs/sim/gmoccapy/spindle_sim.hal` - `/home/mes123456/cnc_wams/linuxcnc/configs/sim/gmoccapy/simulated_home.hal` - `/home/mes123456/cnc_wams/linuxcnc/configs/sim/gmoccapy/gmoccapy_postgui.hal` ## 13. 按钮图标整理索引 本配置的 gmoccapy 图标主题来自 `/home/mes123456/cnc_wams/linuxcnc/configs/sim/gmoccapy/gmoccapy_XYZAB.pref` 中的 `icon_theme = classic`。界面按钮图标不是全部直接写在 `gmoccapy.glade` 中,运行时还会由 `/home/mes123456/cnc_wams/linuxcnc/bin/gmoccapy` 的 `_set_icon_theme()` 按 `Gtk.IconTheme` 重新绑定到 `classic` 主题图标。 图标整理结果已单独保存到: - `/home/mes123456/cnc_wams/work/working3/gmoccapy_button_icons/button_icon_inventory.md` - `/home/mes123456/cnc_wams/work/working3/gmoccapy_button_icons/button_icon_inventory.csv` - `/home/mes123456/cnc_wams/work/working3/gmoccapy_button_icons/files/` 清单覆盖 Glade 静态按钮、Python 动态生成按钮、运行时 active/inactive 状态图标、 ToolEdit/OffsetPage 内嵌按钮,以及 `[MACROS]` 中宏按钮的自定义图片。当前整理结果 共 211 行,复制实际图标文件 112 个;其中 `i_am_lost` 和 `go_to_position` 宏按钮使用 NGC 文件内 `(IMAGE, ...)` 声明的 PNG 图片,其余无图标宏按钮使用文字标签。