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;
|
using System.Threading.Tasks;
|
|
namespace Bro.M071.Process
|
{
|
[Process("M071", EnumHelper.DeviceAttributeType.Device)]
|
public partial class M071Process : ProcessControl
|
{
|
#region 构造函数
|
public M071Process() : base() { }
|
public M071Process(string productionCode) : base(productionCode) { }
|
#endregion
|
|
#region 配置
|
M071Config Config
|
{
|
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
|
|
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();
|
});
|
|
var pMeasure = new ProductionMeasurement()
|
{
|
Barcode = BarCode,
|
Measurements = measurements,
|
};
|
|
pMeasure.InitialMeasurementsPropertyChanged();
|
pMeasure.PropertyChanged += MeasureProduction_PropertyChanged;
|
|
Config.SnapshotPointCollection.Where(u => u.IsEnabled).ToList().ForEach(s =>
|
{
|
_pauseHandle.WaitHandle.WaitOne();
|
|
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;
|
|
IImageSet 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);
|
}
|
|
/// <summary>
|
/// 暂停标志
|
/// WaitHandle 暂停句柄 默认为非阻塞 可执行
|
/// WaitResult 暂停标志 true 正常执行 false 暂停中
|
/// </summary>
|
ManualWaitConfirm _pauseHandle = new ManualWaitConfirm()
|
{
|
WaitHandle = new ManualResetEvent(true),
|
WaitResult = true,
|
};
|
|
[ProcessMethod("", "PauseJob", "暂停流程", InvokeType.TestInvoke)]
|
public ProcessResponse PauseJob(IOperationConfig opConfig, IDevice invokeDevice, IDevice sourceDevice)
|
{
|
if (_pauseHandle.WaitResult)
|
{
|
#region 板卡暂停动作
|
#endregion
|
|
_pauseHandle.WaitHandle.Reset();
|
}
|
else
|
{
|
#region 板卡恢复动作
|
#endregion
|
|
_pauseHandle.WaitHandle.Set();
|
}
|
|
_pauseHandle.WaitResult = !_pauseHandle.WaitResult;
|
return new ProcessResponse(_pauseHandle.WaitResult);
|
}
|
#region 私有方法
|
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, IImageSet 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();
|
});
|
}
|
#endregion
|
}
|
}
|