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