Files
XplorePlane/XplorePlane/Models/CncModels.cs
T
zhengxuan.zhang b95941cb50 feat: CNC 编排新增硬件控制能力(位置硬件还原 + 四类动作节点)
在 CNC 编排层补齐 P0 硬件控制能力,使检测编排可覆盖设备测试与校准流程。

位置节点硬件状态还原(核心):
- SavePositionNode 新增可选探测器采集参数快照,兼容旧 .xp 文件
- 执行到位后按序还原射线源电压/电流与探测器参数(先电压后电流)
- 射线未开弹窗提醒并暂停;还原失败弹窗提示并暂停不继续;服务不可用降级跳过
- 新增 ICncInteractionService 封装弹窗交互,便于单元测试

四类硬件动作节点:
- 射线源控制:开/关/设参/暖机/训机,安全时序 + 稳定等待
- 探测器校正:暗场/增益/坏像素/自动
- 安全门控制:开门/关门,复用内置联锁
- 几何设置:按 FDD 或放大倍率反算定位

模型、编辑器与工具栏接线:
- CncNodeType 追加四枚举值 + 四类节点 record + 多态判别符 + 值域校验
- 编辑器新增插入命令、类型判定、图标与工具栏入口
- IDetectorService 预留当前采集参数读取接口(暂返回 null,待硬件层完善)

系统设置:
- 新增数据存储根目录与日志目录配置及浏览按钮
- 修复保存时重复打开配置文件导致的配置冲突异常

测试:
- 新增 33 个单元测试,覆盖序列化往返、旧文件兼容、节点分派/降级/失败、
  位置还原全路径与混合程序执行
2026-07-03 14:09:24 +08:00

271 lines
10 KiB
C#
Raw 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.
using System;
using System.Collections.Generic;
using System.Text.Json.Serialization;
namespace XplorePlane.Models
{
// ── CNC 节点类型枚举 | CNC Node Type Enumeration ──────────────────
/// <summary>CNC 节点类型 | CNC node type</summary>
[JsonConverter(typeof(JsonStringEnumConverter))]
public enum CncNodeType
{
ReferencePoint,
SaveNodeWithImage,
SaveNode,
SavePosition,
InspectionModule,
InspectionMarker,
PauseDialog,
WaitDelay,
CompleteProgram,
Reset,
// ── 硬件控制节点(P0| Hardware control nodes ──
RaySourceControl,
DetectorCorrection,
DoorControl,
Geometry
}
// ── CNC 节点基类与派生类型 | CNC Node Base & Derived Types ────────
/// <summary>
/// CNC 节点抽象基类(不可变)| CNC node abstract base (immutable)
/// 使用 System.Text.Json 多态序列化 | Uses System.Text.Json polymorphic serialization
/// </summary>
[JsonDerivedType(typeof(ReferencePointNode), "ReferencePoint")]
[JsonDerivedType(typeof(SaveNodeWithImageNode), "SaveNodeWithImage")]
[JsonDerivedType(typeof(SaveNodeNode), "SaveNode")]
[JsonDerivedType(typeof(SavePositionNode), "SavePosition")]
[JsonDerivedType(typeof(InspectionModuleNode), "InspectionModule")]
[JsonDerivedType(typeof(InspectionMarkerNode), "InspectionMarker")]
[JsonDerivedType(typeof(PauseDialogNode), "PauseDialog")]
[JsonDerivedType(typeof(WaitDelayNode), "WaitDelay")]
[JsonDerivedType(typeof(CompleteProgramNode), "CompleteProgram")]
[JsonDerivedType(typeof(ResetNode), "Reset")]
[JsonDerivedType(typeof(RaySourceControlNode), "RaySourceControl")]
[JsonDerivedType(typeof(DetectorCorrectionNode), "DetectorCorrection")]
[JsonDerivedType(typeof(DoorControlNode), "DoorControl")]
[JsonDerivedType(typeof(GeometryNode), "Geometry")]
public abstract record CncNode(
Guid Id,
int Index,
CncNodeType NodeType,
string Name);
/// <summary>参考点节点 | Reference point node</summary>
public record ReferencePointNode(
Guid Id,
int Index,
string Name,
double StageX,
double StageY,
double SourceZ,
double DetectorZ,
double DetectorSwing,
double FDD,
bool IsRayOn,
double Voltage,
double Current,
double StageRotation = 0,
double FixtureRotation = 0,
double FOD = 0,
double Magnification = 0) : CncNode(Id, Index, CncNodeType.ReferencePoint, Name);
/// <summary>保存节点(含图像)| Save node with image</summary>
public record SaveNodeWithImageNode(
Guid Id,
int Index,
string Name,
MotionState MotionState,
RaySourceState RaySourceState,
DetectorState DetectorState,
string ImageFileName) : CncNode(Id, Index, CncNodeType.SaveNodeWithImage, Name);
/// <summary>保存节点(不含图像)| Save node without image</summary>
public record SaveNodeNode(
Guid Id,
int Index,
string Name,
MotionState MotionState,
RaySourceState RaySourceState,
DetectorState DetectorState) : CncNode(Id, Index, CncNodeType.SaveNode, Name);
/// <summary>保存位置节点 | Save position node</summary>
public record SavePositionNode(
Guid Id,
int Index,
string Name,
MotionState MotionState,
RaySourceState RaySourceState = null,
bool SaveImage = false,
string ManualImagePath = "",
DetectorAcquisitionSnapshot DetectorAcq = null) : CncNode(Id, Index, CncNodeType.SavePosition, Name);
/// <summary>检测模块节点 | Inspection module node</summary>
public record InspectionModuleNode(
Guid Id,
int Index,
string Name,
PipelineModel Pipeline) : CncNode(Id, Index, CncNodeType.InspectionModule, Name);
/// <summary>检测标记节点 | Inspection marker node</summary>
public record InspectionMarkerNode(
Guid Id,
int Index,
string Name,
string MarkerType,
double MarkerX,
double MarkerY) : CncNode(Id, Index, CncNodeType.InspectionMarker, Name);
/// <summary>停顿对话框节点 | Pause dialog node</summary>
public record PauseDialogNode(
Guid Id,
int Index,
string Name,
string DialogTitle,
string DialogMessage) : CncNode(Id, Index, CncNodeType.PauseDialog, Name);
/// <summary>等待延时节点 | Wait delay node</summary>
public record WaitDelayNode(
Guid Id,
int Index,
string Name,
int DelayMilliseconds) : CncNode(Id, Index, CncNodeType.WaitDelay, Name);
/// <summary>完成程序节点 | Complete program node</summary>
public record CompleteProgramNode(
Guid Id,
int Index,
string Name) : CncNode(Id, Index, CncNodeType.CompleteProgram, Name);
/// <summary>复位节点:执行时调用运动层接口将各轴回到复位/原点位置 | Reset node: invokes the motion-layer interface to home/reset axes during execution</summary>
public record ResetNode(
Guid Id,
int Index,
string Name) : CncNode(Id, Index, CncNodeType.Reset, Name);
// ── 硬件控制节点(P0| Hardware Control Nodes ────────────────────
/// <summary>探测器可下发采集参数快照(用于位置节点还原)| Detector down-loadable acquisition parameters snapshot (for position node restore)</summary>
public record DetectorAcquisitionSnapshot(
int BinningIndex,
int Pga,
decimal FrameRate);
/// <summary>射线源动作 | X-ray source action</summary>
[JsonConverter(typeof(JsonStringEnumConverter))]
public enum RaySourceAction
{
/// <summary>开射线 | Turn on X-ray</summary>
TurnOn,
/// <summary>关射线 | Turn off X-ray</summary>
TurnOff,
/// <summary>设置参数(电压+电流,不改变开关状态)| Set voltage/current without changing on/off state</summary>
SetParameters,
/// <summary>暖机 | Warm-up</summary>
WarmUp,
/// <summary>训机 | Training</summary>
Training
}
/// <summary>射线源控制节点 | X-ray source control node</summary>
public record RaySourceControlNode(
Guid Id,
int Index,
string Name,
RaySourceAction Action,
double Voltage, // 电压(kV| Voltage (kV)
double Current, // 电流(μA| Current (μA)
bool WaitForStable = true,
int StableTimeoutMs = 10000) : CncNode(Id, Index, CncNodeType.RaySourceControl, Name);
/// <summary>探测器校正类型 | Detector correction type</summary>
[JsonConverter(typeof(JsonStringEnumConverter))]
public enum DetectorCorrectionType
{
/// <summary>暗场校正 | Dark field correction</summary>
Dark,
/// <summary>增益(亮场)校正 | Gain (bright field) correction</summary>
Gain,
/// <summary>坏像素校正 | Bad pixel correction</summary>
BadPixel,
/// <summary>自动校正(暗场+增益+坏像素)| Auto correction (dark + gain + bad pixel)</summary>
Auto
}
/// <summary>探测器校正节点 | Detector correction node</summary>
public record DetectorCorrectionNode(
Guid Id,
int Index,
string Name,
DetectorCorrectionType CorrectionType,
int FrameCount = 10) : CncNode(Id, Index, CncNodeType.DetectorCorrection, Name);
/// <summary>安全门动作 | Safety door action</summary>
[JsonConverter(typeof(JsonStringEnumConverter))]
public enum DoorAction
{
/// <summary>开门 | Open door</summary>
Open,
/// <summary>关门 | Close door</summary>
Close
}
/// <summary>安全门控制节点 | Safety door control node</summary>
public record DoorControlNode(
Guid Id,
int Index,
string Name,
DoorAction Action,
bool WaitForComplete = true,
int TimeoutMs = 15000) : CncNode(Id, Index, CncNodeType.DoorControl, Name);
/// <summary>几何设置模式 | Geometry setup mode</summary>
[JsonConverter(typeof(JsonStringEnumConverter))]
public enum GeometryMode
{
/// <summary>由 FOD + FDD 反算 | Inverse from FOD + FDD</summary>
ByFdd,
/// <summary>由 FOD + 放大倍率反算 | Inverse from FOD + magnification</summary>
ByMagnification
}
/// <summary>几何设置节点 | Geometry setup node</summary>
public record GeometryNode(
Guid Id,
int Index,
string Name,
GeometryMode Mode,
double Fod, // 焦点-物体距离(mm| Focus-object distance (mm)
double Fdd = 0, // 焦点-探测器距离(mm| Focus-detector distance (mm)
double Magnification = 0,
bool WaitForSettled = true) : CncNode(Id, Index, CncNodeType.Geometry, Name);
// ── CNC 程序 | CNC Program ────────────────────────────────────────
/// <summary>CNC 程序(不可变)| CNC program (immutable)</summary>
public record CncProgram(
Guid Id,
string Name,
DateTime CreatedAt,
DateTime UpdatedAt,
IReadOnlyList<CncNode> Nodes
);
// ── 节点执行状态 | Node Execution State ──────────────────────────
/// <summary>节点执行状态枚举 | Node execution state enumeration</summary>
public enum NodeExecutionState
{
/// <summary>未执行(默认)| Not yet executed (default)</summary>
Idle,
/// <summary>正在执行 | Currently executing</summary>
Running,
/// <summary>执行成功 | Execution succeeded</summary>
Succeeded,
/// <summary>执行失败 | Execution failed</summary>
Failed
}
}