Files

168 lines
6.9 KiB
C#
Raw Permalink Normal View History

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<string, double> actualPositions)
{
var positions = actualPositions ?? new Dictionary<string, double>(StringComparer.Ordinal);
ActualPositions = new ReadOnlyDictionary<string, double>(new Dictionary<string, double>(positions, StringComparer.Ordinal));
}
public IReadOnlyDictionary<string, double> 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<OriginCalibrationExecutionResult> ExecuteAsync(IEnumerable<AvoidanceAxisItem> avoidanceAxes, IEnumerable<CalibrationAxisItem> calibrationAxes, CancellationToken cancellationToken = default(CancellationToken))
{
var avoidanceAxisList = avoidanceAxes == null ? new List<AvoidanceAxisItem>() : avoidanceAxes.Where(item => item != null).ToList();
var calibrationAxisList = calibrationAxes == null ? new List<CalibrationAxisItem>() : 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<string, double>(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<TItem>(IEnumerable<TItem> items, Func<TItem, string> axisNameAccessor, Func<TItem, double> positionAccessor)
{
if (items == null)
{
return new MotionMoveRequest[0];
}
var requests = new List<MotionMoveRequest>();
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();
}
}
}