using MainShell.Common; using MainShell.Common.VisionTemple.ViewModel; using MainShell.Hardware; using MainShell.Log; using MainShell.Motion; using MainShell.PageCalib.OriginCalib.Model; using MainShell.PageCalib.OriginCalib.Service; using MainShell.Resources.CustomControl; using MwFramework.Device; using Stylet; using System; using System.Collections.ObjectModel; using System.Linq; using System.Threading.Tasks; using System.Windows; namespace MainShell.PageCalib.OriginCalib.ViewModel { public class OriginCalibModuleViewModel : PropertyChangedBase { private readonly HardwareManager _hardware; private readonly OriginCalibrationMotionService _motionService; private readonly OriginCalibModuleItem _item; private readonly VisionTempleWindowViewModel _visionTempleWindowViewModel; private int _index; private bool _isCalibrating; public OriginCalibModuleItem Item => _item; public int Index { get { return _index; } set { SetAndNotify(ref _index, value); } } public string ModuleName { get { return _item.ModuleName; } set { _item.ModuleName = value; NotifyOfPropertyChange(nameof(ModuleName)); } } public bool IsIndependent { get { return _item.IsIndependent; } set { _item.IsIndependent = value; NotifyOfPropertyChange(nameof(IsIndependent)); NotifyOfPropertyChange(nameof(ShowIndependentBadge)); } } public bool IsCalibrating { get { return _isCalibrating; } set { SetAndNotify(ref _isCalibrating, value); NotifyOfPropertyChange(nameof(CanStartCalib)); // 标定进行中禁用避让示教和删除操作 foreach (AvoidanceAxisViewModel axis in AvoidanceAxes) { axis.CanTeach = !value; } } } public bool CanStartCalib { get { return !IsCalibrating; } } public bool HasAvoidanceAxes { get { return AvoidanceAxes.Count > 0; } } public System.Windows.Visibility ShowIndependentBadge { get { return IsIndependent ? System.Windows.Visibility.Visible : System.Windows.Visibility.Collapsed; } } public System.Windows.Visibility ShowAvoidanceBadge { get { return HasAvoidanceAxes ? System.Windows.Visibility.Visible : System.Windows.Visibility.Collapsed; } } public ObservableCollection AvoidanceAxes { get; } = new ObservableCollection(); public ObservableCollection CalibrationAxes { get; } = new ObservableCollection(); public OriginCalibModuleViewModel( OriginCalibModuleItem item, HardwareManager hardware, OriginCalibrationMotionService motionService, VisionTempleWindowViewModel visionTempleWindowViewModel) { _item = item ?? throw new ArgumentNullException(nameof(item)); _hardware = hardware ?? throw new ArgumentNullException(nameof(hardware)); _motionService = motionService ?? throw new ArgumentNullException(nameof(motionService)); _visionTempleWindowViewModel = visionTempleWindowViewModel ?? throw new ArgumentNullException(nameof(visionTempleWindowViewModel)); foreach (AvoidanceAxisItem axisItem in item.AvoidanceAxes) { AvoidanceAxes.Add(new AvoidanceAxisViewModel(axisItem, hardware, motionService, OnRemoveAvoidanceAxis)); } foreach (CalibrationAxisItem calibItem in item.CalibrationAxes) { CalibrationAxes.Add(new CalibrationAxisViewModel(calibItem)); } } public void AddAvoidanceAxis() { AvoidanceAxisItem newItem = new AvoidanceAxisItem { AxisName = "NewAxis", Position = 0.0 }; _item.AvoidanceAxes.Add(newItem); AvoidanceAxisViewModel newVm = new AvoidanceAxisViewModel(newItem, _hardware, _motionService, OnRemoveAvoidanceAxis); newVm.CanTeach = !_isCalibrating; AvoidanceAxes.Add(newVm); NotifyOfPropertyChange(nameof(HasAvoidanceAxes)); NotifyOfPropertyChange(nameof(ShowAvoidanceBadge)); } private void OnRemoveAvoidanceAxis(AvoidanceAxisViewModel vm) { if (_isCalibrating) { "原点标定进行中,无法删除避让轴。".LogSysError(); LocalizedMessageBox.Show(MessageKey.OriginCalibDeleteAxisDuringCalibration, MessageKey.TitleWarning, MessageBoxButton.OK, MessageBoxImage.Warning); return; } try { string.Format("原点标定模块“{1}”准备删除避让轴“{0}”。", vm.AxisName, ModuleName).LogInfo(); _item.AvoidanceAxes.Remove(vm.Item); AvoidanceAxes.Remove(vm); NotifyOfPropertyChange(nameof(HasAvoidanceAxes)); NotifyOfPropertyChange(nameof(ShowAvoidanceBadge)); string.Format("原点标定删除避让轴成功,当前剩余 {0} 个避让轴。", AvoidanceAxes.Count).LogInfo(); } catch (Exception ex) { string.Format("原点标定删除避让轴“{0}”失败:{1}", vm.AxisName, ex.Message).LogSysError(); LocalizedMessageBox.ShowFormat(MessageKey.OriginCalibDeleteAxisFailed, MessageKey.TitleError, MessageBoxButton.OK, MessageBoxImage.Error, ex.Message); } } public void TeachCalibPositions() { foreach (CalibrationAxisViewModel calibAxis in CalibrationAxes) { if (_hardware.AxesDic != null && _hardware.AxesDic.ContainsKey(calibAxis.AxisName)) { calibAxis.TargetPosition = Math.Round(_hardware.AxesDic[calibAxis.AxisName].State.ActualPos, 3); } } } public void MakeTemplate() { try { if(Item.ModuleName== OriginCalibModuleNames.GantryX2) { _visionTempleWindowViewModel.SetCamera(CameraType.TopWideCamera); } else { _visionTempleWindowViewModel.SetCamera(CameraType.TopPositionCamera); } _visionTempleWindowViewModel.TemplatePath = _item.TemplatePath; $"原点标定模块“{ModuleName}”打开视觉模板制作窗口。".LogInfo(); _visionTempleWindowViewModel.ShowWindow(); } catch (Exception ex) { $"原点标定模块“{ModuleName}”打开视觉模板制作窗口失败:{ex.Message}".LogSysError(); LocalizedMessageBox.ShowFormat( MessageKey.OriginCalibOpenVisionTemplateFailed, MessageKey.TitleError, MessageBoxButton.OK, MessageBoxImage.Error, ex.Message); } } public async Task StartCalib() { if (IsCalibrating) { return; } IsCalibrating = true; LoadingService.Instance.Show(string.Format("模块 {0} 正在标定...", ModuleName), true, true); try { string.Format( "原点标定模块“{0}”开始标定,避让轴数量:{1},标定轴数量:{2}。", ModuleName, AvoidanceAxes.Count, CalibrationAxes.Count).LogInfo(); var calibrationResult = await _motionService.ExecuteAsync( AvoidanceAxes.Select(x => x.Item), CalibrationAxes.Select(x => x.Item), LoadingService.Instance.Token); // 执行模块特定的后处理逻辑,通常在运动完成后、标定写入前 if (_item.PostProcessor != null) { string.Format( "原点标定模块“{0}”执行后处理“{1}”。", ModuleName, _item.PostProcessor.Name).LogInfo(); try { await _item.PostProcessor.ExecuteAsync(calibrationResult, LoadingService.Instance.Token, new CenterRecognitionParameters { TemplatePath = _item.TemplatePath, Type = CenterRecognitionType.Template }); string.Format( "原点标定模块“{0}”后处理“{1}”完成。", ModuleName, _item.PostProcessor.Name).LogInfo(); } catch (OperationCanceledException) { string.Format( "原点标定模块“{0}”后处理“{1}”被取消。", ModuleName, _item.PostProcessor.Name).LogInfo(); throw; } catch (Exception ex) { string.Format( "原点标定模块“{0}”后处理“{1}”失败:{2}", ModuleName, _item.PostProcessor.Name, ex.Message).LogSysError(); throw; } } foreach (CalibrationAxisViewModel calibAxis in CalibrationAxes) { IAxis axis = ResolveCalibrationAxis(calibAxis.AxisName); if (axis != null) { calibAxis.LastPosition = Math.Round(GetActualPosition(axis), 3); calibAxis.IsCalibrated = true; continue; } double lastPosition; if (calibrationResult.ActualPositions.TryGetValue(calibAxis.AxisName, out lastPosition)) { calibAxis.LastPosition = lastPosition; calibAxis.IsCalibrated = true; } } string.Format("原点标定模块“{0}”标定完成。", ModuleName).LogInfo(); } catch (OperationCanceledException) { string.Format("原点标定模块“{0}”取消标定。", ModuleName).LogInfo(); LocalizedMessageBox.Show(MessageKey.OriginCalibCalibrationCanceled, MessageKey.TitleWarning, MessageBoxButton.OK, MessageBoxImage.Warning); } catch (Exception ex) { string.Format("原点标定模块“{0}”标定失败:{1}", ModuleName, ex.Message).LogSysError(); LocalizedMessageBox.ShowFormat(MessageKey.OriginCalibCalibrationFailed, MessageKey.TitleError, MessageBoxButton.OK, MessageBoxImage.Error, ex.Message); } finally { LoadingService.Instance.Hide(); IsCalibrating = false; } } public void ResetModule() { foreach (CalibrationAxisViewModel calibAxis in CalibrationAxes) { calibAxis.Reset(); } string.Format("原点标定模块“{0}”已复位。", ModuleName).LogInfo(); } private IAxis ResolveCalibrationAxis(string axisName) { if (string.IsNullOrWhiteSpace(axisName)) { return null; } if (_hardware.AxesDic != null && _hardware.AxesDic.ContainsKey(axisName)) { return _hardware.AxesDic[axisName]; } if (string.Equals(axisName, "X1", StringComparison.OrdinalIgnoreCase)) { return _hardware.Axis_X1; } if (string.Equals(axisName, "Y1", StringComparison.OrdinalIgnoreCase)) { return _hardware.Axis_Y1; } if (string.Equals(axisName, "X2", StringComparison.OrdinalIgnoreCase)) { return _hardware.Axis_X2; } if (string.Equals(axisName, "Y2", StringComparison.OrdinalIgnoreCase)) { return _hardware.Axis_Y2; } if (string.Equals(axisName, "WSX3", StringComparison.OrdinalIgnoreCase)) { return _hardware.Axis_WS_X3; } return null; } private static double GetActualPosition(IAxis axis) { if (axis == null) { return 0; } return axis.State != null ? axis.State.ActualPos : axis.GetPositionImmediate(); } } }