Files

830 lines
34 KiB
Markdown
Raw Permalink Normal View History

# 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) 提供逼近对位流程框架
其中基础运动控制、预检查、安全联停和平台联动已经可以作为业务入口直接使用;逼近对位部分仍需补齐真实坐标变换,才能形成可用于生产的完整闭环。