|
|
@@ -0,0 +1,496 @@
|
|
|
+using Cognex.VisionPro;
|
|
|
+using Cognex.VisionPro.ToolBlock;
|
|
|
+using MaterialDesignThemes.Wpf;
|
|
|
+using Prism.Commands;
|
|
|
+using Prism.Events;
|
|
|
+using Prism.Ioc;
|
|
|
+using Prism.Mvvm;
|
|
|
+using Prism.Regions;
|
|
|
+using Prism.Services.Dialogs;
|
|
|
+using System;
|
|
|
+using System.Collections.Generic;
|
|
|
+using System.Data;
|
|
|
+using System.Linq;
|
|
|
+using System.Threading;
|
|
|
+using System.Threading.Tasks;
|
|
|
+using Team.FFFeederService;
|
|
|
+using Team.FFFeederService.Interfaces;
|
|
|
+using TeamAAS_VP.Core;
|
|
|
+using TeamAAS_VP.Data;
|
|
|
+using TeamAAS_VP.Enums;
|
|
|
+using TeamAAS_VP.Events;
|
|
|
+using TeamAAS_VP.Interfaces;
|
|
|
+using TeamAAS_VP.Models;
|
|
|
+using TeamAAS_VP.Models.Calibration;
|
|
|
+using TeamAAS_VP.Resources.Languages;
|
|
|
+using TeamAAS_VP.Services;
|
|
|
+using TeamAAS_VP.Views.Setting;
|
|
|
+
|
|
|
+namespace TeamAAS_VP.ViewModels.Product
|
|
|
+{
|
|
|
+ public class VisionStaticAccuracyAnalyzerViewModel : BindableBase, IDialogAware
|
|
|
+ {
|
|
|
+ IRegionManager _regionManager;
|
|
|
+ IEventAggregator _eventAggregator;
|
|
|
+ IContainerProvider _container;
|
|
|
+ IDialogService _dialogService;
|
|
|
+ IFeederService _feederService;
|
|
|
+ IRobotService _robotService;
|
|
|
+ ICameraService _cameraService;
|
|
|
+ ISystemDatabaseService _systemDatabaseService;
|
|
|
+
|
|
|
+ //测试过程中控制取消的CTS
|
|
|
+ CancellationTokenSource _cts;
|
|
|
+
|
|
|
+ #region 属性
|
|
|
+
|
|
|
+ private ICogImage _Image;
|
|
|
+
|
|
|
+ public ICogImage Image
|
|
|
+ {
|
|
|
+ get { return _Image; }
|
|
|
+ set { SetProperty(ref _Image, value); }
|
|
|
+ }
|
|
|
+
|
|
|
+ private Cognex.VisionPro.CogGraphicCollection _Graphic;
|
|
|
+
|
|
|
+ public Cognex.VisionPro.CogGraphicCollection Graphic
|
|
|
+ {
|
|
|
+ get { return _Graphic; }
|
|
|
+ set { SetProperty(ref _Graphic, value); }
|
|
|
+ }
|
|
|
+
|
|
|
+ private ProcedureModel _SelectProcedure;
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// 选中的流程
|
|
|
+ /// </summary>
|
|
|
+ public ProcedureModel SelectProcedure
|
|
|
+ {
|
|
|
+ get { return _SelectProcedure; }
|
|
|
+ set
|
|
|
+ {
|
|
|
+ SetProperty(ref _SelectProcedure, value);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private ICamera _Camera;
|
|
|
+
|
|
|
+ public ICamera Camera
|
|
|
+ {
|
|
|
+ get { return _Camera; }
|
|
|
+ set { SetProperty(ref _Camera, value); }
|
|
|
+ }
|
|
|
+
|
|
|
+ private string _Message = "等待开始...";
|
|
|
+ public string Message
|
|
|
+ {
|
|
|
+ get { return _Message; }
|
|
|
+ set { SetProperty(ref _Message, value); }
|
|
|
+ }
|
|
|
+
|
|
|
+ private bool _IsRunning;
|
|
|
+
|
|
|
+ public bool IsRunning
|
|
|
+ {
|
|
|
+ get { return _IsRunning; }
|
|
|
+ set { SetProperty(ref _IsRunning, value); }
|
|
|
+ }
|
|
|
+
|
|
|
+ private CogToolBlock _VisionTool;
|
|
|
+ public CogToolBlock VisionTool
|
|
|
+ {
|
|
|
+ get { return _VisionTool; }
|
|
|
+ set { SetProperty(ref _VisionTool, value); }
|
|
|
+ }
|
|
|
+
|
|
|
+ private int _RepeatCount = 10;
|
|
|
+ /// <summary>
|
|
|
+ /// 重复次数
|
|
|
+ /// </summary>
|
|
|
+ public int RepeatCount
|
|
|
+ {
|
|
|
+ get { return _RepeatCount; }
|
|
|
+ set { SetProperty(ref _RepeatCount, value); }
|
|
|
+ }
|
|
|
+
|
|
|
+ private int _CurrentProgress;
|
|
|
+ /// <summary>
|
|
|
+ /// 当前进度
|
|
|
+ /// </summary>
|
|
|
+ public int CurrentProgress
|
|
|
+ {
|
|
|
+ get { return _CurrentProgress; }
|
|
|
+ set { SetProperty(ref _CurrentProgress, value); }
|
|
|
+ }
|
|
|
+
|
|
|
+ private int _SuccessCount;
|
|
|
+ /// <summary>
|
|
|
+ /// 成功次数
|
|
|
+ /// </summary>
|
|
|
+ public int SuccessCount
|
|
|
+ {
|
|
|
+ get { return _SuccessCount; }
|
|
|
+ set { SetProperty(ref _SuccessCount, value); }
|
|
|
+ }
|
|
|
+
|
|
|
+ private int _FailCount;
|
|
|
+ /// <summary>
|
|
|
+ /// 失败次数
|
|
|
+ /// </summary>
|
|
|
+ public int FailCount
|
|
|
+ {
|
|
|
+ get { return _FailCount; }
|
|
|
+ set { SetProperty(ref _FailCount, value); }
|
|
|
+ }
|
|
|
+
|
|
|
+ private double _SuccessRate;
|
|
|
+ /// <summary>
|
|
|
+ /// 成功率
|
|
|
+ /// </summary>
|
|
|
+ public double SuccessRate
|
|
|
+ {
|
|
|
+ get { return _SuccessRate; }
|
|
|
+ set { SetProperty(ref _SuccessRate, value); }
|
|
|
+ }
|
|
|
+
|
|
|
+ //测试结果列表DataTable
|
|
|
+ private DataTable _TestResult;
|
|
|
+ public DataTable TestResult
|
|
|
+ {
|
|
|
+ get { return _TestResult; }
|
|
|
+ set { SetProperty(ref _TestResult, value); }
|
|
|
+ }
|
|
|
+
|
|
|
+ private SnackbarMessageQueue _MessageQueue;
|
|
|
+ public SnackbarMessageQueue MessageQueue
|
|
|
+ {
|
|
|
+ get { return _MessageQueue; }
|
|
|
+ set { SetProperty(ref _MessageQueue, value); }
|
|
|
+ }
|
|
|
+ #endregion
|
|
|
+
|
|
|
+ #region 命令
|
|
|
+ private DelegateCommand _ConfirmCommand;
|
|
|
+ public DelegateCommand ConfirmCommand =>
|
|
|
+ _ConfirmCommand ?? (_ConfirmCommand = new DelegateCommand(ExecuteConfirmCommand).ObservesCanExecute(() => IsRunning));
|
|
|
+
|
|
|
+ private DelegateCommand _CancelCommand;
|
|
|
+ public DelegateCommand CancelCommand =>
|
|
|
+ _CancelCommand ?? (_CancelCommand = new DelegateCommand(ExecuteCancelCommand).ObservesCanExecute(() => IsRunning));
|
|
|
+
|
|
|
+ private DelegateCommand _StartTestCommand;
|
|
|
+ public DelegateCommand StartTestCommand =>
|
|
|
+ _StartTestCommand ?? (_StartTestCommand = new DelegateCommand(ExecuteStartTestCommand, CanExecuteStartTestCommand).ObservesProperty(() => IsRunning));
|
|
|
+
|
|
|
+ private DelegateCommand _StopTestCommand;
|
|
|
+ public DelegateCommand StopTestCommand =>
|
|
|
+ _StopTestCommand ?? (_StopTestCommand = new DelegateCommand(() => { _cts?.Cancel(); }, () => IsRunning).ObservesProperty(() => IsRunning));
|
|
|
+
|
|
|
+ //暂停测试命令
|
|
|
+ private DelegateCommand _PauseTestCommand;
|
|
|
+ public DelegateCommand PauseTestCommand =>
|
|
|
+ _PauseTestCommand ?? (_PauseTestCommand = new DelegateCommand(() => { _cts?.Cancel(); }, () => IsRunning).ObservesProperty(() => IsRunning));
|
|
|
+
|
|
|
+ private DelegateCommand _ExportCSVCommand;
|
|
|
+ public DelegateCommand ExportCSVCommand =>
|
|
|
+ _ExportCSVCommand ?? (_ExportCSVCommand = new DelegateCommand(ExecuteExportCSVCommand));
|
|
|
+
|
|
|
+ private DelegateCommand _ExportReportCommand;
|
|
|
+ public DelegateCommand ExportReportCommand =>
|
|
|
+ _ExportReportCommand ?? (_ExportReportCommand = new DelegateCommand(ExecuteExportReportCommand));
|
|
|
+
|
|
|
+ private DelegateCommand _ClearDataCommand;
|
|
|
+ public DelegateCommand ClearDataCommand =>
|
|
|
+ _ClearDataCommand ?? (_ClearDataCommand = new DelegateCommand(ExecuteClearDataCommand));
|
|
|
+
|
|
|
+
|
|
|
+ #endregion
|
|
|
+
|
|
|
+ #region 事件
|
|
|
+
|
|
|
+ #endregion
|
|
|
+
|
|
|
+ public VisionStaticAccuracyAnalyzerViewModel(IRegionManager regionManager, IEventAggregator ea, IContainerProvider container, IDialogService dialogService,
|
|
|
+ IFeederService feederService, IRobotService robotService, ICameraService cameraService, ISystemDatabaseService systemDatabaseService)
|
|
|
+ {
|
|
|
+ _regionManager = regionManager;
|
|
|
+ _eventAggregator = ea;
|
|
|
+ _container = container;
|
|
|
+ _dialogService = dialogService;
|
|
|
+ _feederService = feederService;
|
|
|
+ _robotService = robotService;
|
|
|
+ _cameraService = cameraService;
|
|
|
+ _systemDatabaseService = systemDatabaseService;
|
|
|
+ MessageQueue= new SnackbarMessageQueue(TimeSpan.FromSeconds(1));
|
|
|
+ }
|
|
|
+
|
|
|
+ #region 方法
|
|
|
+ /// <summary>
|
|
|
+ /// 确定
|
|
|
+ /// </summary>
|
|
|
+ void ExecuteConfirmCommand()
|
|
|
+ {
|
|
|
+
|
|
|
+
|
|
|
+ IDialogParameters parameters = new DialogParameters();
|
|
|
+ //parameters.Add("Tool", Tool);
|
|
|
+ //parameters.Add("RobotCameraRotationMatrix", RobotCameraRotationMatrix);
|
|
|
+ //parameters.Add("Angle", Angle);
|
|
|
+ RequestClose?.Invoke(new DialogResult(ButtonResult.OK, parameters));
|
|
|
+ }
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// 取消
|
|
|
+ /// </summary>
|
|
|
+ void ExecuteCancelCommand()
|
|
|
+ {
|
|
|
+ IDialogParameters parameters = new DialogParameters();
|
|
|
+ //parameters.Add("Tool", Tool);
|
|
|
+ RequestClose?.Invoke(new DialogResult(ButtonResult.Cancel, parameters));
|
|
|
+ }
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// 开始测试
|
|
|
+ /// </summary>
|
|
|
+ async void ExecuteStartTestCommand()
|
|
|
+ {
|
|
|
+ IsRunning = true;
|
|
|
+ _cts = new CancellationTokenSource();
|
|
|
+ CurrentProgress = 0;
|
|
|
+ SuccessCount = 0;
|
|
|
+ SuccessRate = 0;
|
|
|
+ FailCount = 0;
|
|
|
+ Message = "测试进行中...";
|
|
|
+
|
|
|
+ try
|
|
|
+ {
|
|
|
+ while (CurrentProgress < RepeatCount)
|
|
|
+ {
|
|
|
+ if (_cts.Token.IsCancellationRequested)
|
|
|
+ {
|
|
|
+ Message = "测试已取消!";
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ await Task.Delay(1000);
|
|
|
+ CurrentProgress++;
|
|
|
+ SuccessCount++;
|
|
|
+ SuccessRate = (double)SuccessCount / CurrentProgress * 100;
|
|
|
+ SendTaskMessage($"测试进行中... {CurrentProgress}/{RepeatCount}");
|
|
|
+ }
|
|
|
+ if (CurrentProgress >= RepeatCount)
|
|
|
+ {
|
|
|
+ Message = "测试完成!";
|
|
|
+ }
|
|
|
+ }
|
|
|
+ catch (Exception ex)
|
|
|
+ {
|
|
|
+ LogHelper.WriteLogError("视觉静态重复测试时出错!", ex);
|
|
|
+ }
|
|
|
+ finally
|
|
|
+ {
|
|
|
+ IsRunning = false;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ bool CanExecuteStartTestCommand()
|
|
|
+ {
|
|
|
+ return !IsRunning;
|
|
|
+ }
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// 清除数据
|
|
|
+ /// </summary>
|
|
|
+ void ExecuteClearDataCommand()
|
|
|
+ {
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// 导出测试报告
|
|
|
+ /// </summary>
|
|
|
+ void ExecuteExportReportCommand()
|
|
|
+ {
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// 导出测试数据为CSV文件
|
|
|
+ /// </summary>
|
|
|
+ void ExecuteExportCSVCommand()
|
|
|
+ {
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// 执行相机拍照并运行 ToolBlock,返回是否成功并通过 out 参数返回 Outputs、图像和图形集合。
|
|
|
+ /// </summary>
|
|
|
+ /// <param name="outputCollection"></param>
|
|
|
+ /// <param name="outImage"></param>
|
|
|
+ /// <param name="outGraphicCollection"></param>
|
|
|
+ /// <returns></returns>
|
|
|
+ public bool ExecutePhotoEx(out CogToolBlockTerminalCollection outputCollection, out ICogImage outImage, out CogGraphicCollection outGraphicCollection)
|
|
|
+ {
|
|
|
+ outImage = null;
|
|
|
+ outGraphicCollection = null;
|
|
|
+ try
|
|
|
+ {
|
|
|
+ // 1. 采集图像
|
|
|
+ bool succed = Camera.SetExposureTime(SelectProcedure.ExposureTime);
|
|
|
+ if (!succed)
|
|
|
+ {
|
|
|
+ SendTaskMessage(Lang.相机曝光设置失败);
|
|
|
+ }
|
|
|
+ succed = Camera.SetGain(SelectProcedure.Gain);
|
|
|
+ if (!succed)
|
|
|
+ {
|
|
|
+ SendTaskMessage(Lang.相机增益设置失败);
|
|
|
+ }
|
|
|
+ DateTime nowtime = DateTime.Now;
|
|
|
+ LogHelper.WriteLogInfo(Lang.开始采集图像);
|
|
|
+ var image = Camera.Grab();
|
|
|
+ if (image == null)
|
|
|
+ {
|
|
|
+
|
|
|
+ SendTaskMessage(Lang.图像采集失败);
|
|
|
+ outputCollection = null;
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ outImage = image;
|
|
|
+ VisionTool.Inputs["InputImage"].Value = image;
|
|
|
+ LogHelper.WriteLogInfo(string.Format(Lang.采集图像完成用时0ms, (DateTime.Now - nowtime).Milliseconds));
|
|
|
+
|
|
|
+ // 2. 为ToolBlock传入其他输入终端
|
|
|
+ //if (InputTerminal != null)
|
|
|
+ //{
|
|
|
+ // LogHelper.WriteLogInfo(Lang.为ToolBlock传入输入终端);
|
|
|
+ // foreach (var item in InputTerminal)
|
|
|
+ // {
|
|
|
+ // if (VisionTool.Inputs.Contains(item.Key))
|
|
|
+ // {
|
|
|
+ // LogHelper.WriteLogInfo($"传入[{item.Key}]={item.Value}");
|
|
|
+ // VisionTool.Inputs[item.Key].Value = item.Value;
|
|
|
+ // }
|
|
|
+ // else
|
|
|
+ // {
|
|
|
+ // LogHelper.WriteLogInfo($"创建并传入[{item.Key}]={item.Value}");
|
|
|
+ // VisionTool.Inputs.Add(new CogToolBlockTerminal(item.Key, item.Value));
|
|
|
+ // }
|
|
|
+ // }
|
|
|
+ //}
|
|
|
+
|
|
|
+ // 3. 运行视觉工具
|
|
|
+ LogHelper.WriteLogInfo(Lang.开始运行视觉工具);
|
|
|
+ VisionTool.Run(); //运行ToolBlock
|
|
|
+
|
|
|
+ if (VisionTool.RunStatus.Result == CogToolResultConstants.Accept)
|
|
|
+ {
|
|
|
+ SendTaskMessage(Lang.视觉流程执行耗时.Replace("{0}", SelectProcedure.Name).Replace("{1}", $"{VisionTool.RunStatus.ProcessingTime:F1}"));
|
|
|
+ outputCollection = VisionTool.Outputs; //获取输出终端集合
|
|
|
+ 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}", SelectProcedure.Name).Replace("{1}", $"{VisionTool.RunStatus.ProcessingTime:F1}"));
|
|
|
+ SendTaskMessage(VisionTool.RunStatus.Message);
|
|
|
+ outputCollection = null;
|
|
|
+ outGraphicCollection = outputCollection["Graphic"].Value as CogGraphicCollection;
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ catch (Exception ex)
|
|
|
+ {
|
|
|
+ SendTaskMessage(ex.Message);
|
|
|
+ LogHelper.WriteLogError(Lang.执行相机取图并执行视觉工具组时出错, ex);
|
|
|
+ outputCollection = null;
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ public void SendTaskMessage(string msg)
|
|
|
+ {
|
|
|
+ App.Current.Dispatcher.Invoke(() =>
|
|
|
+ {
|
|
|
+ MessageQueue.Clear();
|
|
|
+ MessageQueue.Enqueue(msg);
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// 相机拍照
|
|
|
+ /// </summary>
|
|
|
+ /// <returns></returns>
|
|
|
+ //private async Task<(bool IsSuccess, double X, double Y, double U, int ImageWidth, int ImageHeight)> CaptureAndProcess()
|
|
|
+ //{
|
|
|
+ // if (Feeder != null)
|
|
|
+ // {
|
|
|
+ // Feeder.OpenLight();
|
|
|
+ // Feeder.SetLightTimeOut((ushort)SelectCalibration.Brightness);
|
|
|
+ // }
|
|
|
+ // await Task.Delay(200);
|
|
|
+ // //采集图像
|
|
|
+ // if (Camera != null)
|
|
|
+ // {
|
|
|
+ // SelectCalibration.ToolBlock.Inputs["InputImage"].Value = Camera.Grab();
|
|
|
+
|
|
|
+ // }
|
|
|
+ // App.Current.Dispatcher.Invoke(() =>
|
|
|
+ // {
|
|
|
+ // Graphic = null;
|
|
|
+ // Image = (ICogImage)SelectCalibration.ToolBlock.Inputs["InputImage"].Value;
|
|
|
+ // });
|
|
|
+
|
|
|
+ // SelectCalibration.ToolBlock.Run();
|
|
|
+ // CogToolBlockTerminalCollection outputCollection = SelectCalibration.ToolBlock.Outputs;
|
|
|
+ // App.Current.Dispatcher.Invoke(() =>
|
|
|
+ // {
|
|
|
+ // Graphic = outputCollection["Graphic"].Value as CogGraphicCollection;
|
|
|
+ // });
|
|
|
+
|
|
|
+ // bool Found = (bool)(outputCollection["Found"].Value);
|
|
|
+ // if (Found)
|
|
|
+ // {
|
|
|
+ // var strpoints = outputCollection["Point"].Value.ToString();
|
|
|
+ // string[] items = strpoints.Split(',');
|
|
|
+ // double x = double.Parse(items[0]);
|
|
|
+ // double y = double.Parse(items[1]);
|
|
|
+ // return (true, x, y, 0, Image.Width, Image.Height);
|
|
|
+ // }
|
|
|
+ // else
|
|
|
+ // {
|
|
|
+ // return (false, 0, 0, 0, Image.Width, Image.Height);
|
|
|
+ // }
|
|
|
+ //}
|
|
|
+ #endregion
|
|
|
+
|
|
|
+ #region 继承
|
|
|
+ public string Title { get; set; } = "视觉静态精度分析仪";
|
|
|
+
|
|
|
+ public event Action<IDialogResult> RequestClose;
|
|
|
+
|
|
|
+ public bool CanCloseDialog()
|
|
|
+ {
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+
|
|
|
+ public void OnDialogClosed()
|
|
|
+ {
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ public void OnDialogOpened(IDialogParameters parameters)
|
|
|
+ {
|
|
|
+ SelectProcedure = parameters.GetValue<ProcedureModel>("SelectedProcedure");
|
|
|
+ Camera = _cameraService.GetCamera(SelectProcedure.CameraId);
|
|
|
+ VisionTool = parameters.GetValue<CogToolBlock>("ToolBlock");
|
|
|
+ }
|
|
|
+ #endregion
|
|
|
+ }
|
|
|
+}
|