241 lines
8.5 KiB
C#
241 lines
8.5 KiB
C#
using MainShell.Common;
|
||
using MainShell.Hardware;
|
||
using MainShell.Log;
|
||
using MainShell.ParaSetting.Model;
|
||
using MainShell.Vision;
|
||
using MaxwellFramework.Core.Interfaces;
|
||
using MwFramework.Device;
|
||
using MwFramework.ManagerService;
|
||
using System;
|
||
using System.Globalization;
|
||
using System.Reflection;
|
||
using System.Windows;
|
||
|
||
namespace MainShell.Process
|
||
{
|
||
public class DefaultWaferMachineAdapter : IWaferMachineAdapter
|
||
{
|
||
private readonly HardwareManager _hardwareManager;
|
||
private readonly IParamList _parameterList;
|
||
|
||
public DefaultWaferMachineAdapter(HardwareManager hardwareManager, IParameterManager parameterManager)
|
||
{
|
||
_hardwareManager = hardwareManager ?? throw new ArgumentNullException(nameof(hardwareManager));
|
||
_parameterList = parameterManager as IParamList;
|
||
}
|
||
|
||
public CameraType GetCameraSource(WaferDiePositionContext context)
|
||
{
|
||
return CameraType.TopPositionCamera;
|
||
}
|
||
|
||
public MwCamera GetCamera(WaferDiePositionContext context)
|
||
{
|
||
return ResolveCamera(GetCameraSource(context));
|
||
}
|
||
|
||
public Point GetCameraFieldOfView(WaferDiePositionContext context)
|
||
{
|
||
DeviceFoundationSetting deviceFoundationSetting = GetDeviceFoundationSetting();
|
||
CameraFovSettingItem cameraFovSettingItem = GetCameraFovSettingItem(deviceFoundationSetting, GetCameraSource(context));
|
||
if (cameraFovSettingItem == null || cameraFovSettingItem.FovX <= 0d || cameraFovSettingItem.FovY <= 0d)
|
||
{
|
||
LogManager.LogProcessInfo("晶圆定位:DefaultWaferMachineAdapter 正在使用相机视野默认回退值。");
|
||
return new Point(1.0d, 1.0d);
|
||
}
|
||
|
||
return new Point(cameraFovSettingItem.FovX, cameraFovSettingItem.FovY);
|
||
}
|
||
|
||
public double GetExposureTimeMilliseconds(WaferDiePositionContext context)
|
||
{
|
||
MwCamera camera = GetCamera(context);
|
||
if (camera == null)
|
||
{
|
||
return 0d;
|
||
}
|
||
|
||
try
|
||
{
|
||
double exposureTime = 0d;
|
||
DriverLibResult result = camera.GetExposureTime(ref exposureTime);
|
||
if (result != DriverLibResult.DriverLibNoError || double.IsNaN(exposureTime) || double.IsInfinity(exposureTime) || exposureTime < 0d)
|
||
{
|
||
return 0d;
|
||
}
|
||
|
||
return exposureTime;
|
||
}
|
||
catch (Exception)
|
||
{
|
||
return 0d;
|
||
}
|
||
}
|
||
|
||
public CameraCaptureOptions CreateSoftTriggerCaptureOptions(WaferDiePositionContext context)
|
||
{
|
||
CameraCaptureOptions options = CameraCaptureOptions.CreateSoftTrigger(5000);
|
||
options.TriggerDelay = 20d;
|
||
return options;
|
||
}
|
||
|
||
public Point AdjustPointWithinSoftLimit(Point candidatePoint, WaferDiePositionContext context, double offsetMm, out bool adjusted, out string reason)
|
||
{
|
||
IAxis axisX = _hardwareManager.Axis_PHS_X1;
|
||
IAxis axisY = _hardwareManager.Axis_Stage_Y3;
|
||
double adjustedX = candidatePoint.X;
|
||
double adjustedY = candidatePoint.Y;
|
||
bool adjustedXFlag = TryClampByAxisSoftLimit(axisX, adjustedX, offsetMm, out adjustedX, out string adjustedXReason);
|
||
bool adjustedYFlag = TryClampByAxisSoftLimit(axisY, adjustedY, offsetMm, out adjustedY, out string adjustedYReason);
|
||
|
||
adjusted = adjustedXFlag || adjustedYFlag;
|
||
if (!adjusted)
|
||
{
|
||
reason = string.Empty;
|
||
return candidatePoint;
|
||
}
|
||
|
||
reason = BuildAdjustmentReason(adjustedXReason, adjustedYReason);
|
||
return new Point(adjustedX, adjustedY);
|
||
}
|
||
|
||
private DeviceFoundationSetting GetDeviceFoundationSetting()
|
||
{
|
||
return _parameterList == null ? null : _parameterList.GetParameter<DeviceFoundationSetting>();
|
||
}
|
||
|
||
private MwCamera ResolveCamera(CameraType cameraType)
|
||
{
|
||
MwCameraExtend cameraExtend = GetCameraExtend(cameraType);
|
||
if (cameraExtend == null)
|
||
{
|
||
return null;
|
||
}
|
||
|
||
return cameraExtend.Camera;
|
||
}
|
||
|
||
private MwCameraExtend GetCameraExtend(CameraType cameraType)
|
||
{
|
||
return _hardwareManager.GetCamera(cameraType);
|
||
}
|
||
|
||
private static CameraFovSettingItem GetCameraFovSettingItem(DeviceFoundationSetting deviceFoundationSetting, CameraType cameraType)
|
||
{
|
||
if (deviceFoundationSetting == null || deviceFoundationSetting.CameraSettingItem == null)
|
||
{
|
||
return null;
|
||
}
|
||
|
||
deviceFoundationSetting.CameraSettingItem.EnsureDefaultCameras();
|
||
switch (cameraType)
|
||
{
|
||
case CameraType.TopWideCamera:
|
||
return deviceFoundationSetting.CameraSettingItem.DownCamera;
|
||
|
||
case CameraType.MapCamera:
|
||
return deviceFoundationSetting.CameraSettingItem.MapCamera;
|
||
|
||
case CameraType.TopPositionCamera:
|
||
default:
|
||
return deviceFoundationSetting.CameraSettingItem.UpCamera;
|
||
}
|
||
}
|
||
|
||
private static bool TryClampByAxisSoftLimit(IAxis axis, double candidateValue, double offsetMm, out double adjustedValue, out string reason)
|
||
{
|
||
adjustedValue = candidateValue;
|
||
reason = string.Empty;
|
||
|
||
if (axis == null)
|
||
{
|
||
return false;
|
||
}
|
||
|
||
bool hasNegativeLimit = TryGetAxisLimit(axis, true, out double negativeLimit);
|
||
bool hasPositiveLimit = TryGetAxisLimit(axis, false, out double positiveLimit);
|
||
if (!hasNegativeLimit && !hasPositiveLimit)
|
||
{
|
||
return false;
|
||
}
|
||
|
||
double minLimit = hasNegativeLimit && hasPositiveLimit ? Math.Min(negativeLimit, positiveLimit) : negativeLimit;
|
||
double maxLimit = hasNegativeLimit && hasPositiveLimit ? Math.Max(negativeLimit, positiveLimit) : positiveLimit;
|
||
double minAllowed = hasNegativeLimit ? minLimit + Math.Max(0d, offsetMm) : double.NegativeInfinity;
|
||
double maxAllowed = hasPositiveLimit ? maxLimit - Math.Max(0d, offsetMm) : double.PositiveInfinity;
|
||
|
||
if (candidateValue < minAllowed)
|
||
{
|
||
adjustedValue = minAllowed;
|
||
reason = string.Format(
|
||
CultureInfo.InvariantCulture,
|
||
"{0}: clamp to negative soft limit {1:F3} with offset {2:F3}.",
|
||
axis.Name,
|
||
adjustedValue,
|
||
offsetMm);
|
||
return true;
|
||
}
|
||
|
||
if (candidateValue > maxAllowed)
|
||
{
|
||
adjustedValue = maxAllowed;
|
||
reason = string.Format(
|
||
CultureInfo.InvariantCulture,
|
||
"{0}: clamp to positive soft limit {1:F3} with offset {2:F3}.",
|
||
axis.Name,
|
||
adjustedValue,
|
||
offsetMm);
|
||
return true;
|
||
}
|
||
|
||
return false;
|
||
}
|
||
|
||
private static bool TryGetAxisLimit(IAxis axis, bool isNegativeLimit, out double limitValue)
|
||
{
|
||
limitValue = 0d;
|
||
if (axis == null)
|
||
{
|
||
return false;
|
||
}
|
||
|
||
try
|
||
{
|
||
double axisLimit = 0d;
|
||
MotionErrorCode errorCode = isNegativeLimit ? axis.GetSoftMel(ref axisLimit) : axis.GetSoftPel(ref axisLimit);
|
||
if (errorCode != MotionErrorCode.NoError)
|
||
{
|
||
return false;
|
||
}
|
||
|
||
limitValue = axisLimit;
|
||
if (double.IsNaN(limitValue) || double.IsInfinity(limitValue))
|
||
{
|
||
return false;
|
||
}
|
||
|
||
return true;
|
||
}
|
||
catch (Exception)
|
||
{
|
||
}
|
||
|
||
return false;
|
||
}
|
||
|
||
private static string BuildAdjustmentReason(string adjustedXReason, string adjustedYReason)
|
||
{
|
||
if (string.IsNullOrWhiteSpace(adjustedXReason))
|
||
{
|
||
return adjustedYReason ?? string.Empty;
|
||
}
|
||
|
||
if (string.IsNullOrWhiteSpace(adjustedYReason))
|
||
{
|
||
return adjustedXReason;
|
||
}
|
||
|
||
return adjustedXReason + " | " + adjustedYReason;
|
||
}
|
||
}
|
||
} |