168 lines
6.9 KiB
C#
168 lines
6.9 KiB
C#
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();
|
|
}
|
|
}
|
|
} |