using Aurora.Api; using Aurora.Api.Devices; using VisionCommon; using VisionAligner; using VisionCalibrator; using VisionSequence.Pattern; using VisionSequence.Inspector; using Hermes; using System.Collections.Generic; using System.Linq; using VisionInspector; using VisionCommonUI; using System; using VisionCommonUI.Resources; namespace VisionSequence.Aligner { /// /// C2_F2 얼라인 시퀀스 파라미터 /// public class AlignSeqParams_C2_F2 : SeqParamsBase { /// 얼라인 키 정보 public AlignInfo AlignInfo { get; set; } /// FOV별로 이동시킬 절대위치 public Dictionary FovPositions { get; set; } /// 메인 화면 타입 public eDisplayType DisplayType { get; set; } /// /// C2_F2 얼라인 시퀀스 파라미터를 얻어온다. /// /// 얼라인 키 정보 /// FOV별로 이동시킬 절대위치. null일 경우, 자동으로 Adapter에 정의된 티칭위치로 이동 /// 메인 화면 타입 /// 시퀀스 모드 public AlignSeqParams_C2_F2( AlignInfo alignInfo, Dictionary fovPositions = null, eDisplayType displayType = eDisplayType.Main_1, eSeqMode seqMode = eSeqMode.Auto) : base(seqMode) { this.AlignInfo = alignInfo; this.FovPositions = fovPositions; this.DisplayType = displayType; } } /// /// CAM 2대 / FOV 2개 / 포지션 이동 (X) / 2 Point Align / 2 MeasurePatterns to 2 ReferencePatterns /// public class AlignSeq_C2_F2 : SubSeqBase { private readonly Logger LOG = new Logger(typeof(AlignSeq_C2_F2).Name); private AlignSeqParams_C2_F2 _Params; private AlignRecipe _AlignRecipe; private SubSysInfo _SubSysInfo; private VisionAligner.Aligner _Aligner; private Calibrator _Calibrator; private Dictionary _FovInfos = new Dictionary(); private Dictionary _MeasureResults = new Dictionary(); private Dictionary _ReferenceResults = new Dictionary(); private string _SeqName; private bool _IsForceOk = false; #region Sequence Id private const string SEQ_ID_INIT = "INIT"; private const string SEQ_ID_CLEAR = "CLEAR"; private const string SEQ_ID_SET_REFERENCE = "SET_REFERENCE"; // FOV1, FOV2 동시 동작 private const string SEQ_ID_FORK = "FORK"; private const string SEQ_ID_SET_FIND_MEASURE_SEQ_PARAMS_1 = "SET_FIND_MEASURE_SEQ_PARAMS_1"; private const string SEQ_ID_FIND_MEASURE_SEQ_1 = "FIND_MEASURE_SEQ_1"; private const string SEQ_ID_CHECK_MEASURE_FOUND_1 = "CHECK_MEASURE_FOUND_1"; private const string SEQ_ID_SET_MEASURE_1 = "SET_MEASURE_1"; private const string SEQ_ID_SET_FIND_MEASURE_SEQ_PARAMS_2 = "SET_FIND_MEASURE_SEQ_PARAMS_2"; private const string SEQ_ID_FIND_MEASURE_SEQ_2 = "FIND_MEASURE_SEQ_2"; private const string SEQ_ID_CHECK_MEASURE_FOUND_2 = "CHECK_MEASURE_FOUND_2"; private const string SEQ_ID_SET_MEASURE_2 = "SET_MEASURE_2"; private const string SEQ_ID_JOIN = "JOIN"; private const string SEQ_ID_MARK_NG = "MARK_NG"; // FOV1, FOV2 패턴 거리 검사 private const string SEQ_ID_CHECK_PATTERN_DISTANCE_INSP_ENABLED = "CHECK_PATTERN_DISTANCE_INSP_ENABLED"; private const string SEQ_ID_SET_PATTERN_DISTANCE_INSP_SEQ_PARAMS = "SET_PATTERN_DISTANCE_INSP_SEQ_PARAMS"; private const string SEQ_ID_PATTERN_DISTANCE_INSP_SEQ = "PATTERN_DISTANCE_INSP_SEQ"; private const string SEQ_ID_CHECK_PATTERN_DISTANCE_INSP_STATUS = "CHECK_PATTERN_DISTANCE_INSP"; private const string SEQ_ID_DISTANCE_NG = "DISTANCE_NG"; private const string SEQ_ID_ALIGN = "ALIGN"; private const string SEQ_ID_SEQ_COMPLETE = "SEQ_COMPLETE"; #endregion /// /// 생성자 /// public AlignSeq_C2_F2() { } private void SetActions(SequenceBuilder sb) { SequenceBuilder grabFindProcSeqBuilder_1 = SubSeqManager.CreateSubSeqBuilder(new GrabFindProcSeq(), typeof(GrabFindProcSeq).Name); SequenceBuilder grabFindProcSeqBuilder_2 = SubSeqManager.CreateSubSeqBuilder(new GrabFindProcSeq(), typeof(GrabFindProcSeq).Name); SequenceBuilder patternDistanceInspSeqBuilder = SubSeqManager.CreateSubSeqBuilder(new InspSeq_PatternDistance(), typeof(InspSeq_PatternDistance).Name); sb.AddAction(SEQ_ID_INIT, Init); sb.AddAction(SEQ_ID_CLEAR, Clear); sb.AddAction(SEQ_ID_SET_REFERENCE, SetReference); // FOV1, FOV2 동시 동작 sb.AddFork(SEQ_ID_FORK); sb.AddAction(SEQ_ID_SET_FIND_MEASURE_SEQ_PARAMS_1, SetFindMeasureSeqParams); sb.AddSubsequence(SEQ_ID_FIND_MEASURE_SEQ_1, grabFindProcSeqBuilder_1); sb.AddDecision(SEQ_ID_CHECK_MEASURE_FOUND_1, CheckFound); sb.AddAction(SEQ_ID_SET_MEASURE_1, SetMeasure); sb.AddAction(SEQ_ID_SET_FIND_MEASURE_SEQ_PARAMS_2, SetFindMeasureSeqParams); sb.AddSubsequence(SEQ_ID_FIND_MEASURE_SEQ_2, grabFindProcSeqBuilder_2); sb.AddDecision(SEQ_ID_CHECK_MEASURE_FOUND_2, CheckFound); sb.AddAction(SEQ_ID_SET_MEASURE_2, SetMeasure); sb.AddJoin(SEQ_ID_JOIN); sb.AddAction(SEQ_ID_MARK_NG, MarkNG); // FOV1, FOV2 패턴 거리 검사 sb.AddDecision(SEQ_ID_CHECK_PATTERN_DISTANCE_INSP_ENABLED, CheckPatternDistanceInspEnabled); sb.AddAction(SEQ_ID_SET_PATTERN_DISTANCE_INSP_SEQ_PARAMS, SetPatternDistanceInspSeqParams); sb.AddSubsequence(SEQ_ID_PATTERN_DISTANCE_INSP_SEQ, patternDistanceInspSeqBuilder); sb.AddDecision(SEQ_ID_CHECK_PATTERN_DISTANCE_INSP_STATUS, CheckPatternDistanceInspStatus); sb.AddAction(SEQ_ID_DISTANCE_NG, DistanceNG); sb.AddAction(SEQ_ID_ALIGN, Align); 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_CLEAR] > sb[SEQ_ID_SET_REFERENCE] > sb[SEQ_ID_FORK] > sb[SEQ_ID_SET_FIND_MEASURE_SEQ_PARAMS_1] > sb[SEQ_ID_FIND_MEASURE_SEQ_1] // FOV1 패턴 찾기 > sb[SEQ_ID_CHECK_MEASURE_FOUND_1] > sb[SEQ_ID_SET_MEASURE_1] > sb[SEQ_ID_JOIN] > sb[SEQ_ID_CHECK_PATTERN_DISTANCE_INSP_ENABLED] > sb[SEQ_ID_SET_PATTERN_DISTANCE_INSP_SEQ_PARAMS] // FOV1, FOV2 패턴 거리 검사 > sb[SEQ_ID_PATTERN_DISTANCE_INSP_SEQ] > sb[SEQ_ID_CHECK_PATTERN_DISTANCE_INSP_STATUS] > sb[SEQ_ID_ALIGN] > sb[SEQ_ID_SEQ_COMPLETE] ); sb.Flows( sb[SEQ_ID_FORK] > sb[SEQ_ID_SET_FIND_MEASURE_SEQ_PARAMS_2] > sb[SEQ_ID_FIND_MEASURE_SEQ_2] // FOV2 패턴 찾기 > sb[SEQ_ID_CHECK_MEASURE_FOUND_2] > sb[SEQ_ID_SET_MEASURE_2] > sb[SEQ_ID_JOIN] ); sb.Flows( sb[SEQ_ID_CHECK_MEASURE_FOUND_1] // FOV1 마크 NG > sb[SEQ_ID_MARK_NG] > sb[SEQ_ID_SEQ_COMPLETE] ); sb.Flows( sb[SEQ_ID_CHECK_MEASURE_FOUND_1] // Node Error > sb[SEQ_ID_SEQ_COMPLETE] ); sb.Flows( sb[SEQ_ID_CHECK_MEASURE_FOUND_2] // FOV2 마크 NG > sb[SEQ_ID_MARK_NG] > sb[SEQ_ID_SEQ_COMPLETE] ); sb.Flows( sb[SEQ_ID_CHECK_MEASURE_FOUND_2] // Node Error > sb[SEQ_ID_SEQ_COMPLETE] ); sb.Flows( sb[SEQ_ID_CHECK_PATTERN_DISTANCE_INSP_ENABLED] // 패턴 거리 검사 Skip후, Align > sb[SEQ_ID_ALIGN] ); sb.Flows( sb[SEQ_ID_CHECK_PATTERN_DISTANCE_INSP_STATUS] // FOV1, FOV2 패턴 거리 검사 NG > sb[SEQ_ID_DISTANCE_NG] > 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_C2_F2; } else { LOG.E($"Param is null."); return null; } _IsForceOk = false; _AlignRecipe = VisionRecipeManager.GetAlignRecipe(_Params.AlignInfo); _SubSysInfo = _Params.AlignInfo.ToSubSysInfo(); _Aligner = AlignAgentManager.GetAlignAgent(_Params.AlignInfo); SetFovInfos(); _Calibrator = CalibratorManager.GetCalibrator(_FovInfos[eFovId.Fov1]); return SequenceAction.Ok(); } private void SetFovInfos() { foreach (FovInfo fovInfo in VisionRecipeManager.GetFovInfos(_SubSysInfo)) { if (!_FovInfos.ContainsKey(fovInfo.FovId)) { _FovInfos.Add(fovInfo.FovId, fovInfo); } } } private SequenceActionResult Clear( SequenceContext context, string id, SequenceActionResult param) { _MeasureResults.Clear(); _ReferenceResults.Clear(); return SequenceAction.Ok(); } private SequenceActionResult SetReference( SequenceContext context, string id, SequenceActionResult param) { foreach (var fovInfoPair in _FovInfos) { eFovId fovId = fovInfoPair.Key; var refMaterialPos = VisionRecipeManager.GetRefPoint(_SubSysInfo, fovId); _ReferenceResults.Add( fovId, new BaseResult() { MaterialPosition = refMaterialPos.Clone() as StaticPoint }); } return SequenceAction.Ok(); } private SequenceActionResult SetFindMeasureSeqParams( SequenceContext context, string id, SequenceActionResult param) { eFovId curFovId = eFovId.None; switch (id) { case SEQ_ID_SET_FIND_MEASURE_SEQ_PARAMS_1: curFovId = eFovId.Fov1; break; case SEQ_ID_SET_FIND_MEASURE_SEQ_PARAMS_2: curFovId = eFovId.Fov2; break; } var procPatternInfo = VisionRecipeManager.GetProcPatternInfo(_FovInfos[curFovId], _AlignRecipe.AlignId.ToString(), eProcPatternId.ProcPattern1); var fovRecipe = VisionRecipeManager.GetFovRecipe(_FovInfos[curFovId]); var patternAgent = FovPatternAgentManager.GetAgent(_SubSysInfo); PatternIndex patternIndex = null; if (procPatternInfo.IsFovPattern) { patternIndex = new FovPatternIndex(_FovInfos[curFovId], fovRecipe.FovName, procPatternInfo.PatternId); } else { patternAgent = CamPatternAgentManager.GetAgent(fovRecipe.CamRecipe.CamId); patternIndex = new CamPatternIndex(fovRecipe.CamRecipe.CamId, procPatternInfo.PatternId); } PatternInfo patternInfo = patternAgent.GetPatternInfo(patternIndex); patternInfo.PatternName = procPatternInfo.PatternName; return SequenceAction.Ok(new GrabFindProcSeqParams(_FovInfos[curFovId], patternInfo, _Params.DisplayType, _Params.SeqMode)); } private string CheckFound( SequenceContext context, string id, ICollection branches, SequenceActionResult param) { var patternResult = param.Param as PatternResult; if (patternResult.Status != eFoundStatus.NotFound) { if (patternResult.Status == eFoundStatus.ForceOK) { _IsForceOk = true; } switch (patternResult.FovId) { case eFovId.Fov1: return SEQ_ID_SET_MEASURE_1; case eFovId.Fov2: return SEQ_ID_SET_MEASURE_2; } } else { return SEQ_ID_MARK_NG; } LOG.FuncE("CheckFound Node Error!!"); return SEQ_ID_SEQ_COMPLETE; } private SequenceActionResult SetMeasure( SequenceContext context, string id, SequenceActionResult param) { // Param : PatternResult try { var patternResult = param.Param as PatternResult; var baseResults = patternResult.Results.ToList(); _MeasureResults.Add(patternResult.FovId, baseResults[0]); } catch (Exception e) { LOG.FuncE(e.Message); } return SequenceAction.Ok(); } private SequenceActionResult MarkNG( SequenceContext context, string id, SequenceActionResult param) { context.PutValue( string.Format(VisionContextKeys.CNTXT_KEY_ALIGN_RESULT, _Params.AlignInfo.GetKey()), new AlignResult() { AlignName = _AlignRecipe.AlignName, Status = AlignStatus.NOT_FOUND, AlignAlgorithm = _AlignRecipe.ProcParams.AlignAlgorithm, }); return SequenceAction.Ok(); } #region 패턴 간에 거리 검사 private string CheckPatternDistanceInspEnabled( SequenceContext context, string id, ICollection branches, SequenceActionResult param) { if (_AlignRecipe.InspParams.PatternDistanceParam.Enabled) { return SEQ_ID_SET_PATTERN_DISTANCE_INSP_SEQ_PARAMS; } else { return SEQ_ID_ALIGN; } } private SequenceActionResult SetPatternDistanceInspSeqParams( SequenceContext context, string id, SequenceActionResult param) { return SequenceAction.Ok( new InspSeqParams_PatternDistance(_Params.AlignInfo, _MeasureResults)); } private string CheckPatternDistanceInspStatus( SequenceContext context, string id, ICollection branches, SequenceActionResult param) { // Param : List var patternDistanceResults = param.Param as List; foreach (PatternDistanceResult result in patternDistanceResults) { if (result.InspStatus == InspStatus.NG) { return SEQ_ID_DISTANCE_NG; } } return SEQ_ID_ALIGN; } private SequenceActionResult DistanceNG( SequenceContext context, string id, SequenceActionResult param) { context.PutValue( string.Format(VisionContextKeys.CNTXT_KEY_ALIGN_RESULT, _Params.AlignInfo.GetKey()), new AlignResult() { AlignName = _AlignRecipe.AlignName, Status = AlignStatus.DISTANCE_NG, AlignAlgorithm = _AlignRecipe.ProcParams.AlignAlgorithm, }); return SequenceAction.Ok(); } #endregion private SequenceActionResult Align( SequenceContext context, string id, SequenceActionResult param) { var meaPoints = new List(); var refPoints = new List(); _MeasureResults = _MeasureResults.OrderBy(obj => obj.Key).ToDictionary(obj => obj.Key, obj => obj.Value); foreach (var meaResultPair in _MeasureResults) { meaPoints.Add((meaResultPair.Value as BaseResult).MaterialPosition); foreach (var refResultPair in _ReferenceResults) { if (refResultPair.Key == meaResultPair.Key) { refPoints.Add((refResultPair.Value as BaseResult).MaterialPosition); break; } } } var flipY = (int)_Calibrator.GetFlipY(); var alignResult = _Aligner.Align(meaPoints, refPoints, flipY); if (alignResult == null) { return SequenceAction.Error(); } else { context.PutValue(string.Format(VisionContextKeys.CNTXT_KEY_ALIGN_RESULT, _Params.AlignInfo.GetKey()), alignResult); } return SequenceAction.Ok(alignResult); } private SequenceActionResult SeqComplete( SequenceContext context, string id, SequenceActionResult param) { AlignResult alignResult = context.GetValue(string.Format(VisionContextKeys.CNTXT_KEY_ALIGN_RESULT, _Params.AlignInfo.GetKey())); if (alignResult == null) { return SequenceAction.Error(); } alignResult.AlignName = _AlignRecipe.AlignName; if (_IsForceOk && alignResult.Status == AlignStatus.OK) { alignResult.Status = AlignStatus.F_OK; } if (_MeasureResults.Keys.Count > 0) { context.PutValue(string.Format(VisionContextKeys.CNTXT_KEY_LAST_MEASURE_FOV_ID, _Params.AlignInfo.GetKey()), _MeasureResults.Keys.ToList().Max()); } 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) { } } }