using Bro.Common.Base;
|
using Bro.Common.Helper;
|
using Bro.Common.Interface;
|
using Bro.Common.Model;
|
using HalconDotNet;
|
using Lmi3d.GoSdk;
|
using Lmi3d.GoSdk.Messages;
|
using Lmi3d.Zen;
|
using Lmi3d.Zen.Io;
|
using Newtonsoft.Json;
|
using System;
|
using System.Collections.Generic;
|
using System.Drawing;
|
using System.IO;
|
using System.Linq;
|
using System.Runtime.CompilerServices;
|
using System.Runtime.InteropServices;
|
using System.Text;
|
using System.Threading;
|
using System.Threading.Tasks;
|
using static Bro.Common.Helper.EnumHelper;
|
|
namespace Bro.Device.Gocator
|
{
|
[Device("Gocator", "Gocator激光扫描仪", EnumHelper.DeviceAttributeType.Device)]
|
public class GocatorDriver : CameraBase
|
{
|
#region CameraBase
|
public override IOperationConfig GetOperationConfigFromDevice()
|
{
|
var opConfig = new GocatorOperationConfig();
|
GoSetup setup = sensor.Setup;
|
opConfig.Exposure = (float)setup.GetExposure(GoRole.Main);
|
opConfig.JobName = sensor.DefaultJob;
|
|
return opConfig;
|
}
|
|
public override void Snapshot()
|
{
|
GoDataSet dataSet = null;
|
if (IIConfig.IsAsyncMode)
|
{
|
if (!IIConfig.IsHardwareTrigger)
|
{
|
_snapFlag = true;
|
if (!_snapHandle.WaitOne(IIConfig.SnapshotTimeout))
|
{
|
LogAsync(DateTime.Now, $"{Name}获取图像超时", "");
|
return;
|
}
|
|
dataSet = _currentData;
|
}
|
}
|
else
|
{
|
try
|
{
|
dataSet = system.ReceiveData(IIConfig.SnapshotTimeout);
|
}
|
catch (Exception ex)
|
{
|
LogAsync(DateTime.Now, $"{Name}获取图像异常", ex.GetExceptionMessage());
|
return;
|
}
|
}
|
|
HandleGoData(dataSet);
|
|
dataSet.Dispose();
|
}
|
|
private void HandleGoData(GoDataSet dataSet, GoImageSet imgSet = null)
|
{
|
if (dataSet == null)
|
{
|
return;
|
}
|
|
for (UInt32 i = 0; i < dataSet.Count; i++)
|
{
|
GoDataMsg dataObj = (GoDataMsg)dataSet.Get(i);
|
switch (dataObj.MessageType)
|
{
|
case GoDataMessageType.Surface:
|
{
|
GoSurfaceMsg surfaceMsg = (GoSurfaceMsg)dataObj;
|
long width = surfaceMsg.Width;
|
long height = surfaceMsg.Length;
|
long bufferSize = width * height;
|
IntPtr bufferPointer = surfaceMsg.Data;
|
|
|
float zoomFactor = (float)((double)surfaceMsg.YResolution / (double)surfaceMsg.XResolution);
|
int zoomHeight = (int)(zoomFactor * height);
|
|
//IntPtr zoomPtr = Marshal.AllocHGlobal(zoomHeight * (int)width * 2);
|
//IntPtr zoomPtr = Marshal.AllocHGlobal(zoomHeight * (int)width * 4);
|
IntPtr zoomPtr = Marshal.AllocHGlobal(zoomHeight * (int)width * (int)IIConfig.ByteNums);
|
|
//没有插值,默认0
|
//Parallel.For(0, height, h =>
|
// {
|
// CopyMemory((IntPtr)((long)zoomPtr + width * 2 * Math.Floor(h * zoomFactor)), (IntPtr)((long)bufferPointer + width * 2 * h), width * 2);
|
// });
|
|
if (IIConfig.ByteNums == GocatorDataByteNums.Byte2)
|
{
|
//使用上一行原有数据
|
Parallel.For(0, zoomHeight, h =>
|
{
|
int originHeightIndex = (int)Math.Floor((double)height * h / (double)zoomHeight);
|
|
CopyMemory((IntPtr)((long)zoomPtr + width * 2 * h), (IntPtr)((long)bufferPointer + width * 2 * originHeightIndex), width * 2);
|
});
|
}
|
else
|
{
|
//使用上一行原有数据
|
Parallel.For(0, zoomHeight, h =>
|
{
|
int originHeightIndex = (int)Math.Floor((double)height * h / (double)zoomHeight);
|
|
byte[] rowBuffer = new byte[width * 4];
|
Parallel.For(0, width, w =>
|
{
|
rowBuffer[w * 4 + 2] = Marshal.ReadByte(bufferPointer, (int)(width * 2 * originHeightIndex + w * 2));
|
rowBuffer[w * 4 + 3] = Marshal.ReadByte(bufferPointer, (int)(width * 2 * originHeightIndex + w * 2 + 1));
|
});
|
|
Marshal.Copy(rowBuffer, 0, (IntPtr)((long)zoomPtr + width * 2 * h), rowBuffer.Length);
|
});
|
}
|
|
if (imgSet != null)
|
{
|
imgSet.HImage = new HImage();
|
//imgSet.HImage.GenImage1("uint2", (int)width, zoomHeight, zoomPtr);
|
//imgSet.HImage.GenImage1("int4", (int)width, zoomHeight, zoomPtr);
|
imgSet.HImage.GenImage1(IIConfig.ByteNums == GocatorDataByteNums.Byte2 ? "uint2" : "int4", (int)width, zoomHeight, zoomPtr);
|
|
//imgSet.HImage_2 = imgSet.HImage.Clone();
|
//imgSet.HImage_2.GenImage1("uint2", (int)width, zoomHeight, zoomPtr);
|
//imgSet.HImage_2.GenImage1("int4", (int)width, zoomHeight, zoomPtr);
|
|
imgSet.HImage_2 = new HImage();
|
imgSet.HImage_2.GenImage1(IIConfig.ByteNums == GocatorDataByteNums.Byte2 ? "uint2" : "int4", (int)width, zoomHeight, zoomPtr);
|
|
LaserScanParam para = new LaserScanParam()
|
{
|
Resolution_X = surfaceMsg.XResolution,
|
Resolution_Y = surfaceMsg.YResolution,
|
Resolution_Z = surfaceMsg.ZResolution,
|
Offset_X = surfaceMsg.XOffset,
|
Offset_Y = surfaceMsg.YOffset,
|
Offset_Z = surfaceMsg.ZOffset,
|
Angle_Z = surfaceMsg.ZAngle,
|
};
|
imgSet.ImageData = JsonConvert.SerializeObject(para);
|
|
//imgSet.HImage_2 = imgSet.HImage_2.ZoomImageSize((int)width, zoomHeight, "constant");
|
}
|
|
Generate16GrayImageByPointer((int)width, zoomHeight, zoomPtr, imgSet?.Id).ContinueWith(t =>
|
{
|
Marshal.FreeHGlobal(zoomPtr);
|
});
|
|
//int zoomHeight = (int)(((double)surfaceMsg.YResolution / (double)surfaceMsg.XResolution) * (double)surfaceMsg.Length);
|
|
//if (imgSet != null)
|
//{
|
// imgSet.HImage = new HImage();
|
// imgSet.HImage.GenImage1("uint2", (int)width, (int)height, bufferPointer);
|
// imgSet.HImage = imgSet.HImage.ZoomImageSize((int)width, zoomHeight, "constant");
|
|
|
// imgSet.HImage_2 = new HImage();
|
// imgSet.HImage_2.GenImage1("uint2", (int)width, (int)height, bufferPointer);
|
|
// imgSet.HImage_2 = imgSet.HImage_2.ZoomImageSize((int)width, zoomHeight, "constant");
|
//}
|
|
//Generate16GrayImageByPointer((int)width, (int)height, bufferPointer, imgSet?.Id);
|
}
|
break;
|
//case GoDataMessageType.SurfaceIntensity:
|
// {
|
// GoSurfaceIntensityMsg surfaceMsg = (GoSurfaceIntensityMsg)dataObj;
|
// long width = surfaceMsg.Width;
|
// long height = surfaceMsg.Length;
|
// long bufferSize = width * height;
|
// IntPtr bufferPointer = surfaceMsg.Data;
|
|
// //int zoomHeight = (surfaceMsg.YResolution * (int)surfaceMsg.Length * 10) / surfaceMsg.XResolution;
|
|
// int zoomHeight = (int)(((double)surfaceMsg.YResolution / (double)surfaceMsg.XResolution) * (double)surfaceMsg.Length);
|
|
// if (imgSet != null)
|
// {
|
// imgSet.HImage = new HImage();
|
// imgSet.HImage.GenImage1("uint2", (int)width, (int)height, bufferPointer);
|
// imgSet.HImage = imgSet.HImage.ZoomImageSize((int)width, zoomHeight, "constant");
|
|
|
// imgSet.HImage_2 = new HImage();
|
// imgSet.HImage_2.GenImage1("uint2", (int)width, (int)height, bufferPointer);
|
|
// imgSet.HImage_2 = imgSet.HImage_2.ZoomImageSize((int)width, zoomHeight, "constant");
|
// }
|
|
// Generate16GrayImageByPointer((int)width, (int)height, bufferPointer, imgSet?.Id);
|
// }
|
// break;
|
}
|
|
dataObj.Dispose();
|
}
|
}
|
|
[MethodImpl(MethodImplOptions.Synchronized)]
|
public override IImageSet Snapshot(IOperationConfig config)
|
{
|
GocatorOperationConfig opConfig = config as GocatorOperationConfig;
|
if (!IIConfig.IsAsyncMode)
|
{
|
if (opConfig.IsOpenConnection)
|
{
|
while (sensor.State != GoState.Ready)
|
{
|
Thread.Sleep(10);
|
}
|
|
do
|
{
|
try
|
{
|
sensor.Start();
|
LogAsync(DateTime.Now, $"传感器状态:{sensor.State.ToString()}", "");
|
if (sensor.State != GoState.Running)
|
{
|
Thread.Sleep(100);
|
}
|
else
|
{
|
break;
|
}
|
}
|
catch (Exception ex)
|
{
|
LogAsync(DateTime.Now, $"开启异常:{ex.GetExceptionMessage()}", "");
|
Thread.Sleep(100);
|
}
|
} while (true);
|
|
LogAsync(DateTime.Now, $"传感器启动成功", "");
|
}
|
|
if (!opConfig.IsSnapshotAction)
|
{
|
return null;
|
}
|
}
|
|
GoImageSet imgSet = new GoImageSet();
|
InitialImageSet(imgSet, (config as CameraOprerationConfigBase).ImageSaveOption);
|
|
GoDataSet dataSet = null;
|
if (IIConfig.IsAsyncMode)
|
{
|
if (opConfig.IsSnapshotAction)
|
{
|
if (!IIConfig.IsHardwareTrigger)
|
{
|
_snapFlag = true;
|
if (!_snapHandle.WaitOne(IIConfig.SnapshotTimeout))
|
{
|
LogAsync(DateTime.Now, $"{Name}获取图像超时", "");
|
return null;
|
}
|
|
dataSet = _currentData;
|
}
|
}
|
else
|
{
|
imgSet = null;
|
}
|
}
|
else
|
{
|
if (!opConfig.IsSnapshotAction)
|
{
|
return null;
|
}
|
|
int reTryTime = 3;
|
do
|
{
|
try
|
{
|
dataSet = system.ReceiveData(IIConfig.SnapshotTimeout);
|
reTryTime = 0;
|
}
|
catch (Exception ex)
|
{
|
reTryTime--;
|
LogAsync(DateTime.Now, $"{Name}获取图像异常", ex.GetExceptionMessage());
|
|
if (reTryTime <= 0)
|
{
|
imgSet.HImage = null;
|
dataSet = null;
|
system.ClearData();
|
}
|
}
|
} while (reTryTime > 0);
|
}
|
|
if (!IIConfig.IsAsyncMode)
|
{
|
if (!opConfig.IsOpenConnection)
|
{
|
while (sensor.State == GoState.Busy)
|
{
|
Thread.Sleep(100);
|
}
|
|
do
|
{
|
try
|
{
|
sensor.Stop();
|
|
LogAsync(DateTime.Now, $"传感器状态:{sensor.State.ToString()}", "");
|
if (sensor.State != GoState.Ready)
|
{
|
Thread.Sleep(100);
|
}
|
else
|
{
|
break;
|
}
|
}
|
catch (Exception ex)
|
{
|
LogAsync(DateTime.Now, $"关闭异常:{ex.GetExceptionMessage()}", "");
|
Thread.Sleep(100);
|
}
|
} while (true);
|
LogAsync(DateTime.Now, $"传感器关闭成功", "");
|
}
|
}
|
|
sensor.Flush();
|
|
if (dataSet != null)
|
{
|
HandleGoData(dataSet, imgSet);
|
|
dataSet.Dispose();
|
|
if (imgSet.HImage == null)
|
{
|
LogAsync(DateTime.Now, $"{Name}未能获取HImage图像", "");
|
}
|
}
|
|
return imgSet;
|
}
|
|
float _currentExposure = 0;
|
string _currentJob = "";
|
public override void UploadOperationConfig(IOperationConfig config)
|
{
|
if (config is GocatorOperationConfig opConfig)
|
{
|
if (opConfig.Exposure > 0 && opConfig.Exposure != _currentExposure)
|
{
|
sensor.Setup.SetExposure(GoRole.Main, opConfig.Exposure);
|
_currentExposure = opConfig.Exposure;
|
}
|
|
if (!string.IsNullOrWhiteSpace(opConfig.JobName) && _currentJob != opConfig.JobName)
|
{
|
LogAsync(DateTime.Now, $"{Name}切换当前任务为{opConfig.JobName}", "");
|
sensor.CopyFile(_currentJob, "_live.job");
|
|
bool isChanged = false;
|
sensor.LoadedJob(ref _currentJob, ref isChanged);
|
LogAsync(DateTime.Now, $"{Name}当前任务{_currentJob}", "");
|
}
|
|
sensor.Flush();
|
}
|
}
|
|
protected override void Init()
|
{
|
KApiLib.Construct();
|
GoSdkLib.Construct();
|
|
system = new GoSystem();
|
|
if (IIConfig.IsUseAccelerator)
|
{
|
accelerator = new GoAccelerator();
|
}
|
|
KIpAddress ip = KIpAddress.Parse(IConfig.CameraIP);
|
|
if (IIConfig.IsUseAccelerator)
|
{
|
accelerator.Start();
|
}
|
|
sensor = system.FindSensorByIpAddress(ip);
|
|
if (IIConfig.IsUseAccelerator)
|
{
|
accelerator.Attach(sensor);
|
}
|
sensor.Connect();
|
|
if (IIConfig.IsUseAccelerator)
|
{
|
sensor.Flush();
|
accelerator.Start();
|
}
|
|
sensor.Setup.ScanMode = GoMode.Surface;
|
|
system.EnableData(true);
|
|
if (IIConfig.IsAsyncMode)
|
{
|
system.SetDataHandler(onData);
|
}
|
|
_currentExposure = (float)sensor.Setup.GetExposure(GoRole.Main);
|
if (IIConfig.DefaultExposure > 0 && _currentExposure != IIConfig.DefaultExposure)
|
{
|
sensor.Setup.SetExposure(GoRole.Main, IIConfig.DefaultExposure);
|
_currentExposure = (float)sensor.Setup.GetExposure(GoRole.Main);
|
}
|
|
bool isChanged = false;
|
sensor.LoadedJob(ref _currentJob, ref isChanged);
|
LogAsync(DateTime.Now, $"{Name}当前任务{_currentJob}", "");
|
|
if (!string.IsNullOrWhiteSpace(IIConfig.DefaultJob) && IIConfig.DefaultJob != _currentJob)
|
{
|
sensor.CopyFile(IIConfig.DefaultJob, "_live.job");
|
//_currentJob = IIConfig.DefaultJob;
|
|
sensor.LoadedJob(ref _currentJob, ref isChanged);
|
LogAsync(DateTime.Now, $"{Name}当前任务{_currentJob}", "");
|
}
|
|
sensor.Flush();
|
}
|
|
protected override void Start()
|
{
|
base.Start();
|
|
if (sensor.State != GoState.Ready)
|
{
|
system.Start();
|
}
|
|
if (IIConfig.IsAsyncMode)
|
{
|
sensor.Start();
|
}
|
else
|
{
|
//if (sensor.State == GoState.Ready)
|
{
|
sensor.Stop();
|
}
|
}
|
}
|
|
protected override void Stop()
|
{
|
base.Stop();
|
|
if (IIConfig.IsAsyncMode)
|
system.Stop();
|
|
if (IIConfig.IsUseAccelerator)
|
{
|
accelerator.Stop();
|
}
|
|
sensor.Disconnect();
|
}
|
|
protected override void Pause()
|
{
|
}
|
|
protected override void Resume()
|
{
|
}
|
#endregion
|
|
GoSystem system = null;
|
GoAccelerator accelerator = null;
|
GoSensor sensor = null;
|
|
public GocatorInitialConfig IIConfig
|
{
|
get => InitialConfig as GocatorInitialConfig;
|
}
|
|
volatile bool _snapFlag = false;
|
readonly ManualResetEvent _snapHandle = new ManualResetEvent(false);
|
|
GoDataSet _currentData = null;
|
/// <summary>
|
/// 异步模式获取数据
|
/// </summary>
|
/// <param name="data"></param>
|
private void onData(KObject data)
|
{
|
GoDataSet dataSet = (GoDataSet)data;
|
|
if (IIConfig.IsHardwareTrigger)
|
{
|
GoImageSet imgSet = new GoImageSet();
|
InitialImageSet(imgSet, IConfig.ImageSaveOption);
|
|
HandleGoData(dataSet, imgSet);
|
|
if (imgSet.HImage != null)
|
{
|
OnHImageOutput?.BeginInvoke(this, imgSet.HImage, imgSet.Id, null, null);
|
}
|
else
|
{
|
LogAsync(DateTime.Now, $"{Name}获取HImage失败", "");
|
}
|
}
|
else
|
{
|
if (_snapFlag)
|
{
|
_snapFlag = false;
|
|
_currentData = dataSet.Clone<GoDataSet>();
|
_snapHandle.Set();
|
}
|
}
|
|
dataSet.Dispose();
|
}
|
|
#region 重写图片保存操作
|
public override async void SaveOriginImage(Bitmap map, Bitmap showImage, string imgSetId)
|
{
|
Task.Run(() =>
|
{
|
OnImageUpdated?.Invoke(this, showImage, imgSetId);
|
});
|
|
GoImageSet set = _imageSetList[imgSetId] as GoImageSet;
|
|
if (set == null)
|
return;
|
|
set.Image = map;
|
|
await Task.Run(() =>
|
{
|
lock (set.SaveLock)
|
{
|
if (set.ImageSaveOption.IsSaveOriginImage && !set.IsOriginSaved)
|
{
|
string imgDir = CheckImageDirectory(set.ImageSaveOption.ImageSaveSubDirectory, "Origin");
|
|
try
|
{
|
//SaveImageByNameAndType(map, set.Id, set.ImageSaveOption.ImageFormat, imgDir);
|
string filePath = Path.Combine(imgDir, $"{set.Id}.tif");
|
set.HImage_2.WriteImage("tiff", 0, filePath);
|
}
|
catch (Exception ex)
|
{
|
LogAsync(DateTime.Now, $"{set.Id}原图保存失败", ex.GetExceptionMessage());
|
}
|
}
|
set.IsOriginSaved = true;
|
ClearImageSet(set);
|
}
|
});
|
}
|
|
/// <summary>
|
/// 保存特定类型图片,例如NG图片
|
/// </summary>
|
/// <param name="prefix">图片类型说明 例如“NG”</param>
|
/// <param name="imgSetId">图片ID</param>
|
public override async void SaveSelectedImage(string prefix, string imgSetId)
|
{
|
await Task.Run(() =>
|
{
|
GoImageSet set = _imageSetList[imgSetId] as GoImageSet;
|
if (set == null)
|
return;
|
|
lock (set.SaveLock)
|
{
|
if (set.ImageSaveOption.AddtionalSaveType.Contains(prefix) && !set.IsAddtionalSaved)
|
{
|
string imgDir = CheckImageDirectory(set.ImageSaveOption.ImageSaveSubDirectory, prefix);
|
|
while (set.Image == null)
|
{
|
Thread.Sleep(50);
|
}
|
|
try
|
{
|
string filePath = Path.Combine(imgDir, $"{set.Id}.tif");
|
set.HImage_2.WriteImage("tiff", 0, filePath);
|
}
|
catch (Exception ex)
|
{
|
LogAsync(DateTime.Now, $"{set.Id}{prefix}图片保存失败", ex.GetExceptionMessage());
|
}
|
}
|
set.IsAddtionalSaved = true;
|
ClearImageSet(set);
|
}
|
});
|
}
|
|
//public override void ClearImageSet(IImageSet set)
|
//{
|
// if (set.IsOriginSaved && set.IsFitSaved && set.IsAddtionalSaved)
|
// {
|
// (set as GoImageSet).HImage_2?.Dispose();
|
// (set as GoImageSet).HImage_2 = null;
|
// }
|
|
// base.ClearImageSet(set);
|
//}
|
#endregion
|
}
|
|
public class GoImageSet : ImageSet
|
{
|
public HImage HImage_2 { get; set; }
|
|
public override void Dispose()
|
{
|
base.Dispose();
|
|
HImage_2?.Dispose();
|
HImage_2 = null;
|
}
|
}
|
}
|