41e056f85c
[XP.Hardware.MotionControl] README 文档目录树补齐全部文档条目并加入 CoordinateCompensation.md
361 lines
16 KiB
Markdown
361 lines
16 KiB
Markdown
# 像素-载物台映射子模块 | Pixel-to-Stage Mapping Submodule
|
||
|
||
> 文档版本:v2.0
|
||
> 创建日期:2026-06-30
|
||
> 更新日期:2026-07-01
|
||
> 适用模块:XP.Hardware.MotionControl / Calibration
|
||
|
||
---
|
||
|
||
## 1. 概述 | Overview
|
||
|
||
本子模块建立**图像像素坐标**与**载物台物理运动距离**之间的映射关系,使系统能够根据当前放大倍率,将图像上的像素偏移量转换为载物台的实际运动距离(mm)。
|
||
|
||
### 1.1 推荐方式:基于几何配置直接计算(v2.0 新增)
|
||
|
||
核心公式:
|
||
|
||
```
|
||
mmPerPixelX = DetectorPixelSizeX / M
|
||
mmPerPixelY = DetectorPixelSizeY / M
|
||
```
|
||
|
||
其中:
|
||
- `DetectorPixelSizeX`:探测器单像素 X 方向物理尺寸(mm),由探测器硬件规格决定,配置在 App.config 中
|
||
- `DetectorPixelSizeY`:探测器单像素 Y 方向物理尺寸(mm),通常与 X 相同(正方形像素)
|
||
- `M`:当前放大倍率(Magnification),由 FDD / FOD 实时计算得出(参见 GeometryWithDetectorSwing.md)
|
||
|
||
**原理说明**:探测器感光面上每个像素对应固定的物理尺寸(如 0.139mm),经过锥束放大后,载物台平面上每个像素对应的实际物理尺寸 = 像素物理尺寸 / 放大比。这是纯几何关系,无需标定即可直接计算。
|
||
|
||
**优势**:
|
||
- 无需手动标定流程,配置一次即可使用
|
||
- 放大比变化时自动适配(因为 M 是实时计算的)
|
||
- 精度取决于机构精度(FOD/FDD 的准确性),对于大多数定位应用已足够
|
||
|
||
### 1.2 已废弃方式:手动标定向导
|
||
|
||
旧方式通过两点标定求取标定常数 K,公式为 `mmPerPixel = K / M`。该方式已标记为 `[Obsolete]`,代码保留用于向后兼容,但不再推荐使用。
|
||
|
||
当 `DetectorPixelSizeX` 配置为 0 或未配置时,系统会自动回退到手动标定数据(如果存在)。
|
||
|
||
典型应用场景:用户在图像上点击某一点,系统计算该点相对图像中心的像素偏移,自动将载物台移动到使该点居中的物理位置。
|
||
|
||
---
|
||
|
||
## 2. 目录结构 | Directory Structure
|
||
|
||
```
|
||
XP.Hardware.MotionControl/Calibration/
|
||
├── Interfaces/ # 服务接口定义 | Service interfaces
|
||
│ └── IMagnificationCalibrationService.cs
|
||
├── Models/ # 数据模型(已废弃的标定数据)| Data models (deprecated)
|
||
│ └── MagnificationCalibrationData.cs
|
||
├── Implementations/ # 服务实现 | Service implementations
|
||
│ └── MagnificationCalibrationService.cs
|
||
├── ViewModels/ # 向导 ViewModel(已废弃)| Wizard ViewModel (deprecated)
|
||
│ └── CalibrationWizardViewModel.cs
|
||
└── Views/ # 向导窗口(已废弃)| Wizard window (deprecated)
|
||
├── CalibrationWizardWindow.xaml
|
||
└── CalibrationWizardWindow.xaml.cs
|
||
```
|
||
|
||
---
|
||
|
||
## 3. 配置参数 | Configuration
|
||
|
||
在 `App.config` 的 `<appSettings>` 中配置,键名前缀为 `MotionControl:Geometry:`:
|
||
|
||
| 参数 | 键名 | 默认值 | 单位 | 说明 |
|
||
|------|------|--------|------|------|
|
||
| 探测器像素物理尺寸X | `Geometry:DetectorPixelSizeX` | 0.139 | mm | 探测器单像素 X 方向物理尺寸,由探测器规格书获取 |
|
||
| 探测器像素物理尺寸Y | `Geometry:DetectorPixelSizeY` | 0.139 | mm | 探测器单像素 Y 方向物理尺寸,通常与 X 相同 |
|
||
| 像素方向系数X | `Geometry:PixelDirectionX` | 1 | — | 对齐图像 X 轴方向与载物台 X 运动方向(+1 或 -1) |
|
||
| 像素方向系数Y | `Geometry:PixelDirectionY` | -1 | — | 对齐图像 Y 轴方向与载物台 Y 运动方向(+1 或 -1) |
|
||
|
||
### App.config 配置示例
|
||
|
||
```xml
|
||
<!-- 探测器像素物理尺寸(mm)| Detector pixel physical size (mm) -->
|
||
<!-- 用于直接计算像素到载物台距离的映射:mmPerPixel = PixelSize / Magnification -->
|
||
<add key="MotionControl:Geometry:DetectorPixelSizeX" value="0.139" />
|
||
<add key="MotionControl:Geometry:DetectorPixelSizeY" value="0.139" />
|
||
<!-- 像素方向系数:对齐图像像素坐标方向与载物台运动方向(+1 或 -1)| Pixel direction coefficients -->
|
||
<add key="MotionControl:Geometry:PixelDirectionX" value="1" />
|
||
<add key="MotionControl:Geometry:PixelDirectionY" value="-1" />
|
||
```
|
||
|
||
### 如何确定 DetectorPixelSizeX / Y
|
||
|
||
从探测器规格书中获取。例如:
|
||
- Varex 3072×3060 探测器:像素尺寸 0.139mm × 0.139mm
|
||
- 当使用 2×2 Binning 时:等效像素尺寸 0.278mm × 0.278mm
|
||
|
||
**注意**:如果使用了 Binning 模式,需要将像素尺寸乘以 Binning 倍数。
|
||
|
||
### 如何确定 PixelDirectionX / Y
|
||
|
||
实验方法:
|
||
1. 在图像中观察某物体,记下其在图像中的位置(如偏左)
|
||
2. 手动向 X+ 方向移动载物台
|
||
3. 观察物体在图像中的运动方向:
|
||
- 如果物体向图像 X+ 方向移动 → `PixelDirectionX = 1`
|
||
- 如果物体向图像 X- 方向移动 → `PixelDirectionX = -1`
|
||
4. Y 方向同理
|
||
|
||
---
|
||
|
||
## 4. 核心组件 | Core Components
|
||
|
||
### 4.1 IMagnificationCalibrationService(服务接口)
|
||
|
||
| 成员 | 类型 | 说明 |
|
||
|------|------|------|
|
||
| `IsReady` | `bool` (get) | 是否可以进行像素到载物台转换(几何配置有效 或 手动标定已完成) |
|
||
| `IsCalibrated` | `bool` (get) | ⚠️ 已废弃。是否已完成手动标定 |
|
||
| `CurrentData` | `MagnificationCalibrationData` (get) | ⚠️ 已废弃。当前手动标定数据 |
|
||
| `LoadCalibration()` | `bool` | ⚠️ 已废弃。从 JSON 加载手动标定数据 |
|
||
| `SaveCalibration(data)` | `bool` | ⚠️ 已废弃。保存手动标定数据到 JSON |
|
||
| `PixelsToStageMovement(dx, dy, M)` | `(double, double)` | 像素偏移 → 载物台移动距离转换 |
|
||
|
||
### 4.2 转换逻辑优先级 | Conversion Logic Priority
|
||
|
||
```
|
||
PixelsToStageMovement(dxPixels, dyPixels, currentMagnification):
|
||
1. 优先:几何直接计算(当 DetectorPixelSizeX > 0 时)
|
||
mmPerPixelX = DetectorPixelSizeX / M
|
||
mmPerPixelY = DetectorPixelSizeY / M
|
||
stageDx = dxPixels × mmPerPixelX × PixelDirectionX
|
||
stageDy = dyPixels × mmPerPixelY × PixelDirectionY
|
||
|
||
2. 回退:手动标定数据(当几何配置无效且标定文件存在时)
|
||
mmPerPixel = K / M
|
||
stageDx = dxPixels × mmPerPixel × DirectionX
|
||
stageDy = dyPixels × mmPerPixel × DirectionY
|
||
|
||
3. 异常:两者均不可用时抛出 InvalidOperationException
|
||
```
|
||
|
||
### 4.3 MagnificationCalibrationService(服务实现)
|
||
|
||
- 通过构造函数注入 `ILoggerService` 和 `MotionControlConfig`
|
||
- 启动时自动判断使用几何计算模式还是手动标定模式,并输出日志
|
||
- 标定文件路径:`{AppBaseDirectory}/Calibration/MagnificationCalibration.json`(仅作为 fallback)
|
||
- 作为**单例**注册到 `MotionControlModule` 的 DI 容器
|
||
|
||
**异常约定 | Exception Contract**
|
||
|
||
| 条件 | 异常类型 | 说明 |
|
||
|------|----------|------|
|
||
| `IsReady == false` 时调用转换 | `InvalidOperationException` | 几何配置无效且未完成手动标定 |
|
||
| `currentMagnification <= 0` | `ArgumentException` | 放大倍率必须为正数 |
|
||
|
||
---
|
||
|
||
## 5. 关键算法 | Key Algorithms
|
||
|
||
### 5.1 几何直接计算(推荐)| Geometry Direct Calculation (Recommended)
|
||
|
||
```
|
||
stageDx_mm = dxPixels × (DetectorPixelSizeX / M) × PixelDirectionX
|
||
stageDy_mm = dyPixels × (DetectorPixelSizeY / M) × PixelDirectionY
|
||
```
|
||
|
||
**物理意义**:
|
||
- 探测器感光面上每个像素的物理尺寸是固定的(由硬件决定)
|
||
- 锥束投影下,载物台平面上的等效像素尺寸 = 探测器像素尺寸 / 放大比
|
||
- 放大比 M = FDD / FOD,由几何计算器根据当前轴位置实时计算
|
||
|
||
**精度分析**:
|
||
- 假设 DetectorPixelSizeX = 0.139mm(精确值,来自规格书)
|
||
- 放大比 M 的精度取决于 FOD/FDD 的精度(即轴位置 + 几何原点偏移的精度)
|
||
- 若 FOD 有 1mm 误差(500mm 中),放大比相对误差约 0.2%
|
||
- 对于 100mm 视场范围,位置误差约 0.2mm,满足绝大多数定位需求
|
||
|
||
### 5.2 手动标定(已废弃)| Manual Calibration (Deprecated)
|
||
|
||
```
|
||
K = M × FovDistance / DetectorPixelCountX (标定常数计算)
|
||
mmPerPixel = K / currentMagnification (使用时转换)
|
||
```
|
||
|
||
K 本质上就是探测器单像素的物理尺寸(理想情况下 K ≈ DetectorPixelSizeX),手动标定的意义在于:
|
||
- 修正 FOD/FDD 的系统性偏差
|
||
- 补偿探测器实际像素尺寸与标称值的差异
|
||
- 对精度要求极高的场景仍可使用
|
||
|
||
---
|
||
|
||
## 6. 模块集成 | Module Integration
|
||
|
||
在 `MotionControlModule.RegisterTypes` 中注册:
|
||
|
||
```csharp
|
||
// 注册放大比标定服务(单例)| Register magnification calibration service (singleton)
|
||
containerRegistry.RegisterSingleton<IMagnificationCalibrationService, MagnificationCalibrationService>();
|
||
```
|
||
|
||
### 外部调用示例 | External Usage Example
|
||
|
||
```csharp
|
||
public class SomeViewModel
|
||
{
|
||
private readonly IMotionControlService _motion;
|
||
|
||
public SomeViewModel(IMotionControlService motion)
|
||
{
|
||
_motion = motion;
|
||
}
|
||
|
||
// 用户点击图像某点,计算相对图像中心的像素偏移后,一键驱动载物台移动
|
||
// User clicks a point on image, calculates pixel offset from center, and drives stage movement
|
||
public void CenterOnPixel(double dxPixels, double dyPixels)
|
||
{
|
||
// 直接驱动载物台移动(内部自动获取放大比、计算距离、执行运动)
|
||
// Directly drives stage move (internally gets magnification, calculates distance, executes motion)
|
||
var result = _motion.MoveStageByPixelOffset(dxPixels, dyPixels);
|
||
|
||
if (!result.Success)
|
||
{
|
||
// 处理错误 | Handle error
|
||
MessageBox.Show(result.ErrorMessage);
|
||
}
|
||
}
|
||
|
||
// 仅预览计算结果,不实际移动 | Preview calculation only, no actual move
|
||
public string PreviewMove(double dxPixels, double dyPixels)
|
||
{
|
||
var result = _motion.MoveStageByPixelOffset(dxPixels, dyPixels, executeMove: false);
|
||
return result.ErrorMessage; // 成功时包含计算的位移信息 | Contains displacement info on success
|
||
}
|
||
}
|
||
```
|
||
|
||
也可以使用底层接口单独计算(不驱动运动):
|
||
|
||
```csharp
|
||
public class AnotherViewModel
|
||
{
|
||
private readonly IMagnificationCalibrationService _calibration;
|
||
private readonly IMotionControlService _motion;
|
||
|
||
public AnotherViewModel(
|
||
IMagnificationCalibrationService calibration,
|
||
IMotionControlService motion)
|
||
{
|
||
_calibration = calibration;
|
||
_motion = motion;
|
||
}
|
||
|
||
// 仅计算像素偏移对应的载物台距离(不移动)
|
||
// Calculate only, no move
|
||
public (double dx, double dy) CalculateOffset(double dxPixels, double dyPixels)
|
||
{
|
||
if (!_calibration.IsReady) return (0, 0);
|
||
|
||
var geometry = _motion.GetCurrentGeometry();
|
||
return _calibration.PixelsToStageMovement(dxPixels, dyPixels, geometry.Magnification);
|
||
}
|
||
}
|
||
```
|
||
|
||
### 6.1 两种用途辨析:点击居中 vs 坐标系补偿 | Click-to-Center vs Coordinate Compensation
|
||
|
||
`MoveStageByPixelOffset` 与坐标系补偿接口都基于相同的像素→mm 换算(内部统一由私有方法 `TryConvertPixelToStageMm` 计算),但用途不同:
|
||
|
||
| 用途 | 接口 | 是否记录补偿 | 说明 |
|
||
|------|------|--------------|------|
|
||
| 点击居中 | `MoveStageByPixelOffset(dx, dy)` | 否 | 用户点击图像某点,一次性把该点移到中心,不影响后续运动 |
|
||
| 坐标系补偿 | `ApplyPixelOffsetCompensation(dx, dy)` | 是 | 主框架坐标匹配后记录补偿并修正到位,后续定点运动可叠加补偿 |
|
||
|
||
坐标系补偿的完整说明见 `MotionControl_Design.md` 第 14 节与 `GUIDENCE.md` 第 11 节。
|
||
|
||
---
|
||
|
||
## 7. 版本变更说明 | Change Log
|
||
|
||
### v2.1(2026-07-28)
|
||
|
||
**新增坐标系补偿功能**
|
||
|
||
- **新增** `IMotionControlService` 坐标系补偿接口:`ApplyPixelOffsetCompensation`、`RecordPixelOffsetCompensation`、`GetStageCompensation`、`SetStageCompensation`、`ResetStageCompensation`
|
||
- **新增** `CompensationMode` 枚举(`Replace` 默认 / `Accumulate`)
|
||
- **新增** `StageCompensationChangedEvent` 事件
|
||
- **变更** `MoveToTarget` / `MoveAllToTarget` 增加 `applyCompensation` 参数(默认 `false`),仅对 StageX/StageY 叠加补偿
|
||
- **重构** 将 `MoveStageByPixelOffset` 的像素→mm 换算抽为私有方法 `TryConvertPixelToStageMm`,供补偿接口复用(对外行为不变)
|
||
- 补偿功能复用现有几何配置,无需新增 App.config 参数
|
||
|
||
### v2.0(2026-07-01)
|
||
|
||
**重大变更:从手动标定改为基于几何配置的直接计算**
|
||
|
||
- **新增** `GeometryConfig.DetectorPixelSizeX` / `DetectorPixelSizeY`:探测器像素物理尺寸配置
|
||
- **新增** `GeometryConfig.PixelDirectionX` / `PixelDirectionY`:像素方向系数配置
|
||
- **新增** `IMagnificationCalibrationService.IsReady` 属性:替代 `IsCalibrated`
|
||
- **废弃** 手动标定向导流程:标记为 `[Obsolete]`,代码保留但不再推荐使用
|
||
- **废弃** `IsCalibrated`、`CurrentData`、`LoadCalibration()`、`SaveCalibration()` 接口成员
|
||
- **变更** `MagnificationCalibrationService` 构造函数:新增 `MotionControlConfig` 依赖注入
|
||
- **变更** `PixelsToStageMovement` 转换逻辑:优先使用几何计算,回退到手动标定数据
|
||
|
||
**迁移指南**:
|
||
1. 在 App.config 中配置 `DetectorPixelSizeX` 和 `DetectorPixelSizeY`(从探测器规格书获取)
|
||
2. 配置 `PixelDirectionX` 和 `PixelDirectionY`(通过实验确定方向对应关系)
|
||
3. 将代码中的 `IsCalibrated` 替换为 `IsReady`
|
||
4. 无需再运行标定向导,系统启动后即可使用像素映射功能
|
||
|
||
### v1.0(2026-06-30)
|
||
|
||
- 初始版本,基于两点手动标定的像素-载物台映射
|
||
|
||
---
|
||
|
||
## 8. 已废弃:标定向导流程 | Deprecated: Calibration Wizard Flow
|
||
|
||
> ⚠️ 以下内容为 v1.0 的手动标定向导,已废弃。仅在 `DetectorPixelSizeX` 未配置时作为 fallback 使用。
|
||
|
||
向导窗口 `CalibrationWizardWindow` 基于 **Telerik RadWizard + Crystal 主题**,分为五步:
|
||
|
||
| 步骤 | 名称 | 主要内容 | 下一步条件 |
|
||
|------|------|----------|-----------|
|
||
| Step 1 | 标定介绍 | 显示标定原理和核心公式;输入探测器 X 方向像素数 | `DetectorPixelCountX > 0` |
|
||
| Step 2 | 标定点 1 | 输入 M1、X 视野实际距离;实时显示 K1 | `M1 > 0` 且 `FovDistance1 > 0` |
|
||
| Step 3 | 标定点 2 | 输入 M2、X 视野实际距离;实时显示 K2、一致性检查结果 | `M2 > 0` 且 `FovDistance2 > 0` |
|
||
| Step 4 | 方向标定 | 选择 X/Y 方向系数(+1/-1) | — |
|
||
| Step 5 | 验证与保存 | 标定结果汇总;输入测试放大比显示 mm/pixel;保存 | 保存成功后关闭窗口 |
|
||
|
||
标定文件路径:`{AppBaseDirectory}/Calibration/MagnificationCalibration.json`
|
||
|
||
---
|
||
|
||
## 9. 多语言支持 | Localization
|
||
|
||
所有向导界面文本通过模块级 Resources 资源文件管理,支持简体中文(zh-CN)、繁体中文(zh-TW)和英文(en-US)。
|
||
|
||
- 资源文件位置:`XP.Hardware.MotionControl/Resources/Resources*.resx`
|
||
- 资源键前缀:`Calibration_`
|
||
- XAML 绑定方式:`{loc:Localization Calibration_WizardTitle}`
|
||
- 服务日志输出采用双语格式(中文 | English)
|
||
|
||
---
|
||
|
||
## 10. 错误处理与日志 | Error Handling & Logging
|
||
|
||
- 启动时输出当前模式信息(几何直接计算 / 手动标定 fallback)
|
||
- 几何配置无效时输出 Warn 级别日志
|
||
- 标定文件加载失败时输出 Error/Warn 级别日志(不影响几何计算模式)
|
||
- `PixelsToStageMovement` 在非法输入时抛出明确异常
|
||
- 统一使用 `ILoggerService.ForModule<MagnificationCalibrationService>()` 获取模块化日志实例
|
||
|
||
---
|
||
|
||
## 11. 关联文档 | Related Documents
|
||
|
||
| 文档 | 说明 |
|
||
|------|------|
|
||
| `README.md` | MotionControl 模块总体说明 |
|
||
| `GeometryWithDetectorSwing.md` | FOD/FDD/放大倍率(M)几何计算模型 |
|
||
| `MotionControl_Design.md` | 运动控制模块设计文档 |
|
||
|
||
---
|
||
|
||
**最后更新 | Last Updated**: 2026-07-01
|