291 lines
10 KiB
C#
291 lines
10 KiB
C#
using Aurora.Api;
|
|
using Aurora.Api.Devices;
|
|
using VisionCommon;
|
|
using VisionAligner;
|
|
using VisionSequence.Pattern;
|
|
using System.Collections.Generic;
|
|
using Hermes;
|
|
using System.Threading.Tasks;
|
|
using System.Diagnostics;
|
|
using System.Threading;
|
|
using System.Linq;
|
|
using VisionLight;
|
|
|
|
namespace VisionSequence.Aligner {
|
|
/// <summary>
|
|
/// 드라이런(Dry Run) 시퀀스 파라미터
|
|
/// </summary>
|
|
public class AlignSeqParams_DryRun {
|
|
/// <summary>얼라인 키 정보</summary>
|
|
public AlignInfo AlignInfo { get; set; }
|
|
/// <summary>FOV 키 정보</summary>
|
|
public Dictionary<eFovId, FovInfo> FovInfos { get; set; }
|
|
/// <summary>이동할 포지션 타입</summary>
|
|
public ePositionType PositionType { get; set; }
|
|
/// <summary>메인 화면 타입</summary>
|
|
public eDisplayType DisplayType { get; set; }
|
|
/// <summary>FOV별로 이동시킬 절대위치</summary>
|
|
public Dictionary<eFovId, Position> FovPositions { get; set; }
|
|
|
|
/// <summary>
|
|
/// 드라이런(Dry Run) 시퀀스 파라미터를 얻어온다.
|
|
/// </summary>
|
|
/// <param name="alignInfo">얼라인 키 정보</param>
|
|
/// <param name="fovInfos">FOV 키 정보</param>
|
|
/// <param name="positionType">포지션 타입</param>
|
|
/// <param name="displayType">메인 화면 타입</param>
|
|
/// <param name="fovPositions">FOV별로 이동시킬 절대위치. null일 경우, 자동으로 Adapter에 정의된 티칭위치로 이동</param>
|
|
public AlignSeqParams_DryRun(
|
|
AlignInfo alignInfo,
|
|
Dictionary<eFovId, FovInfo> fovInfos,
|
|
ePositionType positionType = ePositionType.Teaching,
|
|
eDisplayType displayType = eDisplayType.Main_1,
|
|
Dictionary<eFovId, Position> fovPositions = null) {
|
|
|
|
this.AlignInfo = alignInfo;
|
|
this.FovInfos = fovInfos;
|
|
this.PositionType = positionType;
|
|
this.DisplayType = displayType;
|
|
this.FovPositions = fovPositions;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 드라이런(Dry Run)을 위한 시퀀스 : 티칭 위치 이동 후 그랩만 수행
|
|
/// </summary>
|
|
public class AlignSeq_DryRun : SubSeqBase {
|
|
private readonly Logger LOG = new Logger(typeof(AlignSeq_DryRun).Name);
|
|
|
|
private AlignSeqParams_DryRun _Params;
|
|
private AlignRecipe _AlignRecipe;
|
|
private SubSysInfo _SubSysInfo;
|
|
private SubSysRecipe _SubSysRecipe;
|
|
|
|
private string _SeqName;
|
|
|
|
#region Sequence Id
|
|
private const string SEQ_ID_INIT = "INIT";
|
|
private const string SEQ_ID_GRAB_AND_MOVE = "GRAB_AND_MOVE";
|
|
private const string SEQ_ID_SEQ_COMPLETE = "SEQ_COMPLETE";
|
|
#endregion
|
|
|
|
/// <summary>
|
|
/// 생성자
|
|
/// </summary>
|
|
public AlignSeq_DryRun() {
|
|
}
|
|
|
|
private void SetActions(SequenceBuilder sb) {
|
|
sb.AddAction(SEQ_ID_INIT, Init);
|
|
sb.AddAction(SEQ_ID_GRAB_AND_MOVE, GrabAndMove);
|
|
sb.AddAction(SEQ_ID_SEQ_COMPLETE, SeqComplete);
|
|
}
|
|
|
|
public override SequenceBuilder Builder(string seqName) {
|
|
_SeqName = seqName;
|
|
|
|
SequenceBuilder sb = new SequenceBuilder(1000);
|
|
SetActions(sb);
|
|
sb.OnStopped(OnStopped);
|
|
sb.OnForceError(OnForceError);
|
|
|
|
sb.Flows(
|
|
sb.Init
|
|
> sb[SEQ_ID_INIT]
|
|
> sb[SEQ_ID_GRAB_AND_MOVE]
|
|
> sb[SEQ_ID_SEQ_COMPLETE]
|
|
);
|
|
sb.Flows(
|
|
sb[SEQ_ID_SEQ_COMPLETE]
|
|
> sb.Final
|
|
);
|
|
|
|
#if SEQ_DRAW
|
|
sb.Draw($"{GetType().Name}.pdf");
|
|
#endif
|
|
|
|
return sb;
|
|
}
|
|
|
|
private SequenceActionResult Init(
|
|
SequenceContext context,
|
|
string id,
|
|
SequenceActionResult param) {
|
|
|
|
if (param.Param != null) {
|
|
_Params = param.Param as AlignSeqParams_DryRun;
|
|
}
|
|
else {
|
|
LOG.E($"Param is null.");
|
|
return null;
|
|
}
|
|
|
|
_AlignRecipe = VisionRecipeManager.GetAlignRecipe(_Params.AlignInfo);
|
|
_SubSysInfo = VisionRecipeManager.GetSubSysInfo(_Params.AlignInfo.UnitId, _Params.AlignInfo.SubSysId);
|
|
_SubSysRecipe = VisionRecipeManager.GetSubSysRecipe(_SubSysInfo);
|
|
|
|
return SequenceAction.Ok();
|
|
}
|
|
|
|
private SequenceActionResult GrabAndMove(
|
|
SequenceContext context,
|
|
string id,
|
|
SequenceActionResult param) {
|
|
|
|
switch (_AlignRecipe.ProcParams.ProcFovType) {
|
|
case eProcFovType.C1_F1_M2C:
|
|
case eProcFovType.C1_F1_M2R:
|
|
GrabSingle(eFovId.Fov1);
|
|
break;
|
|
case eProcFovType.C1_F2_MV:
|
|
GrabSingle(eFovId.Fov1);
|
|
MoveFovPos(eFovId.Fov2);
|
|
GrabSingle(eFovId.Fov2);
|
|
break;
|
|
//case eProcFovType.C1_F3_MV:
|
|
// GrabSingle(eFovId.Fov1);
|
|
// MoveFovPos(eFovId.Fov2);
|
|
// GrabSingle(eFovId.Fov2);
|
|
// MoveFovPos(eFovId.Fov3);
|
|
// GrabSingle(eFovId.Fov3);
|
|
// break;
|
|
case eProcFovType.C1_F4_MV:
|
|
GrabSingle(eFovId.Fov1);
|
|
MoveFovPos(eFovId.Fov2);
|
|
GrabSingle(eFovId.Fov2);
|
|
MoveFovPos(eFovId.Fov3);
|
|
GrabSingle(eFovId.Fov3);
|
|
MoveFovPos(eFovId.Fov4);
|
|
GrabSingle(eFovId.Fov4);
|
|
break;
|
|
case eProcFovType.C2_F4_MV:
|
|
GrabMulti(new List<FovInfo>() { _Params.FovInfos[eFovId.Fov1], _Params.FovInfos[eFovId.Fov2] });
|
|
MoveFovPos(eFovId.Fov3);
|
|
GrabMulti(new List<FovInfo>() { _Params.FovInfos[eFovId.Fov3], _Params.FovInfos[eFovId.Fov4] });
|
|
break;
|
|
case eProcFovType.C2_F2:
|
|
case eProcFovType.C4_F4:
|
|
GrabMulti();
|
|
break;
|
|
}
|
|
|
|
return SequenceAction.Ok();
|
|
}
|
|
|
|
private int GrabSingle(eFovId fovId) {
|
|
// 개별 FOV 그랩
|
|
var cameraAgent = CameraAgentManager.GetCameraAgent(_Params.FovInfos[fovId]);
|
|
var cameraDisplay = CameraDisplayManager.GetDisplay(_Params.FovInfos[fovId], _Params.DisplayType);
|
|
var lightParams = LightHub.Instance.GetLightParams(VisionRecipeManager.GetCamRecipe(_Params.FovInfos[fovId]).CamId);
|
|
var grabImage = GrabFindSeqUtil.GetProcGrabImage(_Params.FovInfos[fovId], new LightInfo() { LightParams = lightParams });
|
|
|
|
var image = (object)grabImage;
|
|
return cameraAgent.GrabSync(cameraDisplay, ref image);
|
|
}
|
|
|
|
private void GrabMulti(List<FovInfo> fovInfos) {
|
|
var results = new List<int>();
|
|
|
|
// 그룹 FOV 그랩
|
|
foreach (FovInfo fovInfo in fovInfos) {
|
|
Task.Run(() => {
|
|
results.Add(GrabSingle(fovInfo.FovId));
|
|
});
|
|
}
|
|
|
|
WaitGrabMultiFinished(results);
|
|
}
|
|
|
|
private void GrabMulti() {
|
|
var results = new List<int>();
|
|
|
|
// 전체 FOV 그랩
|
|
foreach (FovInfo fovInfo in _Params.FovInfos.Values) {
|
|
Task.Run(() => {
|
|
results.Add(GrabSingle(fovInfo.FovId));
|
|
});
|
|
}
|
|
|
|
WaitGrabMultiFinished(results);
|
|
}
|
|
|
|
/// <summary>
|
|
/// 각 그랩이 스레드로 병렬처리 되므로, 모든 그랩 완료 후 이동을 보장받기 위해 그랩이 모두 끝날 때까지 기다린다.
|
|
/// </summary>
|
|
/// <param name="results">모든 그랩 결과</param>
|
|
private void WaitGrabMultiFinished(List<int> results) {
|
|
var timer = new Stopwatch();
|
|
int grabTimeOut = 300; // 300 ms
|
|
bool isGrabMultiFinished = false;
|
|
timer.Start();
|
|
|
|
while (true) {
|
|
foreach (int result in results) {
|
|
var distinctResults = results.Distinct().ToList(); // 중복이 제거된 그랩 결과
|
|
if (distinctResults.Count == 1) {
|
|
if (distinctResults[0] == E1.OK) {
|
|
isGrabMultiFinished = true;
|
|
break; // 그랩 결과가 모두 OK이면 성공
|
|
}
|
|
}
|
|
}
|
|
|
|
if (isGrabMultiFinished) {
|
|
break;
|
|
}
|
|
if (timer.ElapsedMilliseconds > grabTimeOut) {
|
|
LOG.FuncE($"Dry Run Grab Time-Out!! [{grabTimeOut} ms]");
|
|
break;
|
|
}
|
|
|
|
Thread.Sleep(10);
|
|
}
|
|
|
|
timer.Stop();
|
|
}
|
|
|
|
private SequenceActionResult MoveFovPos(eFovId fovId) {
|
|
int res = EquipAdapter.Instance.TeachingMotionManager.MovePosition(_Params.FovInfos[fovId], _Params.PositionType);
|
|
|
|
if (res == E1.OK) {
|
|
ApplyGrabDelay(_SubSysInfo);
|
|
return SequenceAction.Ok();
|
|
}
|
|
else {
|
|
return SequenceAction.Error(E2.ABORTED);
|
|
}
|
|
}
|
|
|
|
private SequenceActionResult SeqComplete(
|
|
SequenceContext context,
|
|
string id,
|
|
SequenceActionResult param) {
|
|
|
|
var alignResult = new AlignResult() {
|
|
AlignName = "DryRun",
|
|
Status = AlignStatus.DRY_RUN_OK,
|
|
DisplayType = _Params.DisplayType,
|
|
AlignAlgorithm = _AlignRecipe.ProcParams.AlignAlgorithm,
|
|
};
|
|
context.PutValue(string.Format(VisionContextKeys.CNTXT_KEY_ALIGN_RESULT, _Params.AlignInfo.GetKey()), alignResult);
|
|
|
|
return SequenceAction.Ok(alignResult);
|
|
}
|
|
|
|
void OnStopped(
|
|
SequenceContext context) {
|
|
LOG.I($"{context.SequenceId} - STOP Handler");
|
|
HandleAbnormalFinish(context);
|
|
}
|
|
|
|
void OnForceError(
|
|
SequenceContext context, string id) {
|
|
LOG.E($"{context.SequenceId} - FORCE ERROR Handler");
|
|
HandleAbnormalFinish(context);
|
|
}
|
|
|
|
void HandleAbnormalFinish(
|
|
SequenceContext context) {
|
|
}
|
|
}
|
|
} |