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 (!IIConfig.IsHardwareTrigger)
{
_snapFlag = true;
if (!_snapHandle.WaitOne(IIConfig.SnapshotTimeout))
{
LogAsync(DateTime.Now, $"{Name}获取图像超时", "");
return null;
}
dataSet = _currentData;
}
}
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);
sensor.Flush();
LogAsync(DateTime.Now, $"传感器关闭成功", "");
}
}
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;
///
/// 异步模式获取数据
///
///
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();
_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);
}
});
}
///
/// 保存特定类型图片,例如NG图片
///
/// 图片类型说明 例如“NG”
/// 图片ID
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;
}
}
}