883 lines
21 KiB
Markdown
883 lines
21 KiB
Markdown
# 5axis-xyzbc-trt-sim 执行过程分析
|
||
|
||
本文分析当前 LinuxCNC 源码树中 `5axis-xyzbc-trt-sim` 对应的仿真配置。实际入口配置文件为:
|
||
|
||
```text
|
||
configs/sim/axis/vismach/5axis/table-rotary-tilting/xyzbc-trt.ini
|
||
```
|
||
|
||
该配置是一个 `axis` GUI + `basic_sim.tcl` 仿真 HAL + `xyzbc-trt-kins` 可切换运动学 + PyVCP/halui 控制面板 + Vismach 三维模型的五轴转台仿真。
|
||
|
||
## 1. 启动入口
|
||
|
||
如果从项目中已有快捷方式启动,入口文件是:
|
||
|
||
```text
|
||
linuxcnc-rtcp-5axis-shortcuts/table-rotary-tilting/xyzbc-trt.desktop
|
||
```
|
||
|
||
其中的执行命令为:
|
||
|
||
```bash
|
||
/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. 加载 `tpmod`、`homemod`。
|
||
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 核心配置
|
||
|
||
目标配置文件:
|
||
|
||
```text
|
||
configs/sim/axis/vismach/5axis/table-rotary-tilting/xyzbc-trt.ini
|
||
```
|
||
|
||
关键内容:
|
||
|
||
```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 中:
|
||
|
||
```ini
|
||
[HAL]
|
||
HALFILE = LIB:basic_sim.tcl
|
||
```
|
||
|
||
对应文件:
|
||
|
||
```text
|
||
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-handler` 和 `motion-controller` 加入 `servo-thread`。
|
||
4. 为每个 joint 创建 `pid`。
|
||
5. 为每个 joint 创建 `mux2`。
|
||
6. 将 `joint.N.motor-pos-cmd` 经由 `pid`、`mux2` 接回 `joint.N.motor-pos-fb`,形成理想伺服仿真闭环。
|
||
7. 加载仿真回零、仿真主轴、手动换刀等用户态/实时组件。
|
||
|
||
运行后可生成等效 HAL 文件:
|
||
|
||
```text
|
||
configs/sim/axis/vismach/5axis/table-rotary-tilting/xyzbc-trt_cmds.hal
|
||
```
|
||
|
||
其中关键 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 的典型连接形态为:
|
||
|
||
```hal
|
||
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 初始化
|
||
|
||
运动学源码入口:
|
||
|
||
```text
|
||
src/emc/kinematics/xyzbc-trt-kins.c
|
||
src/emc/kinematics/switchkins.c
|
||
src/emc/kinematics/trtfuncs.c
|
||
```
|
||
|
||
`xyzbc-trt-kins.c` 的 `switchkinsSetup()` 根据 `sparm` 配置三套运动学函数。
|
||
|
||
因为 INI 使用:
|
||
|
||
```ini
|
||
KINEMATICS = xyzbc-trt-kins sparm=identityfirst
|
||
```
|
||
|
||
所以实际类型顺序为:
|
||
|
||
- `switchkins-type 0`:identity kinematics
|
||
- `switchkins-type 1`:xyzbc TRT kinematics
|
||
- `switchkins-type 2`:userk 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()` 位于:
|
||
|
||
```text
|
||
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 中对这些参数的设置和连接为:
|
||
|
||
```hal
|
||
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
|
||
```
|
||
|
||
因此实际计算中:
|
||
|
||
```text
|
||
dx = x-offset = -20
|
||
dz = z-offset + tool-offset
|
||
```
|
||
|
||
`tool-offset` 来自 `motion.tooloffset.z`,也就是 LinuxCNC 当前刀长补偿的 Z 分量。
|
||
|
||
## 6. xyzbc 正/逆运动学
|
||
|
||
`xyzbcKinematicsForward()` 位于:
|
||
|
||
```text
|
||
src/emc/kinematics/trtfuncs.c
|
||
```
|
||
|
||
它从 joint 坐标计算当前笛卡尔位姿:
|
||
|
||
```text
|
||
joints[X/Y/Z/B/C] -> EmcPose XYZBC
|
||
```
|
||
|
||
`xyzbcKinematicsInverse()` 从程序位姿计算 joint 目标:
|
||
|
||
```text
|
||
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 目标。
|
||
|
||
路径为:
|
||
|
||
```text
|
||
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:
|
||
|
||
```text
|
||
joint feedback/cmd
|
||
-> kinematicsForward()
|
||
-> xyzbcKinematicsForward()
|
||
-> 当前 XYZBC 位姿
|
||
```
|
||
|
||
## 7. Vismach 可视化模型
|
||
|
||
INI 中启动 Vismach:
|
||
|
||
```hal
|
||
loadusr -W xyzbc-trt-gui
|
||
```
|
||
|
||
对应文件:
|
||
|
||
```text
|
||
bin/xyzbc-trt-gui
|
||
src/hal/user_comps/vismach/xyzbc-trt-gui.py
|
||
```
|
||
|
||
`xyzbc-trt-gui.py` 创建 HAL 用户组件:
|
||
|
||
```python
|
||
c = hal.component("xyzbc-trt-gui")
|
||
```
|
||
|
||
并创建输入 pin:
|
||
|
||
- `table-x`
|
||
- `saddle-y`
|
||
- `spindle-z`
|
||
- `tilt-b`
|
||
- `rotate-c`
|
||
- `z-offset`
|
||
- `x-offset`
|
||
- `tool-offset`
|
||
|
||
INI 中连接为:
|
||
|
||
```hal
|
||
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:
|
||
|
||
```hal
|
||
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 根据:
|
||
|
||
```ini
|
||
[DISPLAY]
|
||
PYVCP = ./xyzbc-trt.xml
|
||
```
|
||
|
||
加载:
|
||
|
||
```text
|
||
configs/sim/axis/vismach/5axis/table-rotary-tilting/xyzbc-trt.xml
|
||
```
|
||
|
||
该 XML 创建一个 `SWITCHKINS` 面板,包含:
|
||
|
||
- 多状态标签:`0:IDENTITY`、`1: XYZBC`、`2: USERK`
|
||
- 按钮 `IDENTITY`
|
||
- 按钮 `TCP:XYZBC`
|
||
- 按钮 `userk`
|
||
- 按钮 `vismach-clear`
|
||
|
||
AXIS 创建 PyVCP 组件后,再执行:
|
||
|
||
```ini
|
||
[HAL]
|
||
POSTGUI_HALFILE = switchkins_postgui.hal
|
||
```
|
||
|
||
对应文件:
|
||
|
||
```text
|
||
configs/sim/axis/vismach/5axis/table-rotary-tilting/switchkins_postgui.hal
|
||
```
|
||
|
||
其中连接:
|
||
|
||
```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]` 配置为:
|
||
|
||
```ini
|
||
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 子程序位于:
|
||
|
||
```text
|
||
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> = 0`,identity
|
||
- `M428`:`#<kinstype> = 1`,xyzbc TRT
|
||
- `M430`:`#<kinstype> = 2`,userk
|
||
|
||
以 `M428` 为例,`428remap.ngc` 中核心语句为:
|
||
|
||
```ngc
|
||
#<kinstype> = 1
|
||
#<SWITCHKINS_PIN> = 3
|
||
M68 E#<SWITCHKINS_PIN> Q#<kinstype>
|
||
M66 E0 L0
|
||
```
|
||
|
||
实际等价于:
|
||
|
||
```ngc
|
||
M68 E3 Q1
|
||
M66 E0 L0
|
||
```
|
||
|
||
`M68 E3 Q1` 设置 `motion.analog-out-03 = 1`。
|
||
|
||
INI 已连接:
|
||
|
||
```hal
|
||
net :kinstype-select <= motion.analog-out-03 => motion.switchkins-type
|
||
```
|
||
|
||
因此完整切换路径为:
|
||
|
||
```text
|
||
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 控制循环位于:
|
||
|
||
```text
|
||
src/emc/motion/control.c
|
||
```
|
||
|
||
每个 servo cycle 中会执行:
|
||
|
||
```c
|
||
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。
|
||
|
||
源码路径:
|
||
|
||
```text
|
||
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,所以写入:
|
||
|
||
```text
|
||
motion.analog-out-03
|
||
```
|
||
|
||
再通过 HAL net 传给:
|
||
|
||
```text
|
||
motion.switchkins-type
|
||
```
|
||
|
||
## 12. 演示 G-code 执行过程
|
||
|
||
AXIS 启动后自动打开:
|
||
|
||
```text
|
||
configs/sim/axis/vismach/5axis/table-rotary-tilting/demos/xyzbc_switchkins.ngc
|
||
```
|
||
|
||
该文件内容很短:
|
||
|
||
```ngc
|
||
o<xyzbc_switchkins_sub> call [10] [5] [10][1000][3][0][20][45][20]
|
||
m2
|
||
```
|
||
|
||
它调用:
|
||
|
||
```text
|
||
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` 在四个象限重复类似流程:
|
||
|
||
```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` 的核心流程为:
|
||
|
||
```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. 运行时数据流总览
|
||
|
||
启动阶段:
|
||
|
||
```text
|
||
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
|
||
```
|
||
|
||
切换运动学:
|
||
|
||
```text
|
||
PyVCP button 或 G-code M428/M429/M430
|
||
-> remap ngc
|
||
-> M68 E3 Q<type>
|
||
-> motion.analog-out-03
|
||
-> motion.switchkins-type
|
||
-> handle_kinematicsSwitch()
|
||
-> kinematicsSwitch(type)
|
||
```
|
||
|
||
加工运动:
|
||
|
||
```text
|
||
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 显示
|
||
```
|
||
|
||
反馈显示:
|
||
|
||
```text
|
||
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` 选择 identity,即 `switchkins-type 0`。
|
||
3. `M428` 选择 xyzbc TRT,即 `switchkins-type 1`。
|
||
4. `M430` 选择 userk,即 `switchkins-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. 主要相关文件清单
|
||
|
||
配置入口:
|
||
|
||
```text
|
||
configs/sim/axis/vismach/5axis/table-rotary-tilting/xyzbc-trt.ini
|
||
```
|
||
|
||
HAL/GUI:
|
||
|
||
```text
|
||
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:
|
||
|
||
```text
|
||
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
|
||
```
|
||
|
||
运动学源码:
|
||
|
||
```text
|
||
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 相关:
|
||
|
||
```text
|
||
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 库:
|
||
|
||
```text
|
||
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` 决定系统启动时要加载的主要对象:
|
||
|
||
```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`。实际路径是:
|
||
|
||
```text
|
||
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 子程序:
|
||
|
||
```ngc
|
||
M68 E3 Q1
|
||
M66 E0 L0
|
||
```
|
||
|
||
解释器把 `M68 E3 Q1` 转换为 canonical motion output command,最终由 task 发送给 motion:
|
||
|
||
```text
|
||
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_t`,task 再把它汇总到 `EMC_STAT`。
|
||
|
||
在 `xyzbc-trt` 中,`M68 E3 Q1` 最终被 motion 执行为:
|
||
|
||
```text
|
||
motion.analog-out-03 = 1
|
||
```
|
||
|
||
然后 HAL 连接把这个值传给:
|
||
|
||
```text
|
||
motion.switchkins-type = 1
|
||
```
|
||
|
||
### 16.5 HAL 是实时信号网络
|
||
|
||
本配置最关键的 HAL net 是:
|
||
|
||
```hal
|
||
net :kinstype-select <= motion.analog-out-03 => motion.switchkins-type
|
||
```
|
||
|
||
它的本质是让两个 HAL pin 共享同一个 signal 值:
|
||
|
||
```text
|
||
writer: motion.analog-out-03
|
||
signal: :kinstype-select
|
||
reader: motion.switchkins-type
|
||
```
|
||
|
||
servo-thread 中 `handle_kinematicsSwitch()` 读取 `motion.switchkins-type`,发现从 0 变成 1 后调用:
|
||
|
||
```text
|
||
kinematicsSwitch(1)
|
||
```
|
||
|
||
于是当前运动学从 identity 切换到 xyzbc TRT。
|
||
|
||
### 16.6 Vismach 是 HAL 数据消费者
|
||
|
||
Vismach 模型不参与 NML,也不参与 motion command 调度。它作为 HAL 用户组件读取 pin:
|
||
|
||
```hal
|
||
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 该配置的数据链总图
|
||
|
||
```text
|
||
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 显示状态
|
||
```
|
||
|
||
详细通用原理见:
|
||
|
||
```text
|
||
项目分析/LinuxCNC数据系统核心原理.md
|
||
```
|