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 { /// /// 드라이런(Dry Run) 시퀀스 파라미터 /// public class AlignSeqParams_DryRun { /// 얼라인 키 정보 public AlignInfo AlignInfo { get; set; } /// FOV 키 정보 public Dictionary FovInfos { get; set; } /// 이동할 포지션 타입 public ePositionType PositionType { get; set; } /// 메인 화면 타입 public eDisplayType DisplayType { get; set; } /// FOV별로 이동시킬 절대위치 public Dictionary FovPositions { get; set; } /// /// 드라이런(Dry Run) 시퀀스 파라미터를 얻어온다. /// /// 얼라인 키 정보 /// FOV 키 정보 /// 포지션 타입 /// 메인 화면 타입 /// FOV별로 이동시킬 절대위치. null일 경우, 자동으로 Adapter에 정의된 티칭위치로 이동 public AlignSeqParams_DryRun( AlignInfo alignInfo, Dictionary fovInfos, ePositionType positionType = ePositionType.Teaching, eDisplayType displayType = eDisplayType.Main_1, Dictionary fovPositions = null) { this.AlignInfo = alignInfo; this.FovInfos = fovInfos; this.PositionType = positionType; this.DisplayType = displayType; this.FovPositions = fovPositions; } } /// /// 드라이런(Dry Run)을 위한 시퀀스 : 티칭 위치 이동 후 그랩만 수행 /// 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 /// /// 생성자 /// 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() { _Params.FovInfos[eFovId.Fov1], _Params.FovInfos[eFovId.Fov2] }); MoveFovPos(eFovId.Fov3); GrabMulti(new List() { _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 fovInfos) { var results = new List(); // 그룹 FOV 그랩 foreach (FovInfo fovInfo in fovInfos) { Task.Run(() => { results.Add(GrabSingle(fovInfo.FovId)); }); } WaitGrabMultiFinished(results); } private void GrabMulti() { var results = new List(); // 전체 FOV 그랩 foreach (FovInfo fovInfo in _Params.FovInfos.Values) { Task.Run(() => { results.Add(GrabSingle(fovInfo.FovId)); }); } WaitGrabMultiFinished(results); } /// /// 각 그랩이 스레드로 병렬처리 되므로, 모든 그랩 완료 후 이동을 보장받기 위해 그랩이 모두 끝날 때까지 기다린다. /// /// 모든 그랩 결과 private void WaitGrabMultiFinished(List 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) { } } }