Przeglądaj źródła

视觉拍照流程支持自动控制光源并异步化

实现拍照前后自动开关光源,相关接口与调用流程全部异步化。IRemoteCommandService增加光源控制方法,RemoteCommandService实现光源通道遍历与亮度设置。所有拍照相关流程确保异常或失败时光源能正确关闭,提升系统健壮性和自动化水平。
孝锋 徐 8 miesięcy temu
rodzic
commit
144906ffd3

+ 2 - 2
TeamAAS-VM/Core/Management.cs

@@ -1068,7 +1068,7 @@ namespace TeamAAS_VP.Core
 
                             // 执行视觉任务
                             var _cts = new CancellationTokenSource();
-                            var visionResult = _remoteCommandService.ExecutePhotoGetSinglePoint(process, null,null, _cts.Token);
+                            var visionResult =await _remoteCommandService.ExecutePhotoGetSinglePoint(process, null,null, _cts.Token);
                             if (visionResult.IsSucceed)
                             {
                                 DowmCameraResults[cameraIndex] = new PointF((float)visionResult.X, (float)visionResult.Y);
@@ -1144,7 +1144,7 @@ namespace TeamAAS_VP.Core
 
                             // 执行视觉任务
                             var _cts = new CancellationTokenSource();
-                            var visionResult = _remoteCommandService.ExecutePhotoGetSinglePoint(process, null, new double[] { currentPosition.X , currentPosition.Y, currentPosition.U}, _cts.Token);
+                            var visionResult =await _remoteCommandService.ExecutePhotoGetSinglePoint(process, null, new double[] { currentPosition.X , currentPosition.Y, currentPosition.U}, _cts.Token);
                             if (visionResult.IsSucceed)
                             {
                                 UpCameraPutResults[cameraIndex]=new PointF((float)visionResult.X, (float)visionResult.Y);

+ 15 - 1
TeamAAS-VM/Interfaces/IRemoteCommandService.cs

@@ -248,7 +248,7 @@ namespace TeamAAS_VP.Interfaces
         /// <param name="robotCoord"></param>
         /// <param name="cancellationToken"></param>
         /// <returns></returns>
-        (bool IsSucceed, double X, double Y, double U) ExecutePhotoGetSinglePoint(ProcedureModel procedure, Dictionary<string, string> InputTerminal, double[] robotCoord, CancellationToken cancellationToken);
+        Task<(bool IsSucceed, double X, double Y, double U)> ExecutePhotoGetSinglePoint(ProcedureModel procedure, Dictionary<string, string> InputTerminal, double[] robotCoord, CancellationToken cancellationToken);
 
         /// <summary>
         /// 获取需要输出项
@@ -317,5 +317,19 @@ namespace TeamAAS_VP.Interfaces
         /// <param name="isUpdateParame"></param>
         /// <returns></returns>
         Task ExecuteFeederWorks(IVoiceCoilMotorFeeder feeder, FeederWorks works, CancellationToken cancellationToken, bool isUpdateParame = true);
+
+        /// <summary>
+        /// 在拍照前设置光源亮度和打开光源
+        /// </summary>
+        /// <param name="procedure">流程模型</param>
+        /// <returns></returns>
+        Task SetLightBeforePhoto(ProcedureModel procedure);
+
+        /// <summary>
+        /// 在拍照后关闭光源
+        /// </summary>
+        /// <param name="procedure">流程模型</param>
+        /// <returns></returns>
+        Task TurnOffLightAfterPhoto(ProcedureModel procedure);
     }
 }

+ 122 - 44
TeamAAS-VM/Services/RemoteCommandService.cs

@@ -52,6 +52,7 @@ namespace TeamAAS_VP.Services
         private readonly IContainerProvider _container;
         private readonly IRegionManager _regionManager;
         private readonly ISystemDatabaseService _systemDatabaseService;
+        private readonly ILightManagerService _lightManagerService;
 
         /// <summary>
         /// 节拍计时任务的取消令牌,用于 StartCycleTiming/StopCycleTiming。
@@ -109,7 +110,7 @@ namespace TeamAAS_VP.Services
         /// <param name="container">IOC 容器提供者,用于脚本执行时解析依赖。</param>
         /// <param name="systemDatabaseService">系统数据库服务,用于记录产量/报警等。</param>
         public RemoteCommandService(IEventAggregator eventAggregator, IRegionManager regionManager, IProductService productService, IConfigService configService, ICalibrationService calibrationService,
-            IFeederService feederService, ICameraService cameraService, IRobotService robotService, IContainerProvider container, ISystemDatabaseService systemDatabaseService)
+            IFeederService feederService, ICameraService cameraService, IRobotService robotService, IContainerProvider container, ISystemDatabaseService systemDatabaseService, ILightManagerService lightManagerService)
         {
             _eventAggregator = eventAggregator;
             _regionManager = regionManager;
@@ -121,6 +122,7 @@ namespace TeamAAS_VP.Services
             _robotService = robotService;
             _container = container;
             _systemDatabaseService = systemDatabaseService;
+            _lightManagerService = lightManagerService;
         }
 
         /// <summary>
@@ -1158,6 +1160,7 @@ namespace TeamAAS_VP.Services
                 }
             }
 
+            await SetLightBeforePhoto(procedure);
             //执行Feeder相机拍照前的任务
             await ExecuteFeederForPhotoBefore(feeder, procedure, doVibrateFirst, doCaptureFirst, cancellationToken);
 
@@ -1175,6 +1178,7 @@ namespace TeamAAS_VP.Services
                 if (cancellationToken != null && cancellationToken.IsCancellationRequested)
                 {
                     await feeder.CloseLightAsync();
+                    await TurnOffLightAfterPhoto(procedure);
                     return (false, new string[] { "VisionTaskCancelled" });
                 }
 
@@ -1200,6 +1204,7 @@ namespace TeamAAS_VP.Services
                 if (!Found)
                 {
                     SendTaskMessage(Lang.拍照NG, MessageLevel.Debug);
+                    await TurnOffLightAfterPhoto(procedure);
                     await ExecuteFeederForPhotoLater(feeder, procedure, cancellationToken);
                     continue;
                 }
@@ -1300,6 +1305,7 @@ namespace TeamAAS_VP.Services
                 {
                     await feeder.CloseLightAsync();
                 }
+                await TurnOffLightAfterPhoto(procedure);
 
                 //如果输出模式是AllAtOnce或者BatchedUntilTerminator,则分次发送数据
                 if (procedure.OutputPointMode == OutputPointMode.UntilTerminator || procedure.OutputPointMode == OutputPointMode.BatchedUntilTerminator)
@@ -1323,6 +1329,7 @@ namespace TeamAAS_VP.Services
             {
                 await feeder.CloseLightAsync();
             }
+            await TurnOffLightAfterPhoto(procedure);
             SendTaskMessage(Lang.多次拍照失败, MessageLevel.Alarm);
             return (false, new string[] { "VisionFailed" });
         }
@@ -1336,6 +1343,7 @@ namespace TeamAAS_VP.Services
             DateTime startTime = DateTime.Now;
             try
             {
+                await SetLightBeforePhoto(procedure);
                 // 触发命令传入的输入终端
                 Dictionary<string, string> InputTerminal = null;
 
@@ -1434,6 +1442,10 @@ namespace TeamAAS_VP.Services
                 LogHelper.WriteLogError("执行普通视觉任务时出错!", ex);
                 return (false, "Exception");
             }
+            finally
+            {
+                await TurnOffLightAfterPhoto(procedure);
+            }
         }
 
         /// <summary>
@@ -1558,59 +1570,73 @@ namespace TeamAAS_VP.Services
         /// <param name="robotCoord"></param>
         /// <param name="cancellationToken"></param>
         /// <returns></returns>
-        public (bool IsSucceed ,double X,double Y,double U) ExecutePhotoGetSinglePoint(ProcedureModel procedure, Dictionary<string, string> InputTerminal, double[] robotCoord, CancellationToken cancellationToken)
+        public async Task<(bool IsSucceed, double X, double Y, double U)> ExecutePhotoGetSinglePoint(ProcedureModel procedure, Dictionary<string, string> InputTerminal, double[] robotCoord, CancellationToken cancellationToken)
         {
             DateTime nowtime = DateTime.Now;
-            //拍照失败时,需要多次拍照
-            for (int i = 0; i < procedure.FeederFailLimit; i++)
+            await SetLightBeforePhoto(procedure);
+            try
             {
-                SendTaskMessage(Lang.开始执行视觉流程.Replace("{0}", $"{i + 1}").Replace("{1}", procedure.Name), MessageLevel.Info);
-
-                // 1. 执行相机拍照并运行视觉工具
-                bool visionSucceed = ExecutePhoto(procedure, InputTerminal, out CogToolBlockTerminalCollection outputCollection);
-                if (!visionSucceed)
+                //拍照失败时,需要多次拍照
+                for (int i = 0; i < procedure.FeederFailLimit; i++)
                 {
-                    SendTaskMessage(Lang.视觉任务执行失败, MessageLevel.Error);
-                    continue;
-                }
+                    SendTaskMessage(Lang.开始执行视觉流程.Replace("{0}", $"{i + 1}").Replace("{1}", procedure.Name), MessageLevel.Info);
 
-                if (!outputCollection.Contains("Found"))
-                {
-                    SendTaskMessage(Lang.未找到视觉输出结果, MessageLevel.Error);
-                    return (false,0,0,0);
-                }
+                    // 1. 执行相机拍照并运行视觉工具
+                    bool visionSucceed = ExecutePhoto(procedure, InputTerminal, out CogToolBlockTerminalCollection outputCollection);
+                    if (!visionSucceed)
+                    {
+                        SendTaskMessage(Lang.视觉任务执行失败, MessageLevel.Error);
+                        continue;
+                    }
 
-                // 2. 获取视觉输出结果
-                bool Found = (bool)(outputCollection["Found"].Value);
-                if (!Found)
-                {
-                    SendTaskMessage(Lang.拍照NG, MessageLevel.Debug);
-                    continue;
-                }
+                    if (!outputCollection.Contains("Found"))
+                    {
+                        SendTaskMessage(Lang.未找到视觉输出结果, MessageLevel.Error);
+                        return (false, 0, 0, 0);
+                    }
 
-                SendTaskMessage(Lang.拍照OK, MessageLevel.Debug);
+                    // 2. 获取视觉输出结果
+                    bool Found = (bool)(outputCollection["Found"].Value);
+                    if (!Found)
+                    {
+                        SendTaskMessage(Lang.拍照NG, MessageLevel.Debug);
+                        continue;
+                    }
 
-                // 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);
+                    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);
+                    }
+                    return (true, calibResult.X, calibResult.Y, calibResult.U);
                 }
-                return (true, calibResult.X, calibResult.Y, calibResult.U);
+                SendTaskMessage(Lang.多次拍照失败, MessageLevel.Alarm);
+                return (false, 0, 0, 0);
+            }
+            catch (Exception ex)
+            {
+                LogHelper.WriteLogError("执行相机取图并获取单点位时出错!", ex);
+                return (false, 0, 0, 0);
+            }
+            finally
+            {
+                await TurnOffLightAfterPhoto(procedure);
+
             }
-            SendTaskMessage(Lang.多次拍照失败, MessageLevel.Alarm);
-            return (false, 0, 0, 0);
         }
 
         /// <summary>
@@ -2021,6 +2047,58 @@ namespace TeamAAS_VP.Services
                 }
             }
         }
+
+        /// <summary>
+        /// 在拍照前设置光源亮度和打开光源
+        /// </summary>
+        /// <param name="procedure">流程模型</param>
+        /// <returns></returns>
+        public async Task SetLightBeforePhoto(ProcedureModel procedure)
+        {
+            //判断当前流程是否启用光源控制
+            if (procedure.IsControlLightChannels)
+            {
+                //打开所有需要控制的光源通道
+                foreach (var lightChannel in procedure.LightChannels)
+                {
+                    bool isSucceed = false;
+                    isSucceed = await _lightManagerService.TurnOnGlobalChannelAsync(lightChannel.GlobalIndex);
+                    if (!isSucceed)
+                    {
+                        LogHelper.WriteLogInfo($"设置光源通道{lightChannel.GlobalIndex}打开失败!");
+                    }
+                    isSucceed = await _lightManagerService.SetGlobalChannelBrightnessAsync(lightChannel.GlobalIndex, lightChannel.DefaultBrightness);
+                    if (!isSucceed)
+                    {
+                        LogHelper.WriteLogInfo($"设置光源通道{lightChannel.GlobalIndex}亮度{lightChannel.DefaultBrightness}失败!");
+                    }
+                }
+            }
+        }
+
+        /// <summary>
+        /// 在拍照后关闭光源
+        /// </summary>
+        /// <param name="procedure">流程模型</param>
+        /// <returns></returns>
+        public async Task TurnOffLightAfterPhoto(ProcedureModel procedure)
+        {
+            //判断当前流程是否启用光源控制
+            if (procedure.IsControlLightChannels)
+            {
+                //关闭所有需要控制的光源通道
+                foreach (var lightChannel in procedure.LightChannels)
+                {
+                    bool isSucceed = false;
+                    isSucceed = await _lightManagerService.TurnOffGlobalChannelAsync(lightChannel.GlobalIndex);
+                    if (!isSucceed)
+                    {
+                        LogHelper.WriteLogInfo($"设置光源通道{lightChannel.GlobalIndex}关闭失败!");
+                    }
+                }
+            }
+        }
+
         #endregion
     }
 }

+ 1 - 1
TeamAAS-VM/ViewModels/Product/PlcPointParamsViewModel.cs

@@ -918,7 +918,7 @@ namespace TeamAAS_VP.ViewModels.Product
 
                 var _cts = new CancellationTokenSource();
                 // 2. 执行拍照并获取识别结果
-                var recognitionResult = _remoteCommandService.ExecutePhotoGetSinglePoint(SelectProcedure, null, new double[] { rpoint.X, rpoint.Y, 0 }, _cts.Token);
+                var recognitionResult =await _remoteCommandService.ExecutePhotoGetSinglePoint(SelectProcedure, null, new double[] { rpoint.X, rpoint.Y, 0 }, _cts.Token);
                 if (!recognitionResult.IsSucceed)
                 {
                     _eventAggregator.GetEvent<SnackbarMessageNotification>().Publish(new MessageParameter() { Msg = "取料拍照点位矫正失败,识别未成功!", Duration = 1 });