# GMOCCAPY 控制面板功能、数据流与控制流 更新时间:2026-08-25 本文是后续分析 GMOCCAPY 控制面板的总入口。它把普通三轴 `gmoccapy.ini` 和五轴 XYZAC RTCP 案例放在同一套模型中,区分 UI 控件、GMOCCAPY Python handler、LinuxCNC command/status、TASK/motion、HAL 和 Vismach 的责任边界。 ## 1. 范围与版本边界 | 项目 | 当前工作区/运行时 | |---|---| | 仓库源码 | `linuxcnc/VERSION = 2.10.0~pre0` | | 仓库 GMOCCAPY 源码 | `linuxcnc/src/emc/usr_intf/gmoccapy/gmoccapy.py`,`_RELEASE = 3.4.3` | | 实际系统 GUI | `/usr/bin/gmoccapy`,运行时版本 `3.5.2`,系统 LinuxCNC `2.10.0~pre1` | | 普通面板入口 | [`run-gmoccapy.sh`](../run-gmoccapy.sh),默认 `configs/sim/gmoccapy/gmoccapy.ini` | | 五轴 RTCP 入口 | [`run-5axis-rtcp.sh`](../run-5axis-rtcp.sh),默认 XYZAC TRT switchkins | | 发布/仿真边界 | POSIX non-realtime 仿真;不等同于实时硬件验证 | 截图中的 `Important change(s)` 弹窗来自系统 GMOCCAPY 3.5.2,不存在于仓库 3.4.3 源文件中;两套来源不能混为一个源码版本。详细证据见 [GMOCCAPY 分析报告](gmoccapy-analysis.md)。 ## 2. 总体架构 ```text 快捷方式 / linuxcnc -r CASE.ini │ ▼ LinuxCNC 启动器与 INI 解析 │ ├── linuxcncsvr / NML 状态与命令通道 ├── milltask / RS274NGC interpreter / task mode ├── motmod + kinematics / fixed servo cycle ├── HAL files / HALUI / simulated devices └── DISPLAY=gmoccapy 或 DISPLAY=axis │ ▼ GMOCCAPY Gtk/Glade 控制面板 │ ┌─────────┴─────────┐ │ │ 用户点击/键盘/HAL linuxcnc.stat/HAL status │ ▲ ▼ │ Python handler ── command ─┴── TASK/motion/HAL feedback │ ├── 模式/按钮页切换 ├── 程序加载/预览 ├── AUTO 运行/暂停/停止/单步 ├── MDI 命令 └── homing、tool、offset、spindle、coolant ``` GMOCCAPY 不是运动学计算器。它负责把操作员动作转换为 LinuxCNC command,并把 LinuxCNC status/HAL status 投影回界面;真正的解释器、轨迹规划、逆解/正解和关节命令由 LinuxCNC runtime 完成。 ## 3. 启动控制流 ### 3.1 快捷方式层 `run-gmoccapy.sh` 和 `run-5axis-rtcp.sh` 都遵循相同模式: 1. 计算仓库绝对路径,避免从任意工作目录启动时相对路径漂移。 2. 校验 INI、演示程序、LinuxCNC launcher 是否存在。 3. 进入 LinuxCNC 根目录。 4. 执行 `/usr/bin/linuxcnc -r CASE.ini`,保留终端诊断。 五轴快捷方式额外检查 RTCP 子程序中确实存在 `M428`,并支持 `xyzac-trt.ini` 与 `xyzbc-trt.ini` 两个变体。 ### 3.2 INI 到进程 以普通 GMOCCAPY 为例: ```text [DISPLAY] DISPLAY=gmoccapy [TASK] TASK=milltask [HAL] core_sim.hal + spindle_sim.hal + simulated_home.hal [EMCIO] TOOL_TABLE=tool.tbl [RS274NGC] PARAMETER_FILE=sim.var, SUBROUTINE_PATH=macros [KINS] trivkins coordinates=xyz ``` 启动器随后创建 `linuxcncsvr`、`milltask`、`halui` 和 GMOCCAPY。GMOCCAPY 进程通过 `-ini` 得到同一个 INI 路径,不能自行替代 TASK/motion/HAL。 ### 3.3 GMOCCAPY 初始化顺序 仓库源码 `gmoccapy.py` 的主初始化顺序为: 1. 解析 `-user_mode`、`-logo` 参数(约 `243-270` 行)。 2. 读取 INI(`_get_ini_data()`,约 `272-275` 行)。 3. 读取偏好文件(`_get_pref_data()`)。 4. 动态创建 DRO、home、touch-off、jog、macro 等控件(约 `280-305` 行)。 5. 建立 GMOCCAPY HAL pins(约 `307` 行)。 6. 连接 Glade signals(约 `315-320` 行)。 7. 显示主窗口(约 `324-325` 行)。 8. 初始化主题、G-code preview、kinematics view、offset/tool editor、keyboard 和文件选择器(约 `327-342` 行)。 系统 3.5.2 运行时在 GUI 初始化后额外调用 `_startup_message()`,生成版本提示弹窗;它属于安装包新增功能,不属于仓库 3.4.3 初始化链。 ## 4. 控制面板模式和按钮门控 ### 4.1 模式按钮 Glade 中的主要模式控件: | 控件 | 作用 | handler/状态 | |---|---|---| | `rbt_manual` | MANUAL/JOG | `on_rbt_manual_pressed()` 发出 `MODE_MANUAL` | | `rbt_mdi` | MDI | `on_rbt_mdi_pressed()` 发出 `MODE_MDI` | | `rbt_auto` | AUTO | `on_rbt_auto_pressed()` 发出 `MODE_AUTO` | | `tbtn_setup` | 设置页 | 进入设置前强制 MANUAL,并禁用模式按钮 | | `tbtn_user_tabs` | 用户页 | 切换主 notebook 页面 | `on_hal_status_mode_auto()` 在收到 HAL status 后将主页面切回 page 0,把按钮 notebook 切到 `_BB_AUTO`,并将 jog notebook 切到 AUTO 页面(约 `2804-2824` 行)。因此“点击 AUTO 图标”与“看到 AUTO 按钮组”是同一个状态转换的两个可观察结果。 ### 4.2 急停、上电、homing 门控 `on_tbtn_setup_toggled()` 和 HAL status handler 根据以下条件设置按钮敏感度: ```text ESTOP → manual/mdi/auto 均禁用 ON + 未 homed → 只允许 manual ON + all_homed 或 NO_FORCE_HOMING → manual/mdi/auto 全部可用 ``` 对应仓库源码约为 `3793-3808` 行。未满足条件时,点击 AUTO 会被 `on_hal_status_mode_auto()` 拒绝,显示 `It is not possible to change to Auto Mode at the moment`,并回到 MANUAL。 这解释了为什么控制面板可能“没有加载按钮”:加载按钮不在 MANUAL 页面,而且 AUTO 页面本身可能因状态门控没有激活。 ## 5. G-code 加载数据流 ### 5.1 控件链 ```text rbt_auto │ on_hal_status_mode_auto() ▼ hbtb_auto / _BB_AUTO │ │ btn_load(图标 img_open,tooltip=Load a new program) │ on_btn_load_clicked() ▼ _BB_LOAD_FILE + IconFileSelection1 │ │ 用户选中路径 │ btn_select / IconFileSelection1_selected ▼ hal_action_open.load_file(path) ▼ LinuxCNC task/interpreter + preview/status ▼ ntb_preview page 0 + ntb_button _BB_AUTO + stat.file ``` ### 5.2 打开文件界面 `on_btn_load_clicked()`(`gmoccapy.py:5046-5078`)执行: 1. `ntb_button.set_current_page(_BB_LOAD_FILE)`。 2. `ntb_preview.set_current_page(3)`。 3. 打开 full-size preview。 4. `_show_iconview_tab(True)`。 5. 刷新 `IconFileSelection1` 文件列表。 6. 暂时禁用 MANUAL、MDI 和设置按钮,避免文件选择过程中切换模式。 文件选择器在 `_init_IconFileSelection()` 和 `_init_file_to_load()` 中读取 `PROGRAM_PREFIX` 与 `[FILTER] PROGRAM_EXTENSION`。普通案例 `PROGRAM_PREFIX = ../../nc_files/` 最终指向仓库的 `linuxcnc/nc_files`。 ### 5.3 确认文件 `on_IconFileSelection1_selected()`(`gmoccapy.py:5114-5125`)执行: 1. 将选中的 `path` 交给 `hal_action_open.load_file(path)`。 2. 恢复 preview page 0。 3. 关闭 full-size preview 和 icon view。 4. 把按钮 notebook 切回 `_BB_AUTO`。 5. 重新启用 MANUAL、MDI 和设置按钮。 这一步是“加载程序”,不是“运行程序”。运行还需要 `btn_run`/`AUTO_RUN`;源码键盘 handler 将 `R` 映射为运行、`P` 映射为暂停、`S` 映射为恢复。 ### 5.4 启动时自动加载 `on_window1_show()` 会读取偏好项 `open_file`(约 `2920-2924` 行)。如果用户在设置页指定“启动时加载文件”,GMOCCAPY 会在窗口显示后直接调用 `hal_action_open.load_file(file)`。这条路径绕过手动点击文件选择器,但仍通过同一个 LinuxCNC load action。 ## 6. AUTO 运行控制流 ```text btn_run / R ▼ linuxcnc.command().auto(AUTO_RUN, line) ▼ milltask / RS274NGC interpreter ▼ TP queue → motion controller → kinematics → joint commands ▼ HAL simulated device / spindle / coolant / tool change ▼ linuxcnc.stat + hal_status ▼ GMOCCAPY DRO、progress、preview、button sensitivity ``` 相关按钮属于 `hbtb_auto`:`btn_load`、`btn_reload`、`btn_run`、`btn_stop`、`tbtn_pause`、`btn_step`、`btn_from_line`、`tbtn_optional_blocks`、`btn_edit`。Glade 负责控件和 signal 绑定,Python handler 负责调用 LinuxCNC command;运动本身不在 GTK handler 中实现。 ## 7. MDI、Jog、Home、Tool 和 Offset 数据流 ### MDI `rbt_mdi` 将 task mode 设为 `MODE_MDI`。MDI 输入提交后进入 LinuxCNC interpreter;G-code 解析错误通过 LinuxCNC error channel 返回,再由 GMOCCAPY notification/error handler 显示。 ### Jog JOG 按钮由 `_make_jog_button()` 动态生成;轴/关节列表来自 INI 的 `COORDINATES`、kinematics 类型和 joint-axis mapping。Jog 命令仍经 LinuxCNC command 通道,不直接改变 DRO;DRO 的真值来自 status feedback。 ### Home Home 按钮最终调用 `command.home(joint_or_axis)`。仿真 HAL 的 `sim_home_switch` 或自定义 home HAL 决定 home switch 状态;`all_homed` HAL status 决定 MDI/AUTO 是否重新开放。 ### Tool/Offset 工具表来自 `[EMCIO] TOOL_TABLE`,offset page 和 tool editor 通过 LinuxCNC tool data/action 更新。G43/G49/G43.1 的解释器语义由 RS274NGC 负责;GMOCCAPY 只显示和提交工具/offset 操作。系统 3.5.2 的启动提示明确提醒:AUTO 中换刀后的 G43 不能假定由界面自动恢复,应由程序/REMAP 明确处理。 ## 8. 五轴 XYZAC RTCP 控制流 ### 8.1 配置层 五轴案例 `xyzac-trt.ini` 的关键字段: ```text [DISPLAY] OPEN_FILE = ./demos/xyzac_switchkins.ngc [RS274NGC] SUBROUTINE_PATH = ./remap_subs [RS274NGC] REMAP = M428 ... ngc=428remap [RS274NGC] REMAP = M429 ... ngc=429remap [RS274NGC] REMAP = M430 ... ngc=430remap [KINS] KINEMATICS = xyzac-trt-kins sparm=identityfirst [TRAJ] COORDINATES = XYZAC [HAL] HALCMD = net ... motion.switchkins-type [HAL] HALCMD = loadusr -W xyzac-trt-gui ``` ### 8.2 switchkins 状态 `xyzac-trt-kins.c` 将 `sparm=identityfirst` 定义为: ```text switchkins-type 0 → identity kinematics switchkins-type 1 → xyzac TRT kinematics switchkins-type 2 → userk kinematics ``` `trtfuncs.c` 为 XYZAC/XYZBC 实现 forward/inverse mapping,并声明 `tool-offset`、旋转中心和轴 offset HAL pins。XYZAC 的五个关节是 `X Y Z A C`;A 是倾斜台,C 是水平旋转台。 ### 8.3 M428/M429 控制链 ```text G-code M428 ▼ 428remap.ngc ├── M68 E3 Q1 写 motion.analog-out-03 = 1 ├── M66 E0 L0 等待同步 └── 检查 motion.switchkins-type == 1 ▼ xyzac-trt-kins inverse/forward ▼ XYZAC joint commands with TCP/RTCP compensation ``` `M429` 对称地写入 `Q0`,切回 identity;`M430` 写入 `Q2`,进入 userk。`helix_ac.ngc` 演示了典型顺序:先用 M429 在 machine coordinates 安全定位,再用 M428 执行带 A/C 姿态变化的螺旋插补,结束后再切回 M429 做返回定位。 ### 8.4 Vismach feedback INI 中的 HAL nets 将以下反馈送到 `xyzac-trt-gui`: ```text joint.0.pos-fb → table-x joint.1.pos-fb → saddle-y joint.2.pos-fb → spindle-z joint.3.pos-fb → tilt-a joint.4.pos-fb → rotate-c motion.tooloffset.z → tool-offset xyzac-trt-kins.y-offset/z-offset → Vismach geometry ``` 因此 Vismach 不是运动 authority;它是 joint feedback、tool offset 和 geometry offset 的可视化消费者。 ## 9. 状态真值与可观察结果 | 状态 | authority | 面板表现 | |---|---|---| | 急停 | TASK/motion state | E-stop active,模式按钮禁用 | | 上电 | TASK state + HAL | Power icon active,允许进一步操作 | | all homed | HAL status / joint state | MDI/AUTO 解除门控 | | 当前模式 | `stat.task_mode` | MANUAL/MDI/AUTO 页面切换 | | 当前文件 | `stat.file` / file-loaded status | 顶部文件名、G-code view、Run gate | | 解释器状态 | `stat.interp_state` | Run/Pause/Step/Stop 敏感度 | | 当前 G/M codes | `stat.gcodes` / `stat.mcodes` | G-Code 信息区域 | | 机床位置 | `stat.position` / joint feedback | DRO 和 Vismach | | kinematics mode | `motion.switchkins-type` | AXIS switchkins 面板/RTCP 模式 | 任何未来 Web/WASM 控制面板都应消费这些 authority 的 snapshot/event,而不是在 JS/GUI 层镜像一套可写的机床状态。 ## 10. 现有证据与复现 ```bash ./run-gmoccapy.sh ./run-5axis-rtcp.sh ./run-5axis-rtcp.sh xyzbc-trt.ini ``` 已验证的五轴运行证据: - [5axis-rtcp-running.png](5axis-rtcp-running.png) - [5axis-rtcp-shortcut.md](5axis-rtcp-shortcut.md) - `linuxcnc` 状态返回 `file=./demos/xyzac_switchkins.ngc` - AXIS 标题包含 `sim-xyzac-trt-kins (switchkins)` - `xyzac-trt-gui` 进程和五轴 Vismach 预览存在 ## 11. 后续分析顺序 分析任何新的 GMOCCAPY/五轴控制问题时,按以下顺序取证: 1. 先记录实际运行时路径、LinuxCNC 版本、GMOCCAPY 版本;不要把系统安装脚本和仓库源码混为一份。 2. 读取 INI 的 DISPLAY/TASK/HAL/RS274NGC/KINS/TRAJ/EMCIO 段,建立配置闭包。 3. 在 Glade 中找到 widget ID,再在 `gmoccapy.py` 找 signal handler;不要只根据截图猜按钮语义。 4. 追踪 handler 发出的 `linuxcnc.command()`,确认 command 进入 TASK/motion/HAL 的路径。 5. 用 `linuxcnc.stat()`、HAL pins、日志和 Vismach feedback 交叉验证,不把 DRO 或 preview 当作 authority。 6. 五轴问题先确认 kinematics type、M428/M429 状态、tool offset、rotation center/axis offset,再分析轨迹差异。 7. 任何缺失的官方 oracle、实时硬件、浏览器或资源输入都保留为明确 blocker,不以 GUI 截图替代完整等价证明。