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

34 KiB
Raw Blame History

Motion 运动框架使用说明

1. 文档范围

本文档基于当前代码实际实现整理,描述 MainShell/Motion 目录下已经存在的运动控制能力、调用入口、约束行为与示例代码。

说明:

  • 文档内容以当前源码实现为准。
  • 若旧文档、注释或设计稿与代码不一致,以代码为准。
  • 本文档仅描述已经实现的能力,不对未来规划功能做扩展解释。

适用对象:

  • 业务流程开发人员
  • 手动功能开发人员
  • 运动控制维护人员
  • 需要接入平台联动或视觉逼近对位功能的开发人员

2. 模块总览

当前 MainShell/Motion 目录中的能力主要包括:

  1. 单轴运动控制
  2. 批量安全运动入口
  3. 运动前安全检查与报警上报
  4. 平台三轴联动封装
  5. 速度参数下发管理
  6. 逼近对位流程框架

主要文件如下:

3. 分层理解

3.1 单轴执行层

MotionController 直接面向 IAxis / IAxisFunc,负责:

3.2 基础设施层

MotionInfrastructure.cs 中提供了几类基础设施:

3.3 请求与结果模型层

MotionMoveRequestMotionResult / MotionBatchResult 用于统一描述:

  • 运动目标
  • 超时时间
  • 报警号
  • 请求来源与标签
  • 批次号与关联号
  • 单轴结果
  • 批量结果

3.4 业务统一入口层

SafeAxisMotion 是当前推荐的业务调用入口,负责:

  • 通过轴名解析实际轴对象
  • 复用 MotionController
  • 单轴绝对/相对运动
  • 多轴绝对联动
  • 单轴/多轴回零
  • 调用 MotionPrecheckService.ValidateAsync() 做运动前安全校验
  • 失败时联动取消并停止相关轴
  • 失败后按请求配置上报报警
  • 为结果补充 CorrelationId / BatchId / FailureStage

3.5 业务场景服务层

StagePlatformMotionService 封装平台三轴动作:

3.6 视觉逼近对位层

ApproachAlignmentService 封装迭代式逼近对位流程:

  1. 识别中心
  2. 将视觉中心转换为各轴目标位置
  3. 驱动多轴移动
  4. 再次识别中心
  5. 重新计算目标位置与当前误差
  6. 判断是否收敛

4. 当前代码中的真实能力

结合当前代码,以下能力已经明确存在:

  • 单轴绝对移动
  • 单轴相对移动
  • 单轴 Jog
  • 单轴停止
  • 单轴回零
  • 多轴绝对联动移动
  • 多轴批量回零
  • 运动前安全检查
  • 失败报警上报
  • 平台三轴等高/平面联动
  • 基于视觉中心识别的迭代式逼近对位框架
  • 轴速度配置与速度档位下发

以下内容需要特别注意:

  • 批量移动仅支持绝对运动,不支持批量相对运动
  • 逼近对位中的 CoordinateTransformer 仍是占位实现
  • 文档中若提到通过 SafeAxisMotion 直接调用逼近对位,不符合当前代码真实入口

5. MotionController 说明

MotionController 是单轴动作的最终执行器。

5.1 关键属性

5.2 关键事件

5.3 关键方法

5.4 内部保障机制

MotionController 内部具备以下保障:

5.5 失败返回行为

ExecuteProtectedMotionAsync() 会捕获执行异常,并在最终返回的 MotionResult 中体现成功、取消和异常信息,而不是始终直接向外抛出异常。

因此调用后建议统一执行:

var result = await controller.MoveAbsAsync(100.0, 10000, cancellationToken);
result.EnsureSuccess();

6. MotionInfrastructure 说明

MotionInfrastructure.cs 提供了运动框架的关键支撑能力。

6.1 MotionAlarmReporter

MotionAlarmReporterAlarmOperate 做了一层封装:

  • 传入 null 报警号时直接返回 false
  • 传入有效报警号时调用 ReportAlarmAsync() 间接触发报警

6.2 MotionPrecheckService

MotionPrecheckService 在构造函数中聚合了以下安全检查:

  • MotionRequestDuplicateAxisCheck
  • MotionBatchSameSourceCheck
  • EmergencyStopReleasedCheck
  • SafetyDoorClosedCheck
  • AutoFlowModeCheck
  • StageVacuumReadyCheck
  • BondHeadSafePositionCheck
  • StagePlatformPlaneMoveSafetyCheck

调用 ValidateAsync() 时,会:

  1. 逐条执行安全规则
  2. 对失败规则记录系统错误日志
  3. 使用规则上的 AlarmId 或传入的 fallbackAlarmId 上报报警
  4. 最终抛出 InvalidOperationException

这意味着:

  • 当前代码中已经存在统一运动前预检查机制
  • SafeAxisMotion 的各类入口会先走预检查,再执行实际运动

6.3 MotionExecutionLogger

MotionExecutionLogger 负责处理:

它会输出开始位置、目标位置、结束位置、耗时、是否取消、失败阶段等日志信息。

6.4 MotionControllerRegistry

MotionControllerRegistry 负责:

  • 按轴名缓存控制器实例
  • 对同名且同引用的轴复用已有控制器
  • 在创建控制器时自动挂接 MotionExecutionLogger 事件

业务侧一般不需要自己维护 MotionController 生命周期,直接通过 SafeAxisMotion 使用即可。

7. MotionMoveRequest 说明

MotionMoveRequest 当前并不轻量,除基础字段外还已经支持业务元数据。

7.1 主要属性

7.2 创建方式

绝对运动:

相对运动:

补充元数据:

7.3 行为说明

  • TargetPosition 对绝对运动表示目标位置,对相对运动表示位移量
  • Tags 会通过 NormalizeTags() 去空、去重
  • WithMetadata() 会保留原请求主体,仅覆盖指定元数据
  • 批量绝对移动时会由 SafeAxisMotion 自动补充 CorrelationIdBatchId

8. MotionResult 与 MotionBatchResult 说明

MotionResult 包含:

常用方法:

MotionBatchResult 包含:

如果批量结果中只有一根轴失败,EnsureSuccess() 会直接抛该轴异常;如果多根轴失败,会抛 AggregateException

9. SafeAxisMotion 说明

SafeAxisMotion 是当前业务最推荐使用的统一入口。

9.1 主要能力

  • 单轴绝对移动
  • 单轴相对移动
  • 多轴绝对联动移动
  • 单轴回零
  • 多轴批量回零
  • 轴名解析
  • 控制器缓存与日志挂接
  • 运动前安全预检查
  • 失败联动停轴
  • 失败报警
  • 批次与关联信息补充

9.2 主要异步方法

单轴移动:

批量绝对移动:

回零:

同步封装:

9.3 真实执行流程

MoveAbsAsync() 为例,执行顺序为:

  1. 构造 MotionMoveRequest
  2. 调用 EnsureRequestBatchMetadata() 补齐关联元数据
  3. 解析轴对象
  4. 调用 MotionPrecheckService.ValidateAsync() 执行预检查
  5. 调用内部 MoveAbsInternalAsync()
  6. 通过 MotionControllerRegistry.GetController() 获取控制器并执行运动
  7. 按请求补充结果元数据与失败阶段
  8. 必要时上报报警

9.4 批量运动行为说明

SafeMoveAsync() 当前执行的是多轴绝对联动:

9.5 超时与失败细节

  • NormalizeTimeout() 会把小于等于 0 的超时值恢复为默认值
  • 失败结果会通过 WithFailureDetails() 写入 FailureStageTimedOutStoppedByCoordinatorCorrelationIdBatchId
  • alarmId 为空时,失败不会触发报警
  • stopOnFailure = false 时,失败不会触发联动停轴

10. MotionSafetyStateProvider 说明

MotionSafetyStateProvider 为预检查规则提供外部状态。

10.1 主要能力

10.2 行为说明

  • DeviceIo 离线时,多数安全状态会直接返回不可用或不安全结果
  • 安全门支持 SecurityDoorShield 旁路逻辑
  • 自动流程判断不是只看精确名称,也支持来源字符串包含 Auto

11. StagePlatformMotionService 说明

StagePlatformMotionService 封装平台三轴 Axis_Stage_Z7Axis_Stage_Z8Axis_Stage_Z9 的联动动作。

11.1 主要方法

11.2 内部实现方式

11.3 使用建议

只要是平台三轴动作,建议统一走 StagePlatformMotionService,不要在业务代码里手工拼三轴请求。

12. AxisSpeedManager 说明

AxisSpeedManager 用于从系统参数生成速度曲线并下发到轴参数。

12.1 相关类型

12.2 主要方法

12.3 真实行为说明

SetAxisSpeed(string axisName, double speed) 的行为不是固定倍数计算,而是:

  1. 从速度参数表中找到该轴对应的 SpeedTypeItem
  2. 以配置基准速度 speedItem.Speed 为基数
  3. speed / speedItem.Speed 计算缩放比例
  4. 按比例缩放 Acc / Dec / Jerk
  5. 最终通过 ApplyAxisMotionProfile() 下发到轴参数

SetAxisSpeed(string axisName, AxisSpeedProfile profile) 的行为是:

ApplySpeedSettings() 的行为是:

  • GlobalParam.SpeedParaSysSetting.SpeedTypeItemCollection.SpeedTypeItemList 读取所有速度配置
  • 根据当前 CurrentSpeedType 通过 MapCurrentSpeedTypeText() 映射到 Low / Medium / High
  • 对每根轴生成对应档位的速度参数并下发

12.4 校验与异常

AxisSpeedManager 会校验:

  • 轴名不能为空
  • 轴必须存在
  • 轴必须有对应速度配置
  • 速度、加速度、减速度、Jerk 必须为正且有限值,见 ValidatePositiveFinite()
  • 百分比必须在 (0, 100] 范围内,见 ValidatePercent()

13. 逼近对位模块说明

13.1 组成文件

13.2 核心类型

ApproachAlignment.cs 中定义了:

13.3 ApproachAlignmentRequest 说明

ApproachAlignmentRequest 构造函数要求至少传入一根轴,并提供以下默认值:

  • Camera = CameraType.UpCamera
  • MaxIterations = 5
  • MoveTimeoutMilliseconds = 30000
  • RecognitionTimeoutMilliseconds = 10000

13.4 ApproachAlignmentService 流程

ApproachAlignmentService.ApproachAlignmentAsync() 当前流程如下:

  1. 最多执行 MaxIterations 次迭代
  2. 首次迭代调用 RecognizeCenterAsync() 识别中心
  3. 调用 ICoordinateTransformer.TransformAsync() 计算各轴目标位置
  4. 将目标位置转成 MotionMoveRequest.ForAxisName()
  5. 调用 SafeAxisMotion.SafeMoveAsync() 执行多轴移动
  6. 再次识别中心
  7. 再次转换,得到理论目标位置
  8. 读取各轴当前位置并计算误差
  9. 若全部轴误差都小于等于容差,则成功结束
  10. 否则进入下一轮迭代

13.5 CenterRecognizer 现状

CenterRecognizer 已接入视觉算法服务:

  • 依赖 IVisionAlgorithmService
  • 使用 VisionProcessRequest
  • AlgorithmType = VisionAlgorithmType.FindCenter
  • CaptureOptions = CameraCaptureOptions.CreateStream(timeoutMilliseconds)
  • 从结果中读取 OffsetX / OffsetY
  • 识别失败或超时返回 null

13.6 CoordinateTransformer 现状

CoordinateTransformer 当前仍是占位实现。

实际行为:

  • 若轴列表为空,则返回 Succeeded = false
  • 否则延时约 10ms 后,为每根轴写入 0.0 作为目标位置
  • 返回 Succeeded = true

这表示:

  • 逼近对位的流程框架已经存在
  • 但真实标定坐标变换尚未完成
  • 若直接用于生产逻辑,会把各轴目标位置算成固定 0.0

13.7 当前真实入口

当前应直接注入并调用 ApproachAlignmentService.ApproachAlignmentAsync(),而不是通过 SafeAxisMotion 调用逼近对位。

14. 推荐调用方式

14.1 普通业务运动

优先调用 SafeAxisMotion

14.2 平台三轴业务

统一调用 StagePlatformMotionService

14.3 单轴调试或事件监听

可以直接使用 MotionController

14.4 逼近对位业务

当前应直接调用 ApproachAlignmentService,前提是先替换 CoordinateTransformer 为真实可用的标定变换实现。

15. 示例代码

15.1 单轴绝对移动

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 单轴相对移动

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 带元数据的多轴绝对联动

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 单轴回零

public async Task HomeAxisZAsync(CancellationToken cancellationToken)
{
    var result = await _safeAxisMotion.HomeAsync(
        "Axis_Z",
        timeoutMilliseconds: 30000,
        cancellationToken: cancellationToken,
        alarmId: 7001);

    result.EnsureSuccess();
}

15.5 多轴批量回零

public async Task HomeAllAxesAsync(CancellationToken cancellationToken)
{
    var batch = await _safeAxisMotion.SafeHomeAsync(
        cancellationToken,
        "Axis_X",
        "Axis_Y",
        "Axis_Z");

    batch.EnsureSuccess();
}

15.6 平台三轴等高移动

public async Task MoveStageFlatAsync(CancellationToken cancellationToken)
{
    var batch = await _stagePlatformMotionService.MoveFlatAsync(
        20.0,
        timeoutMilliseconds: 20000,
        cancellationToken: cancellationToken);

    batch.EnsureSuccess();
}

15.7 平台三轴平面移动

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 监听事件

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 切换速度档位

public void ApplyMediumSpeedToStageX()
{
    _axisSpeedManager.SetAxisSpeed("Axis_Stage_X", AxisSpeedProfile.Medium);
}

15.10 使用 AxisSpeedManager 设置自定义速度

public void ApplyCustomSpeedToStageX()
{
    _axisSpeedManager.SetAxisSpeed("Axis_Stage_X", 150.0);
}

15.11 逼近对位调用示例

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 自定义真实坐标转换器示例

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. 注意事项

17. 总结

当前 MainShell/Motion 模块已经具备一套较完整的运动控制框架:

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