HalconLogicNodes.cs 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Threading;
  4. using TeamAAS.FlowEditor.Models;
  5. using TeamAAS.FlowEditor.Plugins;
  6. using Plugins.Halcon.Models;
  7. namespace Plugins.Halcon
  8. {
  9. // ─────────────────────────────────────────────────────────────────────
  10. // HALCON 逻辑判断分类算子(从主程序集迁入分类 DLL)。
  11. // 显示名/类型全名保持不变 —— 工具箱、流程文件、公式绑定全部兼容。
  12. // ─────────────────────────────────────────────────────────────────────
  13. /// <summary>H条件判断:对若干「左值 运算符 右值」条件求值,命中则执行对应后继节点(分支)。</summary>
  14. [Serializable]
  15. [Plugin("H条件判断", PluginCategory.Halocn模块, typeof(HalconIfModel), "CallSplit",
  16. NodeShape = NodeCategory.Decision, IsSubFlowNode = true, VisionCategory = VisionPlugin.其他,
  17. Description = "逻辑判断:按数值条件命中分支,执行对应后继节点(如 面积>阈值 走 OK 分支)")]
  18. public class HalconIfPlugin : BasePlugin<HalconIfModel>
  19. {
  20. public override List<OutputField> DeclareOutputs()
  21. {
  22. var list = new List<OutputField>
  23. {
  24. new OutputField("结果", typeof(bool)),
  25. new OutputField("执行分支数", typeof(int)),
  26. };
  27. int n = Model?.Conditions?.Count ?? 0;
  28. for (int i = 1; i <= n; i++)
  29. list.Add(new OutputField($"[分支]执行流程{i}", typeof(string)));
  30. return list;
  31. }
  32. public override NodeRunStatus PluginRun(CancellationToken token, out Dictionary<string, object> results)
  33. {
  34. var res = new Dictionary<string, object>();
  35. results = res;
  36. BranchTargets = new List<string>();
  37. int index = 0;
  38. try
  39. {
  40. var conditions = Model.Conditions ?? new List<HalconCondition>();
  41. Log(3, $"开始条件判断,共 {conditions.Count} 个条件");
  42. for (int i = 0; i < conditions.Count; i++)
  43. {
  44. var c = conditions[i];
  45. double left = ToDouble(GetResolve(c.Left));
  46. bool ok = Compare(left, c.Op, c.Right);
  47. Log(4, $"条件{i + 1}: {left:F3} {c.Op} {c.Right:F3} = {ok} → 目标[{c.TargetNodeName}]");
  48. if (ok && !string.IsNullOrWhiteSpace(c.TargetNodeName))
  49. {
  50. BranchTargets.Add(c.TargetNodeName);
  51. res[$"[分支]执行流程{index + 1}"] = c.TargetNodeName;
  52. index++;
  53. }
  54. }
  55. res["执行分支数"] = index;
  56. res["结果"] = index > 0;
  57. if (index == 0)
  58. {
  59. res["Error"] = "无命中分支";
  60. Log(1, "条件判断无任何分支命中", TeamAAS.LogLevel.Warning);
  61. return NodeRunStatus.Failed;
  62. }
  63. Log(2, $"条件判断命中 {index} 个分支: {string.Join(", ", BranchTargets)}");
  64. return NodeRunStatus.Success;
  65. }
  66. catch (Exception ex)
  67. {
  68. res["Error"] = ex.Message;
  69. res["结果"] = false;
  70. Log(1, $"条件判断异常: {ex.Message}", TeamAAS.LogLevel.Error);
  71. return NodeRunStatus.Failed;
  72. }
  73. }
  74. private static double ToDouble(object v)
  75. {
  76. if (v == null) return 0d;
  77. try { return Convert.ToDouble(v); }
  78. catch { return 0d; }
  79. }
  80. private static bool Compare(double left, HalconCompareOp op, double right)
  81. {
  82. switch (op)
  83. {
  84. case HalconCompareOp.大于: return left > right;
  85. case HalconCompareOp.大于等于: return left >= right;
  86. case HalconCompareOp.小于: return left < right;
  87. case HalconCompareOp.小于等于: return left <= right;
  88. case HalconCompareOp.等于: return Math.Abs(left - right) < 1e-9;
  89. case HalconCompareOp.不等于: return Math.Abs(left - right) >= 1e-9;
  90. default: return false;
  91. }
  92. }
  93. }
  94. }
  95. namespace Plugins.Halcon.Models
  96. {
  97. using PropertyGridLib.Attributes;
  98. using PropertyGridLib.Controls;
  99. using System.ComponentModel;
  100. using TeamAAS.FlowEditor.Plugins;
  101. using TeamAAS.FlowEngine.FormulaData;
  102. /// <summary>Halcon 条件判断:对若干「左值 运算符 右值」条件求值,命中则跳到对应后继节点(分支)。</summary>
  103. [Serializable]
  104. public class HalconIfModel : HalconOperatorModelBase
  105. {
  106. [Category("属性")]
  107. [DisplayName("1.条件集合")]
  108. [Description("按顺序判定每个条件,命中的分支对应后继节点会被执行(可命中多个)")]
  109. [CollectionEditor(CanAdd = true, CanRemove = true, CanSort = true)]
  110. public List<HalconCondition> Conditions { get; set; } = new List<HalconCondition>();
  111. }
  112. [Serializable]
  113. public class HalconCondition
  114. {
  115. public HalconCondition()
  116. {
  117. Left = new FormulaBound<object>();
  118. }
  119. [Category("条件")]
  120. [DisplayName("1.左值")]
  121. [Description("从子流程前序节点输出中选择(如 &{区域特征1.面积})")]
  122. [FormulaEditor(typeof(PluginDataProvider))]
  123. public FormulaBound<object> Left { get; set; }
  124. [Category("条件")]
  125. [DisplayName("2.运算符")]
  126. [Description("左值与右值的比较方式")]
  127. public HalconCompareOp Op { get; set; } = HalconCompareOp.大于;
  128. [Category("条件")]
  129. [DisplayName("3.右值")]
  130. [Description("比较阈值(数值)")]
  131. public double Right { get; set; } = 0;
  132. [Category("条件")]
  133. [DisplayName("4.执行节点名")]
  134. [Description("条件命中时要执行的后继节点的「节点名称」(须与本判断节点相连)")]
  135. public string TargetNodeName { get; set; } = "";
  136. public override string ToString() => $"{Left?.Formula ?? ""} {Op} {Right} → {TargetNodeName}";
  137. }
  138. [Serializable]
  139. public enum HalconCompareOp
  140. {
  141. 大于 = 0,
  142. 大于等于 = 1,
  143. 小于 = 2,
  144. 小于等于 = 3,
  145. 等于 = 4,
  146. 不等于 = 5,
  147. }
  148. }