src/Bro.Common.Device/DeviceBase/PLCBase.cs
@@ -280,6 +280,11 @@ return locations; } public bool MoveToPoint(IOperationConfig opConfig) { throw new NotImplementedException(); } #endregion } src/Bro.Common.Device/Interface/IMotion.cs
@@ -1,4 +1,5 @@ using Bro.Common.Helper; using Bro.Common.Interface; using System; using System.Collections.Generic; using System.Linq; @@ -13,6 +14,13 @@ public interface IMotion { List<AxisInfo> GetCurrentAxisInfo(params string[] axisName); /// <summary> /// 运动机构点到点移动 /// </summary> /// <param name="opConfig">运动配置</param> /// <returns>true:正常结束 false:异常结束</returns> bool MoveToPoint(IOperationConfig opConfig); } public class AxisInfo : IComplexDisplay src/Bro.Common.Model/Model/Spec.cs
@@ -15,7 +15,7 @@ { [Category("通用配置")] [Description("标准代码")] public string Code { get; set; } public virtual string Code { get; set; } [Category("通用配置")] [Description("启用状态,true:启用;false:禁用")] @@ -25,22 +25,22 @@ [Category("标准配置")] [Description("标准值")] [DisplayName("标准值")] public float StandardValue { get; set; } public double StandardValue { get; set; } [Category("标准配置")] [Description("正公差")] [DisplayName("正公差")] public float Tolrenance_Positive { get; set; } public double Tolrenance_Positive { get; set; } [Category("标准配置")] [Description("负公差")] [DisplayName("负公差")] public float Tolrenance_Negative { get; set; } public double Tolrenance_Negative { get; set; } protected float? actualValue = null; protected double? actualValue = null; [Browsable(false)] [JsonIgnore] public virtual float? ActualValue public virtual double? ActualValue { get { @@ -67,7 +67,7 @@ [Browsable(false)] [JsonIgnore] public bool MeasureResult { get; set; } = false; public bool? MeasureResult { get; set; } = null; public virtual string GetCSVHead() { src/Bro.Device.Gocator/Bro.Device.Gocator.csproj
@@ -45,5 +45,15 @@ <Compile Include="GocatorDriver.cs" /> <Compile Include="Properties\AssemblyInfo.cs" /> </ItemGroup> <ItemGroup> <ProjectReference Include="..\Bro.Common.Device\Bro.Common.Device.csproj"> <Project>{987308DD-8BAA-463A-94E2-77D62E01A5BF}</Project> <Name>Bro.Common.Device</Name> </ProjectReference> <ProjectReference Include="..\Bro.Common.Model\Bro.Common.Model.csproj"> <Project>{1a3cbfe7-3f78-42c3-95c5-10360450dbea}</Project> <Name>Bro.Common.Model</Name> </ProjectReference> </ItemGroup> <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> </Project> src/Bro.Device.Gocator/GocatorConfig.cs
@@ -1,4 +1,6 @@ using System; using Bro.Common.Base; using Bro.Common.Helper; using System; using System.Collections.Generic; using System.Linq; using System.Text; @@ -6,7 +8,13 @@ namespace Bro.Device.Gocator { class GocatorConfig [Device("Gocator", "Gocator激光扫描仪", EnumHelper.DeviceAttributeType.InitialConfig)] public class GocatorInitialConfig : CameraInitialConfigBase { } [Device("Gocator", "Gocator激光扫描仪", EnumHelper.DeviceAttributeType.OperationConfig)] public class GocatorOperationConfig : CameraOprerationConfigBase { } } src/Bro.Device.Gocator/GocatorDriver.cs
@@ -1,4 +1,7 @@ using System; using Bro.Common.Base; using Bro.Common.Helper; using Bro.Common.Interface; using System; using System.Collections.Generic; using System.Linq; using System.Text; @@ -6,7 +9,37 @@ namespace Bro.Device.Gocator { class GocatorDriver [Device("Gocator", "Gocator激光扫描仪", EnumHelper.DeviceAttributeType.Device)] public class GocatorDriver : CameraBase { public override IOperationConfig GetOperationConfigFromDevice() { throw new NotImplementedException(); } public override void Snapshot() { throw new NotImplementedException(); } public override void UploadOperationConfig(IOperationConfig config) { throw new NotImplementedException(); } protected override void Init() { throw new NotImplementedException(); } protected override void Pause() { throw new NotImplementedException(); } protected override void Resume() { throw new NotImplementedException(); } } } src/Bro.M071.Process/Bro.M071.Process.csproj
@@ -39,6 +39,17 @@ <Reference Include="Autofac, Version=4.9.4.0, Culture=neutral, PublicKeyToken=17863af14b0044da, processorArchitecture=MSIL"> <HintPath>..\..\packages\Autofac.4.9.4\lib\net45\Autofac.dll</HintPath> </Reference> <Reference Include="halcondotnet, Version=12.0.0.0, Culture=neutral, PublicKeyToken=4973bed59ddbf2b8, processorArchitecture=MSIL"> <SpecificVersion>False</SpecificVersion> <HintPath>..\..\libs\halcon12\halcondotnet.dll</HintPath> </Reference> <Reference Include="hdevenginedotnet, Version=12.0.0.0, Culture=neutral, PublicKeyToken=4973bed59ddbf2b8, processorArchitecture=MSIL"> <SpecificVersion>False</SpecificVersion> <HintPath>..\..\libs\halcon12\hdevenginedotnet.dll</HintPath> </Reference> <Reference Include="Newtonsoft.Json, Version=11.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL"> <HintPath>..\..\packages\Newtonsoft.Json.11.0.2\lib\net45\Newtonsoft.Json.dll</HintPath> </Reference> <Reference Include="System" /> <Reference Include="System.Core" /> <Reference Include="System.Xml.Linq" /> src/Bro.M071.Process/M071Config.cs
@@ -22,10 +22,10 @@ public List<string> KeyNameCollection { get; set; } = new List<string>(); [Category("公共字典配置")] [Description("检测标准集合")] [Description("检测类型和标准集合")] [TypeConverter(typeof(CollectionCountConvert))] [Editor(typeof(ComplexCollectionEditor<Spec>), typeof(UITypeEditor))] public List<Spec> MeasureSpecCollection { get; set; } = new List<Spec>(); [Editor(typeof(ComplexCollectionEditor<MeasureType>), typeof(UITypeEditor))] public List<MeasureType> MeasureTypeCollection { get; set; } = new List<MeasureType>(); [Category("公共字典配置")] [Description("单键算法配置集合")] src/Bro.M071.Process/M071Converters.cs
@@ -49,10 +49,10 @@ if (iConfig is M071Config config) { config.SnapshotPointCollection.ForEach(s => { table[s.Id] = s.Name; }); config.SnapshotPointCollection.Where(u => u.IsEnabled).ToList().ForEach(s => { table[s.Id] = s.Name; }); } } @@ -141,7 +141,7 @@ if (iConfig is M071Config config) { var resultIds = config.KeyUnitCollection.Where(u => u.Key == (context.Instance as KeyUnitBind).Key).Select(u => u.KeyResult).ToList(); var resultIds = config.KeyUnitCollection.Where(u => u.IsEnabled && u.Key == (context.Instance as KeyUnitBind).Key).Select(u => u.KeyResultId).ToList(); var result = config.KeyResultCollection.Where(u => resultIds.Contains(u.Id)).SelectMany(u => u.Results).ToList(); @@ -149,10 +149,10 @@ { result.ForEach(r => { table[r] = r; table.Add(r, r); }); table[""] = ""; table.Add("All", "All"); } } } @@ -181,7 +181,7 @@ if (iConfig is M071Config config) { return new StandardValuesCollection(config.MeasureSpecCollection.Select(u => u.Code).ToList()); return new StandardValuesCollection(config.MeasureTypeCollection.Select(u => u.Code).ToList()); } } src/Bro.M071.Process/M071Models.cs
@@ -3,6 +3,7 @@ using Bro.Common.Helper; using Bro.Common.Interface; using Bro.Common.Model; using Newtonsoft.Json; using System; using System.Collections.Generic; using System.ComponentModel; @@ -34,6 +35,19 @@ } } public class MeasureType : Spec { [Category("检测类型")] [Description("检测类型")] [DisplayName("检测类型")] public override string Code { get; set; } [Category("检测算法")] [Description("检测算法路径")] [Editor(typeof(FileDialogEditor), typeof(UITypeEditor))] public string AlgorithemPath { get; set; } } public class KeyResult : IComplexDisplay { [Browsable(false)] @@ -59,7 +73,7 @@ { public string GetDisplayText() { return Name + " " + string.Join(" ", Destination.Select(u => u.GetDisplayText())) + " " + CameraOp.GetDisplayText(); return (IsEnabled ? "" : "禁用 ") + Name + " " + string.Join(" ", Destination.Select(u => u.GetDisplayText())) + " " + CameraOp.GetDisplayText(); } public List<string> GetHalconToolPathList() @@ -81,6 +95,10 @@ [Description("拍照点名称")] public string Name { get; set; } [Category("启用设置")] [Description("true:启用 false:禁用")] public bool IsEnabled { get; set; } = true; [Category("设备配置")] [Description("运动设备")] [TypeConverter(typeof(DeviceSelectorConverter<IMotion>))] @@ -101,6 +119,7 @@ public class KeyUnit : IComplexDisplay, IHalconToolPath { #region 配置 private string key = ""; [Category("键名配置")] [Description("单键检测键名")] @@ -118,24 +137,36 @@ [Description("别名")] public string AlignName { get; set; } [Category("启用设置")] [Description("true:启用 false:禁用")] public bool IsEnabled { get; set; } = true; [Category("图像来源")] [Description("拍照点位")] [TypeConverter(typeof(SnapshotPointConverter))] public string SnapshotPoint { get; set; } public string SnapshotPointId { get; set; } [Category("图像来源")] [Description("拍照点位获取的图片索引")] public int ImageIndex { get; set; } = 0; [Description("拍照点位获取的图片序号,从1开始")] public int ImageSeq { get; set; } = 1; [Category("算法配置")] [Description("单键检测配置算法类型")] [TypeConverter(typeof(KeyAlgorithemConverter))] public string KeyAlgorithem { get; set; } public string KeyAlgorithemId { get; set; } [Category("算法配置")] [Description("单键检测配置结果类型")] [TypeConverter(typeof(KeyResultConverter))] public string KeyResult { get; set; } public string KeyResultId { get; set; } #endregion #region 检测相关字段 public Dictionary<string, double> KeyValues = null; //public SnapshotPoint SnapshotPoint = null; public string KeyAlgorithemPath = ""; public List<string> KeyResultList = null; #endregion public string GetDisplayText() { @@ -144,15 +175,68 @@ public List<string> GetHalconToolPathList() { return null; using (var scope = GlobalVar.Container.BeginLifetimeScope()) { IProcessConfig iConfig = scope.Resolve<IProcessConfig>(); if (iConfig is M071Config config) { var algo = config.KeyAlgorithemCollection.FirstOrDefault(u => u.Id == KeyAlgorithemId); if (algo != null) { return new List<string>() { algo.AlgorithemPath }; } } } return new List<string>(); } } public class MeasurementUint : IComplexDisplay public class ProductionMeasurement : INotifyPropertyChanged, IDisposable { public string Barcode { get; set; } public List<MeasurementUint> Measurements { get; set; } = new List<MeasurementUint>(); public event PropertyChangedEventHandler PropertyChanged; public void Dispose() { Barcode = null; Measurements?.ForEach(m => m?.Dispose()); Measurements = null; GC.Collect(); } public void InitialMeasurementsPropertyChanged() { Measurements.ForEach(m => m.PropertyChanged += M_PropertyChanged); } private object pChangedLock = new object(); private void M_PropertyChanged(object sender, PropertyChangedEventArgs e) { lock (pChangedLock) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("Measurements")); } } } public class MeasurementUint : IComplexDisplay, INotifyPropertyChanged, IDisposable { public string Id = Guid.NewGuid().ToString(); #region 配置 [Category("名称")] [Description("名称")] public string Name { get; set; } = ""; [Category("启用设置")] [Description("true:启用 false:禁用")] public bool IsEnabled { get; set; } = true; [Category("算法配置")] [Description("检测和标准类型")] @@ -164,24 +248,51 @@ [TypeConverter(typeof(ComplexObjectConvert))] [Editor(typeof(ComplexCollectionEditor<KeyUnitBind>), typeof(UITypeEditor))] public List<KeyUnitBind> KeyUnitCollection { get; set; } = new List<KeyUnitBind>(); #endregion #region 显示 [Browsable(false)] public RectangleF DisplayLocation { get; set; } = new RectangleF(); public Rectangle DisplayLocation { get; set; } = new Rectangle(); #endregion #region 检测结果 [Browsable(false)] public MeasureType Spec { get; set; } = null; #endregion public bool IsUpdated = false; public event PropertyChangedEventHandler PropertyChanged; public void Dispose() { KeyUnitCollection?.ForEach(k => k?.Dispose()); KeyUnitCollection = null; } public string GetDisplayText() { if (string.IsNullOrWhiteSpace(Name)) { return string.Join("-", KeyUnitCollection.Select(u => u.GetDisplayText())) + "-" + MeasureType.ToString(); return (IsEnabled ? "" : "禁用 ") + string.Join("-", KeyUnitCollection.Select(u => u.GetDisplayText())) + "-" + MeasureType.ToString(); } else { return Name; return (IsEnabled ? "" : "禁用 ") + Name; } } public void InitialKeyUnitMeasureChanged() { KeyUnitCollection.ForEach(k => k.PropertyChanged += K_PropertyChanged); } private void K_PropertyChanged(object sender, PropertyChangedEventArgs e) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("KeyUnitCollection")); } } public class KeyUnitBind : IComplexDisplay public class KeyUnitBind : IComplexDisplay, INotifyPropertyChanged, IDisposable { [Category("单键配置")] [Description("单键配置")] @@ -193,6 +304,26 @@ [TypeConverter(typeof(KeyUnitResultConverter))] public string KeyResult { get; set; } = ""; //[Browsable(false)] //public NoticedDictionary<string, double?> MeasureValueDict { get; set; } = new NoticedDictionary<string, double?>(); [Browsable(false)] public Dictionary<string, double?> MeasureValueDict { get; set; } = new Dictionary<string, double?>(); public event PropertyChangedEventHandler PropertyChanged; //public void InitialMeasureValueDictPropertyChanged() //{ // MeasureValueDict.PropertyChanged += MeasureValueDict_PropertyChanged; //} //private void MeasureValueDict_PropertyChanged(object sender, PropertyChangedEventArgs e) //{ // PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("MeasureValueDict")); //} public bool? IsDone = null; public string GetDisplayText() { string msg = Key; @@ -201,5 +332,55 @@ return msg; } public void Dispose() { MeasureValueDict = null; } object valueDictLock = new object(); public void FillKeyValues(Dictionary<string, double> valuePairs) { lock (valueDictLock) { if (valuePairs == null || valuePairs.Count == 0) { IsDone = false; } foreach (KeyValuePair<string, double> pair in valuePairs) { if (MeasureValueDict.ContainsKey(pair.Key)) { MeasureValueDict[pair.Key] = pair.Value; } } if (MeasureValueDict.Values.All(u => u != null)) { IsDone = true; } if (IsDone != null) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("IsDone")); } } } } //public class NoticedDictionary<T1, T2> : Dictionary<T1, T2>, INotifyPropertyChanged //{ // public event PropertyChangedEventHandler PropertyChanged; // public new T2 this[T1 index] // { // get => base[index]; // set // { // base[index] = value; // PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("Index")); // } // } //} } src/Bro.M071.Process/M071Process.cs
@@ -1,8 +1,13 @@ using Bro.Common.Helper; using Bro.Common.Base; using Bro.Common.Helper; using Bro.Common.Interface; using Bro.Common.Model; using Bro.Process; using HalconDotNet; using System; using System.Collections.Generic; using System.ComponentModel; using System.IO; using System.Linq; using System.Text; using System.Threading.Tasks; @@ -23,5 +28,361 @@ get => IConfig as M071Config; } #endregion #region 事件 public event Action OnMeasureStart; public event Action<string> OnBarcodeChanged; public event Action<IShapeElement> OnElementUpdated; #endregion public override void Open() { InitialSetting(); base.Open(); } private void InitialSetting() { Config.SnapshotPointCollection.ForEach(u => { u.GetHalconToolPathList().ForEach(path => { LoadHalconTool(path, u.Id); }); }); Config.KeyUnitCollection.ForEach(u => { if (!u.IsEnabled) return; var snapshotPoint = Config.SnapshotPointCollection.FirstOrDefault(s => s.Id == u.SnapshotPointId && s.IsEnabled); if (snapshotPoint == null) throw new ProcessException($"{u.AlignName}未设置可用拍照点位"); if (u.ImageSeq < 1) throw new ProcessException($"{u.AlignName}图片序号小于1"); var algo = Config.KeyAlgorithemCollection.FirstOrDefault(a => a.Id == u.KeyAlgorithemId); if (algo == null) throw new ProcessException($"{u.AlignName}未设置检测算法"); u.KeyAlgorithemPath = algo.AlgorithemPath; LoadHalconTool(u.KeyAlgorithemPath, u.AlignName); var resultSet = Config.KeyResultCollection.FirstOrDefault(r => r.Id == u.KeyResultId); if (resultSet == null) throw new ProcessException($"{u.AlignName}未设置检测结果配置"); u.KeyResultList = new List<string>(resultSet.Results); }); Config.MeasurementUnitCollection.ForEach(u => { if (!u.IsEnabled) return; var spec = Config.MeasureTypeCollection.FirstOrDefault(s => s.Code == u.MeasureType); if (spec == null) throw new ProcessException($"{u.GetDisplayText()}未设置检测类型"); u.Spec = new MeasureType(); u.Spec.DataFrom(spec); LoadHalconTool(u.Spec.AlgorithemPath, u.Id); u.KeyUnitCollection.ForEach(b => { var keyRespone = Config.KeyUnitCollection.Where(ku => ku.IsEnabled && ku.Key == b.Key).ToList(); if (keyRespone.Count == 0) throw new ProcessException($"{u.GetDisplayText()}对应的单键不存在或不可用"); if (b.KeyResult == "All") { keyRespone.SelectMany(kr => kr.KeyResultList).ToList().ForEach(r => { b.MeasureValueDict[r] = null; }); } else { b.MeasureValueDict[b.KeyResult] = null; } }); }); } #region InitialHalconTool //protected override void InitialHalconTool() //{ // base.InitialHalconTool(); // Config.SnapshotPointCollection.ForEach(u => // { // u.GetHalconToolPathList().ForEach(path => // { // if (!string.IsNullOrWhiteSpace(path)) // { // string directoryPath = Path.GetDirectoryName(path); // string fileName = Path.GetFileNameWithoutExtension(path); // HDevEngineTool tool = new HDevEngineTool(directoryPath); // tool.LoadProcedure(fileName); // //使用“|”作为间隔符 // _halconToolDict[u.Id + "|" + path] = tool; // } // }); // }); //} #endregion //Dictionary<string, ProductionMeasurement> MeasureDict = new Dictionary<string, ProductionMeasurement>(); private string barCode = ""; public string BarCode { get => barCode; set { if (barCode != value) { barCode = value; OnBarcodeChanged?.Invoke(value); } } } [ProcessMethod("", "StartJob", "开始扫描", InvokeType.TestInvoke)] public ProcessResponse StartJob(IOperationConfig opConfig, IDevice invokeDevice, IDevice sourceDevice) { if (string.IsNullOrWhiteSpace(BarCode)) { throw new ProcessException("未输入产品条码,请勿开始测量"); } OnMeasureStart?.BeginInvoke(null, null); var measurements = Config.MeasurementUnitCollection.Where(u => u.IsEnabled).ToList().DeepSerializeClone(); measurements.ForEach(m => { m.InitialKeyUnitMeasureChanged(); //m.KeyUnitCollection.ForEach(k => k.InitialMeasureValueDictPropertyChanged()); }); //MeasureDict[BarCode] = new ProductionMeasurement() //{ // Barcode = BarCode, // Measurements = measurements, //}; //MeasureDict[BarCode].InitialMeasurementsPropertyChanged(); //MeasureDict[BarCode].PropertyChanged += MeasureProduction_PropertyChanged; var pMeasure = new ProductionMeasurement() { Barcode = BarCode, Measurements = measurements, }; pMeasure.InitialMeasurementsPropertyChanged(); pMeasure.PropertyChanged += MeasureProduction_PropertyChanged; Config.SnapshotPointCollection.Where(u => u.IsEnabled).ToList().ForEach(s => { IDevice device = DeviceCollection.FirstOrDefault(u => u.Id == s.MotionDevice); if (device == null) throw new ProcessException($"{s.Name}拍照点位未设置运动设备"); IMotion motionDevice = device as IMotion; if (motionDevice == null) throw new ProcessException($"{s.Name}拍照点位设置{device.Name}不是运动设备"); if (!motionDevice.MoveToPoint(null)) { throw new ProcessException("运动中止", null, ExceptionLevel.Info); } CameraBase camera = DeviceCollection.FirstOrDefault(u => u.Id == s.CameraOp.Device) as CameraBase; if (camera == null) return; ImageSet imgSet = camera.Snapshot(s.CameraOp.OpConfig); if (imgSet == null) return; RunImageHandle(camera, s.CameraOp.OpConfig, imgSet, s.Id, s.Name, pMeasure.Measurements); }); BarCode = ""; return new ProcessResponse(true); } private void MeasureProduction_PropertyChanged(object sender, PropertyChangedEventArgs e) { if (sender is ProductionMeasurement pMeasure) { //检查是否全部完成 pMeasure.Measurements.ForEach(m => { if (m.KeyUnitCollection.All(k => k.IsDone != null)) { if (!m.IsUpdated) { if (m.KeyUnitCollection.Any(k => k.IsDone == false)) { m.Spec.ActualValue = -999; } else { string toolKey = m.Id + "|" + m.Spec.AlgorithemPath; if (!_halconToolDict.ContainsKey(toolKey)) { LogAsync(DateTime.Now, $"{m.GetDisplayText()}{m.Spec.Code}算法未初始化", ""); m.Spec.ActualValue = -999; } else { var array = m.KeyUnitCollection.SelectMany(u => u.MeasureValueDict.Values.ToList().ConvertAll(v => v ?? -999)).ToArray(); _halconToolDict[toolKey].InputTupleDic["INPUT_Params"] = new HTuple(array); if (!_halconToolDict[toolKey].RunProcedure(out string error)) { LogAsync(DateTime.Now, $"{m.GetDisplayText()}{m.Spec.Code}算法异常,{error}", ""); m.Spec.ActualValue = -999; } else { m.Spec.ActualValue = _halconToolDict[toolKey].GetResultTuple("OUTPUT_Result").D; LogAsync(DateTime.Now, $"{m.GetDisplayText()}数据{m.Spec.ActualValue},结果{(m.Spec.MeasureResult == null ? "TBD" : (m.Spec.MeasureResult == true ? "OK" : "NG"))}", ""); } } } //输出图形基元到界面 todo OnElementUpdated?.BeginInvoke(null, null, null); m.IsUpdated = true; } } }); if (!pMeasure.Measurements.All(m => m.IsUpdated)) { return; } //MES输出 todo //Excel报表输出 todo //数据库保存 todo //MeasureDict.Remove(pMeasure.Barcode); pMeasure.Dispose(); } } private async void RunImageHandle(CameraBase camera, IOperationConfig opConfig, ImageSet imgSet, string snapshotId, string snapshotName, List<MeasurementUint> measureList) { await Task.Run(() => { var keys = Config.KeyUnitCollection.Where(u => u.IsEnabled && u.SnapshotPointId == snapshotId); var keyBindCollection = measureList.SelectMany(u => u.KeyUnitCollection).Where(u => keys.Any(k => k.Key == u.Key)).ToList(); string toolKey = (opConfig as CameraOprerationConfigBase).AlgorithemPath; HObject images = imgSet.HImage; if (!string.IsNullOrWhiteSpace(toolKey)) { toolKey = snapshotId + "|" + toolKey; if (!_halconToolDict.ContainsKey(toolKey)) { LogAsync(DateTime.Now, $"{snapshotName}未初始化取图算法配置", ""); keyBindCollection.ForEach(k => k.FillKeyValues(null)); return; } _halconToolDict[toolKey].InputImageDic["INPUT_Image"] = imgSet.HImage; if (!_halconToolDict[toolKey].RunProcedure(out string error)) { LogAsync(DateTime.Now, $"{snapshotName}取图算法异常,{error}", ""); keyBindCollection.ForEach(k => k.FillKeyValues(null)); return; } images = _halconToolDict[toolKey].GetResultObject("OUTPUT_Images"); } HOperatorSet.CountObj(images, out HTuple count); if (count == 0) { LogAsync(DateTime.Now, $"{snapshotName}取图算法未输出图像", ""); keyBindCollection.ForEach(k => k.FillKeyValues(null)); return; } var excludeKeys = keys.Where(u => u.ImageSeq > count).ToList(); if (excludeKeys.Count > 0) { LogAsync(DateTime.Now, $"{string.Join(" ", excludeKeys.Select(u => u.AlignName))}未在图片获取序列中", ""); keyBindCollection.Where(k => excludeKeys.Any(u => u.Key == k.Key)).ToList().ForEach(k => { k.FillKeyValues(null); }); } Parallel.For(1, count.I, (i) => { HOperatorSet.SelectObj(images, out HObject image, i); keys.Where(u => u.ImageSeq == i).ToList().ForEach(k => { Dictionary<string, double> resultDict = null; var keyBindList = keyBindCollection.Where(u => u.Key == k.Key).ToList(); string keyToolKey = k.AlignName + "|" + k.KeyAlgorithemPath; if (!_halconToolDict.ContainsKey(keyToolKey)) { LogAsync(DateTime.Now, $"{k.AlignName}检测算法未初始化", ""); } else { _halconToolDict[keyToolKey].InputImageDic["INPUT_Image"] = image; if (!_halconToolDict[keyToolKey].RunProcedure(out string error)) { LogAsync(DateTime.Now, $"{k.AlignName}检测算法异常,{error}", ""); } else { var results = _halconToolDict[keyToolKey].GetResultTuple("OUTPUT_Results").HTupleToDouble(); if (results.Count == 0 || results.Any(u => u < 0)) { LogAsync(DateTime.Now, $"{k.AlignName}检测结果异常", ""); } else { resultDict = k.KeyResultList.ToDictionary(u => u, u => { int index = k.KeyResultList.IndexOf(u); return results[index]; }); } } } keyBindList.ForEach(kb => kb.FillKeyValues(resultDict)); }); image.Dispose(); }); if (count.I != 1) imgSet.HImage.Dispose(); }); } } } src/Bro.M071.Process/packages.config
@@ -1,4 +1,5 @@ <?xml version="1.0" encoding="utf-8"?> <packages> <package id="Autofac" version="4.9.4" targetFramework="net452" /> <package id="Newtonsoft.Json" version="11.0.2" targetFramework="net452" /> </packages> src/Bro.Process/ProcessControl.cs
@@ -398,7 +398,7 @@ #endregion #region Halcon算子设置 private void InitialHalconTool() protected virtual void InitialHalconTool() { foreach (HDevEngineTool tool in _halconToolDict.Values) { @@ -413,22 +413,27 @@ { toolPath.GetHalconToolPathList().ForEach(path => { if (!string.IsNullOrWhiteSpace(path)) { string directoryPath = Path.GetDirectoryName(path); string fileName = Path.GetFileNameWithoutExtension(path); HDevEngineTool tool = new HDevEngineTool(directoryPath); tool.LoadProcedure(fileName); //使用“|”作为间隔符 _halconToolDict[monitorSet.Id + "|" + path] = tool; } LoadHalconTool(path, monitorSet.Id); }); } }); } protected void LoadHalconTool(string algorithemPath, string prefix) { if (!string.IsNullOrWhiteSpace(algorithemPath)) { string directoryPath = Path.GetDirectoryName(algorithemPath); string fileName = Path.GetFileNameWithoutExtension(algorithemPath); HDevEngineTool tool = new HDevEngineTool(directoryPath); tool.LoadProcedure(fileName); //使用“|”作为间隔符 _halconToolDict[prefix + "|" + algorithemPath] = tool; } } /// <summary> /// 获取预先载入的Halcon算法 /// </summary> src/Bro.UI.Config/Ctrls/CtrlMethodInvoke.Designer.cs
@@ -82,9 +82,9 @@ | System.Windows.Forms.AnchorStyles.Left) | System.Windows.Forms.AnchorStyles.Right))); this.tableLayoutPanel1.SetColumnSpan(this.propOpConfig, 4); this.propOpConfig.Location = new System.Drawing.Point(23, 65); this.propOpConfig.Location = new System.Drawing.Point(23, 64); this.propOpConfig.Name = "propOpConfig"; this.propOpConfig.Size = new System.Drawing.Size(553, 359); this.propOpConfig.Size = new System.Drawing.Size(553, 360); this.propOpConfig.TabIndex = 15; this.propOpConfig.ToolbarVisible = false; // @@ -111,7 +111,8 @@ // btnInvoke // this.btnInvoke.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); this.btnInvoke.Location = new System.Drawing.Point(501, 36); this.btnInvoke.Location = new System.Drawing.Point(501, 35); this.btnInvoke.Margin = new System.Windows.Forms.Padding(3, 2, 3, 3); this.btnInvoke.Name = "btnInvoke"; this.btnInvoke.Size = new System.Drawing.Size(75, 23); this.btnInvoke.TabIndex = 19; @@ -129,13 +130,13 @@ this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle()); this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 20F)); this.tableLayoutPanel1.Controls.Add(this.propOpConfig, 1, 3); this.tableLayoutPanel1.Controls.Add(this.btnInvoke, 4, 2); this.tableLayoutPanel1.Controls.Add(this.cboTestMethod, 3, 2); this.tableLayoutPanel1.Controls.Add(this.cboTestExecuteDevice, 2, 2); this.tableLayoutPanel1.Controls.Add(this.cboTestSourceDevices, 1, 2); this.tableLayoutPanel1.Controls.Add(this.label8, 2, 1); this.tableLayoutPanel1.Controls.Add(this.label5, 1, 1); this.tableLayoutPanel1.Controls.Add(this.label2, 3, 1); this.tableLayoutPanel1.Controls.Add(this.btnInvoke, 4, 2); this.tableLayoutPanel1.Dock = System.Windows.Forms.DockStyle.Fill; this.tableLayoutPanel1.Location = new System.Drawing.Point(0, 0); this.tableLayoutPanel1.Margin = new System.Windows.Forms.Padding(20); src/Bro.UI.Model.Winform/Helper/MenuFormFactory.cs
@@ -21,6 +21,9 @@ var assm = new DirectoryInfo(AppDomain.CurrentDomain.BaseDirectory).GetFiles(DLLPATTERN).Select(u => Assembly.LoadFrom(u.FullName)).ToList(); assm.AddRange(AppDomain.CurrentDomain.GetAssemblies()); assm = assm.Distinct().ToList(); //var types = assm.SelectMany(a => a.GetTypes()); menuFrmTypeDict = assm.SelectMany(a => a.GetTypes()) .Where(t => {