2026-01-26 18:56:53 +09:00

319 lines
14 KiB
C#

/*
* Copyright (c) 2025 LG Electronics Inc.
* SPDX-License-Identifier: LicenseRef-LGE-Proprietary
*/
using Aurora.Api;
using Aurora.Api.DataType;
using PropertyTools.DataAnnotations;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
namespace VisionCommon {
/// <summary>
/// 카메라 디바이스 모델 리스트
/// </summary>
public enum eCamModel {
DEFAULT, // 공용 카메라 디바이스 사용 (AuroraVision에서 정의한 카메라 디바이스)
MachineCamera_A = 50, // 장비 전용 카메라 디바이스 A
MachineCamera_B, // 장비 전용 카메라 디바이스 B
MachineCamera_C // 장비 전용 카메라 디바이스 C
}
/// <summary>
/// 그래버 유형
/// </summary>
public enum eBoardType {
Mock, // Mock Camera
MIL_GIGE, // MIL GigE
MIL_CL_SOLIOS, // MIL CameraLink
MIL_CXP_RADIENT, // MIL CoaXPress
MIL_CXP_RAPIXO, // MIL CoaXPress
COGNEX_GIGE, // Cognex GigE
EURESYS_GIGELINK, // Euresys GigELink (With MIL Image Processing)
EURESYS_COAXLINK, // Euresys CoaxLink (With MIL Image Processing)
EURESYS_GRABLINK, // Euresys GrabLink (With MIL Image Processing)
}
/// <summary>
/// 그래버 슬롯 위치 (MIL에서 Auto 인덱싱 해줌에 주의)
/// </summary>
public enum eBoardSlotPos {
M_DEV0 = 0, // MIL - M_DEV0
M_DEV1 = 1, // MIL - M_DEV1
M_DEV2 = 2, // MIL - M_DEV2
M_DEV3 = 3, // MIL - M_DEV3
M_DEV4 = 4, // MIL - M_DEV4
M_DEV5 = 5, // MIL - M_DEV5
}
/// <summary>
/// 그래버 포트 위치 (MIL에서 Auto 인덱싱 해줌에 주의)
/// </summary>
public enum eBoardPortPos {
M_DEV0 = 0, // MIL - M_DEV0
M_DEV1 = 1, // MIL - M_DEV1
M_DEV2 = 2, // MIL - M_DEV2
M_DEV3 = 3, // MIL - M_DEV3
M_DEV4 = 4, // MIL - M_DEV4
M_DEV5 = 5, // MIL - M_DEV5
M_DEV6 = 6, // MIL - M_DEV6
M_DEV7 = 7 // MIL - M_DEV7
}
/// <summary>
/// 카메라 트리거 유형
/// </summary>
public enum eTrigType {
HW, // Hardware Trigger (External Trigger)
SW // Software Trigger (Internal Trigger)
}
/// <summary>
/// 카메라 트리거 발생 주체
/// </summary>
public enum eTrigSubject {
/// <summary>트리거 발생 주체가 외부(버퍼) 프로그램인 경우</summary>
External,
/// <summary>트리거 발생 주체가 Aurora인 경우</summary>
Internal
}
/// <summary>
/// GenICam "TriggerSource" Features
/// </summary>
public enum eTrigSrc {
Software,
Line0,
Line1,
Line2,
Line3,
Line4,
Line5,
LinkTrigger0, // 유레시스 용
LinkTrigger1, // 유레시스 용
LinkTrigger2, // 유레시스 용
LinkTrigger3, // 유레시스 용
LinkTrigger4, // 유레시스 용
LinkTrigger5, // 유레시스 용
CXPin,
}
public class CamConnConfig {
[SelectorStyle(SelectorStyle.ComboBox)]
public eBoardType BoardType { get; set; } = eBoardType.MIL_GIGE;
[SelectorStyle(SelectorStyle.ComboBox)]
public eBoardSlotPos BoardSlotPos { get; set; } = eBoardSlotPos.M_DEV0;
[SelectorStyle(SelectorStyle.ComboBox)]
public eBoardPortPos BoardPortPos { get; set; } = eBoardPortPos.M_DEV0;
/// <summary>
/// MIL : *.dcf 파일로 카메라 연결. EX) "D:\\Aurora\\DcfFiles\\CAM1.dcf"
/// Euresys : *.cti 파일로 카메라 연결. EX) "C:\\Program Files\\Euresys\\eGrabber\\cti\\x86_64\\gigelink.cti"
/// </summary>
[InputFilePath]
public string ConnFilePath { get; set; } = ""; // MIL DCF파일로 카메라를 연결할 경우 사용. EX) "D:\\Aurora\\DcfFiles\\CAM1.dcf"
public string IpAddress { get; set; } = ""; // GigE 고정 IP로 카메라를 연결할 경우 사용. EX) "100.100.200.10"
}
#region For Child Image Buffer
public class ChildBufRowCol : ICloneable {
public bool Enabled { get; set; } = true; // 버퍼 할당 유무
public int RowIdx { get; set; } = 0; // 행 인덱스
public int ColIdx { get; set; } = 0; // 열 인덱스
public int PosIdx { get; set; } = 0; // 위치 인덱스
public MotionPoint MotorPos { get; set; } = new MotionPoint(); // 모터 위치 X,Y
public MotionPoint MotorPosOffset { get; set; } = new MotionPoint(); // 모터 위치 오프셋 X,Y
public Rectangle Rect { get; set; } = new Rectangle(); // Child 이미지 영역 위치 & 사이즈
public object Clone() {
return new ChildBufRowCol() {
Enabled = this.Enabled,
RowIdx = this.RowIdx,
ColIdx = this.ColIdx,
PosIdx = this.PosIdx,
MotorPos = this.MotorPos.Clone() as MotionPoint,
MotorPosOffset = this.MotorPosOffset.Clone() as MotionPoint,
Rect = new Rectangle(this.Rect.X, this.Rect.Y, this.Rect.Width, this.Rect.Height)
};
}
}
public class ChildImage : ICloneable {
public bool Enabled { get; set; } = false; // Child 이미지 버퍼 사용 유무
public int RowCnt { get; set; } = 1; // 행 개수
public int ColCnt { get; set; } = 1; // 열 개수
public List<ChildBufRowCol> ChildBufRowCols { get; set; } = new List<ChildBufRowCol>(); // Child 이미지 버퍼 행/열 위치 정보
public object Clone() {
return new ChildImage() {
Enabled = this.Enabled,
RowCnt = this.RowCnt,
ColCnt = this.ColCnt,
ChildBufRowCols = this.ChildBufRowCols.ConvertAll(o => o.Clone() as ChildBufRowCol)
};
}
/// <summary>
/// 활성화된 모터 위치 인덱스 기준으로 오름차순 정렬된 Child 객체 리스트 가져오기
/// </summary>
/// <returns>활성화된 모터 위치 인덱스 기준으로 오름차순 정렬된 Child 객체 리스트</returns>
public List<ChildBufRowCol> GetSortedChildBufRowCols() {
var childBufRowCol = this.ChildBufRowCols.Where(o => o.Enabled == true).OrderBy(o => o.PosIdx).ToList();
return childBufRowCol;
}
}
#endregion
public class FlipAndRotation : ICloneable {
public eImageFlip ImageFlip { get; set; } = eImageFlip.None; // 반전 (좌우 or 상하)
public eImageRotation ImageRotation { get; set; } = eImageRotation.None; // 회전 (0, 90, 180, 270)
public double ImageRotationOffset { get; set; } = 0; // 회전 ImageRotation을 기준으로 +/- 각도 Offset 적용
public object Clone() {
return new FlipAndRotation() {
ImageFlip = this.ImageFlip,
ImageRotation = this.ImageRotation,
ImageRotationOffset = this.ImageRotationOffset
};
}
}
public class SetupDirection : ICloneable {
public int RotationX { get; set; } = 0;
public eFlipY FlipY { get; set; } = eFlipY.False;
public eDirection DirectionT { get; set; } = eDirection.Plus;
public object Clone() {
return new SetupDirection() {
RotationX = this.RotationX,
FlipY = this.FlipY
};
}
public CoordSystem ToCoordSystem() {
return new CoordSystem(Angle.CreateWithDegree(RotationX), FlipY, DirectionT);
}
}
/// <summary>
/// 이미지 취득을 위한 카메라 트리거 모드 관리
/// </summary>
public class TriggerMode : ICloneable {
public bool IsSoftware { get; set; } = true; // True : SW트리거 그랩 / False : HW트리거 그랩 (One-Shot 트리거 API 사용)
public bool IsExternal { get; set; } = false; // True : 외부 트리거 사용 / False : 외부 트리거 미사용 / *외부 : 버퍼 프로그램
public bool IsFlying { get; set; } = false; // True : Flying 그랩 사용 / False : Flying 그랩 미사용
public object Clone() {
return new TriggerMode() {
IsSoftware = this.IsSoftware,
IsExternal = this.IsExternal,
IsFlying = this.IsFlying
};
}
}
public class HwTrigConfig {
public eTrigSubject TrigSubject { get; set; } = eTrigSubject.Internal;
public int OutIdx { get; set; } = 5632; // FlexAttach CAM1 예시
public int OutPort { get; set; } = 22; // OutIdx에서 변환 가능 : (OutIdx & 0xFF00) >> 8
public int OutBit { get; set; } = 0; // OutIdx에서 변환 가능 : OutIdx & 0x00FF
public int OffDelay_Ms { get; set; } = 10;
public int ProcBufSize { get; set; } = 10; // HwTrigger CallBack 핸들러 버퍼 사이즈 (플라잉 모드시에는 플라잉 트리거 횟수로 사용)
}
public class CamConfig : IDeviceConfig, ICloneCopy<CamConfig> {
public string Name { get; set; } = string.Empty;
[SelectorStyle(SelectorStyle.ComboBox)]
public eCamModel CamModel { get; set; } = eCamModel.DEFAULT; // 공용 카메라 디바이스를 사용할지, 아니면 장비 전용 카메라 디바이스를 사용할지 결정
public IConnConfig ConnConfig { get; set; }
public CamConnConfig CamConnConfig { get; set; } = new CamConnConfig();
public eTrigSrc TrigSrc { get; set; } = eTrigSrc.Software;
public TriggerMode TriggerMode { get; set; } = new TriggerMode();
public HwTrigConfig HwTrigConfig { get; set; } = new HwTrigConfig();
public ImageSize ImageSize { get; set; }
public double ImageSizeRatioX { get; set; } = 1; // 원본 사이즈 대비 가로 비율. EX) 1이면 정사이즈, 0.5이면 1/2크기, RatioX,Y가 모두 0.5이면 이미지는 1/4크기가 됨.
public double ImageSizeRatioY { get; set; } = 1; // 원본 사이즈 대비 세로 비율. EX) 1이면 정사이즈, 0.5이면 1/2크기, RatioX,Y가 모두 0.5이면 이미지는 1/4크기가 됨.
public ChildImage ChildImage { get; set; } = new ChildImage();
public FlipAndRotation FlipAndRotation { get; set; } = new FlipAndRotation();
public double ExposureTime_Ms { get; set; } = 30; // 단위 : ms
public int LiveDelay_Ms { get; set; } = 50; // 단위 : ms
public int GrabRetry { get; set; } = 3;
public int GrabTimeout_Ms { get; set; } = 300; // 단위 : ms
public SetupDirection SetupDirection { get; set; } = new SetupDirection();
public static IDeviceConfig GetDefaultConfig() => new CamConfig();
public CamConfig() {
ImageSize = new ImageSize() {
Width = 2448, // 단위 : pixel
Height = 2048, // 단위 : pixel
Channel = 1, // 1 : Gray, 3 : Color(RGB)
BitDepth = 8 // 단위 : bit
};
}
public CamConfig Clone() {
return ((ICloneable)this).Clone() as CamConfig;
}
object ICloneable.Clone() {
var cloneObj = new CamConfig();
CopyTo(cloneObj);
return cloneObj;
}
public void CopyTo(CamConfig target) {
target.Name = this.Name;
target.CamConnConfig = new CamConnConfig() {
BoardType = this.CamConnConfig.BoardType,
BoardSlotPos = this.CamConnConfig.BoardSlotPos,
BoardPortPos = this.CamConnConfig.BoardPortPos,
ConnFilePath = this.CamConnConfig.ConnFilePath,
IpAddress = this.CamConnConfig.IpAddress
};
target.TrigSrc = this.TrigSrc;
target.TriggerMode = this.TriggerMode.Clone() as TriggerMode;
target.HwTrigConfig = new HwTrigConfig() {
TrigSubject = this.HwTrigConfig.TrigSubject,
OutIdx = this.HwTrigConfig.OutIdx,
OutPort = this.HwTrigConfig.OutPort,
OutBit = this.HwTrigConfig.OutBit,
OffDelay_Ms = this.HwTrigConfig.OffDelay_Ms,
ProcBufSize = this.HwTrigConfig.ProcBufSize,
};
target.ImageSize = new ImageSize() {
Width = this.ImageSize.Width,
Height = this.ImageSize.Height,
Channel = this.ImageSize.Channel,
BitDepth = this.ImageSize.BitDepth,
};
target.ImageSizeRatioX = this.ImageSizeRatioX;
target.ImageSizeRatioY = this.ImageSizeRatioY;
target.ChildImage = this.ChildImage.Clone() as ChildImage;
target.FlipAndRotation = this.FlipAndRotation.Clone() as FlipAndRotation;
target.ExposureTime_Ms = this.ExposureTime_Ms;
target.LiveDelay_Ms = this.LiveDelay_Ms;
target.GrabRetry = this.GrabRetry;
target.GrabTimeout_Ms = this.GrabTimeout_Ms;
target.SetupDirection = this.SetupDirection.Clone() as SetupDirection;
}
/// <summary>
/// 항상 SW트리거로만 동작하는지 체크
/// </summary>
/// <returns>항상 SW트리거로 동작하면 True</returns>
public bool IsAlwaysSwTrigger() {
return TriggerMode.IsSoftware && !TriggerMode.IsExternal && !TriggerMode.IsFlying;
}
/// <summary>
/// 항상 HW트리거로만 동작하는지 체크
/// </summary>
/// <returns>항상 HW트리거로 동작하면 True</returns>
public bool IsAlwaysHwTrigger() {
return !TriggerMode.IsSoftware;
}
}
}