将Feature/XP.Common和Feature/XP.Hardware分支合并至Develop/XP.forHardwareAndCommon,完善XPapp注册和相关硬件类库通用类库功能。

This commit is contained in:
QI Mingxuan
2026-04-16 17:31:13 +08:00
parent 6ec4c3ddaa
commit 2bd6e566c3
581 changed files with 74600 additions and 222 deletions
@@ -0,0 +1,520 @@
# 探测器摆动几何计算模型 | Geometry Calculation with Detector Swing
> 文档版本:v1.0
> 创建日期:2026-04-13
> 适用模块:XP.Hardware.MotionControl
---
## 1. 问题背景 | Background
原始几何计算假设射线源(Source)、载物台旋转中心(Stage)、探测器(Detector)三者共线于 Z 轴,使用简单的绝对坐标差值计算 FOD 和 FDD。
但实际系统中,探测器具有摆动轴(DetectorSwing),可在 XZ 平面内绕固定旋转中心(Pivot)旋转。当摆动角度 θ ≠ 0 时,探测器感光面中心偏离 Z 轴,射线束从射线源到探测器的路径不再沿 Z 轴方向,FOD 和 FDD 的定义需要重新考虑。
---
## 2. 物理模型 | Physical Model
### 2.1 坐标系定义 | Coordinate System
- Z 轴:垂直方向(射线源和探测器的主运动方向)
- X 轴:水平方向(探测器摆动平面内的横向)
- 原点:系统参考零点
### 2.2 关键几何元素 | Key Geometry Elements
```
探测器中心 D ● (Dx, Dz)
\
\ R ← 摆动半径(Pivot 到探测器感光面中心的距离)
\
\ θ ← 摆动角度
/
摆动旋转中心 P ● (Px=0, Pz=SwingPivotZ)
|
|
载物台旋转中心 O ● (Ox=0, Oz=StageRotationCenterZ)
|
| ← 射线束中心线(从 S 到 D)
|
射线源 S (Sx=0, Sz=SourceZ_abs)
```
### 2.3 各点坐标 | Point Coordinates
| 点 | X 坐标 | Z 坐标 | 说明 |
|----|--------|--------|------|
| S(射线源)| 0 | `SourceZ_pos + SourceZOrigin` | 射线源始终在 Z 轴上 |
| O(载物台旋转中心)| 0 | `StageRotationCenterZ`(配置固定值)| 载物台平面与 Z 轴的交点 |
| P(摆动旋转中心)| 0 | `SwingPivotZ`(配置固定值)| 探测器摆动的旋转中心,在 Z 轴上 |
| D(探测器感光面中心)| `Dx` | `Dz` | 由摆动角度和半径计算得出 |
### 2.4 探测器中心坐标计算 | Detector Center Coordinate Calculation
摆动角度 θ 定义:θ = 0 时探测器正对射线源(D 在 Z 轴上,P 正上方),正角度为顺时针(向 X 正方向偏转)。
```
Dx = Px + R × sin(θ) = R × sin(θ) (因为 Px = 0
Dz = Pz - R × cos(θ) (探测器感光面在 Pivot 下方,朝向射线源)
```
注意:这里假设 θ=0 时探测器在 Pivot 正下方(朝向射线源方向),Z 轴向上为正。射线源在底部(Z 值小),探测器在顶部(Z 值大),探测器感光面朝下。公式为:
```
Dx = R × sin(θ)
Dz = Pz - R × cos(θ)
```
---
## 3. FOD 和 FDD 的正确定义 | Correct FOD and FDD Definitions
### 3.1 FOD(焦点到物体距离)| Focus-to-Object Distance
FOD 的定义是:射线源焦点到载物台旋转中心的距离,沿射线束中心线方向测量。
但在平面 CT 系统中,更常用的定义是:射线源到载物台旋转中心沿 Z 轴的投影距离(因为载物台是一个平面,射线束穿过载物台平面的位置才是关键)。
**方案 A:沿射线束中心线的 FOD(几何真实距离)**
射线束中心线从 S 到 D,载物台平面在 Z = StageRotationCenterZ 处。FOD 是射线源 S 到射线束与载物台平面交点的距离。
射线束参数方程(从 S 到 D):
```
x(t) = Sx + t × (Dx - Sx) = t × Dx
z(t) = Sz + t × (Dz - Sz)
```
载物台平面在 Z = Oz,求交点时 t:
```
t_stage = (Oz - Sz) / (Dz - Sz)
```
交点坐标:
```
x_intersect = t_stage × Dx
z_intersect = Oz
```
FOD = S 到交点的欧几里得距离:
```
FOD = sqrt((x_intersect - Sx)² + (z_intersect - Sz)²)
= sqrt((t_stage × Dx)² + (Oz - Sz)²)
```
**方案 B:沿 Z 轴的 FOD(简化定义,与原始实现一致)**
```
FOD_z = |Sz - Oz|
```
这是原始实现的方式,不受探测器摆动影响。
### 3.2 FDD(焦点到探测器距离)| Focus-to-Detector Distance
FDD 是射线源焦点到探测器感光面中心的欧几里得距离:
```
FDD = sqrt((Dx - Sx)² + (Dz - Sz)²)
= sqrt((R × sin(θ))² + (Pz - R × cos(θ) - Sz)²)
```
当 θ = 0 时:
```
FDD = |Pz - R - Sz|
```
此时 `Pz - R` 就是探测器感光面中心在 Z 轴上的绝对坐标(Pivot 下方 R 处),与原始公式 `|DetectorZ_abs - SourceZ_abs|` 一致。
### 3.3 放大倍率 | Magnification
```
M = FDD / FOD
```
---
## 4. 推荐方案 | Recommended Approach
### 4.1 采用方案 A(射线束中心线投影)
对于平面 CT 系统,FOD 应该是沿射线束中心线测量的,因为放大倍率 M = FDD / FOD 直接决定了成像的几何放大关系。
### 4.2 正算公式汇总 | Forward Calculation Summary
已知输入:
- `Sz`:射线源 Z 绝对坐标 = SourceZ_pos + SourceZOrigin
- `Pz`:摆动旋转中心 Z 绝对坐标 = SwingPivotZ(配置)
- `R`:摆动半径 = SwingRadius(配置)
- `θ`:探测器摆动角度 = DetectorSwing 实际角度(度)
- `Oz`:载物台旋转中心 Z 绝对坐标 = StageRotationCenterZ(配置)
计算步骤:
```
1. 探测器中心坐标:
Dx = R × sin(θ)
Dz = Pz - R × cos(θ)
2. FDD = sqrt(Dx² + (Dz - Sz)²)
3. 射线束与载物台平面交点参数:
t_stage = (Oz - Sz) / (Dz - Sz)
4. 交点 X 坐标:
x_intersect = t_stage × Dx
5. FOD = sqrt(x_intersect² + (Oz - Sz)²)
6. M = FDD / FOD
```
### 4.3 反算公式汇总 | Inverse Calculation Summary
反算场景:给定目标 FOD 和 FDD(以及当前探测器摆动角度 θ),计算 SourceZ 和 DetectorZ 的目标位置。
**重要约束**:反算时,探测器摆动角度 θ 是已知的当前值(或目标值),不由 FOD/FDD 反算决定。
已知输入:
- `targetFOD`:目标 FOD
- `targetFDD`:目标 FDD
- `θ`:探测器摆动角度(当前值或目标值)
- `Pz``R``Oz`:配置参数
当 θ = 0 时(简化情况,退化为原始公式):
```
Dx = 0, Dz = Pz - R
FOD = |Sz - Oz| → Sz = Oz - targetFOD(射线源在载物台下方)
FDD = |Dz - Sz| → Dz = Sz + targetFDD
DetectorZ_pos = Dz - DetectorZOrigin
```
当 θ ≠ 0 时:
由 FOD 求 SourceZ
```
FOD 的定义涉及射线束方向,而射线束方向取决于 S 和 D 的位置。
D 的位置取决于 DetectorZ(通过 Pz 和 R 和 θ 计算)。
但在本系统中,探测器的 Z 位置由 DetectorZ 轴控制,
而摆动角度 θ 只改变探测器在 XZ 平面内的朝向。
实际上,Pz(摆动旋转中心)的 Z 坐标 = DetectorZ_pos + DetectorZOrigin + PivotOffset
其中 PivotOffset 是从 DetectorZ 轴位置到 Pivot 点的固定偏移。
简化模型:Pivot 的 Z 坐标随 DetectorZ 轴移动。
```
**关键认识**:摆动旋转中心 P 是固定在探测器机械臂上的,它随 DetectorZ 轴一起上下移动。因此:
```
Pz = DetectorZ_pos + DetectorZOrigin + PivotOffsetFromDetectorOrigin
```
其中 `PivotOffsetFromDetectorOrigin` 是一个固定的机械偏移量(配置参数)。
但为了简化,我们可以将 Pivot 的 Z 坐标直接表示为:
```
Pz = DetectorZ_abs + SwingPivotOffset
```
其中 `SwingPivotOffset` 是 Pivot 相对于 DetectorZ 绝对坐标的固定偏移。
探测器感光面中心:
```
Dx = R × sin(θ)
Dz = Pz - R × cos(θ) = DetectorZ_abs + SwingPivotOffset - R × cos(θ)
```
反算步骤:
1. 由 targetFOD 确定 SourceZ
- 当 θ 较小时,FOD ≈ |Sz - Oz|,所以 Sz ≈ Oz - targetFOD
- 精确求解需要迭代(因为 FOD 的定义涉及射线束方向,而射线束方向又取决于 D 的位置)
2. 由 targetFDD 和已知 Sz 确定 DetectorZ
```
FDD² = Dx² + (Dz - Sz)²
= (R × sin(θ))² + (DetectorZ_abs + SwingPivotOffset - R × cos(θ) - Sz)²
```
设 `A = SwingPivotOffset - R × cos(θ)``B = R × sin(θ)`,则:
```
FDD² = B² + (DetectorZ_abs + A - Sz)²
DetectorZ_abs + A - Sz = ±sqrt(FDD² - B²)
DetectorZ_abs = Sz - A + sqrt(FDD² - B²) (取正值,探测器在射线源上方)
```
3. 转换为轴相对坐标:
```
SourceZ_pos = Sz - SourceZOrigin
DetectorZ_pos = DetectorZ_abs - DetectorZOrigin
```
---
## 5. 配置参数完整说明 | Complete Configuration Parameters
所有参数在 `App.config` 的 `<appSettings>` 中配置,键名前缀为 `MotionControl:`。
### 5.1 几何计算相关参数 | Geometry Calculation Parameters
以下参数直接参与 FOD/FDD/放大倍率的计算:
| 参数 | 键名 | 默认值 | 单位 | 说明 |
|------|------|--------|------|------|
| 射线源Z原点偏移 | `Geometry:SourceZOrigin` | 0 | mm | 射线源Z轴的原点偏移。绝对坐标 = 轴位置 + Origin。用于将轴的相对坐标转换为系统绝对坐标 |
| 探测器Z原点偏移 | `Geometry:DetectorZOrigin` | 600 | mm | 探测器Z轴的原点偏移。含义同上。通常设为探测器回零时感光面中心的绝对Z坐标 |
| 载物台旋转中心Z | `Geometry:StageRotationCenterZ` | 300 | mm | 载物台旋转中心的绝对Z坐标(固定值)。载物台平面与Z轴的交点,FOD 的参考基准 |
| 摆动旋转中心偏移 | `Geometry:SwingPivotOffset` | 0 | mm | 探测器摆动旋转中心(Pivot)相对于 DetectorZ 绝对坐标的Z方向偏移。Pivot 在探测器上方(Z 值更大),正值。Pivot 的绝对Z坐标 = DetectorZ_abs + SwingPivotOffset |
| 摆动半径 | `Geometry:SwingRadius` | 0 | mm | Pivot 到探测器感光面中心的距离。当值为 0 时,系统退化为无摆动的简化模型(完全向后兼容) |
参数间的关系:
```
射线源绝对Z坐标 Sz = SourceZ_pos + SourceZOrigin
探测器绝对Z坐标 DetZ_abs = DetectorZ_pos + DetectorZOrigin
摆动旋转中心Z坐标 Pz = DetZ_abs + SwingPivotOffset
探测器感光面中心 Dx = SwingRadius × sin(θ)
Dz = Pz - SwingRadius × cos(θ)
载物台旋转中心 Oz = StageRotationCenterZ(固定值)
```
### 5.2 直线轴配置 | Linear Axis Configuration
每个直线轴包含 3 个参数,键名格式为 `MotionControl:<AxisName>:<Param>`
| 轴名 | Min | Max | Origin | 说明 |
|------|-----|-----|--------|------|
| SourceZ | 0 | 500 | 0 | 射线源Z轴,控制射线源上下运动(mm) |
| DetectorZ | 0 | 600 | 0 | 探测器Z轴,控制探测器上下运动(mm) |
| StageX | -150 | 150 | 0 | 载物台X轴,控制载物台前后运动(mm) |
| StageY | -150 | 150 | 0 | 载物台Y轴,控制载物台左右运动(mm) |
- `Min` / `Max`:轴的软限位范围(相对坐标),超出范围的移动命令会被拒绝
- `Origin`:轴的原点偏移,用于将相对坐标转换为绝对坐标
### 5.3 旋转轴配置 | Rotary Axis Configuration
每个旋转轴包含 4 个参数,键名格式为 `MotionControl:<AxisName>:<Param>`
| 轴名 | Min | Max | Origin | Enabled | 说明 |
|------|-----|-----|--------|---------|------|
| DetectorSwing | -45 | 45 | 0 | true | 探测器摆动轴,在XZ平面内旋转(度) |
| StageRotation | -360 | 360 | 0 | true | 载物台旋转轴,绕Z轴旋转(度) |
| FixtureRotation | -90 | 90 | 0 | true | 夹具旋转轴,可选配置(度) |
- `Enabled`:是否启用该旋转轴,`false` 时 UI 隐藏且拒绝所有命令
### 5.4 运行参数 | Runtime Parameters
| 参数 | 键名 | 默认值 | 单位 | 说明 |
|------|------|--------|------|------|
| 轮询周期 | `MotionControl:PollingInterval` | 100 | ms | PLC 状态轮询周期,每个周期读取所有轴位置并重新计算几何参数 |
| 默认速度 | `MotionControl:DefaultVelocity` | 500 | - | 未指定速度时使用的默认运动速度 |
---
## 5.5 实际设备配置示例 | Real Device Configuration Example
以下是一个典型平面CT设备的配置示例和测量方法。
### 设备物理布局
假设设备的实际机械尺寸如下:
```
Z=1000mm (顶部)
┃ DetectorZ 轴行程 0~800mm
┃ 探测器回零时 DetectorZ 绝对坐标在 Z=500mm 处
┃ |
┃ D | 探测器感光面中心(朝下,面向射线源)
┃ ● |
┃ \θ |
┃ \ | R=200mm
┃ \ |
┃ \|
┃ ● P 摆动旋转中心 (Z=580mm,随 DetectorZ 移动)
┃ |
┃ |
┃ ● O 载物台旋转中心 (Z=350mm,固定)
┃ |
┃ |
┃ |
┃ ● S 射线源焦点 (Z=50mm,即 SourceZ_pos=0 时)
┃ SourceZ 轴行程 0~500mm
┃ 射线源回零时焦点在 Z=50mm 处
Z=0mm (底部)
```
### 测量方法
1. **SourceZOrigin(射线源原点偏移)**
- 将射线源移动到回零位置(SourceZ_pos = 0
- 测量此时射线源焦点的绝对Z坐标 → 即为 SourceZOrigin
- 本例:焦点在 Z=50mm → `SourceZOrigin = 50`
2. **DetectorZOrigin(探测器原点偏移)**
- 将探测器移动到回零位置(DetectorZ_pos = 0
- 测量此时探测器Z轴参考点的绝对Z坐标 → 即为 DetectorZOrigin
- 本例:参考点在 Z=500mm → `DetectorZOrigin = 500`
3. **StageRotationCenterZ(载物台旋转中心Z坐标)**:
- 测量载物台旋转中心的绝对Z坐标(固定值,由机械结构决定)
- 本例:Z=350mm → `StageRotationCenterZ = 350`
4. **SwingPivotOffset(摆动旋转中心偏移)**:
- 将探测器移动到回零位置,此时 DetectorZ_abs = 0 + 500 = 500mm
- 测量摆动旋转中心(Pivot)的绝对Z坐标 → 本例 Z=580mm
- SwingPivotOffset = Pz - DetectorZ_abs = 580 - 500 = 80mm
- `SwingPivotOffset = 80`
- 注意:Pivot 随 DetectorZ 轴一起移动,此偏移是固定的机械常数
5. **SwingRadius(摆动半径)**
- 测量 Pivot 到探测器感光面中心的距离(固定值,由机械臂长度决定)
- 本例:200mm → `SwingRadius = 200`
### 对应的 App.config 配置
```xml
<!-- 直线轴配置 -->
<add key="MotionControl:SourceZ:Min" value="0" />
<add key="MotionControl:SourceZ:Max" value="500" />
<add key="MotionControl:SourceZ:Origin" value="0" />
<add key="MotionControl:DetectorZ:Min" value="0" />
<add key="MotionControl:DetectorZ:Max" value="800" />
<add key="MotionControl:DetectorZ:Origin" value="0" />
<add key="MotionControl:StageX:Min" value="-150" />
<add key="MotionControl:StageX:Max" value="150" />
<add key="MotionControl:StageX:Origin" value="0" />
<add key="MotionControl:StageY:Min" value="-150" />
<add key="MotionControl:StageY:Max" value="150" />
<add key="MotionControl:StageY:Origin" value="0" />
<!-- 旋转轴配置 -->
<add key="MotionControl:DetectorSwing:Min" value="-45" />
<add key="MotionControl:DetectorSwing:Max" value="45" />
<add key="MotionControl:DetectorSwing:Origin" value="0" />
<add key="MotionControl:DetectorSwing:Enabled" value="true" />
<add key="MotionControl:StageRotation:Min" value="-360" />
<add key="MotionControl:StageRotation:Max" value="360" />
<add key="MotionControl:StageRotation:Origin" value="0" />
<add key="MotionControl:StageRotation:Enabled" value="true" />
<add key="MotionControl:FixtureRotation:Min" value="-90" />
<add key="MotionControl:FixtureRotation:Max" value="90" />
<add key="MotionControl:FixtureRotation:Origin" value="0" />
<add key="MotionControl:FixtureRotation:Enabled" value="false" />
<!-- 几何参数 -->
<add key="MotionControl:Geometry:SourceZOrigin" value="50" />
<add key="MotionControl:Geometry:DetectorZOrigin" value="500" />
<add key="MotionControl:Geometry:StageRotationCenterZ" value="350" />
<add key="MotionControl:Geometry:SwingPivotOffset" value="80" />
<add key="MotionControl:Geometry:SwingRadius" value="200" />
<!-- 运行参数 -->
<add key="MotionControl:PollingInterval" value="100" />
<add key="MotionControl:DefaultVelocity" value="500" />
```
### 验证计算
以上述配置为例,当 SourceZ_pos=100, DetectorZ_pos=200, θ=15° 时:
```
Sz = 100 + 50 = 150mm (射线源绝对Z,底部)
DetZ_abs = 200 + 500 = 700mm (探测器绝对Z,顶部)
Pz = 700 + 80 = 780mm (Pivot 绝对Z,探测器上方)
Dx = 200 × sin(15°) = 200 × 0.2588 = 51.76mm (探测器中心X偏移)
Dz = 780 - 200 × cos(15°) = 780 - 193.19 = 586.81mm (探测器感光面中心ZPivot 下方)
FDD = sqrt(51.76² + (586.81 - 150)²)
= sqrt(2679.1 + 190,729.5)
= sqrt(193,408.6)
≈ 439.78mm
射线束与载物台平面交点参数:
t_stage = (350 - 150) / (586.81 - 150) = 200 / 436.81 = 0.4579
x_intersect = 0.4579 × 51.76 = 23.70mm
FOD = sqrt(23.70² + 200²)
= sqrt(561.7 + 40000)
= sqrt(40561.7)
≈ 201.40mm
M = FDD / FOD = 439.78 / 201.40 ≈ 2.183
对比 θ=0 时(同样轴位置):
Dx = 0, Dz = 780 - 200 = 580mm
FDD_0 = |150 - 580| = 430mm
FOD_0 = |150 - 350| = 200mm
M_0 = 430 / 200 = 2.15
可以看到 θ=15° 时 FDD 略大(439.78 vs 430),FOD 略大(201.40 vs 200),
放大倍率从 2.15 升为 2.183。这是因为摆动使探测器感光面中心在 X 方向偏移,
增加了射线源到探测器的欧几里得距离。
```
---
## 6. 几何示意图 | Geometry Diagram
### 6.1 θ = 0(无摆动,退化为原始模型)
```
D ●─────────────────── 探测器感光面中心 (Z = Pz - R)
|
| R(摆动半径)
|
P ●─────────────────── 摆动旋转中心 (Z = Pz = DetZ_abs + Offset)
|
|
O ●─────────────────── 载物台旋转中心 (Z = Oz)
|
| FOD = |Sz - Oz|
|
S ●─────────────────── 射线源 (Z = Sz)
FDD = |Sz - (Pz - R)| = |Sz - Dz|
```
### 6.2 θ ≠ 0(有摆动)
```
D ●────/──────────── 探测器感光面中心 (Dx, Dz)
/ /
/θ /
/ /
P ●────/──────────────── 摆动旋转中心 (0, Pz)
| /
| / 射线束与载物台平面的交点 I (x_i, Oz)
O ●──/────────────────── 载物台旋转中心 (0, Oz)
| /
| / ← 射线束中心线
| /
|/
S ●─────────────────── 射线源 (0, Sz)
Dx = R × sin(θ)
Dz = Pz - R × cos(θ)
FDD = sqrt(Dx² + (Dz - Sz)²)
FOD = sqrt(x_i² + (Oz - Sz)²)
其中 x_i = Dx × (Oz - Sz) / (Dz - Sz)
```
---
## 7. 特殊情况处理 | Edge Cases
| 情况 | 处理方式 |
|------|----------|
| θ = 0 | 退化为原始公式,Dx = 0FDD = \|Dz - Sz\| |
| SwingRadius = 0 | 完全退化为原始模型(无摆动影响) |
| FOD ≈ 0 | 放大倍率返回 NaN(与原始行为一致) |
| Dz = Sz | FDD 方向水平,t_stage 无穷大,FOD 计算需要特殊处理 |
| FDD < \|R × sin(θ)\| | 反算时 sqrt 内为负数,目标不可达,返回错误 |
---
**最后更新 | Last Updated**: 2026-04-14