소스 검색

新增视觉拍照接口,支持返回图像与图形数据

新增 ExecutePhotoGetSinglePointWithImage 接口,支持在视觉识别流程中同时返回拍照图像和识别图形结果。服务层实现了完整的拍照、视觉处理及数据提取流程,视图模型已集成新接口并支持界面显示图像和图形。优化了日志与异常处理,提升了系统调试和可视化能力。
孝锋 徐 8 달 전
부모
커밋
03247190b7

+ 11 - 0
TeamAAS-VM/Interfaces/IRemoteCommandService.cs

@@ -1,3 +1,4 @@
+using Cognex.VisionPro;
 using Cognex.VisionPro.ToolBlock;
 using System;
 using System.Collections.Generic;
@@ -250,6 +251,16 @@ namespace TeamAAS_VP.Interfaces
         /// <returns></returns>
         Task<(bool IsSucceed, double X, double Y, double U)> ExecutePhotoGetSinglePoint(ProcedureModel procedure, Dictionary<string, string> InputTerminal, double[] robotCoord, CancellationToken cancellationToken);
 
+        /// <summary>
+        /// 执行相机拍照获取单个点位结果,并且返回图像和图形
+        /// </summary>
+        /// <param name="procedure"></param>
+        /// <param name="InputTerminal"></param>
+        /// <param name="robotCoord"></param>
+        /// <param name="cancellationToken"></param>
+        /// <returns></returns>
+        Task<(bool IsSucceed, double X, double Y, double U, ICogImage Image, CogGraphicCollection Graphic)> ExecutePhotoGetSinglePointWithImage(ProcedureModel procedure, Dictionary<string, string> InputTerminal, double[] robotCoord, CancellationToken cancellationToken);
+
         /// <summary>
         /// 获取需要输出项
         /// </summary>

+ 177 - 0
TeamAAS-VM/Services/RemoteCommandService.cs

@@ -1562,6 +1562,103 @@ namespace TeamAAS_VP.Services
             }
         }
 
+        /// <summary>
+        /// 执行相机拍照并运行 ToolBlock,返回是否成功并通过 out 参数返回 Outputs、图像和图形集合。
+        /// </summary>
+        /// <param name="procedure"></param>
+        /// <param name="InputTerminal"></param>
+        /// <param name="outputCollection"></param>
+        /// <param name="outImage"></param>
+        /// <param name="outGraphicCollection"></param>
+        /// <returns></returns>
+        public bool ExecutePhotoEx(ProcedureModel procedure, Dictionary<string, string> InputTerminal, out CogToolBlockTerminalCollection outputCollection,out ICogImage outImage,out CogGraphicCollection outGraphicCollection)
+        {
+            outImage = null;
+            outGraphicCollection = null;
+            try
+            {
+                
+                // 1. 采集图像
+                var camera = _cameraService.GetCamera(procedure.CameraId);
+                bool succed = camera.SetExposureTime(procedure.ExposureTime);
+                if (!succed)
+                {
+                    SendTaskMessage($"相机曝光设置失败!", MessageLevel.Error);
+                }
+                succed = camera.SetGain(procedure.Gain);
+                if (!succed)
+                {
+                    SendTaskMessage($"相机增益设置失败!", MessageLevel.Error);
+                }
+                DateTime nowtime = DateTime.Now;
+                LogHelper.WriteLogInfo("开始采集图像");
+                var image = camera.Grab();
+                if (image == null)
+                {
+
+                    SendTaskMessage(Lang.图像采集失败, MessageLevel.Error);
+                    outputCollection = null;
+                    return false;
+                }
+                outImage= image;
+                procedure.ToolBlock.Inputs["InputImage"].Value = image;
+                LogHelper.WriteLogInfo($"采集图像完成;用时:{(DateTime.Now - nowtime).Milliseconds}ms");
+
+                // 2. 为ToolBlock传入其他输入终端
+                if (InputTerminal != null)
+                {
+                    LogHelper.WriteLogInfo($"为ToolBlock传入输入终端");
+                    foreach (var item in InputTerminal)
+                    {
+                        if (procedure.ToolBlock.Inputs.Contains(item.Key))
+                        {
+                            LogHelper.WriteLogInfo($"传入[{item.Key}]={item.Value}");
+                            procedure.ToolBlock.Inputs[item.Key].Value = item.Value;
+                        }
+                        else
+                        {
+                            LogHelper.WriteLogInfo($"创建并传入[{item.Key}]={item.Value}");
+                            procedure.ToolBlock.Inputs.Add(new CogToolBlockTerminal(item.Key, item.Value));
+                        }
+                    }
+                }
+
+                // 3. 运行视觉工具
+                LogHelper.WriteLogInfo("开始运行视觉工具");
+                procedure.ToolBlock.Run();      //运行ToolBlock
+
+                if (procedure.ToolBlock.RunStatus.Result == CogToolResultConstants.Accept)
+                {
+                    SendTaskMessage(Lang.视觉流程执行耗时.Replace("{0}", procedure.Name).Replace("{1}", $"{procedure.ToolBlock.RunStatus.ProcessingTime:F1}"), MessageLevel.Info);
+                    outputCollection = procedure.ToolBlock.Outputs;     //获取输出终端集合
+                    DatabaseHelper.AddCameraRecords(_productService.GetCurrentProduct().Name, procedure.Name, outputCollection);
+                    ICogRecord record = null;
+                    foreach (CogToolBlockTerminal item in outputCollection)
+                    {
+                        if (item.Value is ICogRecord)
+                            record = item.Value as ICogRecord;
+                    }
+                    outGraphicCollection= outputCollection["Graphic"].Value as CogGraphicCollection;
+                    return true;
+                }
+                else
+                {
+                    SendTaskMessage(Lang.视觉流程执行出错耗时.Replace("{0}", procedure.Name).Replace("{1}", $"{procedure.ToolBlock.RunStatus.ProcessingTime:F1}"), MessageLevel.Error);
+                    SendTaskMessage(procedure.ToolBlock.RunStatus.Message, MessageLevel.Error);
+                    outputCollection = null;
+                    outGraphicCollection = outputCollection["Graphic"].Value as CogGraphicCollection;
+                    return false;
+                }
+            }
+            catch (Exception ex)
+            {
+                SendTaskMessage(ex.Message, MessageLevel.Error);
+                LogHelper.WriteLogError("执行相机取图并执行视觉工具组时出错!", ex);
+                outputCollection = null;
+                return false;
+            }
+        }
+
         /// <summary>
         /// 执行相机拍照获取单个点位结果
         /// </summary>
@@ -1639,6 +1736,86 @@ namespace TeamAAS_VP.Services
             }
         }
 
+        /// <summary>
+        /// 执行相机拍照获取单个点位结果,并且返回图像和图形
+        /// </summary>
+        /// <param name="procedure"></param>
+        /// <param name="InputTerminal"></param>
+        /// <param name="robotCoord"></param>
+        /// <param name="cancellationToken"></param>
+        /// <returns></returns>
+        public async Task<(bool IsSucceed, double X, double Y, double U, ICogImage Image, CogGraphicCollection Graphic)> ExecutePhotoGetSinglePointWithImage(ProcedureModel procedure, Dictionary<string, string> InputTerminal, double[] robotCoord, CancellationToken cancellationToken)
+        {
+            DateTime nowtime = DateTime.Now;
+            await SetLightBeforePhoto(procedure);
+            ICogImage outImage=null;
+            CogGraphicCollection outGraphicCollection=null;
+            try
+            {
+                //拍照失败时,需要多次拍照
+                for (int i = 0; i < procedure.FeederFailLimit; i++)
+                {
+                    SendTaskMessage(Lang.开始执行视觉流程.Replace("{0}", $"{i + 1}").Replace("{1}", procedure.Name), MessageLevel.Info);
+
+
+                    // 1. 执行相机拍照并运行视觉工具
+                    bool visionSucceed = ExecutePhotoEx(procedure, InputTerminal, out CogToolBlockTerminalCollection outputCollection, out outImage, out outGraphicCollection);
+                    if (!visionSucceed)
+                    {
+                        SendTaskMessage(Lang.视觉任务执行失败, MessageLevel.Error);
+                        continue;
+                    }
+
+                    if (!outputCollection.Contains("Found"))
+                    {
+                        SendTaskMessage(Lang.未找到视觉输出结果, MessageLevel.Error);
+                        return (false, 0, 0, 0, outImage, outGraphicCollection);
+                    }
+
+                    // 2. 获取视觉输出结果
+                    bool Found = (bool)(outputCollection["Found"].Value);
+                    if (!Found)
+                    {
+                        SendTaskMessage(Lang.拍照NG, MessageLevel.Debug);
+                        continue;
+                    }
+
+                    SendTaskMessage(Lang.拍照OK, MessageLevel.Debug);
+
+                    // 3. 获取视觉输出结果
+                    LogHelper.WriteLogInfo("开始获取视觉输出结果");
+                    //获取相机校准
+                    var calib = _calibrationService.GetCalibration(procedure.CalibrationId);
+                    string points = (string)(outputCollection["Point"].Value);
+                    string[] strpoints = points.Split(';');
+                    //先将pos按照逗号进行分隔,拿到数组
+                    var posParts = strpoints[0].Split(',');
+                    double _pixel_x = double.Parse(posParts[0]);
+                    double _pixel_y = double.Parse(posParts[1]);
+                    double _pixel_u = double.Parse(posParts[2]);
+                    //转换点位-像素转换成机器人绝对坐标
+                    var calibResult = _calibrationService.ConvertPixelToPosition((_pixel_x, _pixel_y, _pixel_u), robotCoord, calib, RobotBrand.XYZ_Platform);
+                    if (!calibResult.IsSucceed)
+                    {
+                        return (false, 0, 0, 0, outImage, outGraphicCollection);
+                    }
+                    return (true, calibResult.X, calibResult.Y, calibResult.U, outImage, outGraphicCollection);
+                }
+                SendTaskMessage(Lang.多次拍照失败, MessageLevel.Alarm);
+                return (false, 0, 0, 0, outImage, outGraphicCollection);
+            }
+            catch (Exception ex)
+            {
+                LogHelper.WriteLogError("执行相机取图并获取单点位时出错!", ex);
+                return (false, 0, 0, 0, outImage, outGraphicCollection);
+            }
+            finally
+            {
+                await TurnOffLightAfterPhoto(procedure);
+
+            }
+        }
+
         /// <summary>
         /// 从 ToolBlock 的输出集合中根据 Procedure 配置提取需要发送的输出项并做必要的坐标转换。
         /// 返回元组:是否成功、错误信息(失败时)和名称->(是否点位, 值) 的字典。

+ 9 - 3
TeamAAS-VM/ViewModels/Product/AutoCorrectLockPointViewModel.cs

@@ -193,7 +193,9 @@ namespace TeamAAS_VP.ViewModels.Product
                 await Robot.CalibMotionAsync(rpoint, 0);
                 await Task.Delay(200);
                 // 执行拍照并获取识别结果
-                var recognitionResult = await _remoteCommandService.ExecutePhotoGetSinglePoint(procedure, null, new double[] { rpoint.X, rpoint.Y, 0 }, _cts.Token);
+                var recognitionResult = await _remoteCommandService.ExecutePhotoGetSinglePointWithImage(procedure, null, new double[] { rpoint.X, rpoint.Y, 0 }, _cts.Token);
+                Image= recognitionResult.Image;
+                Graphic= recognitionResult.Graphic;
                 if (!recognitionResult.IsSucceed)
                 {
                     _eventAggregator.GetEvent<SnackbarMessageNotification>().Publish(new MessageParameter() { Msg = "拍照获取识别结果失败,无法执行取料拍照点位矫正!", Duration = 1 });
@@ -215,7 +217,9 @@ namespace TeamAAS_VP.ViewModels.Product
                     return;
                 await Task.Delay(200);
                 // 执行拍照并获取识别结果
-                recognitionResult = await _remoteCommandService.ExecutePhotoGetSinglePoint(procedure, null, new double[] { rpoint.X, rpoint.Y, 0 }, _cts.Token);
+                recognitionResult = await _remoteCommandService.ExecutePhotoGetSinglePointWithImage(procedure, null, new double[] { rpoint.X, rpoint.Y, 0 }, _cts.Token);
+                Image = recognitionResult.Image;
+                Graphic = recognitionResult.Graphic;
                 if (!recognitionResult.IsSucceed)
                 {
                     _eventAggregator.GetEvent<SnackbarMessageNotification>().Publish(new MessageParameter() { Msg = "拍照获取识别结果失败,无法执行取料拍照点位矫正!", Duration = 1 });
@@ -271,7 +275,9 @@ namespace TeamAAS_VP.ViewModels.Product
                         return;
                     await Task.Delay(200);
                     // 执行拍照并获取识别结果
-                    recognitionResult = await _remoteCommandService.ExecutePhotoGetSinglePoint(procedure, null, new double[] { rpoint.X, rpoint.Y, 0 }, _cts.Token);
+                    recognitionResult = await _remoteCommandService.ExecutePhotoGetSinglePointWithImage(procedure, null, new double[] { rpoint.X, rpoint.Y, 0 }, _cts.Token);
+                    Image = recognitionResult.Image;
+                    Graphic = recognitionResult.Graphic;
                     if (!recognitionResult.IsSucceed)
                     {
                         _eventAggregator.GetEvent<SnackbarMessageNotification>().Publish(new MessageParameter() { Msg = "拍照获取识别结果失败,无法执行取料拍照点位矫正!", Duration = 1 });