using LB_SmartVisionCameraSDK; using LB_SmartVisionCameraSDK.PHM6000; using LB_SmartVisionCommon; using Newtonsoft.Json; using System; using System.Collections.Generic; using System.ComponentModel; using System.Linq; using System.Reflection; using System.Reflection.Metadata; using System.Runtime.InteropServices; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; namespace LB_SmartVisionCameraDevice.PHM6000 { /// /// PHM6000Series-Sensor /// public class PHM6000Sensor { public IntPtr Entry { get; set; }//连接传感器的接口 public string IP { get; set; }//传感器IP public string SerialNo { get; set; }//传感器序列号 public int Port { get; set; }//端口 List LineDatas { get; set; } = new List();//存储扫描到的行数据 public IntPtr CaliEntry = IntPtr.Zero;//测量标定入口 readonly object _lock = new object(); readonly object _lockIntPtr = new object(); //public PanelControl PointPanel { get; set; } //WaitForm ssm; public int Index { get; set; }//传感器序号,主要用于标定 public IntPtr lightPic = IntPtr.Zero;//亮度图 public IntPtr deepPic = IntPtr.Zero;//深度图 public IntPtr pointPic = IntPtr.Zero;//点云图 public IntPtr outlinePic = IntPtr.Zero;//轮廓图 public IntPtr outlineMainPic = IntPtr.Zero;//主界面轮廓图 public CaliModel CaliModel { get; set; }//测量用参数 public CaliOutLine CaliOutLine { get; set; }//测量用参数 public bool isContinuousScan = false; CancellationTokenSource lightCts; CancellationTokenSource deepCts; CancellationTokenSource pointCts; CancellationTokenSource outlineCts; //PILOT2D_FUNC func2d; //VTK3D_FUNC func3d; AcquisitionCallbackZA sendDatacallback;//回调委托(行数据发送给本系统) string path = string.Empty; //int currentRowNumber = 0; /// /// 初始化传感器 /// /// 传感器IP /// 传感器序列号 /// 传感器端口 /// 本系统用于承载图片的控件指针 public PHM6000Sensor(string ip, string serialNo, int port, int index/*, WaitForm ssm*/) { this.IP = ip; this.SerialNo = serialNo; this.Port = port; this.Index = index; //this.ssm = ssm; CaliEntry = SysCalibration.CreateSysCalibrationEntry();//测量标定入口 } public int GetLineCount() { int count; lock (_lock) { count = LineDatas.Count; } return count; } public List GetLineDatas() { LineDatas.Clear(); var o = new List(); lock (_lock) { IntPtr pData = IntPtr.Zero; ulong nIndex = 0; //Config config; //if (!IP.Equals("0.0.0.0")) //{ // config = GetConfig(); //} //else //{ // config = new Config(); //} uint count = 0; while ((pData = PHM6000Profiler.GetLineDataByIndex(Entry, nIndex)) != IntPtr.Zero) { unsafe { LBLineHeadInfo pInfo = Marshal.PtrToStructure(pData); count = pInfo.nPointCount; } LBLineDataZA lBLineDataZA = new LBLineDataZA { info = new LBLineHeadInfo(), data = new LBPointZA[count] }; long length = Marshal.SizeOf(lBLineDataZA) + Marshal.SizeOf(new LBPointZA()) * count; int datacount = int.Parse(length.ToString()); byte[] byteArray = new byte[length]; Marshal.Copy(pData, byteArray, 0, datacount); LineDatas.Add(byteArray); nIndex++; } o.AddRange(LineDatas); } return o; } IntPtr Temp = IntPtr.Zero; public IntPtr GetLineLastData() { lock (_lock) { IntPtr pData = IntPtr.Zero; Temp = IntPtr.Zero; ulong nIndex = 0; uint count = 0; while ((pData = PHM6000Profiler.GetLineDataByIndex(Entry, nIndex)) != IntPtr.Zero) { //Marshal.FreeHGlobal(Temp); Temp = pData; //SysCalibration.AddLineDataArray(CaliEntry, Index, Temp, false, 1); SysCalibration.SetLineDataArray(CaliEntry, Index, Temp); nIndex++; } if (pData == IntPtr.Zero) { } } return Temp; } #region 创建图片控件 public IntPtr CreatePicPtr(IntPtr localPtr, EnumFetchPicType picType) { IntPtr ptr = IntPtr.Zero; PHM6000SensorConfig config; if (!IP.Equals("0.0.0.0")) { config = GetConfig(); } else { config = new PHM6000SensorConfig(); } switch (picType) { case EnumFetchPicType.light: if (lightPic == IntPtr.Zero) { ptr = Pilot2D.CreatePilot2DEntry(localPtr); Pilot2D.SetImageSize(ptr, 4096, config.ScanLineCount); lightPic = ptr; } break; case EnumFetchPicType.deep: if (deepPic == IntPtr.Zero) { ptr = Pilot2D.CreatePilot2DEntry(localPtr); Pilot2D.SetImageSize(ptr, 4096, config.ScanLineCount); deepPic = ptr; } break; case EnumFetchPicType.pointCloud: if (pointPic == IntPtr.Zero) { ptr = PclEntry.CreatePCLWindow(localPtr); //PclInvoke.RenderPCLWindow(ptr, 800, 600); pointPic = ptr; } break; case EnumFetchPicType.outline: if (outlinePic == IntPtr.Zero) { ptr = Pilot2D.CreatePilot2DEntry(localPtr); Pilot2D.SetImageSize(ptr, 4096, 2048); outlinePic = ptr; } break; case EnumFetchPicType.mainOutLine: if (outlineMainPic == IntPtr.Zero) { ptr = Pilot2D.CreatePilot2DEntry(localPtr); Pilot2D.SetImageSize(ptr, 4096, 2048); outlineMainPic = ptr; } break; } return ptr; } #endregion event AcquisitionCompletedCallback acquisitionCompletedCallback = null; public event AcquisitionCompletedCallback acquisitionCompleted = null; public event ShowDebugInfoCallback registerShowDebugInfoCallback = null; public void RegisterShowDebugInfoCallback(ShowDebugInfoCallback callback) { PHM6000Profiler.RegisterShowDebugInfoCallback(Entry, callback); } PILOT2D_FUNC func2d = new PILOT2D_FUNC { AddBarycentreDataZA = Pilot2D.AddBarycentreDataZA, AddDepthData = Pilot2D.AddDepthData, AddIntensityData = Pilot2D.AddIntensityData, ClearAllPoints = Pilot2D.ClearAllPoints, RefreshPilot2D = Pilot2D.RefreshPilot2D, SetImageSize = Pilot2D.SetImageSize, }; VTK3D_FUNC func3d = new VTK3D_FUNC { AddZAPoints = PclEntry.AddZAPoints, ClearPCLPoints = PclEntry.ClearPCLPoints, GetPointCloudBound = PclEntry.GetPointCloudBound, RenderPCLWindow = PclEntry.RenderPCLWindow, SetLookUpTableRange = PclEntry.SetLookUpTableRange, ShowCubeAxes = PclEntry.ShowCubeAxes, ShowLookUpTable = PclEntry.ShowLookUpTable, UpdatePCLPointColors = PclEntry.UpdatePCLPointColors, }; public void StartDataProcess() { //SetShowHandles(Entry, lightPic, deepPic, outlinePic, pointPic); acquisitionCompletedCallback += PHM6000Sensor_acquisitionCompletedCallback; PHM6000Profiler.SetPilot2dFunc(Entry, func2d); PHM6000Profiler.SetVTK3dFunc(Entry, func3d); PHM6000Profiler.RegisterAcquisitionCompletedCallback(Entry, acquisitionCompletedCallback, new IntPtr()); } public void CameraShow() { PHM6000Profiler.SetShowHandles(Entry, lightPic, deepPic, outlinePic, pointPic); } public void MainShow() { PHM6000Profiler.SetShowHandles(Entry, lightPic, deepPic, outlineMainPic, pointPic); } public IntPtr hWnd; private void PHM6000Sensor_acquisitionCompletedCallback(IntPtr pInstance, int nOption) { if (nOption == 2) { //显示点云 bool result = PclEntry.PostMessage(hWnd, CommonVar.WM_RENDER_VTK, 0, (ulong)pInstance); // m_hMainWnd是主窗口句柄 } if (acquisitionCompleted != null) { acquisitionCompleted(pInstance, nOption); } } public IntPtr PInstance; #region 连接传感器 public bool ConnectCamera() { Entry = PHM6000Profiler.CreateCameraEntry(); var addr = Encoding.ASCII.GetBytes(IP); var result = PHM6000Profiler.ConnectToCamera(Entry, addr, Port); if (result == 0) { return true; } return false; } #endregion #region 从传感器获取参数配置 public PHM6000SensorConfig GetConfig() { //获取参数 PHM6000SensorConfig config; if (IP.Equals("0.0.0.0")) { config = new PHM6000SensorConfig(); return config; } //先从本地获取配置 path = $"{SerialNo}-config.lb"; if (File.Exists(path)) { config = ConfigManager.LoadConfig(@path); } else { config = new PHM6000SensorConfig(); } //----------------- PropertyInfo[] props = config.GetType().GetProperties(); foreach (PropertyInfo p in props) { //跳过自定义参数 var iscustomAttr = p.GetCustomAttribute(); if (iscustomAttr != null) continue; var nameId = Enum.Parse(typeof(EnumNameId), p.Name); int intValue = 0; double doubleValue = 0; int enumValue = 0; var id = Convert.ToInt32(nameId); var rst = PHM6000Profiler.GetProfilerParameter(Entry, id, ref intValue, ref doubleValue, ref enumValue); if (rst == 0) { if (p.PropertyType == typeof(int)) { p.SetValue(config, intValue); } else if (p.PropertyType == typeof(float)) { var value = Convert.ToSingle(doubleValue); p.SetValue(config, value); } else { if (p.Name.Equals("ROI")) { } else { p.SetValue(config, enumValue); } } } } return config; } #endregion void SetTargetParam(PHM6000SensorConfig config) { TARGET_INFO tARGET_INFO = new TARGET_INFO() { //fHeight = config.fHeight, //fWidth = config.fWidth, //fMarginRangeX = config.fMarginRangeX, //fMarginRangeY = config.fMarginRangeY, //fMarginX = config.fMarginX, //fMarginY = config.fMarginY, //nPartitionX = config.nPartitionX, //nPartitionY = config.nPartitionY, }; SysCalibration.SetTargetParameter(CaliEntry, tARGET_INFO); } #region 设置参数 public bool SetConfig(PHM6000SensorConfig config) { //将配置保存到本地 path = $"{SerialNo}-config.lb"; ConfigManager.SaveConfig(config, @path); SetTargetParam(config); //----------- int result = 0; var type = config.GetType(); var propLineScan = type.GetProperty(nameof(config.LineScanTriggerSource)); var val = (EnumLineScanTriggerSource)propLineScan.GetValue(config); var props = config.GetType().GetProperties(); //排除Y轴 props = props.Where(d => d.Name != nameof(config.YResolution)).ToArray(); //排除不需要的项 if (val == EnumLineScanTriggerSource.固定频率) { props = props.Where(d => d.Name != nameof(config.EncoderTriggerDirection) && d.Name != nameof(config.EncoderTriggerInterval) && d.Name != nameof(config.EncoderTriggerSignalCountingMode)).ToArray(); } else { props = props.Where(d => d.Name != nameof(config.SoftwareTriggerRate)).ToArray(); } foreach (var p in props) { //跳过自定义参数 var iscustomAttr = p.GetCustomAttribute(); if (iscustomAttr != null) continue; //判断是6030传感器还是普通传感器 if (SerialNo.StartsWith("LX030") && p.Name == nameof(config.AnalogGain)) { continue; } if (!SerialNo.StartsWith("LX030") && p.Name == nameof(config.AnalogGainFor6030)) { continue; } var id = Convert.ToInt32(Enum.Parse(typeof(EnumNameId), p.Name)); if (p.PropertyType == typeof(int)) { var value = Convert.ToInt32(p.GetValue(config)); result = PHM6000Profiler.SetProfilerParameter(Entry, id, value, 0, 0); } else if (p.PropertyType == typeof(float)) { var value = Convert.ToDouble(p.GetValue(config)); result = PHM6000Profiler.SetProfilerParameter(Entry, id, 0, value, 0); } else { var value = Convert.ToInt32(p.GetValue(config)); result = PHM6000Profiler.SetProfilerParameter(Entry, id, 0, 0, value); //if (p.Name == nameof(config.AnalogGainFor6030)) //{ // var a = value; //} } if (result == -1) { var disattr = p.GetCustomAttribute(); var name = disattr?.DisplayName ?? p.Name; throw new Exception($"设置参数{name}时不成功!"); } } var finalResult = PHM6000Profiler.SaveAllParametersToDevice(Entry); if (finalResult != 0) { return false; } return true; } #endregion #region 断开传感器 public void DisConnectCamera() { if (IP == "0.0.0.0") return; var result = PHM6000Profiler.DisconnectFromCamera(Entry, IP); if (result == -1) { AsyncLogHelper.Error("断开摄像头失败!"); throw new Exception("断开摄像头失败!"); } } public void DestoryCamera() { if (Entry != IntPtr.Zero) { PHM6000Profiler.DestroyCameraEntry(Entry); Entry = IntPtr.Zero; } //if (pointPic != IntPtr.Zero) //{ // PclEntry.ClearPCLPoints(pointPic); // PclEntry.DestroyPCLWindow(pointPic); // pointPic = IntPtr.Zero; //} if (lightPic != IntPtr.Zero) { Pilot2D.ClearAllPoints(lightPic); Pilot2D.DestroyPilot2DEntry(lightPic); lightPic = IntPtr.Zero; } if (outlinePic != IntPtr.Zero) { Pilot2D.ClearAllPoints(outlinePic); Pilot2D.DestroyPilot2DEntry(outlinePic); outlinePic = IntPtr.Zero; } if (outlineMainPic != IntPtr.Zero) { Pilot2D.ClearAllPoints(outlineMainPic); Pilot2D.DestroyPilot2DEntry(outlineMainPic); outlineMainPic = IntPtr.Zero; } if (deepPic != IntPtr.Zero) { Pilot2D.ClearAllPoints(deepPic); Pilot2D.DestroyPilot2DEntry(deepPic); deepPic = IntPtr.Zero; } } public void ClearDatas() { //if (pointPic != IntPtr.Zero) //{ // PclEntry.ClearPCLPoints(pointPic); //} if (lightPic != IntPtr.Zero) { Pilot2D.ClearAllPoints(lightPic); } if (outlinePic != IntPtr.Zero) { Pilot2D.ClearAllPoints(outlinePic); } if (outlineMainPic != IntPtr.Zero) { Pilot2D.ClearAllPoints(outlineMainPic); } if (deepPic != IntPtr.Zero) { Pilot2D.ClearAllPoints(deepPic); } } #endregion #region 单次采集,启动回调 public void StartScan() { if (IP == "0.0.0.0") return; lock (_lock) { LineDatas.Clear(); } int result = PHM6000Profiler.SetAcquisitionCallbackZA(Entry, IntPtr.Zero, IntPtr.Zero);//设置数采回调,注意好像没地方有销毁 if (result == 0) { AsyncLogHelper.Info("PHM6000Profiler.SetAcquisitionCallbackZA(Entry, IntPtr.Zero, IntPtr.Zero)设置成功!"); } else if (result == -1) { AsyncLogHelper.Info("PHM6000Profiler.SetAcquisitionCallbackZA(Entry, IntPtr.Zero, IntPtr.Zero)设置失败!"); } result = PHM6000Profiler.SetAcquisitionMode(Entry, 1, 0);//设置数采模式 if (result == 0) { AsyncLogHelper.Info("PHM6000Profiler.SetAcquisitionMode(Entry, 1, 0)设置成功!"); } else if (result == -1) { AsyncLogHelper.Info("PHM6000Profiler.SetAcquisitionMode(Entry, 1, 0)设置失败!"); } result = PHM6000Profiler.StartAcquisition(Entry, 0, 0, 0.0);//开始采集 if (result == 0) { AsyncLogHelper.Info("PHM6000Profiler.StartAcquisition(Entry, 0, 0, 0.0)设置成功!"); } else if (result == -1) { AsyncLogHelper.Info("PHM6000Profiler.StartAcquisition(Entry, 0, 0, 0.0)设置失败!"); } } #endregion #region 启动连续采集 public void ContinuousScan() { if (IP.Equals("0.0.0.0")) { return; } lock (_lock) { LineDatas.Clear(); } int result = PHM6000Profiler.SetAcquisitionCallbackZA(Entry, IntPtr.Zero, IntPtr.Zero);//设置数采回调,注意好像没地方有销毁 if (result == 0) { AsyncLogHelper.Info("PHM6000Profiler.SetAcquisitionCallbackZA(Entry, IntPtr.Zero, IntPtr.Zero)设置成功!"); } else if (result == -1) { AsyncLogHelper.Info("PHM6000Profiler.SetAcquisitionCallbackZA(Entry, IntPtr.Zero, IntPtr.Zero)设置失败!"); } result = PHM6000Profiler.SetAcquisitionMode(Entry, 1, 1);//设置数采模式 if (result == 0) { AsyncLogHelper.Info("PHM6000Profiler.SetAcquisitionMode(Entry, 1, 1)设置成功!"); } else if (result == -1) { AsyncLogHelper.Info("PHM6000Profiler.SetAcquisitionMode(Entry, 1, 1)设置失败!"); } result = PHM6000Profiler.StartAcquisition(Entry, 0, 0, 0.0);//开始采集 if (result == 0) { AsyncLogHelper.Info("PHM6000Profiler.StartAcquisition(Entry, 0, 0, 0.0)设置成功!"); } else if (result == -1) { AsyncLogHelper.Info("PHM6000Profiler.StartAcquisition(Entry, 0, 0, 0.0)设置失败!"); } } #endregion #region 停止采集,停止图片显示 public void StopScan() { if (IP != "0.0.0.0") { PHM6000Profiler.StopAcquisition(Entry); } } #endregion private void RenderVtk(IntPtr instance) { // 获取当前控件尺寸 int width = 800; int height = 600; // 调用VTK渲染方法 PclEntry.RenderPCLWindow(pointPic, width, height); PclEntry.UpdatePCLPointColors(pointPic, "z"); PclEntry.ShowCubeAxes(pointPic, 1); PclEntry.ShowLookUpTable(pointPic); // 处理颜色范围 double fMin = 0, fMax = 0; if (PclEntry.GetPointCloudBound(pointPic, ref fMin, ref fMax) != 0) { PclEntry.SetLookUpTableRange(pointPic, fMin, fMax); } } #region 保存lb3d文件 public void SaveLb3dData(string filePath) { try { // 使用GB2312编码文件名 Encoding gb2312 = Encoding.GetEncoding("GB2312"); byte[] encodedBytes = gb2312.GetBytes(filePath); //byte[] encodedBytes = Encoding.UTF8.GetBytes(filePath); // 调用原生保存方法 //switch (MainForm.PicModeflg) //{ // case 0: // int result0 = Pilot2D.SavePicture(lightPic, encodedBytes); // break; // case 1: // int result1 = PclInvoke.SaveDataToFile(Entry, encodedBytes); // break; //} } catch (EncoderFallbackException) { MessageBox.Show("文件名包含GB2312不支持的字符", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error); } } #endregion #region // 定义委托和事件 public class AcquisitionCompletedEventArgs : EventArgs { public IntPtr Instance { get; set; } public int Option { get; set; } } // 声明事件 public event EventHandler AcquisitionCompleted; // 触发事件的方法 public void OnAcquisitionCompleted(IntPtr pInstance, int nOption) { if (nOption == 2) { int width = 800; int height = 600; // 调用VTK渲染方法 PclEntry.RenderPCLWindow(pointPic, width, height); PclEntry.UpdatePCLPointColors(pointPic, "z"); PclEntry.ShowCubeAxes(pointPic, 1); PclEntry.ShowLookUpTable(pointPic); // 处理颜色范围 double fMin = 0, fMax = 0; if (PclEntry.GetPointCloudBound(pointPic, ref fMin, ref fMax) != 0) { PclEntry.SetLookUpTableRange(pointPic, fMin, fMax); } } } #endregion //轮廓图标定 public async Task StartOutlineCali(string roiTxt) { var config = GetConfig(); PARAM_BAR pARAM_BAR = new PARAM_BAR() { Height = config.BarHeight, Width = config.BarWidth, HoleCount = config.BarHoleCount, HoleDiameter = config.BarHoleDiameter, HoleDistance = config.BarHoleDistance, DOF = config.BarDOF, }; SENSOR_POSITION stPosition = new SENSOR_POSITION { IsReverse = config.IsReverse, IsOpposite = config.IsOpposite, fStdDistance = config.fStdDistance, fXCenter = config.fXCenter, x = config.x, y = config.y, z = config.z, xAngle = config.xAngle, yAngle = config.yAngle, zAngle = config.zAngle }; SysCalibration.SetSensorPosition(CaliEntry, Index, stPosition); var roi = GetROICaliThkiness(roiTxt, config); SysCalibration.SetLineROI(CaliEntry, Index, roi, false); IntPtr lineLastdatas = GetLineLastData(); await Task.Run(() => { bool result = SysCalibration.AlignmentBar(CaliEntry, Index, Constants.TYPE_STATIONARY, pARAM_BAR); }); return new float[] { }; } public async Task StartOutlineDD(string roiTxt) { var config = GetConfig(); PARAM_BAR param_bar = new PARAM_BAR() { Height = config.BarHeight, Width = config.BarWidth, HoleCount = config.BarHoleCount, HoleDiameter = config.BarHoleDiameter, HoleDistance = config.BarHoleDistance, DOF = config.BarDOF, }; SENSOR_POSITION stPosition = new SENSOR_POSITION { IsReverse = config.IsReverse, IsOpposite = config.IsOpposite, fStdDistance = config.fStdDistance, fXCenter = config.fXCenter, x = config.x, y = config.y, z = config.z, xAngle = config.xAngle, yAngle = config.yAngle, zAngle = config.zAngle }; SysCalibration.SetSensorPosition(CaliEntry, Index, stPosition); var roi = GetROICaliThkiness(roiTxt, config); SysCalibration.SetLineROI(CaliEntry, Index, roi, false); IntPtr lineLastdatas = GetLineLastData(); //var linedata = linedatas[linedatas.Count - 1]; //var ptr = Marshal.AllocHGlobal(linedata.Length); //Marshal.Copy(linedata, 0, ptr, linedata.Length); //Marshal.FreeHGlobal(lineLastdatas); //await Task.Run(() => //{ // bool result = SysCalibration.AlignmentBar(CaliEntry, Index, SysCalibration.TYPE_STATIONARY, pARAM_BAR); //}); } public async Task MeasureDistanceOutLine() { var config = GetConfig(); SENSOR_POSITION sENSOR_POSITION = new SENSOR_POSITION { IsReverse = config.IsReverse, IsOpposite = config.IsOpposite, fStdDistance = config.fStdDistance, fXCenter = config.fXCenter, x = config.x, y = config.y, z = config.z, xAngle = config.xAngle, yAngle = config.yAngle, zAngle = config.zAngle }; SysCalibration.SetSensorPosition(CaliEntry, Index, sENSOR_POSITION);//设置传感器位置 SysCalibration.SetRate(CaliEntry, Index, config.XAxisResolution / 1000, config.YResolution / 1000); SysCalibration.ClearData(CaliEntry, Index);//清除以前数据 var r = await Task.Run(() => { //输入新数据 unsafe { IntPtr pdata = IntPtr.Zero; if (sline + eline != 0 && eline > sline) { for (ulong i = sline; i < eline; i++) { bool useEncoder = false; if (config.LineScanTriggerSource == EnumLineScanTriggerSource.编码器) useEncoder = true; //使用了引用,什么时候完成使用?如果长时间,代码会有内存风险 pdata = PHM6000Profiler.GetLineDataByIndex(Entry, i); if (pdata == IntPtr.Zero) break; SysCalibration.AddLineDataArray(CaliEntry, Index, pdata, useEncoder, 1);//最后个参数是什么意思 } } else { ulong nindex = 0; while ((pdata = PHM6000Profiler.GetLineDataByIndex(Entry, nindex)) != IntPtr.Zero) { bool useEncoder = false; if (config.LineScanTriggerSource == EnumLineScanTriggerSource.编码器) useEncoder = true; //使用了引用,什么时候完成使用?如果长时间,代码会有内存风险 SysCalibration.AddLineDataArray(CaliEntry, Index, pdata, useEncoder, 1);//最后个参数是什么意思 nindex++; } } } SetTargetParam(config);//设置目标测量参数 //var result = SysCalibration.MeasureDistance(CaliEntry); float measuredValue = SysCalibration.MeasureTargetHigh(CaliEntry, Index); var result = (float)Math.Round(measuredValue, 3); return result; }); return r; } public async Task MeasureOutLine​Thickness​() { var result = await Task.Run(() => { var config = GetConfig(); SetTargetParam(config);//设置目标测量参数 float[,] datas = new float[config.nPartitionX, config.nPartitionY]; data = new float[config.nPartitionX * config.nPartitionY]; int number = 0; for (int i = 0; i < config.nPartitionX; i++) { for (int j = 0; j < config.nPartitionY; j++) { number++; float measuredValue = SysCalibration.MeasureRoiHigh(CaliEntry, Index, number); // 保留3位小数 datas[i, j] = (float)Math.Round(measuredValue, 3); } } //lBCMap = SysCalibration.GetDepthMap(CaliEntry, Index, 4); return datas; }); return result; } //二维图标定 public async Task StartLiaghtAndDeepCali(CaliModel caliModel) { //LBLineDataZA lBLineDataZA = new LBLineDataZA(); SENSOR_POSITION sENSOR_POSITION = new SENSOR_POSITION { IsReverse = caliModel.IsReverse, IsOpposite = caliModel.IsOpposite, fStdDistance = caliModel.fStdDistance, fXCenter = caliModel.fXCenter, x = caliModel.x, y = caliModel.y, z = caliModel.z, xAngle = caliModel.xAngle, yAngle = caliModel.yAngle, zAngle = caliModel.zAngle, }; var config = GetConfig(); PARAM_BOARD pARAM_BOARD = new PARAM_BOARD() { //Height = config.Height, //Width = config.Width, //HoleDiameter = config.HoleDiameter, //HoleDistance = config.HoleDistance, //LocationHoleX1 = config.LocationHoleX1, //LocationHoleX2 = config.LocationHoleX2, //LocationHoleY1 = config.LocationHoleY1, //LocationHoleY2 = config.LocationHoleY2, }; SysCalibration.SetSensorPosition(CaliEntry, Index, sENSOR_POSITION);//设置传感器位置 var roi = caliModel.Plane.Split(','); var roi1 = GetROI(caliModel.Plane, config); var roi2 = GetROI(caliModel.Hole1, config); var roi3 = GetROI(caliModel.Hole2, config); var roi4 = GetROI(caliModel.Hole3, config); SysCalibration.SetRate(CaliEntry, Index, config.XAxisResolution / 1000, config.YResolution / 1000); SysCalibration.SetFlatROI(CaliEntry, Index, roi1, true); SysCalibration.SetHoleROI(CaliEntry, Index, 0, roi2, true); SysCalibration.SetHoleROI(CaliEntry, Index, 1, roi3, true); SysCalibration.SetHoleROI(CaliEntry, Index, 2, roi4, true); SysCalibration.SetBoardParameter(CaliEntry, pARAM_BOARD); SysCalibration.ClearData(CaliEntry, Index);//清除以前数据 await Task.Run(() => { //修改此段代码 //foreach (var item in GetLineDatas()) unsafe { IntPtr pdata = IntPtr.Zero; //if (sline + eline != 0 && eline > sline) //{ // for (ulong i = sline; i < eline; i++) // { // bool useEncoder = false; // if (config.LineScanTriggerSource == EnumLineScanTriggerSource.编码器) useEncoder = true; // //使用了引用,什么时候完成使用?如果长时间,代码会有内存风险 // pdata = GetLineDataByIndex(Entry, i); // if (pdata == IntPtr.Zero) // break; // SysCalibration.AddLineDataArray(CaliEntry, Index, pdata, useEncoder, 1);//最后个参数是什么意思 // } //} //else { ulong nindex = 0; while ((pdata = PHM6000Profiler.GetLineDataByIndex(Entry, nindex)) != IntPtr.Zero) { bool useEncoder = false; if (config.LineScanTriggerSource == EnumLineScanTriggerSource.编码器) useEncoder = true; //使用了引用,什么时候完成使用?如果长时间,代码会有内存风险 SysCalibration.AddLineDataArray(CaliEntry, Index, pdata, useEncoder, 1);//最后个参数是什么意思 nindex++; } } } SysCalibration.AlignmentMovingFlat(CaliEntry, Index);//下次打开程序时可能会序号错误 //SysCalibration.SystemCalibration(caliEntry);//error没有真实的孔,就会卡进程 }); } //测量厚度 public async Task MeasureDistance() { var config = GetConfig(); SENSOR_POSITION sENSOR_POSITION = new SENSOR_POSITION { //IsReverse = CaliModel.IsReverse, //IsOpposite = CaliModel.IsOpposite, //fStdDistance = CaliModel.fStdDistance, //fXCenter = CaliModel.fXCenter, //x = CaliModel.x, //y = CaliModel.y, //z = CaliModel.z, //xAngle = CaliModel.xAngle, //yAngle = CaliModel.yAngle, //zAngle = CaliModel.zAngle, }; SysCalibration.SetSensorPosition(CaliEntry, Index, sENSOR_POSITION);//设置传感器位置 SysCalibration.SetRate(CaliEntry, Index, config.XAxisResolution / 1000, config.YResolution / 1000); SysCalibration.ClearData(CaliEntry, Index);//清除以前数据 var r = await Task.Run(() => { //输入新数据 unsafe { IntPtr pdata = IntPtr.Zero; if (sline + eline != 0 && eline > sline) { for (ulong i = sline; i < eline; i++) { bool useEncoder = false; if (config.LineScanTriggerSource == EnumLineScanTriggerSource.编码器) useEncoder = true; //使用了引用,什么时候完成使用?如果长时间,代码会有内存风险 pdata = PHM6000Profiler.GetLineDataByIndex(Entry, i); if (pdata == IntPtr.Zero) break; SysCalibration.AddLineDataArray(CaliEntry, Index, pdata, useEncoder, 1);//最后个参数是什么意思 } } else { ulong nindex = 0; while ((pdata = PHM6000Profiler.GetLineDataByIndex(Entry, nindex)) != IntPtr.Zero) { bool useEncoder = false; if (config.LineScanTriggerSource == EnumLineScanTriggerSource.编码器) useEncoder = true; //使用了引用,什么时候完成使用?如果长时间,代码会有内存风险 SysCalibration.AddLineDataArray(CaliEntry, Index, pdata, useEncoder, 1);//最后个参数是什么意思 nindex++; } } } SetTargetParam(config);//设置目标测量参数 //var result = SysCalibration.MeasureDistance(CaliEntry); float measuredValue = SysCalibration.MeasureTargetHigh(CaliEntry, Index); var result = (float)Math.Round(measuredValue, 3); return result; }); return r; } public static ulong sline = 0; public static ulong eline = 0; public static IntPtr lBCMap = IntPtr.Zero; public static float[] data = null; //测量凹凸 public async Task Measure​Uneven​() { var result = await Task.Run(() => { var config = GetConfig(); //SENSOR_POSITION sENSOR_POSITION = new SENSOR_POSITION //{ // IsReverse = CaliModel.IsReverse, // IsOpposite = CaliModel.IsOpposite, // fStdDistance = CaliModel.fStdDistance, // fXCenter = CaliModel.fXCenter, // x = CaliModel.x, // y = CaliModel.y, // z = CaliModel.z, // xAngle = CaliModel.xAngle, // yAngle = CaliModel.yAngle, // zAngle = CaliModel.zAngle, //}; //SysCalibration.SetSensorPosition(CaliEntry, Index, sENSOR_POSITION);//设置传感器位置 //SysCalibration.SetRate(CaliEntry, Index, config.XAxisResolution / 1000, config.YResolution / 1000); //SysCalibration.ClearData(CaliEntry, Index);//清除以前数据 ////输入新数据 //unsafe //{ // IntPtr pdata = IntPtr.Zero; // if (sline + eline != 0 && eline > sline) // { // for (ulong i = sline; i < eline; i++) // { // bool useEncoder = false; // if (config.LineScanTriggerSource == EnumLineScanTriggerSource.编码器) useEncoder = true; // //使用了引用,什么时候完成使用?如果长时间,代码会有内存风险 // pdata = GetLineDataByIndex(Entry, i); // if (pdata == IntPtr.Zero) // break; // SysCalibration.AddLineDataArray(CaliEntry, Index, pdata, useEncoder, 1);//最后个参数是什么意思 // } // } // else // { // ulong nindex = 0; // while ((pdata = GetLineDataByIndex(Entry, nindex)) != IntPtr.Zero) // { // bool useEncoder = false; // if (config.LineScanTriggerSource == EnumLineScanTriggerSource.编码器) useEncoder = true; // //使用了引用,什么时候完成使用?如果长时间,代码会有内存风险 // SysCalibration.AddLineDataArray(CaliEntry, Index, pdata, useEncoder, 1);//最后个参数是什么意思 // nindex++; // } // } //} SetTargetParam(config);//设置目标测量参数 float[,] datas = new float[config.nPartitionX, config.nPartitionY]; data = new float[config.nPartitionX * config.nPartitionY]; int number = 0; for (int i = 0; i < config.nPartitionX; i++) { for (int j = 0; j < config.nPartitionY; j++) { number++; float measuredValue = SysCalibration.MeasureRoiHigh(CaliEntry, Index, number); // 保留3位小数 datas[i, j] = (float)Math.Round(measuredValue, 3); } } //lBCMap = SysCalibration.GetDepthMap(CaliEntry, Index, 4); return datas; }); return result; } LB_ROI GetROI(string s, PHM6000SensorConfig config) { var roi = s.Split(','); LB_ROI lB_ROI = new LB_ROI() { left = Convert.ToInt32(roi[0]) * config.XAxisResolution / 1000, top = Convert.ToInt32(roi[1]) * config.YResolution / 1000, right = Convert.ToInt32(roi[2]) * config.XAxisResolution / 1000, bottom = Convert.ToInt32(roi[3]) * config.YResolution / 1000, // left = Convert.ToInt32(roi[0]) * 4096 / 2048, // top = (int)(325.0 - 225.0 - float.Parse(roi[1]) * (470.0 - 225.0) / (1024.0 - 1.0) + 0.5), // right = Convert.ToInt32(roi[2]) * 4096 / 2048, // bottom = (int)(325.0 - 225.0 - float.Parse(roi[3]) * (470.0 - 225.0) / (1024.0 - 1.0) + 0.5), //}; //float fTemp; //if (lB_ROI.left > lB_ROI.right) //{ // fTemp = lB_ROI.left; // lB_ROI.left = lB_ROI.right; // lB_ROI.right = fTemp; //} //if (lB_ROI.top > lB_ROI.bottom) //{ // fTemp = lB_ROI.top; // lB_ROI.top = lB_ROI.bottom; // lB_ROI.bottom = fTemp; //} }; return lB_ROI; } LB_ROI GetROICaliThkiness(string s, PHM6000SensorConfig config) { var roi = s.Split(','); LB_ROI lB_ROI = new LB_ROI() { //left = Convert.ToInt32(roi[0]) * config.XAxisResolution / 1000, //top = Convert.ToInt32(roi[1]) * config.YResolution / 1000, //right = Convert.ToInt32(roi[2]) * config.XAxisResolution / 1000, //bottom = Convert.ToInt32(roi[3]) * config.YResolution / 1000, left = Convert.ToInt32(roi[0]) * 4096 / 2048, top = (int)(325.0 - 225.0 - float.Parse(roi[1]) * (470.0 - 225.0) / (1024.0 - 1.0) + 0.5), right = Convert.ToInt32(roi[2]) * 4096 / 2048, bottom = (int)(325.0 - 225.0 - float.Parse(roi[3]) * (470.0 - 225.0) / (1024.0 - 1.0) + 0.5), }; float fTemp; if (lB_ROI.left > lB_ROI.right) { fTemp = lB_ROI.left; lB_ROI.left = lB_ROI.right; lB_ROI.right = fTemp; } if (lB_ROI.top > lB_ROI.bottom) { fTemp = lB_ROI.top; lB_ROI.top = lB_ROI.bottom; lB_ROI.bottom = fTemp; } return lB_ROI; } } #region 传感器列表模型类 /// /// PHM6000SensorModel /// [JsonObject(MemberSerialization.OptOut)] [TypeConverter(typeof(PropertySorter))] public class PHM6000SensorModel { /// /// IP地址 /// [Category("PHM6000SensorModel"), PropertyOrder(2)] [DisplayName("IP地址")] [Browsable(true)] public string IP { get; set; } /// /// 端口 /// [Category("PHM6000SensorModel"), PropertyOrder(3)] [DisplayName("端口")] [Browsable(true)] public int Port { get; set; } /// /// 序列号 /// [Category("PHM6000SensorModel"), PropertyOrder(1)] [DisplayName("序列号")] [Browsable(true)] public string SerialNo { get; set; } /// /// 状态 /// [Category("PHM6000SensorModel"), PropertyOrder(0)] [DisplayName("状态")] [Browsable(true)] public string State { get; set; } /// /// PHM6000Sensor /// [Category("PHM6000SensorModel"), PropertyOrder(4)] [Browsable(false)] public PHM6000Sensor Sensor { get; set; } /// /// Model /// [Category("PHM6000SensorModel"), PropertyOrder(5)] [Browsable(false)] public string Model { get; set; } } #endregion //采集数据时要显示的图类形 public enum EnumFetchPicType { light, deep, pointCloud, outline, mainOutLine } public class FloatArrayToIntPtrConverter { public unsafe static IntPtr ConvertFloatArrayToIntPtr(float[] data) { if (data == null || data.Length == 0) { return IntPtr.Zero; } fixed (float* p = data) { return (IntPtr)p; } } } }