Files
cnc_wams/项目分析/5axis-xyzbc-trt-sim执行过程分析.md
2026-07-05 22:13:40 -04:00

21 KiB
Raw Permalink Blame History

5axis-xyzbc-trt-sim 执行过程分析

本文分析当前 LinuxCNC 源码树中 5axis-xyzbc-trt-sim 对应的仿真配置。实际入口配置文件为:

configs/sim/axis/vismach/5axis/table-rotary-tilting/xyzbc-trt.ini

该配置是一个 axis GUI + basic_sim.tcl 仿真 HAL + xyzbc-trt-kins 可切换运动学 + PyVCP/halui 控制面板 + Vismach 三维模型的五轴转台仿真。

1. 启动入口

如果从项目中已有快捷方式启动,入口文件是:

linuxcnc-rtcp-5axis-shortcuts/table-rotary-tilting/xyzbc-trt.desktop

其中的执行命令为:

/home/mes123456/linuxcnc-master/scripts/rip-environment linuxcnc /home/mes123456/linuxcnc-master/configs/sim/axis/vismach/5axis/table-rotary-tilting/xyzbc-trt.ini

rip-environment 负责设置 RIP 开发环境,然后调用 linuxcnc 脚本并传入 xyzbc-trt.ini

scripts/linuxcnc 会读取 INI 中的关键段:

  • [TASK] TASK = milltask
  • [HAL] HALUI = halui
  • [HAL] HALFILE = LIB:basic_sim.tcl
  • [DISPLAY] DISPLAY = axis
  • [KINS] KINEMATICS = xyzbc-trt-kins sparm=identityfirst
  • [TRAJ] COORDINATES = XYZBC

总体启动顺序如下:

  1. 启动 linuxcncsvr,创建和持有 NML 通道。
  2. 启动 realtime/HAL。
  3. 加载 tpmodhomemod
  4. 启动 [TASK] TASK = milltask
  5. 启动 [HAL] HALUI = halui
  6. 执行 [HAL] HALFILE = LIB:basic_sim.tcl
  7. 执行 INI 中所有 [HAL] HALCMD = ...
  8. 执行 halcmd start,启动实时线程。
  9. 启动 [DISPLAY] DISPLAY = axis

2. INI 核心配置

目标配置文件:

configs/sim/axis/vismach/5axis/table-rotary-tilting/xyzbc-trt.ini

关键内容:

[EMC]
MACHINE = sim-xyzbc-trt-kins (switchkins)

[DISPLAY]
GEOMETRY = XYZB
OPEN_FILE = ./demos/xyzbc_switchkins.ngc
PYVCP = ./xyzbc-trt.xml
JOG_AXES = XYZC
DISPLAY = axis

[RS274NGC]
SUBROUTINE_PATH = ./remap_subs
HAL_PIN_VARS = 1
REMAP = M428 modalgroup=10 ngc=428remap
REMAP = M429 modalgroup=10 ngc=429remap
REMAP = M430 modalgroup=10 ngc=430remap
PARAMETER_FILE = xyzbc.var

[KINS]
KINEMATICS = xyzbc-trt-kins sparm=identityfirst
JOINTS = 5

[TRAJ]
COORDINATES = XYZBC
LINEAR_UNITS = mm
ANGULAR_UNITS = deg

COORDINATES = XYZBC 表示该配置使用 5 个坐标字母,对应 5 个 joint

  • joint.0 -> X
  • joint.1 -> Y
  • joint.2 -> Z
  • joint.3 -> B
  • joint.4 -> C

sparm=identityfirst 是本配置的重要细节。它改变了 xyzbc-trt-kins 的默认类型顺序,使启动时的 switchkins-type 0 是 identity kinematics。

3. basic_sim.tcl 建立仿真 HAL

INI 中:

[HAL]
HALFILE = LIB:basic_sim.tcl

对应文件:

lib/hallib/basic_sim.tcl
lib/hallib/sim_lib.tcl

basic_sim.tcl 读取 INI 中的坐标、joint 数、servo period然后调用 core_sim

core_sim 位于 lib/hallib/sim_lib.tcl,主要完成:

  1. 调用 setup_kins 加载 [KINS] KINEMATICS 指定的运动学模块。
  2. 加载 motmod
  3. motion-command-handlermotion-controller 加入 servo-thread
  4. 为每个 joint 创建 pid
  5. 为每个 joint 创建 mux2
  6. joint.N.motor-pos-cmd 经由 pidmux2 接回 joint.N.motor-pos-fb,形成理想伺服仿真闭环。
  7. 加载仿真回零、仿真主轴、手动换刀等用户态/实时组件。

运行后可生成等效 HAL 文件:

configs/sim/axis/vismach/5axis/table-rotary-tilting/xyzbc-trt_cmds.hal

其中关键 HAL 命令为:

loadrt xyzbc-trt-kins sparm=identityfirst
loadrt motmod base_period_nsec=0 servo_period_nsec=1000000 num_joints=5
loadrt pid names=J0_pid,J1_pid,J2_pid,J3_pid,J4_pid
loadrt mux2 names=J0_mux,J1_mux,J2_mux,J3_mux,J4_mux

addf motion-command-handler servo-thread
addf motion-controller servo-thread

每个 joint 的典型连接形态为:

net J0:pos-cmd joint.0.motor-pos-cmd => J0_pid.command
net J0:on-pos  J0_pid.output         => J0_mux.in1
net J0:pos-fb  J0_mux.out            => joint.0.motor-pos-fb

这说明该仿真没有真实驱动器,反馈位置由仿真 HAL 直接产生。

4. switchkins 初始化

运动学源码入口:

src/emc/kinematics/xyzbc-trt-kins.c
src/emc/kinematics/switchkins.c
src/emc/kinematics/trtfuncs.c

xyzbc-trt-kins.cswitchkinsSetup() 根据 sparm 配置三套运动学函数。

因为 INI 使用:

KINEMATICS = xyzbc-trt-kins sparm=identityfirst

所以实际类型顺序为:

  • switchkins-type 0identity kinematics
  • switchkins-type 1xyzbc TRT kinematics
  • switchkins-type 2userk kinematics

如果没有 identityfirst,默认 type 0 才是 xyzbc-trt-kins

switchkins.c 提供统一包装函数:

  • kinematicsForward()
  • kinematicsInverse()
  • kinematicsSwitch()
  • kinematicsSwitchable()

并创建状态 HAL pin

  • kinstype.is-0
  • kinstype.is-1
  • kinstype.is-2

启动时 switchkins_type = 0,随后调用 kinematicsSwitch(0),因此本配置启动后处于 identity kinematics。

5. xyzbc TRT 几何参数

trtKinematicsSetup() 位于:

src/emc/kinematics/trtfuncs.c

它为 TRT 运动学创建 HAL 输入:

  • xyzbc-trt-kins.x-rot-point
  • xyzbc-trt-kins.y-rot-point
  • xyzbc-trt-kins.z-rot-point
  • xyzbc-trt-kins.x-offset
  • xyzbc-trt-kins.y-offset
  • xyzbc-trt-kins.z-offset
  • xyzbc-trt-kins.tool-offset
  • xyzbc-trt-kins.conventional-directions

INI 中对这些参数的设置和连接为:

net :tool-offset motion.tooloffset.z
net :tool-offset xyzbc-trt-kins.tool-offset xyzbc-trt-gui.tool-offset
net :x-offset    xyzbc-trt-kins.x-offset    xyzbc-trt-gui.x-offset
net :z-offset    xyzbc-trt-kins.z-offset    xyzbc-trt-gui.z-offset
sets :x-offset -20
sets :z-offset -15

setp xyzbc-trt-kins.x-rot-point 0
setp xyzbc-trt-kins.y-rot-point 0
setp xyzbc-trt-kins.z-rot-point 0
setp xyzbc-trt-kins.conventional-directions 0

因此实际计算中:

dx = x-offset = -20
dz = z-offset + tool-offset

tool-offset 来自 motion.tooloffset.z,也就是 LinuxCNC 当前刀长补偿的 Z 分量。

6. xyzbc 正/逆运动学

xyzbcKinematicsForward() 位于:

src/emc/kinematics/trtfuncs.c

它从 joint 坐标计算当前笛卡尔位姿:

joints[X/Y/Z/B/C] -> EmcPose XYZBC

xyzbcKinematicsInverse() 从程序位姿计算 joint 目标:

EmcPose XYZBC -> joints[X/Y/Z/B/C]

关键输入包括:

  • X/Y/Z/B/C 指令位姿
  • B 轴角度
  • C 轴角度
  • x-offset
  • z-offset
  • tool-offset
  • 旋转中心 x/y/z-rot-point
  • conventional-directions

在 coordinated motion 中motion 控制循环调用当前运动学的 inverse将轨迹规划器输出的笛卡尔目标位置转换为 joint 目标。

路径为:

trajectory planner
  -> emcmotStatus->carte_pos_cmd
  -> kinematicsInverse()
  -> xyzbcKinematicsInverse()
  -> joint.N.coarse_pos
  -> joint.N.motor-pos-cmd
  -> 仿真 PID/mux
  -> joint.N.motor-pos-fb

反馈/状态更新时则通过 forward

joint feedback/cmd
  -> kinematicsForward()
  -> xyzbcKinematicsForward()
  -> 当前 XYZBC 位姿

7. Vismach 可视化模型

INI 中启动 Vismach

loadusr -W xyzbc-trt-gui

对应文件:

bin/xyzbc-trt-gui
src/hal/user_comps/vismach/xyzbc-trt-gui.py

xyzbc-trt-gui.py 创建 HAL 用户组件:

c = hal.component("xyzbc-trt-gui")

并创建输入 pin

  • table-x
  • saddle-y
  • spindle-z
  • tilt-b
  • rotate-c
  • z-offset
  • x-offset
  • tool-offset

INI 中连接为:

net :table-x   joint.0.pos-fb xyzbc-trt-gui.table-x
net :saddle-y  joint.1.pos-fb xyzbc-trt-gui.saddle-y
net :spindle-z joint.2.pos-fb xyzbc-trt-gui.spindle-z
net :tilt-b    joint.3.pos-fb xyzbc-trt-gui.tilt-b
net :rotate-c  joint.4.pos-fb xyzbc-trt-gui.rotate-c

因此 Vismach 显示的是 joint 反馈,不是直接显示 G-code 坐标。

偏置和刀长补偿也传给 Vismach

net :tool-offset xyzbc-trt-kins.tool-offset xyzbc-trt-gui.tool-offset
net :x-offset    xyzbc-trt-kins.x-offset    xyzbc-trt-gui.x-offset
net :z-offset    xyzbc-trt-kins.z-offset    xyzbc-trt-gui.z-offset

这样三维模型的几何位置和运动学计算使用同一组偏置。

8. PyVCP 面板与按钮

AXIS 根据:

[DISPLAY]
PYVCP = ./xyzbc-trt.xml

加载:

configs/sim/axis/vismach/5axis/table-rotary-tilting/xyzbc-trt.xml

该 XML 创建一个 SWITCHKINS 面板,包含:

  • 多状态标签:0:IDENTITY1: XYZBC2: USERK
  • 按钮 IDENTITY
  • 按钮 TCP:XYZBC
  • 按钮 userk
  • 按钮 vismach-clear

AXIS 创建 PyVCP 组件后,再执行:

[HAL]
POSTGUI_HALFILE = switchkins_postgui.hal

对应文件:

configs/sim/axis/vismach/5axis/table-rotary-tilting/switchkins_postgui.hal

其中连接:

net :kinstype.is-0 <= kinstype.is-0 => pyvcp.multilabel.0.legend0
net :kinstype.is-1 <= kinstype.is-1 => pyvcp.multilabel.0.legend1
net :kinstype.is-2 <= kinstype.is-2 => pyvcp.multilabel.0.legend2

net :type0-button <= pyvcp.type0-button => halui.mdi-command-00
net :type1-button <= pyvcp.type1-button => halui.mdi-command-01
net :type2-button <= pyvcp.type2-button => halui.mdi-command-02

INI 中 [HALUI] 配置为:

MDI_COMMAND = M429
MDI_COMMAND = M428
MDI_COMMAND = M430

所以按钮和运动学类型的实际关系是:

  • IDENTITY -> halui.mdi-command-00 -> M429 -> type 0
  • TCP:XYZBC -> halui.mdi-command-01 -> M428 -> type 1
  • userk -> halui.mdi-command-02 -> M430 -> type 2

9. M428/M429/M430 切换链路

remap 子程序位于:

configs/sim/axis/vismach/5axis/table-rotary-tilting/remap_subs/428remap.ngc
configs/sim/axis/vismach/5axis/table-rotary-tilting/remap_subs/429remap.ngc
configs/sim/axis/vismach/5axis/table-rotary-tilting/remap_subs/430remap.ngc

由于本配置使用 sparm=identityfirst,实际映射为:

  • M429#<kinstype> = 0identity
  • M428#<kinstype> = 1xyzbc TRT
  • M430#<kinstype> = 2userk

M428 为例,428remap.ngc 中核心语句为:

#<kinstype> = 1
#<SWITCHKINS_PIN> = 3
M68 E#<SWITCHKINS_PIN> Q#<kinstype>
M66 E0 L0

实际等价于:

M68 E3 Q1
M66 E0 L0

M68 E3 Q1 设置 motion.analog-out-03 = 1

INI 已连接:

net :kinstype-select <= motion.analog-out-03 => motion.switchkins-type

因此完整切换路径为:

PyVCP button
  -> halui.mdi-command-01
  -> M428
  -> 428remap.ngc
  -> M68 E3 Q1
  -> motion.analog-out-03 = 1
  -> motion.switchkins-type = 1
  -> motion servo thread 检测到变化
  -> handle_kinematicsSwitch()
  -> kinematicsSwitch(1)
  -> 激活 xyzbc TRT kinematics

M66 E0 L0 用于强制解释器和 motion 同步,确保后续 G-code 在切换后的运动学类型下执行。

10. motion 伺服周期中的 switchkins 处理

motion 控制循环位于:

src/emc/motion/control.c

每个 servo cycle 中会执行:

read_homing_in_pins(ALL_JOINTS);
handle_kinematicsSwitch();
process_inputs();
do_forward_kins();
...
get_pos_cmds(period);
...
output_to_hal();

handle_kinematicsSwitch() 的逻辑:

  1. 如果当前运动学不可切换,直接返回。
  2. 读取 motion.switchkins-type
  3. 如果值没变,直接返回。
  4. 如果值变化,调用 kinematicsSwitch(new_type)
  5. 用当前 joint 位置做一次 forward kinematics。
  6. 更新 emcmotStatus->carte_pos_cmd
  7. 更新 trajectory planner 当前位姿。

这一步很重要切换运动学时LinuxCNC 会用当前 joint 位置重新计算新的笛卡尔位置,避免轨迹规划器还停留在旧运动学解释下的位置。

11. M68 到 motion analog output 的路径

M68 在解释器中被转换为设置 analog output 的 canonical command。

源码路径:

src/emc/rs274ngc/interp_convert.cc
src/emc/task/emccanon.cc
src/emc/task/taskintf.cc
src/emc/motion/command.c

核心过程:

  1. interp_convert.cc 识别 M68 E... Q...
  2. 调用 SET_AUX_OUTPUT_VALUE(index, value)
  3. emccanon.cc 生成 EMC_MOTION_SET_AOUT
  4. task 层调用 emcMotionSetAout()
  5. motion 收到 EMCMOT_SET_AOUT
  6. emcmotAioWrite(index, value) 写入 motion.analog-out-XX

本配置中 index 为 3所以写入

motion.analog-out-03

再通过 HAL net 传给:

motion.switchkins-type

12. 演示 G-code 执行过程

AXIS 启动后自动打开:

configs/sim/axis/vismach/5axis/table-rotary-tilting/demos/xyzbc_switchkins.ngc

该文件内容很短:

o<xyzbc_switchkins_sub> call [10] [5] [10][1000][3][0][20][45][20]
m2

它调用:

configs/sim/axis/vismach/5axis/table-rotary-tilting/remap_subs/xyzbc_switchkins_sub.ngc

参数含义:

  • zmax = 10
  • zmin = 5
  • r = 10
  • frate = 1000
  • n = 3
  • a = 0
  • b = 20
  • c = 45
  • dist = 20

xyzbc_switchkins_sub.ngc 在四个象限重复类似流程:

M429
G53 G0 X0 Y0 Z#<zmax> B0 C0
G10 L20 P0 X0 Y0 Z#<zmax> B0 C0
G0 X... Y... Z#<zmax>
o<helix_bc> call [...]

也就是:

  1. M429 切到 identity。
  2. G53 在机床坐标中移动到安全位置。
  3. G10 L20 P0 重设当前工件坐标系。
  4. 移动到当前象限的加工中心。
  5. 调用 helix_bc

helix_bc.ngc 的核心流程为:

M429
G0 X[#<_x> - #<r>]
G10 L20 P0 X0 Y0 Z#<zmax> B0 C0
M428
G0 B#<b> C#<c>
F#<frate> G2 I#<r> Z#<zmin> P#<n>
M429
G0 X0 Y0 Z#<zmax> B0 C0
G0 X[#<_x> + #<r>]
M428

含义:

  1. 先切回 identity方便做直观的定位和坐标系设置。
  2. 调整 X 到圆弧起点。
  3. 重设 G54。
  4. M428 切换到 xyzbc TRT 运动学。
  5. 移动 B/C 到指定角度。
  6. 执行带 Z 下降的 G2 ... P#<n> 螺旋插补。
  7. 切回 identity回到安全位置。
  8. 最后再次切到 xyzbc保持显示/演示状态。

13. 运行时数据流总览

启动阶段:

desktop/rip-environment
  -> scripts/linuxcnc
  -> linuxcncsvr
  -> realtime/HAL
  -> milltask
  -> halui
  -> basic_sim.tcl
  -> loadrt xyzbc-trt-kins sparm=identityfirst
  -> loadrt motmod num_joints=5
  -> HALCMD loadusr -W xyzbc-trt-gui
  -> axis GUI
  -> PyVCP
  -> switchkins_postgui.hal

切换运动学:

PyVCP button 或 G-code M428/M429/M430
  -> remap ngc
  -> M68 E3 Q<type>
  -> motion.analog-out-03
  -> motion.switchkins-type
  -> handle_kinematicsSwitch()
  -> kinematicsSwitch(type)

加工运动:

G-code XYZBC
  -> interpreter
  -> task
  -> trajectory planner
  -> emcmotStatus->carte_pos_cmd
  -> kinematicsInverse()
  -> xyzbcKinematicsInverse() 或 identityKinematicsInverse()
  -> joint.N.motor-pos-cmd
  -> pid/mux 仿真闭环
  -> joint.N.motor-pos-fb
  -> Vismach 显示

反馈显示:

joint.N.pos-fb
  -> xyzbc-trt-gui table/saddle/spindle/tilt/rotate pins
  -> Vismach 三维模型

kinstype.is-N
  -> pyvcp.multilabel
  -> SWITCHKINS 面板显示当前类型

14. 关键结论

该仿真不是简单的五个独立轴显示程序,而是一个完整的 switchkins 示例:

  1. 启动默认是 identity kinematics因为 sparm=identityfirst
  2. M429 选择 identityswitchkins-type 0
  3. M428 选择 xyzbc TRTswitchkins-type 1
  4. M430 选择 userkswitchkins-type 2
  5. 运动学切换不是按钮直接写运动学模块,而是经过 halui -> MDI -> remap -> M68 -> motion.analog-out-03 -> motion.switchkins-type
  6. xyzbcKinematicsInverse() 是 RTCP/TCP 行为的核心,它根据 XYZBC 指令、B/C 角度、转台偏置和刀长补偿计算 joint 目标。
  7. Vismach 使用 joint feedback 和同一组几何偏置显示机床模型,因此可视化结果跟运动学参数保持一致。
  8. 演示程序通过 identity 与 xyzbc TRT 之间反复切换,展示了在普通机床坐标定位和五轴 TCP 加工之间切换的完整过程。

15. 主要相关文件清单

配置入口:

configs/sim/axis/vismach/5axis/table-rotary-tilting/xyzbc-trt.ini

HAL/GUI

configs/sim/axis/vismach/5axis/table-rotary-tilting/xyzbc-trt.xml
configs/sim/axis/vismach/5axis/table-rotary-tilting/switchkins_postgui.hal
configs/sim/axis/vismach/5axis/table-rotary-tilting/xyzbc-trt_cmds.hal
src/hal/user_comps/vismach/xyzbc-trt-gui.py
bin/xyzbc-trt-gui

G-code/remap

configs/sim/axis/vismach/5axis/table-rotary-tilting/demos/xyzbc_switchkins.ngc
configs/sim/axis/vismach/5axis/table-rotary-tilting/remap_subs/xyzbc_switchkins_sub.ngc
configs/sim/axis/vismach/5axis/table-rotary-tilting/remap_subs/helix_bc.ngc
configs/sim/axis/vismach/5axis/table-rotary-tilting/remap_subs/428remap.ngc
configs/sim/axis/vismach/5axis/table-rotary-tilting/remap_subs/429remap.ngc
configs/sim/axis/vismach/5axis/table-rotary-tilting/remap_subs/430remap.ngc

运动学源码:

src/emc/kinematics/xyzbc-trt-kins.c
src/emc/kinematics/trtfuncs.c
src/emc/kinematics/switchkins.c
src/emc/kinematics/userkfuncs.c
include/kinematics.h

motion/task/interpreter 相关:

src/emc/motion/motion.c
src/emc/motion/control.c
src/emc/motion/command.c
src/emc/rs274ngc/interp_convert.cc
src/emc/task/emccanon.cc
src/emc/task/taskintf.cc

启动脚本和 HAL 库:

scripts/linuxcnc
scripts/rip-environment
lib/hallib/basic_sim.tcl
lib/hallib/sim_lib.tcl

16. 与 LinuxCNC 数据系统核心原理的对应关系

xyzbc-trt 仿真可以看作 LinuxCNC 数据系统的一次完整穿透:从 INI 装配,到 NML 命令,到 task/interpreter到 motion 实时共享内存,到 HAL pin/signal再到 Vismach 显示。

16.1 INI 是装配入口

xyzbc-trt.ini 决定系统启动时要加载的主要对象:

[DISPLAY] DISPLAY = axis
[DISPLAY] PYVCP = ./xyzbc-trt.xml
[DISPLAY] OPEN_FILE = ./demos/xyzbc_switchkins.ngc

[KINS] KINEMATICS = xyzbc-trt-kins sparm=identityfirst
[KINS] JOINTS = 5

[TRAJ] COORDINATES = XYZBC

[HAL] HALFILE = LIB:basic_sim.tcl
[HAL] POSTGUI_HALFILE = switchkins_postgui.hal

INI 本身不做实时控制,它描述“系统应该如何装配”。真正的运行时数据交换由 NML、motion shared memory 和 HAL 完成。

16.2 NML 负责 GUI/halui/task 命令与状态

当用户点击 PyVCP 按钮时,按钮并不直接写 motion.switchkins-type。实际路径是:

PyVCP button
  -> halui.mdi-command-N
  -> halui 通过 NML 发送 MDI 命令
  -> milltask 接收命令
  -> interpreter 执行 M428/M429/M430 remap

这体现了 LinuxCNC 的基本原则GUI 和 halui 表达操作意图task 负责调度和合法性motion 负责实时执行。

16.3 Interpreter/Canonical 层把 M428 转成 motion 能执行的动作

M428 并不是 motion 原生命令,而是 remap 子程序:

M68 E3 Q1
M66 E0 L0

解释器把 M68 E3 Q1 转换为 canonical motion output command最终由 task 发送给 motion

M68 E3 Q1
  -> SET_AUX_OUTPUT_VALUE(3, 1)
  -> EMC_MOTION_SET_AOUT
  -> emcMotionSetAout()
  -> usrmotWriteEmcmotCommand()
  -> realtime motion command shared memory

这说明 G-code 的作用不是直接改 HAL而是通过解释器和 task 进入 motion。

16.4 Motion shared memory 是 task 和实时 motion 的边界

task 写入 emcmot_command_t,实时 motion 读取并执行。motion 每个 servo cycle 更新 emcmot_status_ttask 再把它汇总到 EMC_STAT

xyzbc-trt 中,M68 E3 Q1 最终被 motion 执行为:

motion.analog-out-03 = 1

然后 HAL 连接把这个值传给:

motion.switchkins-type = 1

16.5 HAL 是实时信号网络

本配置最关键的 HAL net 是:

net :kinstype-select <= motion.analog-out-03 => motion.switchkins-type

它的本质是让两个 HAL pin 共享同一个 signal 值:

writer: motion.analog-out-03
signal: :kinstype-select
reader: motion.switchkins-type

servo-thread 中 handle_kinematicsSwitch() 读取 motion.switchkins-type,发现从 0 变成 1 后调用:

kinematicsSwitch(1)

于是当前运动学从 identity 切换到 xyzbc TRT。

16.6 Vismach 是 HAL 数据消费者

Vismach 模型不参与 NML也不参与 motion command 调度。它作为 HAL 用户组件读取 pin

joint.0.pos-fb -> xyzbc-trt-gui.table-x
joint.1.pos-fb -> xyzbc-trt-gui.saddle-y
joint.2.pos-fb -> xyzbc-trt-gui.spindle-z
joint.3.pos-fb -> xyzbc-trt-gui.tilt-b
joint.4.pos-fb -> xyzbc-trt-gui.rotate-c

因此 Vismach 显示的是 HAL 中的 joint feedback 快照,而不是直接读取 G-code 或 motion 内部轨迹队列。

16.7 该配置的数据链总图

INI 装配
  -> basic_sim.tcl 加载 motion/k 等 HAL 模块
  -> AXIS 创建 PyVCP
  -> PyVCP 按钮触发 halui MDI
  -> NML command 到 milltask
  -> interpreter 执行 M428/M429/M430 remap
  -> M68 变成 EMC_MOTION_SET_AOUT
  -> task 写 emcmot_command_t
  -> realtime motion 写 motion.analog-out-03
  -> HAL net 传给 motion.switchkins-type
  -> servo-thread 切换 kinematics
  -> inverse kinematics 生成 joint 目标
  -> 仿真 PID/mux 生成 joint feedback
  -> Vismach 读取 HAL feedback 显示机床
  -> motion status 汇总到 EMC_STAT
  -> AXIS/halui 显示状态

详细通用原理见:

项目分析/LinuxCNC数据系统核心原理.md