2026-06-05 13:44:39 +09:00

318 lines
11 KiB
C#

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.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);
}
}
}