|
|
@@ -1,5 +1,6 @@
|
|
|
using MaterialDesignThemes.Wpf;
|
|
|
using MathNet.Numerics.LinearAlgebra;
|
|
|
+using NPOI.SS.Formula.Functions;
|
|
|
using Prism.Commands;
|
|
|
using Prism.Events;
|
|
|
using Prism.Ioc;
|
|
|
@@ -9,6 +10,7 @@ using Prism.Services.Dialogs;
|
|
|
using System;
|
|
|
using System.Collections.Generic;
|
|
|
using System.Collections.ObjectModel;
|
|
|
+using System.Drawing;
|
|
|
using System.Linq;
|
|
|
using System.Threading;
|
|
|
using System.Threading.Tasks;
|
|
|
@@ -40,6 +42,8 @@ namespace TeamAAS_VP.ViewModels.Product
|
|
|
IRobotService _robotService;
|
|
|
ISystemDatabaseService _systemDatabaseService;
|
|
|
IRemoteCommandService _remoteCommandService;
|
|
|
+ ICalibrationService _calibrationService;
|
|
|
+ CoordinateTransformer local;
|
|
|
|
|
|
#region 属性
|
|
|
|
|
|
@@ -365,7 +369,8 @@ namespace TeamAAS_VP.ViewModels.Product
|
|
|
#endregion
|
|
|
|
|
|
public PlcPointParamsViewModel(IRegionManager regionManager, IEventAggregator ea, IContainerProvider container, IDialogService dialogService,
|
|
|
- IConfigService configService, IRobotService robotService, ISystemDatabaseService systemDatabaseService, IRemoteCommandService remoteCommandService)
|
|
|
+ IConfigService configService, IRobotService robotService, ISystemDatabaseService systemDatabaseService, IRemoteCommandService remoteCommandService,
|
|
|
+ ICalibrationService calibrationService)
|
|
|
{
|
|
|
_regionManager = regionManager;
|
|
|
_eventAggregator = ea;
|
|
|
@@ -378,6 +383,7 @@ namespace TeamAAS_VP.ViewModels.Product
|
|
|
management = _container.Resolve<Management>();
|
|
|
_robotService = robotService;
|
|
|
_remoteCommandService = remoteCommandService;
|
|
|
+ _calibrationService = calibrationService;
|
|
|
}
|
|
|
|
|
|
#region 方法
|
|
|
@@ -505,26 +511,33 @@ namespace TeamAAS_VP.ViewModels.Product
|
|
|
if (Robot == null || !Robot.IsConnected) return;
|
|
|
try
|
|
|
{
|
|
|
- //确认要执行该点位的该运动指令吗
|
|
|
- if (MessageBox.Show($"确认要执行点位 {SelectedPoint.Number} 的 {motionCmd} 指令吗?", "执行点位", MessageBoxButton.YesNo, MessageBoxImage.Question) != MessageBoxResult.Yes)
|
|
|
+ if (SelectedIndex == 4)
|
|
|
{
|
|
|
- return;
|
|
|
+ await ExecuteAutoCorrectLockPointAndExecuteCommand(SelectedPoint);
|
|
|
}
|
|
|
-
|
|
|
- Robot.Timeout = 6000000;
|
|
|
- switch (motionCmd)
|
|
|
+ else
|
|
|
{
|
|
|
- case MotionCommand.Go:
|
|
|
- await Robot.GoAsync(point);
|
|
|
- break;
|
|
|
- case MotionCommand.Jump:
|
|
|
- await Robot.JumpAsync(point, 0);
|
|
|
- break;
|
|
|
- case MotionCommand.Move:
|
|
|
- await Robot.MoveAsync(point);
|
|
|
- break;
|
|
|
- }
|
|
|
- Robot.Timeout = 5000;
|
|
|
+ //确认要执行该点位的该运动指令吗
|
|
|
+ if (MessageBox.Show($"确认要执行点位 {SelectedPoint.Number} 的 {motionCmd} 指令吗?", "执行点位", MessageBoxButton.YesNo, MessageBoxImage.Question) != MessageBoxResult.Yes)
|
|
|
+ {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ //Robot.Timeout = 6000000;
|
|
|
+ switch (motionCmd)
|
|
|
+ {
|
|
|
+ case MotionCommand.Go:
|
|
|
+ await Robot.GoAsync(point);
|
|
|
+ break;
|
|
|
+ case MotionCommand.Jump:
|
|
|
+ await Robot.JumpAsync(point, 0);
|
|
|
+ break;
|
|
|
+ case MotionCommand.Move:
|
|
|
+ await Robot.MoveAsync(point);
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ //Robot.Timeout = 5000;
|
|
|
+ }
|
|
|
_eventAggregator.GetEvent<SnackbarMessageNotification>().Publish(new MessageParameter() { Msg = $"{Lang.完成}!", Duration = 0.4 });
|
|
|
}
|
|
|
catch (Exception ex)
|
|
|
@@ -545,6 +558,13 @@ namespace TeamAAS_VP.ViewModels.Product
|
|
|
|
|
|
try
|
|
|
{
|
|
|
+ //如果当前的选项卡处于锁付点位,则提示用户当前模式不允许进行示教
|
|
|
+ if (SelectedIndex == 4)
|
|
|
+ {
|
|
|
+ MessageBox.Show("当前处于锁付点位模式,不允许进行示教操作!", "示教点位", MessageBoxButton.OK, MessageBoxImage.Warning);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
//弹窗用户是否确认要示教该点位
|
|
|
if (MessageBox.Show($"确认要示教点位 {SelectedPoint.Number} 吗?", "示教点位", MessageBoxButton.YesNo, MessageBoxImage.Question) != MessageBoxResult.Yes)
|
|
|
{
|
|
|
@@ -1124,6 +1144,239 @@ namespace TeamAAS_VP.ViewModels.Product
|
|
|
_eventAggregator.GetEvent<SnackbarMessageNotification>().Publish(new MessageParameter() { Msg = ex.Message, Duration = 1 });
|
|
|
}
|
|
|
}
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// 通过相机先定位产品再执行锁付点位
|
|
|
+ /// </summary>
|
|
|
+ /// <param name="point"></param>
|
|
|
+ private async Task ExecuteAutoCorrectLockPointAndExecuteCommand(PlcPoint point)
|
|
|
+ {
|
|
|
+ var waiting = new WaitingControl();
|
|
|
+ Task<object> task;
|
|
|
+ try
|
|
|
+ {
|
|
|
+ if (Robot == null || !Robot.IsConnected) return;
|
|
|
+ //弹窗提示用户是否确认要通过相机自动矫正锁附点位并执行该点位
|
|
|
+ var resultConfirm = MessageBox.Show($"确认要通过相机自动矫正锁附点位并执行点位 {point.Number} 吗?", "确认", MessageBoxButton.YesNo, MessageBoxImage.Question);
|
|
|
+ if (resultConfirm != MessageBoxResult.Yes)
|
|
|
+ {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ if (Robot == null || !Robot.IsConnected)
|
|
|
+ {
|
|
|
+ _eventAggregator.GetEvent<SnackbarMessageNotification>().Publish(new MessageParameter() { Msg = "机器人未连接,无法执行取料拍照点位矫正!", Duration = 1 });
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ //获取当前产品
|
|
|
+ var product = SelectProduct;
|
|
|
+ if (product == null)
|
|
|
+ {
|
|
|
+ _eventAggregator.GetEvent<SnackbarMessageNotification>().Publish(new MessageParameter() { Msg = "未选择产品,无法执行取料拍照点位矫正!", Duration = 1 });
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ //如果当前Local为空,则自动进行锁付点位的Local计算
|
|
|
+ if (local == null)
|
|
|
+ {
|
|
|
+ //show the dialog
|
|
|
+ task = DialogHost.Show(waiting, "RootDialog", null, null, null);
|
|
|
+ var isCalibSucceed = await AutoCalibLockPointLocal(product);
|
|
|
+ if (!isCalibSucceed)
|
|
|
+ {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ //提示用户,当前系统检测到进入此界面后已经进行过相机产品定位并计算过Local,是否继续使用该Local进行锁付点位的转换计算
|
|
|
+ var resultUseExistingLocal = MessageBox.Show("系统检测到进入此界面后已经进行过相机产品定位并计算过Local,是否继续使用该Local进行锁付点位的转换计算?点击“是”继续使用,点击“否”则重新进行锁付点位的Local计算。", "确认", MessageBoxButton.YesNo, MessageBoxImage.Question);
|
|
|
+ if (resultUseExistingLocal == MessageBoxResult.No)
|
|
|
+ {
|
|
|
+ //show the dialog
|
|
|
+ task = DialogHost.Show(waiting, "RootDialog", null, null, null);
|
|
|
+ var isCalibSucceed = await AutoCalibLockPointLocal(product);
|
|
|
+ if (!isCalibSucceed)
|
|
|
+ {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ //show the dialog
|
|
|
+ task = DialogHost.Show(waiting, "RootDialog", null, null, null);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ //将锁付点位转换到世界坐标系
|
|
|
+ var localPoint = new PointF(point.X_Position, point.Y_Position);
|
|
|
+ var worldPoint = local.ToOldCoord(localPoint.X, localPoint.Y);
|
|
|
+ var point1 = point.Clone();
|
|
|
+ point1.X_Position = (float)worldPoint[0];
|
|
|
+ point1.Y_Position = (float)worldPoint[1];
|
|
|
+ //执行该点位
|
|
|
+ //移动机器人至拍照点位,拍照
|
|
|
+ var rpoint = new RPoint()
|
|
|
+ {
|
|
|
+ X = point.X_Position,
|
|
|
+ Y = point.Y_Position,
|
|
|
+ Z = point.Z_Position_Start,
|
|
|
+ };
|
|
|
+ await Robot.CalibMotionAsync(rpoint, 0);
|
|
|
+
|
|
|
+ _eventAggregator.GetEvent<SnackbarMessageNotification>().Publish(new MessageParameter() { Msg = "完成!", Duration = 1 });
|
|
|
+ }
|
|
|
+ catch (Exception ex)
|
|
|
+ {
|
|
|
+ LogHelper.WriteLogError("通过相机自动矫正锁附点位并执行时出错!", ex);
|
|
|
+ _eventAggregator.GetEvent<SnackbarMessageNotification>().Publish(new MessageParameter() { Msg = ex.Message, Duration = 1 });
|
|
|
+ }
|
|
|
+ finally
|
|
|
+ {
|
|
|
+ try
|
|
|
+ {
|
|
|
+ if (DialogHost.IsDialogOpen("RootDialog"))
|
|
|
+ {
|
|
|
+ DialogHost.Close("RootDialog");
|
|
|
+ }
|
|
|
+ }
|
|
|
+ catch (Exception)
|
|
|
+ {
|
|
|
+
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// 移动相机拍产品两个Msrk点计算Local
|
|
|
+ /// </summary>
|
|
|
+ /// <param name="product"></param>
|
|
|
+ /// <returns></returns>
|
|
|
+ private async Task<bool> AutoCalibLockPointLocal(ProductModel product)
|
|
|
+ {
|
|
|
+ try
|
|
|
+ {
|
|
|
+ //获取锁付相机拍照点位
|
|
|
+ var screwCameraPoint = product.ScrewCameraPoints;
|
|
|
+ if (screwCameraPoint == null || screwCameraPoint.Count < 2)
|
|
|
+ {
|
|
|
+ _eventAggregator.GetEvent<SnackbarMessageNotification>().Publish(new MessageParameter() { Msg = "未获取到锁付相机拍照点位,无法执行取料拍照点位矫正!", Duration = 1 });
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ //获取相机拍照点位对应的锁付点
|
|
|
+ var screwCameraLocalPoint1 = product.ScrewCameraLocalPos1;
|
|
|
+ if (screwCameraLocalPoint1 == null)
|
|
|
+ {
|
|
|
+ _eventAggregator.GetEvent<SnackbarMessageNotification>().Publish(new MessageParameter() { Msg = "未获取到锁付相机拍照点位对应的锁付点,无法执行取料拍照点位矫正!", Duration = 1 });
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ var screwCameraLocalPoint2 = product.ScrewCameraLocalPos2;
|
|
|
+ if (screwCameraLocalPoint2 == null)
|
|
|
+ {
|
|
|
+ _eventAggregator.GetEvent<SnackbarMessageNotification>().Publish(new MessageParameter() { Msg = "未获取到锁付相机拍照点位对应的锁付点,无法执行取料拍照点位矫正!", Duration = 1 });
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ 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 false;
|
|
|
+ }
|
|
|
+ var procedure = ProcedureModels.FirstOrDefault(p => p.Id == product.MoveDownCameraLockPhotoProcedureId);
|
|
|
+ if (procedure == null)
|
|
|
+ {
|
|
|
+ _eventAggregator.GetEvent<SnackbarMessageNotification>().Publish(new MessageParameter() { Msg = "未获取到锁付相机拍照流程,无法执行取料拍照点位矫正!", Duration = 1 });
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ CancellationTokenSource _cts = new CancellationTokenSource();
|
|
|
+ //移动机器人至拍照点位,拍照
|
|
|
+ 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.ExecutePhotoGetSinglePointWithImage(procedure, null, new double[] { rpoint.X, rpoint.Y, 0 }, _cts.Token);
|
|
|
+ //var Image = recognitionResult.Image;
|
|
|
+ //var Graphic = null;
|
|
|
+ //var Graphic = recognitionResult.Graphic;
|
|
|
+ if (!recognitionResult.IsSucceed)
|
|
|
+ {
|
|
|
+ _eventAggregator.GetEvent<SnackbarMessageNotification>().Publish(new MessageParameter() { Msg = "拍照获取识别结果失败,无法执行取料拍照点位矫正!", Duration = 1 });
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ //第一个点位的校正结果
|
|
|
+ PointF worldP1 = new PointF((float)recognitionResult.X, (float)recognitionResult.Y);
|
|
|
+ //移动机器人至拍照点位,拍照
|
|
|
+ rpoint = new RPoint()
|
|
|
+ {
|
|
|
+ X = screwCameraPoint[1].X_Position,
|
|
|
+ Y = screwCameraPoint[1].Y_Position,
|
|
|
+ Z = screwCameraPoint[1].Z_Position_Start,
|
|
|
+ U = screwCameraPoint[1].U_Position,
|
|
|
+ V = screwCameraPoint[1].R_Position,
|
|
|
+ };
|
|
|
+ await Robot.CalibMotionAsync(rpoint, 0);
|
|
|
+ if (_cts.IsCancellationRequested)
|
|
|
+ return false;
|
|
|
+ await Task.Delay(200);
|
|
|
+ // 执行拍照并获取识别结果
|
|
|
+ recognitionResult = await _remoteCommandService.ExecutePhotoGetSinglePointWithImage(procedure, null, new double[] { rpoint.X, rpoint.Y, 0 }, _cts.Token);
|
|
|
+ //Image = recognitionResult.Image;
|
|
|
+ //Graphic = null;
|
|
|
+ //Graphic = recognitionResult.Graphic;
|
|
|
+ if (!recognitionResult.IsSucceed)
|
|
|
+ {
|
|
|
+ _eventAggregator.GetEvent<SnackbarMessageNotification>().Publish(new MessageParameter() { Msg = "拍照获取识别结果失败,无法执行取料拍照点位矫正!", Duration = 1 });
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ //第一个点位的校正结果
|
|
|
+ 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);
|
|
|
+ local = new CoordinateTransformer(worldP1, worldP2, localP1, localP2);
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ catch (Exception ex)
|
|
|
+ {
|
|
|
+ LogHelper.WriteLogError("计算锁付点位产品坐标系坐标时出错!", ex);
|
|
|
+ _eventAggregator.GetEvent<SnackbarMessageNotification>().Publish(new MessageParameter() { Msg = ex.Message, Duration = 1 });
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
#endregion
|
|
|
|
|
|
#region 继承
|
|
|
@@ -1146,6 +1399,7 @@ namespace TeamAAS_VP.ViewModels.Product
|
|
|
{
|
|
|
try
|
|
|
{
|
|
|
+ local = null;
|
|
|
SelectProduct = navigationContext.Parameters.GetValue<ProductModel>("SelectProduct");
|
|
|
|
|
|
SelectedIndex = 0;
|