|
|
@@ -0,0 +1,373 @@
|
|
|
+using Cognex.VisionPro;
|
|
|
+using MaterialDesignThemes.Wpf;
|
|
|
+using Prism.Commands;
|
|
|
+using Prism.Events;
|
|
|
+using Prism.Mvvm;
|
|
|
+using System;
|
|
|
+using System.Collections.Generic;
|
|
|
+using System.Collections.ObjectModel;
|
|
|
+using System.Drawing;
|
|
|
+using System.Linq;
|
|
|
+using System.Threading;
|
|
|
+using System.Threading.Tasks;
|
|
|
+using TeamAAS_VP.Core;
|
|
|
+using TeamAAS_VP.Core.PLCs;
|
|
|
+using TeamAAS_VP.Events;
|
|
|
+using TeamAAS_VP.Interfaces;
|
|
|
+using TeamAAS_VP.Models;
|
|
|
+using TeamAAS_VP.Models.PLC;
|
|
|
+
|
|
|
+namespace TeamAAS_VP.ViewModels.Product
|
|
|
+{
|
|
|
+ public class AutoCorrectLockPointViewModel : BindableBase
|
|
|
+ {
|
|
|
+ private readonly IRobotService _robotService;
|
|
|
+ private readonly IProductService _productService;
|
|
|
+ private readonly IRemoteCommandService _remoteCommandService;
|
|
|
+ private readonly IPlcService _plcService;
|
|
|
+ private readonly IEventAggregator _eventAggregator;
|
|
|
+ private readonly ICalibrationService _calibrationService;
|
|
|
+
|
|
|
+ private 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 List<PlcPoint> _AllScrewPoint;
|
|
|
+ /// <summary>
|
|
|
+ /// 所有的锁付点
|
|
|
+ /// </summary>
|
|
|
+ public List<PlcPoint> AllScrewPoint
|
|
|
+ {
|
|
|
+ get { return _AllScrewPoint; }
|
|
|
+ set { SetProperty(ref _AllScrewPoint, value);
|
|
|
+ if (value!=null)
|
|
|
+ {
|
|
|
+ CorrectPoints = new ObservableCollection<PointEx>();
|
|
|
+ foreach (var item in value)
|
|
|
+ {
|
|
|
+ CorrectPoints.Add(new PointEx(item));
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private ObservableCollection<PointEx> _CorrectPoints;
|
|
|
+ /// <summary>
|
|
|
+ /// 所有校准的点集合
|
|
|
+ /// </summary>
|
|
|
+ public ObservableCollection<PointEx> CorrectPoints
|
|
|
+ {
|
|
|
+ get { return _CorrectPoints; }
|
|
|
+ set { SetProperty(ref _CorrectPoints, value); }
|
|
|
+ }
|
|
|
+
|
|
|
+ //执行中
|
|
|
+ private bool _IsExecuting;
|
|
|
+ public bool IsExecuting
|
|
|
+ {
|
|
|
+ get { return _IsExecuting; }
|
|
|
+ set { SetProperty(ref _IsExecuting, value); }
|
|
|
+ }
|
|
|
+
|
|
|
+ private IRobot _Robot;
|
|
|
+ public IRobot Robot
|
|
|
+ {
|
|
|
+ get { return _Robot; }
|
|
|
+ set { SetProperty(ref _Robot, value); }
|
|
|
+ }
|
|
|
+
|
|
|
+ #endregion
|
|
|
+
|
|
|
+ #region 命令
|
|
|
+ private DelegateCommand _StartAutoCorrectCommand;
|
|
|
+ public DelegateCommand StartAutoCorrectCommand =>
|
|
|
+ _StartAutoCorrectCommand ?? (_StartAutoCorrectCommand = new DelegateCommand(ExecuteStartAutoCorrectCommand, CanExecuteStartAutoCorrectCommand).ObservesProperty(()=> IsExecuting));
|
|
|
+
|
|
|
+ private DelegateCommand _CancelAutoCorrectCommand;
|
|
|
+ public DelegateCommand CancelAutoCorrectCommand =>
|
|
|
+ _CancelAutoCorrectCommand ?? (_CancelAutoCorrectCommand = new DelegateCommand(ExecuteCancelAutoCorrectCommand, CanExecuteCancelAutoCorrectCommand).ObservesProperty(() => IsExecuting));
|
|
|
+
|
|
|
+
|
|
|
+ #endregion
|
|
|
+
|
|
|
+
|
|
|
+ public AutoCorrectLockPointViewModel(IRobotService robotService, IProductService productService, IRemoteCommandService remoteCommandService, IPlcService plcService,
|
|
|
+ IEventAggregator eventAggregator, ICalibrationService calibrationService)
|
|
|
+ {
|
|
|
+ _robotService = robotService;
|
|
|
+ _productService = productService;
|
|
|
+ _remoteCommandService = remoteCommandService;
|
|
|
+ _plcService = plcService;
|
|
|
+ _eventAggregator = eventAggregator;
|
|
|
+ _calibrationService = calibrationService;
|
|
|
+ }
|
|
|
+
|
|
|
+ #region 方法
|
|
|
+
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// 开始校准
|
|
|
+ /// </summary>
|
|
|
+ async void ExecuteStartAutoCorrectCommand()
|
|
|
+ {
|
|
|
+ IsExecuting= true;
|
|
|
+ try
|
|
|
+ {
|
|
|
+ if (Robot == null || !Robot.IsConnected)
|
|
|
+ {
|
|
|
+ _eventAggregator.GetEvent<SnackbarMessageNotification>().Publish(new MessageParameter() { Msg = "机器人未连接,无法执行取料拍照点位矫正!", Duration = 1 });
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ //获取当前产品
|
|
|
+ var product = _productService.GetCurrentProduct();
|
|
|
+ if (product == null)
|
|
|
+ {
|
|
|
+ _eventAggregator.GetEvent<SnackbarMessageNotification>().Publish(new MessageParameter() { Msg = "未选择产品,无法执行取料拍照点位矫正!", Duration = 1 });
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ //获取锁付相机拍照点位
|
|
|
+ var screwCameraPoint = product.ScrewCameraPoints;
|
|
|
+ if (screwCameraPoint == null || screwCameraPoint.Count == 0)
|
|
|
+ {
|
|
|
+ _eventAggregator.GetEvent<SnackbarMessageNotification>().Publish(new MessageParameter() { Msg = "未获取到锁付相机拍照点位,无法执行取料拍照点位矫正!", Duration = 1 });
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ //获取相机拍照点位对应的锁付点
|
|
|
+ var screwCameraLocalPoint1 = product.ScrewCameraLocalPos1;
|
|
|
+ if (screwCameraLocalPoint1 == null)
|
|
|
+ {
|
|
|
+ _eventAggregator.GetEvent<SnackbarMessageNotification>().Publish(new MessageParameter() { Msg = "未获取到锁付相机拍照点位对应的锁付点,无法执行取料拍照点位矫正!", Duration = 1 });
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ var screwCameraLocalPoint2= product.ScrewCameraLocalPos2;
|
|
|
+ if (screwCameraLocalPoint2 == null)
|
|
|
+ {
|
|
|
+ _eventAggregator.GetEvent<SnackbarMessageNotification>().Publish(new MessageParameter() { Msg = "未获取到锁付相机拍照点位对应的锁付点,无法执行取料拍照点位矫正!", Duration = 1 });
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ var ProcedureModels = new ObservableCollection<ProcedureModel>();
|
|
|
+ foreach (var item in product.CameraProcedures)
|
|
|
+ {
|
|
|
+ foreach (var item1 in item.ProcedureModels)
|
|
|
+ {
|
|
|
+ ProcedureModels.Add(item1);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ //获取拍照流程
|
|
|
+ if (product.MoveDownCameraLockPhotoProcedureId == Guid.Empty)
|
|
|
+ {
|
|
|
+ _eventAggregator.GetEvent<SnackbarMessageNotification>().Publish(new MessageParameter() { Msg = "未获取到锁付相机拍照流程,无法执行取料拍照点位矫正!", Duration = 1 });
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ var procedure = ProcedureModels.FirstOrDefault(p => p.Id == product.MoveDownCameraLockPhotoProcedureId);
|
|
|
+ if (procedure == null)
|
|
|
+ {
|
|
|
+ _eventAggregator.GetEvent<SnackbarMessageNotification>().Publish(new MessageParameter() { Msg = "未获取到锁付相机拍照流程,无法执行取料拍照点位矫正!", Duration = 1 });
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ //移动机器人至拍照点位,拍照
|
|
|
+ var rpoint = new RPoint()
|
|
|
+ {
|
|
|
+ X = screwCameraPoint[0].X_Position,
|
|
|
+ Y = screwCameraPoint[0].Y_Position,
|
|
|
+ Z = screwCameraPoint[0].Z_Position_Start,
|
|
|
+ U = screwCameraPoint[0].U_Position,
|
|
|
+ V = screwCameraPoint[0].R_Position,
|
|
|
+ };
|
|
|
+ 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);
|
|
|
+ if (!recognitionResult.IsSucceed)
|
|
|
+ {
|
|
|
+ _eventAggregator.GetEvent<SnackbarMessageNotification>().Publish(new MessageParameter() { Msg = "拍照获取识别结果失败,无法执行取料拍照点位矫正!", Duration = 1 });
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ //第一个点位的校正结果
|
|
|
+ PointF worldP1 = new PointF((float)recognitionResult.X, (float)recognitionResult.Y);
|
|
|
+ //移动机器人至拍照点位,拍照
|
|
|
+ rpoint = new RPoint()
|
|
|
+ {
|
|
|
+ X = screwCameraPoint[0].X_Position,
|
|
|
+ Y = screwCameraPoint[0].Y_Position,
|
|
|
+ Z = screwCameraPoint[0].Z_Position_Start,
|
|
|
+ U = screwCameraPoint[0].U_Position,
|
|
|
+ V = screwCameraPoint[0].R_Position,
|
|
|
+ };
|
|
|
+ await Robot.CalibMotionAsync(rpoint, 0);
|
|
|
+ if (_cts.IsCancellationRequested)
|
|
|
+ return;
|
|
|
+ await Task.Delay(200);
|
|
|
+ // 执行拍照并获取识别结果
|
|
|
+ recognitionResult = await _remoteCommandService.ExecutePhotoGetSinglePoint(procedure, null, new double[] { rpoint.X, rpoint.Y, 0 }, _cts.Token);
|
|
|
+ if (!recognitionResult.IsSucceed)
|
|
|
+ {
|
|
|
+ _eventAggregator.GetEvent<SnackbarMessageNotification>().Publish(new MessageParameter() { Msg = "拍照获取识别结果失败,无法执行取料拍照点位矫正!", Duration = 1 });
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ //第一个点位的校正结果
|
|
|
+ PointF worldP2 = new PointF((float)recognitionResult.X, (float)recognitionResult.Y);
|
|
|
+
|
|
|
+ //计算移动相机与拍照点之间的偏差
|
|
|
+ //获取校准
|
|
|
+ var calibration = _calibrationService.GetCalibration(procedure.CalibrationId);
|
|
|
+
|
|
|
+ //获取mark点
|
|
|
+ var mark = calibration.MarkPoint;
|
|
|
+ //获取中心点
|
|
|
+ var center = calibration.CenterPoint;
|
|
|
+ //计算相机中心与披头之间的坐标偏差
|
|
|
+ var cameraOffsetX = mark.X - center.X;
|
|
|
+ var cameraOffsetY = mark.Y - center.Y;
|
|
|
+
|
|
|
+
|
|
|
+ //根据UpCameraPutResults[]中的索引1、2,和拍照点对应的Local下的坐标,从创建Local坐标系
|
|
|
+ PointF localP1 = new PointF(screwCameraLocalPoint1.X_Position, screwCameraLocalPoint1.Y_Position);
|
|
|
+ PointF localP2 = new PointF(screwCameraLocalPoint2.X_Position, screwCameraLocalPoint2.Y_Position);
|
|
|
+ CoordinateTransformer local = new CoordinateTransformer(worldP1, worldP2, localP1, localP2);
|
|
|
+
|
|
|
+ for (int i = 0; i < product.ScrewPoints.Count; i++)
|
|
|
+ {
|
|
|
+ var localPoint = new PointF(product.ScrewCameraPoints[i].X_Position, product.ScrewCameraPoints[i].Y_Position);
|
|
|
+ var worldPoint = local.ToOldCoord(localPoint.X, localPoint.Y);
|
|
|
+ var point = product.ScrewCameraPoints[i].Clone();
|
|
|
+ point.X_Position = (float)worldPoint[0];
|
|
|
+ point.Y_Position = (float)worldPoint[1];
|
|
|
+ //计算当前点的高度与screwCameraLocalPoint1的Z轴之间的偏差
|
|
|
+ var deltaZ = product.ScrewPoints[i].Z_Position_Start - screwCameraPoint[0].Z_Position_Start;
|
|
|
+
|
|
|
+ //计算相机去拍照点位
|
|
|
+ point.X_Position+= cameraOffsetX;
|
|
|
+ point.Y_Position+= cameraOffsetY;
|
|
|
+ point.Z_Position_Start= screwCameraPoint[0].Z_Position_Start + deltaZ;
|
|
|
+
|
|
|
+ //移动机器人至拍照点位,拍照
|
|
|
+ rpoint = new RPoint()
|
|
|
+ {
|
|
|
+ X = point.X_Position,
|
|
|
+ Y = point.Y_Position,
|
|
|
+ Z = point.Z_Position_Start,
|
|
|
+ U = screwCameraPoint[0].U_Position,
|
|
|
+ V = screwCameraPoint[0].R_Position,
|
|
|
+ };
|
|
|
+ await Robot.CalibMotionAsync(rpoint, 0);
|
|
|
+ if (_cts.IsCancellationRequested)
|
|
|
+ return;
|
|
|
+ await Task.Delay(200);
|
|
|
+ // 执行拍照并获取识别结果
|
|
|
+ recognitionResult = await _remoteCommandService.ExecutePhotoGetSinglePoint(procedure, null, new double[] { rpoint.X, rpoint.Y, 0 }, _cts.Token);
|
|
|
+ if (!recognitionResult.IsSucceed)
|
|
|
+ {
|
|
|
+ _eventAggregator.GetEvent<SnackbarMessageNotification>().Publish(new MessageParameter() { Msg = "拍照获取识别结果失败,无法执行取料拍照点位矫正!", Duration = 1 });
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ //将获取到的点位转换至Local坐标系下
|
|
|
+ var correctedPoint = local.ToNewCoord((float)recognitionResult.X, (float)recognitionResult.Y);
|
|
|
+ CorrectPoints[i].PostX = (float)correctedPoint[0];
|
|
|
+ CorrectPoints[i].PostY = (float)correctedPoint[1];
|
|
|
+ if (_cts.IsCancellationRequested)
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+ catch (Exception)
|
|
|
+ {
|
|
|
+
|
|
|
+ throw;
|
|
|
+ }
|
|
|
+ finally
|
|
|
+ {
|
|
|
+ IsExecuting= false;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ bool CanExecuteStartAutoCorrectCommand()
|
|
|
+ {
|
|
|
+ return !IsExecuting;
|
|
|
+ }
|
|
|
+
|
|
|
+ void ExecuteCancelAutoCorrectCommand()
|
|
|
+ {
|
|
|
+ _cts?.Cancel();
|
|
|
+ }
|
|
|
+
|
|
|
+ bool CanExecuteCancelAutoCorrectCommand()
|
|
|
+ {
|
|
|
+ return IsExecuting;
|
|
|
+ }
|
|
|
+ #endregion
|
|
|
+
|
|
|
+ public class PointEx : BindableBase
|
|
|
+ {
|
|
|
+ private int _Number;
|
|
|
+ public int Number
|
|
|
+ {
|
|
|
+ get { return _Number; }
|
|
|
+ set { SetProperty(ref _Number, value); }
|
|
|
+ }
|
|
|
+
|
|
|
+ private string _Label;
|
|
|
+ public string Label
|
|
|
+ {
|
|
|
+ get { return _Label; }
|
|
|
+ set { SetProperty(ref _Label, value); }
|
|
|
+ }
|
|
|
+
|
|
|
+ private float _PreX;
|
|
|
+ public float PreX
|
|
|
+ {
|
|
|
+ get { return _PreX; }
|
|
|
+ set { SetProperty(ref _PreX, value); }
|
|
|
+ }
|
|
|
+
|
|
|
+ private float _PreY;
|
|
|
+ public float PreY
|
|
|
+ {
|
|
|
+ get { return _PreY; }
|
|
|
+ set { SetProperty(ref _PreY, value); }
|
|
|
+ }
|
|
|
+
|
|
|
+ private float _PostX;
|
|
|
+ public float PostX
|
|
|
+ {
|
|
|
+ get { return _PostX; }
|
|
|
+ set { SetProperty(ref _PostX, value); }
|
|
|
+ }
|
|
|
+
|
|
|
+ private float _PostY;
|
|
|
+ public float PostY
|
|
|
+ {
|
|
|
+ get { return _PostY; }
|
|
|
+ set { SetProperty(ref _PostY, value); }
|
|
|
+ }
|
|
|
+
|
|
|
+ public PointEx()
|
|
|
+ {
|
|
|
+ }
|
|
|
+
|
|
|
+ public PointEx(PlcPoint point)
|
|
|
+ {
|
|
|
+ Number = point.Number;
|
|
|
+ Label = point.Label;
|
|
|
+ PreX = point.X_Position;
|
|
|
+ PreY = point.Y_Position;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|