using Cognex.VisionPro; using Cognex.VisionPro.ToolBlock; using MathNet.Numerics.LinearAlgebra; using MathNet.Numerics.LinearAlgebra.Complex; 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.Drawing; using System.Linq; using System.Threading.Tasks; using System.Windows; using Team.FFFeederService.Interfaces; using TeamAAS_VP.Core; using TeamAAS_VP.Events; using TeamAAS_VP.Interfaces; using TeamAAS_VP.Models; using TeamAAS_VP; using TeamAAS_VP.Resources.Languages; using TeamAAS_VP.Models.Calibration; using TeamAAS_VP.Services; namespace TeamAAS_VP.ViewModels.Calibration { public class CalibrationVerificationViewModel : BindableBase, IConfirmNavigationRequest { IRegionManager _regionManager; IRegionNavigationService _regionNavigationService; IContainerProvider _container; IDialogService _dialogService; IEventAggregator _eventAggregator; IConfigService _configService; IRobotService _robotService; ICameraService _cameraService; IFeederService _feederService; ISystemDatabaseService _systemDatabaseService; #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 CalibrationInfo _SelectCalibration; public CalibrationInfo SelectCalibration { get { return _SelectCalibration; } set { SetProperty(ref _SelectCalibration, value); } } public Management management { get; set; } public IRobot Robot { get; set; } public IVoiceCoilMotorFeeder Feeder { get; set; } private bool _IsRunning = true; public bool IsRunning { get { return _IsRunning; } set { SetProperty(ref _IsRunning, value); } } private ICamera _Camera; public ICamera Camera { get { return _Camera; } set { SetProperty(ref _Camera, value); } } #endregion #region 命令 private DelegateCommand _LoadedCommand; public DelegateCommand LoadedCommand => _LoadedCommand ?? (_LoadedCommand = new DelegateCommand(ExecuteLoadedCommand)); private DelegateCommand _NextCommand; public DelegateCommand NextCommand => _NextCommand ?? (_NextCommand = new DelegateCommand(ExecuteNextCommand).ObservesCanExecute(() => IsRunning)); private DelegateCommand _BackCommand; public DelegateCommand BackCommand => _BackCommand ?? (_BackCommand = new DelegateCommand(ExecuteBackCommand).ObservesCanExecute(() => IsRunning)); private DelegateCommand _StartTestCommand; public DelegateCommand StartTestCommand => _StartTestCommand ?? (_StartTestCommand = new DelegateCommand(ExecuteStartTestCommand).ObservesCanExecute(() => IsRunning)); #endregion #region 事件 #endregion public CalibrationVerificationViewModel(IRegionManager regionManager, IEventAggregator ea, IRegionNavigationService regionNavigationService, IContainerProvider container, IDialogService dialogService, IConfigService configService, IRobotService robotService, ICameraService cameraService, IFeederService feederService, ISystemDatabaseService systemDatabaseService) { _regionManager = regionManager; _regionNavigationService = regionNavigationService; _container = container; _dialogService = dialogService; _eventAggregator = ea; _configService = configService; _robotService = robotService; _cameraService = cameraService; _feederService = feederService; _systemDatabaseService = systemDatabaseService; } #region 方法 void ExecuteLoadedCommand() { if (_systemDatabaseService.GetCurrentUser().userPart == Enums.UserPart.Operator) { IsAllowEdit = false; } else { IsAllowEdit = true; } } /// /// 测试校准 /// async void ExecuteStartTestCommand() { try { if (MessageBox.Show(Lang.是否开始测试, Lang.自动校准, MessageBoxButton.OKCancel, MessageBoxImage.Question) != MessageBoxResult.OK) return; IsRunning = false; double IntervalX = SelectCalibration.Width*0.90 / 2; double IntervalY = SelectCalibration.Height * 0.90 / 2; Vector P1 = Vector.Build.Dense(new double[] { -IntervalX, -IntervalY }); Vector P2 = Vector.Build.Dense(new double[] { IntervalX, -IntervalY }); Vector P3 = Vector.Build.Dense(new double[] { 0, 0 }); Vector P4 = Vector.Build.Dense(new double[] { -IntervalX, IntervalY }); Vector P5 = Vector.Build.Dense(new double[] { IntervalX, IntervalY }); //移动相机标定时,需要先记住特征点的绝对坐标(相对于机器人坐标系) P0 //if (SelectCalibration.CameraMount == Enums.CameraMount.MobileJ4) //{ // P1[0] *= -1; P1[1] *= -1; // P2[0] *= -1; P2[1] *= -1; // P3[0] *= -1; P3[1] *= -1; // P4[0] *= -1; P4[1] *= -1; // P5[0] *= -1; P5[1] *= -1; //} var P0 = Vector.Build.Dense(new double[] { SelectCalibration.CenterPoint.X, SelectCalibration.CenterPoint.Y }); /// /// 机器人与相机之间的旋转矩阵 /// Matrix RobotCameraRotationMatrix = Matrix.Build.DenseOfArray(SelectCalibration.RobotCameraRotationMatrix); //1 P1 = RobotCameraRotationMatrix.Inverse() * P1 + P0; //2 P2 = RobotCameraRotationMatrix.Inverse() * P2 + P0; //3 P3 = RobotCameraRotationMatrix.Inverse() * P3 + P0; //4 P4 = RobotCameraRotationMatrix.Inverse() * P4 + P0; //5 P5 = RobotCameraRotationMatrix.Inverse() * P5 + P0; List rPoints = new List(); rPoints.Add(new RPoint() { Number = 1, X = (float)P1[0], Y = (float)P1[1], Z = SelectCalibration.CenterPoint.Z, U = SelectCalibration.CenterPoint.U, V = SelectCalibration.CenterPoint.V, W = SelectCalibration.CenterPoint.W, Hand = SelectCalibration.CenterPoint.Hand, Local = SelectCalibration.CenterPoint.Local, Tool = SelectCalibration.CenterPoint.Tool }); rPoints.Add(new RPoint() { Number = 2, X = (float)P2[0], Y = (float)P2[1], Z = SelectCalibration.CenterPoint.Z, U = SelectCalibration.CenterPoint.U, V = SelectCalibration.CenterPoint.V, W = SelectCalibration.CenterPoint.W, Hand = SelectCalibration.CenterPoint.Hand, Local = SelectCalibration.CenterPoint.Local, Tool = SelectCalibration.CenterPoint.Tool }); rPoints.Add(new RPoint() { Number = 3, X = (float)P3[0], Y = (float)P3[1], Z = SelectCalibration.CenterPoint.Z, U = SelectCalibration.CenterPoint.U, V = SelectCalibration.CenterPoint.V, W = SelectCalibration.CenterPoint.W, Hand = SelectCalibration.CenterPoint.Hand, Local = SelectCalibration.CenterPoint.Local, Tool = SelectCalibration.CenterPoint.Tool }); rPoints.Add(new RPoint() { Number = 4, X = (float)P4[0], Y = (float)P4[1], Z = SelectCalibration.CenterPoint.Z, U = SelectCalibration.CenterPoint.U, V = SelectCalibration.CenterPoint.V, W = SelectCalibration.CenterPoint.W, Hand = SelectCalibration.CenterPoint.Hand, Local = SelectCalibration.CenterPoint.Local, Tool = SelectCalibration.CenterPoint.Tool }); rPoints.Add(new RPoint() { Number = 5, X = (float)P5[0], Y = (float)P5[1], Z = SelectCalibration.CenterPoint.Z, U = SelectCalibration.CenterPoint.U, V = SelectCalibration.CenterPoint.V, W = SelectCalibration.CenterPoint.W, Hand = SelectCalibration.CenterPoint.Hand, Local = SelectCalibration.CenterPoint.Local, Tool = SelectCalibration.CenterPoint.Tool }); List> TestPos = new List>(); for (int i = 0; i < rPoints.Count; i++) { if (SelectCalibration.CameraMount == Enums.CameraMount.FixedDown) { //移动机器人至i await Robot.CalibMotionAsync(rPoints[i], 0); //关闭吸气 await Robot.CalibOutIOAsync(false); //移动机器人至待机位置 await Robot.CalibMotionAsync(SelectCalibration.HomePoint, 0); } else { //移动机器人至i await Robot.CalibMotionAsync(rPoints[i], rPoints[i].Z); } var pixelpos = Photo(); Matrix matrix = Matrix.Build.DenseOfArray(SelectCalibration.AffineTransformationMaterial); var rpos = matrix * Vector.Build.Dense(new double[] { pixelpos.X, pixelpos.Y ,1}); TestPos.Add(rpos); if (SelectCalibration.CameraMount == Enums.CameraMount.FixedDown) { //移动机器人至i await Robot.CalibMotionAsync(rPoints[i], 0); //打开吸气 await Robot.CalibOutIOAsync(true); } } if (SelectCalibration.CameraMount == Enums.CameraMount.FixedDown) { //移动机器人至待机位置 await Robot.CalibMotionAsync(SelectCalibration.HomePoint, 0); } //RMS(均方根值) 标定偏差 double sumX = 0, sumY = 0; List differenceX = new List(); List differenceY = new List(); for (int i = 0; i < 5; i++) { if (SelectCalibration.CameraMount == Enums.CameraMount.MobileJ4) { //像素直接转换成mm时的点位 double Robot_X, Robot_Y; Robot_X = TestPos[i][0]; Robot_Y= TestPos[i][1]; //机器人当前TOOL 0下的坐标 double curpos_x = 0, curpos_y = 0, curpos_u = 0; curpos_x = rPoints[i].X; curpos_y = rPoints[i].Y; curpos_u = rPoints[i].U; //得到旋转矩阵 double angle = Math.PI * (curpos_u - SelectCalibration.MarkPoint.U) / 180; // 创建T矩阵 Matrix rotationMatrix = Matrix.Build.DenseOfArray(new double[,] { { Math.Cos(angle), -Math.Sin(angle) }, { Math.Sin(angle), Math.Cos(angle) } }); Vector p3 = Vector.Build.Dense(new double[] { Robot_X - SelectCalibration.CalibPoints[0].Robot.X, Robot_Y - SelectCalibration.CalibPoints[0].Robot.Y }); Vector phere = Vector.Build.Dense(new double[] { curpos_x, curpos_y }); var cc = rotationMatrix * p3 + phere; differenceX.Add(cc[0] - SelectCalibration.MarkPoint.X); differenceY.Add(cc[1] - SelectCalibration.MarkPoint.Y); } else { //将tool 0下的坐标转换成Tool n下的坐标 if (SelectCalibration.Tool != null) { ToolCoord toolCoord = new ToolCoord(); toolCoord.SetTool(SelectCalibration.Tool.X, SelectCalibration.Tool.Y); double u1 = rPoints[i].U; if (Robot.Brand == Enums.RobotBrand.Schneider) { u1 *= -1; } var trans = toolCoord.GetToolnCoord(Vector.Build.Dense(new double[] { rPoints[i].X, rPoints[i].Y }), u1); differenceX.Add(trans[0] - TestPos[i][0]); differenceY.Add(trans[1] - TestPos[i][1]); } else { differenceX.Add(rPoints[i].X - TestPos[i][0]); differenceY.Add(rPoints[i].Y - TestPos[i][1]); } } sumX += Math.Pow(differenceX[differenceX.Count - 1], 2); sumY += Math.Pow(differenceY[differenceY.Count - 1], 2); } double rmsX, rmsY; rmsX = Math.Sqrt(sumX / 5); rmsY = Math.Sqrt(sumY / 5); CalibrationTestResult calibrationTestResult = new CalibrationTestResult(); calibrationTestResult.MaxErrorValueX = differenceX.Max(); calibrationTestResult.MinErrorValueX = differenceX.Min(); calibrationTestResult.MaxErrorValueY = differenceY.Max(); calibrationTestResult.MinErrorValueY = differenceY.Min(); calibrationTestResult.RMSEX = rmsX; calibrationTestResult.RMSEY = rmsY; SelectCalibration.CalibrationTestResult = calibrationTestResult; MessageBox.Show(Lang.验证完成); NavigationParameters param = new NavigationParameters(); param.Add("SelectCalibration", SelectCalibration); _regionManager.RequestNavigate("CalibrationRegionContext", "CalibrationResult", param); } catch (Exception ex) { LogHelper.WriteLogError("相机校准-校准验证界面示加载时出错!", ex); _eventAggregator.GetEvent().Publish(new MessageParameter() { Msg = ex.Message, Duration = 1 }); MessageBox.Show(ex.Message); } finally { IsRunning = true; } } /// /// 下一步 /// void ExecuteNextCommand() { NavigationParameters param = new NavigationParameters(); param.Add("SelectCalibration", SelectCalibration); _regionManager.RequestNavigate("CalibrationRegionContext", "CalibrationResult", param); } /// /// 上一步 /// void ExecuteBackCommand() { NavigationParameters param = new NavigationParameters(); param.Add("SelectCalibration", SelectCalibration); _regionManager.RequestNavigate("CalibrationRegionContext", "CalibrationAuto", param); } /// /// 相机拍照 /// /// /// private PointF Photo() { if (Feeder != null) { Feeder.OpenLight(); Feeder.SetLightTimeOut((ushort)SelectCalibration.Brightness); } Task.Delay(200).Wait(); //采集图像 if (Camera != null) { SelectCalibration.ToolBlock.Inputs["InputImage"].Value = Camera.Grab(); Image = (ICogImage)SelectCalibration.ToolBlock.Inputs["InputImage"].Value; } Graphic = null; SelectCalibration.ToolBlock.Run(); CogToolBlockTerminalCollection outputCollection = SelectCalibration.ToolBlock.Outputs; Graphic = outputCollection["Graphic"].Value as CogGraphicCollection; bool Found = (bool)(outputCollection["Found"].Value); if (Found) { var strpoints = outputCollection["Point"].Value.ToString(); string[] items = strpoints.Split(','); return new PointF(float.Parse(items[0]), float.Parse(items[1])); } else { throw new Exception(Lang.拍照失败); } } #endregion #region 继承 /// /// 确认导航请求时调用。此方法允许您在导航之前执行一些操作。 /// /// /// public void ConfirmNavigationRequest(NavigationContext navigationContext, Action continuationCallback) { continuationCallback(true); } /// /// 接收导航请求时调用。传入导航参数,包含有关导航目标的信息。 /// /// /// public async void OnNavigatedTo(NavigationContext navigationContext) { SelectCalibration = navigationContext.Parameters.GetValue("SelectCalibration"); if (SelectCalibration != null) { Robot = _robotService.GetRobot(SelectCalibration.RobotId); if (SelectCalibration.FeederId != Guid.Empty) { Feeder = _feederService.GetFeeder(SelectCalibration.FeederId); } } Camera = _cameraService.GetCamera(SelectCalibration.CameraID); } /// /// 是否允许导航到此视图模型。 /// /// /// public bool IsNavigationTarget(NavigationContext navigationContext) { return true; } /// /// 导航离开此视图模型时调用。您可以在此处执行清理操作或保存状态。 /// /// public void OnNavigatedFrom(NavigationContext navigationContext) { } #endregion private bool _IsAllowEdit = false; public bool IsAllowEdit { get { return _IsAllowEdit; } set { SetProperty(ref _IsAllowEdit, value); } } private void LoginChange(Models.User user) { if (user.userPart == Enums.UserPart.Operator) { IsAllowEdit = false; } else { IsAllowEdit = true; } } } }