/* * 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 { /// /// 카메라 디바이스 모델 리스트 /// public enum eCamModel { DEFAULT, // 공용 카메라 디바이스 사용 (AuroraVision에서 정의한 카메라 디바이스) MachineCamera_A = 50, // 장비 전용 카메라 디바이스 A MachineCamera_B, // 장비 전용 카메라 디바이스 B MachineCamera_C // 장비 전용 카메라 디바이스 C } /// /// 그래버 유형 /// 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) } /// /// 그래버 슬롯 위치 (MIL에서 Auto 인덱싱 해줌에 주의) /// 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 } /// /// 그래버 포트 위치 (MIL에서 Auto 인덱싱 해줌에 주의) /// 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 } /// /// 카메라 트리거 유형 /// public enum eTrigType { HW, // Hardware Trigger (External Trigger) SW // Software Trigger (Internal Trigger) } /// /// 카메라 트리거 발생 주체 /// public enum eTrigSubject { /// 트리거 발생 주체가 외부(버퍼) 프로그램인 경우 External, /// 트리거 발생 주체가 Aurora인 경우 Internal } /// /// GenICam "TriggerSource" Features /// 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; /// /// MIL : *.dcf 파일로 카메라 연결. EX) "D:\\Aurora\\DcfFiles\\CAM1.dcf" /// Euresys : *.cti 파일로 카메라 연결. EX) "C:\\Program Files\\Euresys\\eGrabber\\cti\\x86_64\\gigelink.cti" /// [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 ChildBufRowCols { get; set; } = new List(); // 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) }; } /// /// 활성화된 모터 위치 인덱스 기준으로 오름차순 정렬된 Child 객체 리스트 가져오기 /// /// 활성화된 모터 위치 인덱스 기준으로 오름차순 정렬된 Child 객체 리스트 public List 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); } } /// /// 이미지 취득을 위한 카메라 트리거 모드 관리 /// 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 { 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; } /// /// 항상 SW트리거로만 동작하는지 체크 /// /// 항상 SW트리거로 동작하면 True public bool IsAlwaysSwTrigger() { return TriggerMode.IsSoftware && !TriggerMode.IsExternal && !TriggerMode.IsFlying; } /// /// 항상 HW트리거로만 동작하는지 체크 /// /// 항상 HW트리거로 동작하면 True public bool IsAlwaysHwTrigger() { return !TriggerMode.IsSoftware; } } }