using MainShell.Hardware; using MainShell.Log; using MainShell.Motion; using MainShell.PageCalib.OriginCalib.Model; using MaxwellFramework.Core.Attributes; using MwFramework.Device; using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Linq; using System.Threading; using System.Threading.Tasks; namespace MainShell.PageCalib.OriginCalib.Service { public sealed class OriginCalibrationExecutionResult { public OriginCalibrationExecutionResult(IDictionary actualPositions) { var positions = actualPositions ?? new Dictionary(StringComparer.Ordinal); ActualPositions = new ReadOnlyDictionary(new Dictionary(positions, StringComparer.Ordinal)); } public IReadOnlyDictionary ActualPositions { get; private set; } } [Singleton] public class OriginCalibrationMotionService { private const int PositionSettleDelayMilliseconds = 200; private readonly HardwareManager _hardware; private readonly SafeAxisMotion _safeAxisMotion; public OriginCalibrationMotionService(HardwareManager hardware, SafeAxisMotion safeAxisMotion) { _hardware = hardware ?? throw new ArgumentNullException(nameof(hardware)); _safeAxisMotion = safeAxisMotion ?? throw new ArgumentNullException(nameof(safeAxisMotion)); } public async Task MoveAxisAsync(string axisName, double position, CancellationToken cancellationToken = default(CancellationToken)) { string.Format("原点标定正在移动轴“{0}”到位置 {1:F3}。", axisName, position).LogInfo(); try { var result = await _safeAxisMotion.MoveAbsAsync(axisName, position, MotionController.DefaultTimeoutMilliseconds, cancellationToken).ConfigureAwait(false); result.EnsureSuccess(); string.Format("原点标定轴“{0}”已到达目标位置 {1:F3}。", axisName, position).LogInfo(); } catch (OperationCanceledException) { string.Format("原点标定轴“{0}”移动已取消。", axisName).LogInfo(); throw; } catch (Exception ex) { string.Format("原点标定轴“{0}”移动失败:{1}", axisName, ex.Message).LogSysError(); throw; } } public async Task ExecuteAsync(IEnumerable avoidanceAxes, IEnumerable calibrationAxes, CancellationToken cancellationToken = default(CancellationToken)) { var avoidanceAxisList = avoidanceAxes == null ? new List() : avoidanceAxes.Where(item => item != null).ToList(); var calibrationAxisList = calibrationAxes == null ? new List() : calibrationAxes.Where(item => item != null).ToList(); string.Format( "原点标定执行开始,避让轴数量:{0},标定轴数量:{1}。", avoidanceAxisList.Count, calibrationAxisList.Count).LogInfo(); try { await ExecuteBatchAsync(CreateRequests(avoidanceAxisList, item => item.AxisName, item => item.Position), cancellationToken).ConfigureAwait(false); await ExecuteBatchAsync(CreateRequests(calibrationAxisList, item => item.AxisName, item => item.TargetPosition), cancellationToken).ConfigureAwait(false); string.Format( "原点标定等待 {0} ms 以稳定轴反馈,再读取实际位置。", PositionSettleDelayMilliseconds).LogInfo(); await Task.Delay(PositionSettleDelayMilliseconds, cancellationToken).ConfigureAwait(false); var actualPositions = new Dictionary(StringComparer.Ordinal); foreach (var calibrationAxis in calibrationAxisList) { if (calibrationAxis == null || string.IsNullOrWhiteSpace(calibrationAxis.AxisName)) { continue; } var axis = _hardware.GetAxisByName(calibrationAxis.AxisName); if (axis == null) { continue; } actualPositions[calibrationAxis.AxisName] = Math.Round(GetActualPosition(axis), 3); string.Format( "原点标定已采集轴“{0}”的实际位置:{1:F3}。", calibrationAxis.AxisName, actualPositions[calibrationAxis.AxisName]).LogInfo(); } string.Format("原点标定执行完成,共采集 {0} 个标定轴的实际位置。", actualPositions.Count).LogInfo(); return new OriginCalibrationExecutionResult(actualPositions); } catch (OperationCanceledException) { "原点标定执行已取消。".LogInfo(); throw; } catch (Exception ex) { string.Format("原点标定执行失败:{0}", ex.Message).LogSysError(); throw; } } private async Task ExecuteBatchAsync(MotionMoveRequest[] requests, CancellationToken cancellationToken) { if (requests.Length == 0) { return; } var result = await _safeAxisMotion.SafeMoveAsync(cancellationToken, requests).ConfigureAwait(false); result.EnsureSuccess(); } private MotionMoveRequest[] CreateRequests(IEnumerable items, Func axisNameAccessor, Func positionAccessor) { if (items == null) { return new MotionMoveRequest[0]; } var requests = new List(); foreach (var item in items) { if (item == null) { continue; } var axisName = axisNameAccessor(item); if (string.IsNullOrWhiteSpace(axisName)) { continue; } if (_hardware.GetAxisByName(axisName) == null) { string.Format("原点标定轴“{0}”在硬件管理器中不存在。", axisName).LogSysError(); continue; } requests.Add(MotionMoveRequest.ForAxisName(axisName, positionAccessor(item))); } return requests.ToArray(); } private static double GetActualPosition(IAxis axis) { return axis.State != null ? axis.State.ActualPos : axis.GetPositionImmediate(); } } }