Files
Shi.Ji e31d3560bb 添加 MX-PD-盘古 项目文件
将 MX-PD-盘古 - new 目录下的所有文件添加到主仓库
2026-05-18 11:43:09 +08:00

830 lines
34 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Motion 运动框架使用说明
## 1. 文档范围
本文档基于当前代码实际实现整理,描述 [`MainShell/Motion`](MainShell/Motion) 目录下已经存在的运动控制能力、调用入口、约束行为与示例代码。
说明:
- 文档内容以当前源码实现为准。
- 若旧文档、注释或设计稿与代码不一致,以代码为准。
- 本文档仅描述已经实现的能力,不对未来规划功能做扩展解释。
适用对象:
- 业务流程开发人员
- 手动功能开发人员
- 运动控制维护人员
- 需要接入平台联动或视觉逼近对位功能的开发人员
## 2. 模块总览
当前 [`MainShell/Motion`](MainShell/Motion) 目录中的能力主要包括:
1. 单轴运动控制
2. 批量安全运动入口
3. 运动前安全检查与报警上报
4. 平台三轴联动封装
5. 速度参数下发管理
6. 逼近对位流程框架
主要文件如下:
- [`MotionController.cs`](MainShell/Motion/MotionController.cs):单轴底层执行器
- [`MotionInfrastructure.cs`](MainShell/Motion/MotionInfrastructure.cs):运动报警、预检查、日志、控制器注册表
- [`MotionMoveRequest.cs`](MainShell/Motion/MotionMoveRequest.cs):运动请求模型
- [`MotionResult.cs`](MainShell/Motion/MotionResult.cs):单轴结果与批量结果模型
- [`SafeAxisMotion.cs`](MainShell/Motion/SafeAxisMotion.cs):业务层统一运动入口
- [`StagePlatformMotionService.cs`](MainShell/Motion/StagePlatformMotionService.cs):平台三轴联动封装
- [`AxisSpeedManager.cs`](MainShell/Motion/AxisSpeedManager.cs):轴速度曲线管理
- [`MotionSafetyStateProvider.cs`](MainShell/Motion/MotionSafetyStateProvider.cs):运动安全状态提供器
- [`ApproachAlignment/ApproachAlignment.cs`](MainShell/Motion/ApproachAlignment/ApproachAlignment.cs):逼近对位的数据结构和接口定义
- [`ApproachAlignment/ApproachAlignmentService.cs`](MainShell/Motion/ApproachAlignment/ApproachAlignmentService.cs):逼近对位主流程
- [`ApproachAlignment/CenterRecognizer.cs`](MainShell/Motion/ApproachAlignment/CenterRecognizer.cs):视觉中心识别实现
- [`ApproachAlignment/CoordinateTransformer.cs`](MainShell/Motion/ApproachAlignment/CoordinateTransformer.cs):坐标转换实现
## 3. 分层理解
### 3.1 单轴执行层
[`MotionController`](MainShell/Motion/MotionController.cs:10) 直接面向 `IAxis` / `IAxisFunc`,负责:
- 绝对运动 [`MoveAbsAsync()`](MainShell/Motion/MotionController.cs:35)
- 相对运动 [`MoveRelAsync()`](MainShell/Motion/MotionController.cs:60)
- Jog [`JogAsync()`](MainShell/Motion/MotionController.cs:86)
- 停止 [`StopAsync()`](MainShell/Motion/MotionController.cs:122)
- 回零 [`HomeAsync()`](MainShell/Motion/MotionController.cs:148)
- 运动状态校验、软限位检查、超时与取消
- 运动开始/结束事件通知
### 3.2 基础设施层
[`MotionInfrastructure.cs`](MainShell/Motion/MotionInfrastructure.cs) 中提供了几类基础设施:
- [`MotionAlarmReporter`](MainShell/Motion/MotionInfrastructure.cs:16):统一报警上报
- [`MotionPrecheckService`](MainShell/Motion/MotionInfrastructure.cs:50):运动前安全检查聚合入口
- [`MotionExecutionLogger`](MainShell/Motion/MotionInfrastructure.cs:112):统一记录运动开始/结束日志
- [`MotionControllerRegistry`](MainShell/Motion/MotionInfrastructure.cs:149):缓存并复用每根轴对应的 [`MotionController`](MainShell/Motion/MotionController.cs:10)
### 3.3 请求与结果模型层
[`MotionMoveRequest`](MainShell/Motion/MotionMoveRequest.cs:16) 与 [`MotionResult`](MainShell/Motion/MotionResult.cs:7) / [`MotionBatchResult`](MainShell/Motion/MotionResult.cs:80) 用于统一描述:
- 运动目标
- 超时时间
- 报警号
- 请求来源与标签
- 批次号与关联号
- 单轴结果
- 批量结果
### 3.4 业务统一入口层
[`SafeAxisMotion`](MainShell/Motion/SafeAxisMotion.cs:14) 是当前推荐的业务调用入口,负责:
- 通过轴名解析实际轴对象
- 复用 [`MotionController`](MainShell/Motion/MotionController.cs:10)
- 单轴绝对/相对运动
- 多轴绝对联动
- 单轴/多轴回零
- 调用 [`MotionPrecheckService.ValidateAsync()`](MainShell/Motion/MotionInfrastructure.cs:82) 做运动前安全校验
- 失败时联动取消并停止相关轴
- 失败后按请求配置上报报警
- 为结果补充 `CorrelationId` / `BatchId` / `FailureStage`
### 3.5 业务场景服务层
[`StagePlatformMotionService`](MainShell/Motion/StagePlatformMotionService.cs:11) 封装平台三轴动作:
- 等高移动 [`MoveFlatAsync()`](MainShell/Motion/StagePlatformMotionService.cs:29)
- 平面移动 [`MovePlaneAsync()`](MainShell/Motion/StagePlatformMotionService.cs:39)
### 3.6 视觉逼近对位层
[`ApproachAlignmentService`](MainShell/Motion/ApproachAlignment/ApproachAlignmentService.cs:17) 封装迭代式逼近对位流程:
1. 识别中心
2. 将视觉中心转换为各轴目标位置
3. 驱动多轴移动
4. 再次识别中心
5. 重新计算目标位置与当前误差
6. 判断是否收敛
## 4. 当前代码中的真实能力
结合当前代码,以下能力已经明确存在:
- 单轴绝对移动
- 单轴相对移动
- 单轴 Jog
- 单轴停止
- 单轴回零
- 多轴绝对联动移动
- 多轴批量回零
- 运动前安全检查
- 失败报警上报
- 平台三轴等高/平面联动
- 基于视觉中心识别的迭代式逼近对位框架
- 轴速度配置与速度档位下发
以下内容需要特别注意:
- 批量移动仅支持绝对运动,不支持批量相对运动
- 逼近对位中的 [`CoordinateTransformer`](MainShell/Motion/ApproachAlignment/CoordinateTransformer.cs:14) 仍是占位实现
- 文档中若提到通过 [`SafeAxisMotion`](MainShell/Motion/SafeAxisMotion.cs:14) 直接调用逼近对位,不符合当前代码真实入口
## 5. MotionController 说明
[`MotionController`](MainShell/Motion/MotionController.cs:10) 是单轴动作的最终执行器。
### 5.1 关键属性
- [`AxisName`](MainShell/Motion/MotionController.cs:26)
- [`CurrentPos`](MainShell/Motion/MotionController.cs:27)
- [`IsBusy`](MainShell/Motion/MotionController.cs:28)
- [`IsAlarm`](MainShell/Motion/MotionController.cs:29)
- [`InPos`](MainShell/Motion/MotionController.cs:30)
### 5.2 关键事件
- [`MotionStarted`](MainShell/Motion/MotionController.cs:32)
- [`MotionFinished`](MainShell/Motion/MotionController.cs:33)
### 5.3 关键方法
- [`MoveAbsAsync()`](MainShell/Motion/MotionController.cs:35)
- [`MoveRelAsync()`](MainShell/Motion/MotionController.cs:60)
- [`JogAsync()`](MainShell/Motion/MotionController.cs:86)
- [`StopAsync()`](MainShell/Motion/MotionController.cs:122)
- [`HomeAsync()`](MainShell/Motion/MotionController.cs:148)
### 5.4 内部保障机制
[`MotionController`](MainShell/Motion/MotionController.cs:10) 内部具备以下保障:
- 使用 `SemaphoreSlim` 保证同一根轴同一时刻只执行一个动作,见 [`_motionLock`](MainShell/Motion/MotionController.cs:15)
- 每次运动前调用 [`EnsureMotionStateReady()`](MainShell/Motion/MotionController.cs:280) 检查轴状态
- 运动执行过程中调用 [`EnsureMotionStateHealthyDuringExecution()`](MainShell/Motion/MotionController.cs:304) 检查状态是否恶化
- 绝对与相对移动执行前都会调用 [`EnsureWithinSoftLimit()`](MainShell/Motion/MotionController.cs:328) 做软限位检查
- 取消时通过 [`TryStop()`](MainShell/Motion/MotionController.cs:368) 自动尝试停轴
- 超时时通过 [`ThrowIfTimeoutExceeded()`](MainShell/Motion/MotionController.cs:351) 自动尝试停轴并抛出超时异常
- 完成后统一生成 [`MotionResult`](MainShell/Motion/MotionResult.cs:7)
### 5.5 失败返回行为
[`ExecuteProtectedMotionAsync()`](MainShell/Motion/MotionController.cs:167) 会捕获执行异常,并在最终返回的 [`MotionResult`](MainShell/Motion/MotionResult.cs:7) 中体现成功、取消和异常信息,而不是始终直接向外抛出异常。
因此调用后建议统一执行:
```csharp
var result = await controller.MoveAbsAsync(100.0, 10000, cancellationToken);
result.EnsureSuccess();
```
## 6. MotionInfrastructure 说明
[`MotionInfrastructure.cs`](MainShell/Motion/MotionInfrastructure.cs) 提供了运动框架的关键支撑能力。
### 6.1 MotionAlarmReporter
[`MotionAlarmReporter`](MainShell/Motion/MotionInfrastructure.cs:16) 对 [`AlarmOperate`](MainShell/Alarm/AlarmOperate.cs) 做了一层封装:
- 传入 `null` 报警号时直接返回 `false`
- 传入有效报警号时调用 [`ReportAlarmAsync()`](MainShell/Motion/MotionInfrastructure.cs:25) 间接触发报警
### 6.2 MotionPrecheckService
[`MotionPrecheckService`](MainShell/Motion/MotionInfrastructure.cs:50) 在构造函数中聚合了以下安全检查:
- `MotionRequestDuplicateAxisCheck`
- `MotionBatchSameSourceCheck`
- `EmergencyStopReleasedCheck`
- `SafetyDoorClosedCheck`
- `AutoFlowModeCheck`
- `StageVacuumReadyCheck`
- `BondHeadSafePositionCheck`
- `StagePlatformPlaneMoveSafetyCheck`
调用 [`ValidateAsync()`](MainShell/Motion/MotionInfrastructure.cs:82) 时,会:
1. 逐条执行安全规则
2. 对失败规则记录系统错误日志
3. 使用规则上的 `AlarmId` 或传入的 `fallbackAlarmId` 上报报警
4. 最终抛出 `InvalidOperationException`
这意味着:
- 当前代码中已经存在统一运动前预检查机制
- [`SafeAxisMotion`](MainShell/Motion/SafeAxisMotion.cs:14) 的各类入口会先走预检查,再执行实际运动
### 6.3 MotionExecutionLogger
[`MotionExecutionLogger`](MainShell/Motion/MotionInfrastructure.cs:112) 负责处理:
- [`HandleMotionStarted()`](MainShell/Motion/MotionInfrastructure.cs:114)
- [`HandleMotionFinished()`](MainShell/Motion/MotionInfrastructure.cs:126)
它会输出开始位置、目标位置、结束位置、耗时、是否取消、失败阶段等日志信息。
### 6.4 MotionControllerRegistry
[`MotionControllerRegistry`](MainShell/Motion/MotionInfrastructure.cs:149) 负责:
- 按轴名缓存控制器实例
- 对同名且同引用的轴复用已有控制器
- 在创建控制器时自动挂接 [`MotionExecutionLogger`](MainShell/Motion/MotionInfrastructure.cs:112) 事件
业务侧一般不需要自己维护 [`MotionController`](MainShell/Motion/MotionController.cs:10) 生命周期,直接通过 [`SafeAxisMotion`](MainShell/Motion/SafeAxisMotion.cs:14) 使用即可。
## 7. MotionMoveRequest 说明
[`MotionMoveRequest`](MainShell/Motion/MotionMoveRequest.cs:16) 当前并不轻量,除基础字段外还已经支持业务元数据。
### 7.1 主要属性
- [`AxisName`](MainShell/Motion/MotionMoveRequest.cs:34)
- [`Axis`](MainShell/Motion/MotionMoveRequest.cs:35)
- [`TargetPosition`](MainShell/Motion/MotionMoveRequest.cs:36)
- [`TimeoutMilliseconds`](MainShell/Motion/MotionMoveRequest.cs:37)
- [`AlarmId`](MainShell/Motion/MotionMoveRequest.cs:38)
- [`RequestKind`](MainShell/Motion/MotionMoveRequest.cs:39)
- [`Source`](MainShell/Motion/MotionMoveRequest.cs:40)
- [`Tags`](MainShell/Motion/MotionMoveRequest.cs:41)
- [`CorrelationId`](MainShell/Motion/MotionMoveRequest.cs:42)
- [`BatchId`](MainShell/Motion/MotionMoveRequest.cs:43)
- [`PositionTolerance`](MainShell/Motion/MotionMoveRequest.cs:44)
- [`StopOnFailure`](MainShell/Motion/MotionMoveRequest.cs:45)
### 7.2 创建方式
绝对运动:
- [`ForAxisName()`](MainShell/Motion/MotionMoveRequest.cs:64)
- [`ForAxis()`](MainShell/Motion/MotionMoveRequest.cs:74)
相对运动:
- [`ForRelativeAxisName()`](MainShell/Motion/MotionMoveRequest.cs:84)
- [`ForRelativeAxis()`](MainShell/Motion/MotionMoveRequest.cs:94)
补充元数据:
- [`WithMetadata()`](MainShell/Motion/MotionMoveRequest.cs:47)
### 7.3 行为说明
- `TargetPosition` 对绝对运动表示目标位置,对相对运动表示位移量
- `Tags` 会通过 [`NormalizeTags()`](MainShell/Motion/MotionMoveRequest.cs:104) 去空、去重
- `WithMetadata()` 会保留原请求主体,仅覆盖指定元数据
- 批量绝对移动时会由 [`SafeAxisMotion`](MainShell/Motion/SafeAxisMotion.cs:14) 自动补充 `CorrelationId``BatchId`
## 8. MotionResult 与 MotionBatchResult 说明
[`MotionResult`](MainShell/Motion/MotionResult.cs:7) 包含:
- [`AxisName`](MainShell/Motion/MotionResult.cs:30)
- [`Operation`](MainShell/Motion/MotionResult.cs:31)
- [`TargetPosition`](MainShell/Motion/MotionResult.cs:32)
- [`StartPosition`](MainShell/Motion/MotionResult.cs:33)
- [`EndPosition`](MainShell/Motion/MotionResult.cs:34)
- [`Succeeded`](MainShell/Motion/MotionResult.cs:35)
- [`Cancelled`](MainShell/Motion/MotionResult.cs:36)
- [`Exception`](MainShell/Motion/MotionResult.cs:37)
- [`Message`](MainShell/Motion/MotionResult.cs:38)
- [`AlarmReported`](MainShell/Motion/MotionResult.cs:39)
- [`StartedAtUtc`](MainShell/Motion/MotionResult.cs:40)
- [`FinishedAtUtc`](MainShell/Motion/MotionResult.cs:41)
- [`CorrelationId`](MainShell/Motion/MotionResult.cs:42)
- [`BatchId`](MainShell/Motion/MotionResult.cs:43)
- [`FailureStage`](MainShell/Motion/MotionResult.cs:44)
- [`TimedOut`](MainShell/Motion/MotionResult.cs:45)
- [`StoppedByCoordinator`](MainShell/Motion/MotionResult.cs:46)
- [`DurationMilliseconds`](MainShell/Motion/MotionResult.cs:47)
常用方法:
- [`WithAlarmReported()`](MainShell/Motion/MotionResult.cs:49)
- [`WithFailureDetails()`](MainShell/Motion/MotionResult.cs:59)
- [`EnsureSuccess()`](MainShell/Motion/MotionResult.cs:64)
[`MotionBatchResult`](MainShell/Motion/MotionResult.cs:80) 包含:
- [`Results`](MainShell/Motion/MotionResult.cs:87)
- [`Succeeded`](MainShell/Motion/MotionResult.cs:88)
- [`Cancelled`](MainShell/Motion/MotionResult.cs:89)
- [`EnsureSuccess()`](MainShell/Motion/MotionResult.cs:91)
如果批量结果中只有一根轴失败,[`EnsureSuccess()`](MainShell/Motion/MotionResult.cs:91) 会直接抛该轴异常;如果多根轴失败,会抛 `AggregateException`
## 9. SafeAxisMotion 说明
[`SafeAxisMotion`](MainShell/Motion/SafeAxisMotion.cs:14) 是当前业务最推荐使用的统一入口。
### 9.1 主要能力
- 单轴绝对移动
- 单轴相对移动
- 多轴绝对联动移动
- 单轴回零
- 多轴批量回零
- 轴名解析
- 控制器缓存与日志挂接
- 运动前安全预检查
- 失败联动停轴
- 失败报警
- 批次与关联信息补充
### 9.2 主要异步方法
单轴移动:
- [`MoveAbsAsync()`](MainShell/Motion/SafeAxisMotion.cs:156)
- [`MoveAbsAsync()`](MainShell/Motion/SafeAxisMotion.cs:163)
- [`MoveRelAsync()`](MainShell/Motion/SafeAxisMotion.cs:170)
- [`MoveRelAsync()`](MainShell/Motion/SafeAxisMotion.cs:177)
批量绝对移动:
- [`SafeMoveAsync()`](MainShell/Motion/SafeAxisMotion.cs:57)
回零:
- [`HomeAsync()`](MainShell/Motion/SafeAxisMotion.cs:226)
- [`HomeAsync()`](MainShell/Motion/SafeAxisMotion.cs:234)
- [`SafeHomeAsync()`](MainShell/Motion/SafeAxisMotion.cs:194)
- [`SafeHomeAsync()`](MainShell/Motion/SafeAxisMotion.cs:204)
同步封装:
- [`SafeMove()`](MainShell/Motion/SafeAxisMotion.cs:42)
- [`MoveAbs()`](MainShell/Motion/SafeAxisMotion.cs:76)
- [`MoveRel()`](MainShell/Motion/SafeAxisMotion.cs:96)
- [`Home()`](MainShell/Motion/SafeAxisMotion.cs:136)
- [`SafeHome()`](MainShell/Motion/SafeAxisMotion.cs:116)
### 9.3 真实执行流程
以 [`MoveAbsAsync()`](MainShell/Motion/SafeAxisMotion.cs:156) 为例,执行顺序为:
1. 构造 [`MotionMoveRequest`](MainShell/Motion/MotionMoveRequest.cs:16)
2. 调用 [`EnsureRequestBatchMetadata()`](MainShell/Motion/SafeAxisMotion.cs:385) 补齐关联元数据
3. 解析轴对象
4. 调用 [`MotionPrecheckService.ValidateAsync()`](MainShell/Motion/MotionInfrastructure.cs:82) 执行预检查
5. 调用内部 [`MoveAbsInternalAsync()`](MainShell/Motion/SafeAxisMotion.cs:244)
6. 通过 [`MotionControllerRegistry.GetController()`](MainShell/Motion/MotionInfrastructure.cs:172) 获取控制器并执行运动
7. 按请求补充结果元数据与失败阶段
8. 必要时上报报警
### 9.4 批量运动行为说明
[`SafeMoveAsync()`](MainShell/Motion/SafeAxisMotion.cs:57) 当前执行的是多轴绝对联动:
- 请求数组为空时,返回空的 [`MotionBatchResult`](MainShell/Motion/MotionResult.cs:80)
- 会先对整批请求生成 `batchId`
- 会统一做安全检查
- 会并发启动各轴绝对运动任务
- 任一轴失败时,若请求 `StopOnFailure = true`,会调用 [`CancelAndStopRelatedAxes()`](MainShell/Motion/SafeAxisMotion.cs:438)
- [`CancelAndStopRelatedAxes()`](MainShell/Motion/SafeAxisMotion.cs:438) 会取消协调令牌,并逐轴调用 [`StopAsync()`](MainShell/Motion/MotionController.cs:122)
### 9.5 超时与失败细节
- [`NormalizeTimeout()`](MainShell/Motion/SafeAxisMotion.cs:423) 会把小于等于 0 的超时值恢复为默认值
- 失败结果会通过 [`WithFailureDetails()`](MainShell/Motion/MotionResult.cs:59) 写入 `FailureStage``TimedOut``StoppedByCoordinator``CorrelationId``BatchId`
-`alarmId` 为空时,失败不会触发报警
-`stopOnFailure = false` 时,失败不会触发联动停轴
## 10. MotionSafetyStateProvider 说明
[`MotionSafetyStateProvider`](MainShell/Motion/MotionSafetyStateProvider.cs:13) 为预检查规则提供外部状态。
### 10.1 主要能力
- 读取当前机器模式 [`CurrentMachineMode`](MainShell/Motion/MotionSafetyStateProvider.cs:26)
- 判断急停是否释放 [`IsEmergencyStopReleased()`](MainShell/Motion/MotionSafetyStateProvider.cs:28)
- 判断安全门是否关闭 [`AreSafetyDoorsClosed()`](MainShell/Motion/MotionSafetyStateProvider.cs:39)
- 判断流程是否在运行 [`IsFlowRunning()`](MainShell/Motion/MotionSafetyStateProvider.cs:57)
- 获取当前流程名 [`CurrentFlowName`](MainShell/Motion/MotionSafetyStateProvider.cs:63)
- 判断平台真空是否就绪 [`AreStageVacuumsReady()`](MainShell/Motion/MotionSafetyStateProvider.cs:65)
- 获取吸嘴/打头相关不安全信号 [`GetUnsafeBondHeadSignals()`](MainShell/Motion/MotionSafetyStateProvider.cs:78)
- 判断来源是否属于自动流程 [`IsAutoWorkflowSource()`](MainShell/Motion/MotionSafetyStateProvider.cs:93)
### 10.2 行为说明
-`DeviceIo` 离线时,多数安全状态会直接返回不可用或不安全结果
- 安全门支持 `SecurityDoorShield` 旁路逻辑
- 自动流程判断不是只看精确名称,也支持来源字符串包含 `Auto`
## 11. StagePlatformMotionService 说明
[`StagePlatformMotionService`](MainShell/Motion/StagePlatformMotionService.cs:11) 封装平台三轴 [`Axis_Stage_Z7`](MainShell/Motion/StagePlatformMotionService.cs:45)、[`Axis_Stage_Z8`](MainShell/Motion/StagePlatformMotionService.cs:46)、[`Axis_Stage_Z9`](MainShell/Motion/StagePlatformMotionService.cs:47) 的联动动作。
### 11.1 主要方法
- [`MoveFlatAsync()`](MainShell/Motion/StagePlatformMotionService.cs:29)
- [`MovePlaneAsync()`](MainShell/Motion/StagePlatformMotionService.cs:39)
- [`MoveFlat()`](MainShell/Motion/StagePlatformMotionService.cs:24)
- [`MovePlane()`](MainShell/Motion/StagePlatformMotionService.cs:34)
### 11.2 内部实现方式
- [`MoveFlatAsync()`](MainShell/Motion/StagePlatformMotionService.cs:29) 实际调用 [`MovePlaneAsync()`](MainShell/Motion/StagePlatformMotionService.cs:39)
- [`MovePlaneAsync()`](MainShell/Motion/StagePlatformMotionService.cs:39) 会先调用 [`EnsurePlaneTargetsOrdered()`](MainShell/Motion/StagePlatformMotionService.cs:53)
- 允许的三轴目标最大高差为 `5.0`
- 然后将三根轴封装为带 `Source``Tags` 的 [`MotionMoveRequest`](MainShell/Motion/MotionMoveRequest.cs:16)
- 再统一调用 [`SafeAxisMotion.SafeMoveAsync()`](MainShell/Motion/SafeAxisMotion.cs:57)
- 方法内部已经执行 [`EnsureSuccess()`](MainShell/Motion/MotionResult.cs:91)
### 11.3 使用建议
只要是平台三轴动作,建议统一走 [`StagePlatformMotionService`](MainShell/Motion/StagePlatformMotionService.cs:11),不要在业务代码里手工拼三轴请求。
## 12. AxisSpeedManager 说明
[`AxisSpeedManager`](MainShell/Motion/AxisSpeedManager.cs:38) 用于从系统参数生成速度曲线并下发到轴参数。
### 12.1 相关类型
- [`AxisSpeedProfile`](MainShell/Motion/AxisSpeedManager.cs:13)`Low` / `Medium` / `High` / `Custom`
- [`AxisMotionProfile`](MainShell/Motion/AxisSpeedManager.cs:21):封装 `Velocity` / `Acceleration` / `Deceleration` / `Jerk`
### 12.2 主要方法
- [`SetAxisSpeed(string axisName, double speed)`](MainShell/Motion/AxisSpeedManager.cs:49)
- [`SetAxisSpeed(string axisName, AxisSpeedProfile profile)`](MainShell/Motion/AxisSpeedManager.cs:56)
- [`ApplySpeedSettings()`](MainShell/Motion/AxisSpeedManager.cs:63)
### 12.3 真实行为说明
[`SetAxisSpeed(string axisName, double speed)`](MainShell/Motion/AxisSpeedManager.cs:49) 的行为不是固定倍数计算,而是:
1. 从速度参数表中找到该轴对应的 `SpeedTypeItem`
2. 以配置基准速度 `speedItem.Speed` 为基数
3.`speed / speedItem.Speed` 计算缩放比例
4. 按比例缩放 `Acc` / `Dec` / `Jerk`
5. 最终通过 [`ApplyAxisMotionProfile()`](MainShell/Motion/AxisSpeedManager.cs:85) 下发到轴参数
[`SetAxisSpeed(string axisName, AxisSpeedProfile profile)`](MainShell/Motion/AxisSpeedManager.cs:56) 的行为是:
- 读取当前轴配置中的 `LowPercent` / `MedianPercent` / `HighPercent`
- 调用 [`CreateProfile()`](MainShell/Motion/AxisSpeedManager.cs:151) 生成缩放后的运动参数
- 调用 [`ApplyAxisMotionProfile()`](MainShell/Motion/AxisSpeedManager.cs:85) 下发
[`ApplySpeedSettings()`](MainShell/Motion/AxisSpeedManager.cs:63) 的行为是:
-`GlobalParam.SpeedParaSysSetting.SpeedTypeItemCollection.SpeedTypeItemList` 读取所有速度配置
- 根据当前 `CurrentSpeedType` 通过 [`MapCurrentSpeedTypeText()`](MainShell/Motion/AxisSpeedManager.cs:187) 映射到 `Low` / `Medium` / `High`
- 对每根轴生成对应档位的速度参数并下发
### 12.4 校验与异常
[`AxisSpeedManager`](MainShell/Motion/AxisSpeedManager.cs:38) 会校验:
- 轴名不能为空
- 轴必须存在
- 轴必须有对应速度配置
- 速度、加速度、减速度、Jerk 必须为正且有限值,见 [`ValidatePositiveFinite()`](MainShell/Motion/AxisSpeedManager.cs:216)
- 百分比必须在 `(0, 100]` 范围内,见 [`ValidatePercent()`](MainShell/Motion/AxisSpeedManager.cs:224)
## 13. 逼近对位模块说明
### 13.1 组成文件
- [`ApproachAlignment/ApproachAlignment.cs`](MainShell/Motion/ApproachAlignment/ApproachAlignment.cs)
- [`ApproachAlignment/ApproachAlignmentService.cs`](MainShell/Motion/ApproachAlignment/ApproachAlignmentService.cs)
- [`ApproachAlignment/CenterRecognizer.cs`](MainShell/Motion/ApproachAlignment/CenterRecognizer.cs)
- [`ApproachAlignment/CoordinateTransformer.cs`](MainShell/Motion/ApproachAlignment/CoordinateTransformer.cs)
### 13.2 核心类型
[`ApproachAlignment.cs`](MainShell/Motion/ApproachAlignment/ApproachAlignment.cs:15) 中定义了:
- [`ApproachAlignmentAxis`](MainShell/Motion/ApproachAlignment/ApproachAlignment.cs:15)
- [`ApproachAlignmentRequest`](MainShell/Motion/ApproachAlignment/ApproachAlignment.cs:52)
- [`ApproachAlignmentResult`](MainShell/Motion/ApproachAlignment/ApproachAlignment.cs:109)
- [`CoordinateTransformResult`](MainShell/Motion/ApproachAlignment/ApproachAlignment.cs:151)
- [`ICenterRecognizer`](MainShell/Motion/ApproachAlignment/ApproachAlignment.cs:186)
- [`ICoordinateTransformer`](MainShell/Motion/ApproachAlignment/ApproachAlignment.cs:204)
### 13.3 ApproachAlignmentRequest 说明
[`ApproachAlignmentRequest`](MainShell/Motion/ApproachAlignment/ApproachAlignment.cs:52) 构造函数要求至少传入一根轴,并提供以下默认值:
- `Camera = CameraType.UpCamera`
- `MaxIterations = 5`
- `MoveTimeoutMilliseconds = 30000`
- `RecognitionTimeoutMilliseconds = 10000`
### 13.4 ApproachAlignmentService 流程
[`ApproachAlignmentService.ApproachAlignmentAsync()`](MainShell/Motion/ApproachAlignment/ApproachAlignmentService.cs:42) 当前流程如下:
1. 最多执行 `MaxIterations` 次迭代
2. 首次迭代调用 [`RecognizeCenterAsync()`](MainShell/Motion/ApproachAlignment/ApproachAlignmentService.cs:182) 识别中心
3. 调用 [`ICoordinateTransformer.TransformAsync()`](MainShell/Motion/ApproachAlignment/ApproachAlignment.cs:213) 计算各轴目标位置
4. 将目标位置转成 [`MotionMoveRequest.ForAxisName()`](MainShell/Motion/MotionMoveRequest.cs:64)
5. 调用 [`SafeAxisMotion.SafeMoveAsync()`](MainShell/Motion/SafeAxisMotion.cs:57) 执行多轴移动
6. 再次识别中心
7. 再次转换,得到理论目标位置
8. 读取各轴当前位置并计算误差
9. 若全部轴误差都小于等于容差,则成功结束
10. 否则进入下一轮迭代
### 13.5 CenterRecognizer 现状
[`CenterRecognizer`](MainShell/Motion/ApproachAlignment/CenterRecognizer.cs:14) 已接入视觉算法服务:
- 依赖 `IVisionAlgorithmService`
- 使用 `VisionProcessRequest`
- `AlgorithmType = VisionAlgorithmType.FindCenter`
- `CaptureOptions = CameraCaptureOptions.CreateStream(timeoutMilliseconds)`
- 从结果中读取 `OffsetX` / `OffsetY`
- 识别失败或超时返回 `null`
### 13.6 CoordinateTransformer 现状
[`CoordinateTransformer`](MainShell/Motion/ApproachAlignment/CoordinateTransformer.cs:14) 当前仍是占位实现。
实际行为:
- 若轴列表为空,则返回 `Succeeded = false`
- 否则延时约 10ms 后,为每根轴写入 `0.0` 作为目标位置
- 返回 `Succeeded = true`
这表示:
- 逼近对位的流程框架已经存在
- 但真实标定坐标变换尚未完成
- 若直接用于生产逻辑,会把各轴目标位置算成固定 `0.0`
### 13.7 当前真实入口
当前应直接注入并调用 [`ApproachAlignmentService.ApproachAlignmentAsync()`](MainShell/Motion/ApproachAlignment/ApproachAlignmentService.cs:42),而不是通过 [`SafeAxisMotion`](MainShell/Motion/SafeAxisMotion.cs:14) 调用逼近对位。
## 14. 推荐调用方式
### 14.1 普通业务运动
优先调用 [`SafeAxisMotion`](MainShell/Motion/SafeAxisMotion.cs:14)
- 单轴绝对移动用 [`MoveAbsAsync()`](MainShell/Motion/SafeAxisMotion.cs:156)
- 单轴相对移动用 [`MoveRelAsync()`](MainShell/Motion/SafeAxisMotion.cs:170)
- 多轴绝对联动用 [`SafeMoveAsync()`](MainShell/Motion/SafeAxisMotion.cs:57)
- 单轴回零用 [`HomeAsync()`](MainShell/Motion/SafeAxisMotion.cs:226)
- 多轴回零用 [`SafeHomeAsync()`](MainShell/Motion/SafeAxisMotion.cs:194)
### 14.2 平台三轴业务
统一调用 [`StagePlatformMotionService`](MainShell/Motion/StagePlatformMotionService.cs:11)
- 等高移动用 [`MoveFlatAsync()`](MainShell/Motion/StagePlatformMotionService.cs:29)
- 平面移动用 [`MovePlaneAsync()`](MainShell/Motion/StagePlatformMotionService.cs:39)
### 14.3 单轴调试或事件监听
可以直接使用 [`MotionController`](MainShell/Motion/MotionController.cs:10)
- 适合底层调试
- 适合观察 [`MotionStarted`](MainShell/Motion/MotionController.cs:32) / [`MotionFinished`](MainShell/Motion/MotionController.cs:33)
- 不建议作为一般业务入口
### 14.4 逼近对位业务
当前应直接调用 [`ApproachAlignmentService`](MainShell/Motion/ApproachAlignment/ApproachAlignmentService.cs:17),前提是先替换 [`CoordinateTransformer`](MainShell/Motion/ApproachAlignment/CoordinateTransformer.cs:14) 为真实可用的标定变换实现。
## 15. 示例代码
### 15.1 单轴绝对移动
```csharp
public async Task MoveAxisXAsync(CancellationToken cancellationToken)
{
var result = await _safeAxisMotion.MoveAbsAsync(
"Axis_X",
100.0,
timeoutMilliseconds: 10000,
cancellationToken: cancellationToken,
alarmId: 5001);
result.EnsureSuccess();
}
```
### 15.2 单轴相对移动
```csharp
public async Task NudgeAxisYAsync(CancellationToken cancellationToken)
{
var result = await _safeAxisMotion.MoveRelAsync(
"Axis_Y",
-2.0,
timeoutMilliseconds: 8000,
cancellationToken: cancellationToken,
alarmId: 5002);
result.EnsureSuccess();
}
```
### 15.3 带元数据的多轴绝对联动
```csharp
public async Task MoveXYAsync(double x, double y, CancellationToken cancellationToken)
{
var batch = await _safeAxisMotion.SafeMoveAsync(
cancellationToken,
MotionMoveRequest.ForAxisName(
"Axis_X",
x,
timeoutMilliseconds: 12000,
alarmId: 6001,
source: "Manual.Align",
tags: new[] { "Manual", "Align" },
correlationId: "ALIGN-001",
batchId: "BATCH-ALIGN-001",
positionTolerance: 0.005,
stopOnFailure: true),
MotionMoveRequest.ForAxisName(
"Axis_Y",
y,
timeoutMilliseconds: 12000,
alarmId: 6002,
source: "Manual.Align",
tags: new[] { "Manual", "Align" },
correlationId: "ALIGN-002",
batchId: "BATCH-ALIGN-001",
positionTolerance: 0.005,
stopOnFailure: true));
batch.EnsureSuccess();
}
```
### 15.4 单轴回零
```csharp
public async Task HomeAxisZAsync(CancellationToken cancellationToken)
{
var result = await _safeAxisMotion.HomeAsync(
"Axis_Z",
timeoutMilliseconds: 30000,
cancellationToken: cancellationToken,
alarmId: 7001);
result.EnsureSuccess();
}
```
### 15.5 多轴批量回零
```csharp
public async Task HomeAllAxesAsync(CancellationToken cancellationToken)
{
var batch = await _safeAxisMotion.SafeHomeAsync(
cancellationToken,
"Axis_X",
"Axis_Y",
"Axis_Z");
batch.EnsureSuccess();
}
```
### 15.6 平台三轴等高移动
```csharp
public async Task MoveStageFlatAsync(CancellationToken cancellationToken)
{
var batch = await _stagePlatformMotionService.MoveFlatAsync(
20.0,
timeoutMilliseconds: 20000,
cancellationToken: cancellationToken);
batch.EnsureSuccess();
}
```
### 15.7 平台三轴平面移动
```csharp
public async Task MoveStagePlaneAsync(CancellationToken cancellationToken)
{
var batch = await _stagePlatformMotionService.MovePlaneAsync(
z7Target: 20.000,
z8Target: 20.150,
z9Target: 19.950,
timeoutMilliseconds: 25000,
cancellationToken: cancellationToken);
batch.EnsureSuccess();
}
```
### 15.8 直接使用 MotionController 监听事件
```csharp
var controller = new MotionController(axis);
controller.MotionStarted += (sender, e) =>
{
Console.WriteLine(
$"Start Axis={e.AxisName}, Op={e.Operation}, Start={e.StartPosition}, Target={e.TargetPosition}");
};
controller.MotionFinished += (sender, e) =>
{
Console.WriteLine(
$"Finish Axis={e.AxisName}, Success={e.Succeeded}, Cancelled={e.Cancelled}, End={e.EndPosition}, Error={e.Exception}");
};
var result = await controller.MoveAbsAsync(50.0, 10000, cancellationToken);
result.EnsureSuccess();
```
### 15.9 使用 AxisSpeedManager 切换速度档位
```csharp
public void ApplyMediumSpeedToStageX()
{
_axisSpeedManager.SetAxisSpeed("Axis_Stage_X", AxisSpeedProfile.Medium);
}
```
### 15.10 使用 AxisSpeedManager 设置自定义速度
```csharp
public void ApplyCustomSpeedToStageX()
{
_axisSpeedManager.SetAxisSpeed("Axis_Stage_X", 150.0);
}
```
### 15.11 逼近对位调用示例
```csharp
public async Task<ApproachAlignmentResult> RunApproachAlignmentAsync(CancellationToken cancellationToken)
{
var request = new ApproachAlignmentRequest(
new[]
{
new ApproachAlignmentAxis("Axis_X", 0.01) { Description = "X axis" },
new ApproachAlignmentAxis("Axis_Y", 0.01) { Description = "Y axis" }
},
camera: CameraType.UpCamera)
{
MaxIterations = 5,
MoveTimeoutMilliseconds = 30000,
RecognitionTimeoutMilliseconds = 10000
};
var result = await _approachAlignmentService.ApproachAlignmentAsync(
request,
cancellationToken);
if (!result.Succeeded)
{
throw result.Exception ?? new InvalidOperationException(result.Message);
}
return result;
}
```
### 15.12 自定义真实坐标转换器示例
```csharp
public class CalibratedCoordinateTransformer : ICoordinateTransformer
{
public Task<CoordinateTransformResult> TransformAsync(
double centerX,
double centerY,
IEnumerable<ApproachAlignmentAxis> axes)
{
var result = new CoordinateTransformResult();
foreach (var axis in axes)
{
var target = CalculateTarget(axis.AxisName, centerX, centerY);
result.AxisPositions[axis.AxisName] = target;
}
result.Succeeded = true;
return Task.FromResult(result);
}
private double CalculateTarget(string axisName, double centerX, double centerY)
{
throw new NotImplementedException();
}
}
```
## 16. 注意事项
- [`SafeAxisMotion.SafeMoveAsync()`](MainShell/Motion/SafeAxisMotion.cs:57) 当前仅用于批量绝对移动
- 单轴相对运动支持 [`MoveRelAsync()`](MainShell/Motion/SafeAxisMotion.cs:170),但没有批量相对移动入口
- 运动前安全检查已经存在,不应再按旧文档理解为“未实现”
- [`MotionMoveRequest`](MainShell/Motion/MotionMoveRequest.cs:16) 已支持 `Source``Tags``CorrelationId``BatchId``PositionTolerance``StopOnFailure`
- [`AxisSpeedManager`](MainShell/Motion/AxisSpeedManager.cs:38) 的自定义速度是基于配置比例缩放,不是固定倍数算法
- [`CoordinateTransformer`](MainShell/Motion/ApproachAlignment/CoordinateTransformer.cs:14) 当前仍是占位实现,接入前必须替换
- [`ApproachAlignmentService`](MainShell/Motion/ApproachAlignment/ApproachAlignmentService.cs:17) 是逼近对位真实入口
## 17. 总结
当前 [`MainShell/Motion`](MainShell/Motion) 模块已经具备一套较完整的运动控制框架:
- [`MotionController`](MainShell/Motion/MotionController.cs:10) 负责可靠单轴执行
- [`MotionPrecheckService`](MainShell/Motion/MotionInfrastructure.cs:50) 负责运动前安全校验
- [`SafeAxisMotion`](MainShell/Motion/SafeAxisMotion.cs:14) 负责业务层统一调用、批量联动与失败联停
- [`StagePlatformMotionService`](MainShell/Motion/StagePlatformMotionService.cs:11) 负责平台三轴动作封装
- [`AxisSpeedManager`](MainShell/Motion/AxisSpeedManager.cs:38) 负责轴速度参数下发与档位管理
- [`ApproachAlignmentService`](MainShell/Motion/ApproachAlignment/ApproachAlignmentService.cs:17) 提供逼近对位流程框架
其中基础运动控制、预检查、安全联停和平台联动已经可以作为业务入口直接使用;逼近对位部分仍需补齐真实坐标变换,才能形成可用于生产的完整闭环。