328 lines
12 KiB
C#
328 lines
12 KiB
C#
/*
|
|
* Copyright (c) 2025 LG Electronics Inc.
|
|
* SPDX-License-Identifier: LicenseRef-LGE-Proprietary
|
|
*/
|
|
using Aurora.Api;
|
|
using VisionLight;
|
|
using VisionCommon;
|
|
using Hermes;
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Reactive.Linq;
|
|
using VisionSequence.Pattern;
|
|
using Aurora.View;
|
|
|
|
namespace VisionSequence.Camera {
|
|
/// <summary>
|
|
/// 카메라 그랩 시퀀스 파라미터
|
|
/// </summary>
|
|
public class GrabSeqParams : GrabFindProcSeqParams {
|
|
/// <summary>
|
|
/// 그랩 시퀀스 파라미터 생성자
|
|
/// </summary>
|
|
/// <param name="fovInfo">FOV 키 정보</param>
|
|
/// <param name="patternInfo">패턴 정보</param>
|
|
/// <param name="displayType">메인 화면 타입</param>
|
|
/// <param name="seqMode">매뉴얼 시퀀스 플래그</param>
|
|
public GrabSeqParams(
|
|
FovInfo fovInfo,
|
|
PatternInfo patternInfo,
|
|
eDisplayType displayType = eDisplayType.Main_1,
|
|
eSeqMode seqMode = eSeqMode.Auto) : base(fovInfo, patternInfo, displayType, seqMode) {
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 카메라 그랩 시퀀스
|
|
/// </summary>
|
|
public class GrabSeq : SubSeqBase, IDisposable {
|
|
private readonly Logger LOG = new Logger("GrabSeq");
|
|
private GrabSeqParams _Params;
|
|
private FovRecipe _FovRecipe;
|
|
private CamConfig _CamConfig;
|
|
private CameraAgentBase _CameraAgent;
|
|
private ICameraDisplay _CameraDisplay;
|
|
private object _GrabImage = null;
|
|
|
|
#region Sequence Id
|
|
private const string SEQ_ID_INIT = "INIT";
|
|
private const string SEQ_ID_CHECK_GRAB_DONE = "CHECK_GRAB_DONE";
|
|
private const string SEQ_ID_LIGHT = "LIGHT";
|
|
private const string SEQ_ID_LIGHT_NG = "LIGHT_NG";
|
|
private const string SEQ_ID_GRAB = "GRAB";
|
|
private const string SEQ_ID_GRAB_NG = "GRAB_NG";
|
|
private const string SEQ_ID_SET_IMAGE_IN_OTHER_DISPLAY = "SET_IMAGE_IN_OTHER_DISPLAY";
|
|
private const string SEQ_ID_SEQ_COMPLETE = "SEQ_COMPLETE";
|
|
#endregion
|
|
|
|
/// <summary>
|
|
/// 생성자
|
|
/// </summary>
|
|
public GrabSeq() {
|
|
}
|
|
|
|
private void SetActions(SequenceBuilder sb) {
|
|
sb.AddAction(SEQ_ID_INIT, Init);
|
|
sb.AddDecision(SEQ_ID_CHECK_GRAB_DONE, CheckGrabDone);
|
|
sb.AddDecision(SEQ_ID_LIGHT, SetLight);
|
|
sb.AddAction(SEQ_ID_LIGHT_NG, LightNG);
|
|
sb.AddDecision(SEQ_ID_GRAB, Grab);
|
|
sb.AddAction(SEQ_ID_GRAB_NG, GrabNG);
|
|
sb.AddAction(SEQ_ID_SET_IMAGE_IN_OTHER_DISPLAY, SetImageInOtherDisplay);
|
|
sb.AddAction(SEQ_ID_SEQ_COMPLETE, SeqComplete);
|
|
}
|
|
|
|
public override SequenceBuilder Builder(string 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_CHECK_GRAB_DONE]
|
|
> sb[SEQ_ID_LIGHT]
|
|
> sb[SEQ_ID_GRAB]
|
|
> sb[SEQ_ID_SET_IMAGE_IN_OTHER_DISPLAY]
|
|
> sb[SEQ_ID_SEQ_COMPLETE]
|
|
> sb.Final
|
|
);
|
|
sb.Flows(
|
|
sb[SEQ_ID_LIGHT]
|
|
> sb[SEQ_ID_LIGHT_NG]
|
|
> sb.ForceError
|
|
);
|
|
sb.Flows(
|
|
sb[SEQ_ID_GRAB]
|
|
> sb[SEQ_ID_GRAB_NG]
|
|
> sb.ForceError
|
|
);
|
|
sb.Flows(
|
|
sb[SEQ_ID_CHECK_GRAB_DONE]
|
|
> sb[SEQ_ID_SEQ_COMPLETE]
|
|
);
|
|
|
|
#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 GrabSeqParams;
|
|
}
|
|
else {
|
|
LOG.E($"_Params is null.");
|
|
return null;
|
|
}
|
|
|
|
_FovRecipe = VisionRecipeManager.GetFovRecipe(_Params.FovInfo);
|
|
_CameraDisplay = CameraDisplayManager.GetDisplay(_Params.FovInfo, _Params.DisplayType);
|
|
|
|
SetCameraAgent();
|
|
SetCamConfig();
|
|
|
|
return SequenceAction.Ok();
|
|
}
|
|
|
|
private void SetCameraAgent() {
|
|
_CameraAgent = CameraAgentManager.GetCameraAgent(_Params.FovInfo);
|
|
}
|
|
|
|
private void SetCamConfig() {
|
|
var camRecipe = VisionRecipeManager.GetCamRecipe(_Params.FovInfo);
|
|
_CamConfig = VisionEnv.AuroraEnv.DeviceManager.GetDeviceConfig(camRecipe.CamId.ToString()) as CamConfig;
|
|
}
|
|
|
|
// 사용하는 곳에서 그랩 버퍼 할당, 디바이스에서는 복사본 전달
|
|
private void InitGrabImageBuffer() {
|
|
_GrabImage = GrabFindSeqUtil.GetProcGrabImage(_Params.FovInfo, _Params.PatternInfo.LightInfo);
|
|
}
|
|
|
|
private string CheckGrabDone(
|
|
SequenceContext context,
|
|
string id,
|
|
ICollection<string> branches,
|
|
SequenceActionResult param) {
|
|
|
|
// IsGrabDone 체크 후, GetGrabImage를 수행해야 한다.
|
|
var isGrabDone = GrabFindSeqUtil.IsProcGrabDone(_Params.FovInfo, _Params.PatternInfo.LightInfo);
|
|
InitGrabImageBuffer();
|
|
|
|
if (_Params.SeqMode == eSeqMode.Manual || !isGrabDone) {
|
|
return SEQ_ID_LIGHT;
|
|
}
|
|
|
|
_GrabImage = GrabFindSeqUtil.GetProcGrabImage(_Params.FovInfo, _Params.PatternInfo.LightInfo);
|
|
SetGrabImage(context, _GrabImage);
|
|
|
|
return SEQ_ID_SEQ_COMPLETE;
|
|
}
|
|
|
|
#region Set Params
|
|
private string SetLight(
|
|
SequenceContext context,
|
|
string id,
|
|
ICollection<string> branches,
|
|
SequenceActionResult param) {
|
|
|
|
int chCnt = _Params.PatternInfo.LightInfo.LightParams.Count;
|
|
if (chCnt == 0) {
|
|
string errMsg = "The count of PatternInfo.LightInfo.LightParams is zero.";
|
|
PrintErrorLogAndShowErrorToast(LOG, errMsg);
|
|
|
|
return SEQ_ID_LIGHT_NG;
|
|
}
|
|
|
|
eLightResult res = LightHub.Instance.SetLevels(_Params.PatternInfo.LightInfo.LightParams);
|
|
if (res == eLightResult.NG) {
|
|
string errMsg = "Failed to set light levels.";
|
|
PrintErrorLogAndShowErrorToast(LOG, errMsg);
|
|
|
|
return SEQ_ID_LIGHT_NG;
|
|
}
|
|
|
|
return SEQ_ID_GRAB;
|
|
}
|
|
|
|
private SequenceActionResult LightNG(
|
|
SequenceContext context,
|
|
string id,
|
|
SequenceActionResult param) {
|
|
|
|
LOG.FuncE("Light NG!!");
|
|
EquipAdapter.Instance.VisionAlarm.SetAlarm(eVisionAlarmCode.LIGHT_SET_ERROR);
|
|
|
|
return SequenceAction.Error(E1.GENERIC, null);
|
|
}
|
|
|
|
private string Grab(
|
|
SequenceContext context,
|
|
string id,
|
|
ICollection<string> branches,
|
|
SequenceActionResult param) {
|
|
|
|
_CameraDisplay.SetVisibility();
|
|
if (_GrabImage == null) {
|
|
return SEQ_ID_GRAB_NG;
|
|
}
|
|
|
|
int result = E1.GENERIC;
|
|
bool isProcExtTrig = false; // 공정 중 외부 트리거 여부
|
|
|
|
if (_Params.SeqMode == eSeqMode.VisionImageTest) {
|
|
var visionImageTester = VisionImageTesterManagerBase.GetVisionImageTester(_Params.FovInfo);
|
|
result = visionImageTester.GetCurrentImage(_CameraDisplay, ref _GrabImage);
|
|
}
|
|
else {
|
|
if (_Params.SeqMode == eSeqMode.Auto) {
|
|
if (_CamConfig.TriggerMode.IsExternal) {
|
|
isProcExtTrig = true;
|
|
}
|
|
}
|
|
|
|
if (isProcExtTrig) {
|
|
result = _CameraAgent.GetGrabImageFromBuffer(_CameraDisplay, ref _GrabImage); // 공정 중 외부(버퍼)에서 트리거 발생
|
|
var camDev = _CameraAgent.GetDevice();
|
|
camDev.SetHookCompletedByExtTrig(false);
|
|
}
|
|
else {
|
|
result = _CameraAgent.GrabSync(_CameraDisplay, ref _GrabImage); // 그 외 경우 Aurora에서 트리거 발생
|
|
}
|
|
}
|
|
|
|
if (result != E1.OK) {
|
|
SetGrabImage(context, null);
|
|
return SEQ_ID_GRAB_NG;
|
|
}
|
|
else {
|
|
SetGrabImage(context, _GrabImage);
|
|
return SEQ_ID_SET_IMAGE_IN_OTHER_DISPLAY;
|
|
}
|
|
}
|
|
|
|
private void SetGrabImage(SequenceContext context, object grabImage) {
|
|
GrabFindSeqUtil.SetProcGrabImage(_Params.FovInfo, _Params.PatternInfo.LightInfo, grabImage);
|
|
context.PutValue(string.Format(VisionContextKeys.CNTXT_KEY_GRAB_IMAGE, _Params.FovInfo.GetKey()), grabImage);
|
|
}
|
|
|
|
private SequenceActionResult GrabNG(
|
|
SequenceContext context,
|
|
string id,
|
|
SequenceActionResult param) {
|
|
|
|
LOG.FuncE("Grab NG!!");
|
|
EquipAdapter.Instance.VisionAlarm.SetAlarm(eVisionAlarmCode.CAMERA_GRAB_ERROR);
|
|
|
|
return SequenceAction.Error(E1.GENERIC, null);
|
|
}
|
|
|
|
/// <summary>
|
|
/// 같은 카메라에 대한 다른 메인 디스플레이 군에도 이미지를 Set해준다.
|
|
/// </summary>
|
|
private SequenceActionResult SetImageInOtherDisplay(
|
|
SequenceContext context,
|
|
string id,
|
|
SequenceActionResult param) {
|
|
|
|
int result = E1.GENERIC;
|
|
if (_GrabImage != null && CamCommon.IsMainType(_Params.DisplayType)) {
|
|
foreach (var mainUiRecipe in _FovRecipe.MainUiRecipes) {
|
|
if (mainUiRecipe.MainDisplayType != _Params.DisplayType && mainUiRecipe.FovUiPos != eFovUiPos.None) {
|
|
var cameraDisplay = CameraDisplayManager.GetDisplay(_Params.FovInfo, mainUiRecipe.MainDisplayType);
|
|
result = cameraDisplay.SetImage(_GrabImage);
|
|
if (!result.Equals(E1.OK)) {
|
|
return SequenceAction.Error();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return SequenceAction.Ok();
|
|
}
|
|
#endregion
|
|
|
|
private SequenceActionResult SeqComplete(
|
|
SequenceContext context,
|
|
string id,
|
|
SequenceActionResult param) {
|
|
|
|
var grabImage = context.GetValue<object>(string.Format(VisionContextKeys.CNTXT_KEY_GRAB_IMAGE, _Params.FovInfo.GetKey()));
|
|
if (grabImage == null) {
|
|
LOG.FuncE($"[{_Params.FovInfo.SubSysName}][{_FovRecipe.FovName}] grabImage is null.");
|
|
return SequenceAction.Error(E1.ARGUMENT, grabImage);
|
|
}
|
|
|
|
return SequenceAction.Ok(grabImage);
|
|
}
|
|
|
|
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) {
|
|
}
|
|
|
|
/// <summary>
|
|
/// 이미지 버퍼 명시적 메모리 해제
|
|
/// </summary>
|
|
public void Dispose() {
|
|
IpAdapter.Instance.IpEnvironment.FreeImage(_GrabImage);
|
|
}
|
|
}
|
|
} |