using Aurora; using Aurora.Api; using VisionCommon; using System; using System.Reactive.Linq; using System.Collections.Generic; namespace VisionCalibrator { /// /// 자재 좌표를 모션 좌표로 변환하기 위한 클래스이다. /// public class CoordConverter { private static Logger _StaticLogger = new Logger("StaticCoordConverter"); private Logger _Logger; private IEventObservable _EventObservable; private SubSysInfo _SubSysInfo; private CalRecipe _CalRecipe; private CoordConvRecipe _CoordConvRecipe; /// /// CoordConverter 생성자 /// /// 서브 시스템 정보 public CoordConverter(SubSysInfo subSysInfo) { _SubSysInfo = subSysInfo; _Logger = new Logger(_SubSysInfo.SubSysName); _EventObservable = VisionEnv.AuroraEnv.EventObservable; UpdateRecipe(); var observable = VisionEventId.GetRecipeUpdateObservable(); observable.Subscribe(_ => UpdateRecipe()); } /// /// 리스트로 전달된 자재 좌표를 모션 좌표로 변환한다. /// /// 자재 좌표 리스트 /// 패턴 간의 수평 거리 /// 패턴 간의 수직 거리 /// 수평 Low, 수직 Low 모션 좌표 /// 수평 High, 수직 Low 모션 좌표 /// 수평 Low, 수직 High 모션 좌표 /// 수평 High, 수직 High 모션 좌표 /// 모션 좌표 리스트 public List CoordConvert( List staticPoints, double horiozntalDistance, double verticalDistance, MotionPoint llMotion, MotionPoint hlMotion, MotionPoint lhMotion, MotionPoint hhMotion) { List motionPoints = new List(); foreach (var staticPoint in staticPoints) { motionPoints.Add( CoordConvert( staticPoint.X, staticPoint.Y, horiozntalDistance, verticalDistance, llMotion, hlMotion, lhMotion, hhMotion)); } return motionPoints; } /// /// 자재 좌표를 모션 좌표로 변환한다. /// /// 자재 좌표 /// 패턴 간의 수평 거리 /// 패턴 간의 수직 거리 /// 수평 Low, 수직 Low 모션 좌표 /// 수평 High, 수직 Low 모션 좌표 /// 수평 Low, 수직 High 모션 좌표 /// 수평 High, 수직 High 모션 좌표 /// 모션 좌표 public MotionPoint CoordConvert( StaticPoint staticPoint, double horiozntalDistance, double verticalDistance, MotionPoint llMotion, MotionPoint hlMotion, MotionPoint lhMotion, MotionPoint hhMotion) { return CoordConvert( staticPoint.X, staticPoint.Y, horiozntalDistance, verticalDistance, llMotion, hlMotion, lhMotion, hhMotion); } /// /// 자재 좌표를 모션 좌표로 변환한다. /// /// 자재 X좌표 /// 자재 Y좌표 /// 패턴 간의 수평 거리 /// 패턴 간의 수직 거리 /// 수평 Low, 수직 Low 모션 좌표 /// 수평 High, 수직 Low 모션 좌표 /// 수평 Low, 수직 High 모션 좌표 /// 수평 High, 수직 High 모션 좌표 /// 모션 좌표 public MotionPoint CoordConvert( double staticPointX, double staticPointY, double horiozntalDistance, double verticalDistance, MotionPoint llMotion, MotionPoint hlMotion, MotionPoint lhMotion, MotionPoint hhMotion) { var translatedPoint = new StaticPoint( staticPointX - _CalRecipe.ThetaOrigin.X, staticPointY - _CalRecipe.ThetaOrigin.Y); var motionPoint = CoordConvertInternal( translatedPoint.X, translatedPoint.Y, horiozntalDistance, verticalDistance, llMotion, hlMotion, lhMotion, hhMotion, _CalRecipe.CoordSystem.Clone() as CoordSystem, _CoordConvRecipe.CoordSystem.Clone() as CoordSystem); _Logger.I($"{new StaticPoint(staticPointX, staticPointY)} -> translated : {translatedPoint} -> {motionPoint}"); return motionPoint; } private static MotionPoint CoordConvertInternal( double staticPointX, double staticPointY, double horizonntalDist, double verticalDist, MotionPoint llMotion, MotionPoint hlMotion, MotionPoint lhMotion, MotionPoint hhMotion, CoordSystem csStatic, CoordSystem csMotion) { return NativeCalibrator.CoordConveter( staticPointX, staticPointY, horizonntalDist, verticalDist, new PointData() { X = llMotion.X, Y = llMotion.Y }, new PointData() { X = hlMotion.X, Y = hlMotion.Y }, new PointData() { X = lhMotion.X, Y = lhMotion.Y }, new PointData() { X = hhMotion.X, Y = hhMotion.Y }, csStatic.RotationX.Radian, (int)csStatic.FlipY, csMotion.RotationX.Radian, (int)csMotion.FlipY); } /// /// 모션 좌표를 자재 좌표로 변환한다. /// /// 변환하고 하는 모션 좌표 /// 자재 좌표 1 /// 자재 좌표 2/param> /// 자재 좌표 3/param> /// 자재 좌표 4/param> /// 모션 좌표 1 /// 모션 좌표 2 /// 모션 좌표 3 /// 모션 좌표 4 /// 변환된 자재 좌표 public static StaticPoint CoordConvertInverse( MotionPoint motionPoint, StaticPoint s1, StaticPoint s2, StaticPoint s3, StaticPoint s4, MotionPoint m1, MotionPoint m2, MotionPoint m3, MotionPoint m4) { var staticPoint = CoordConvertInverseInternal( motionPoint.X, motionPoint.Y, s1, s2, s3, s4, m1, m2, m3, m4); _StaticLogger.I($"{motionPoint} -> {staticPoint}"); return staticPoint; } private static StaticPoint CoordConvertInverseInternal( double motionPointX, double motionPointY, StaticPoint s1, StaticPoint s2, StaticPoint s3, StaticPoint s4, MotionPoint m1, MotionPoint m2, MotionPoint m3, MotionPoint m4) { var staticPoint = NativeCalibrator.CoordConvertInverse( motionPointX, motionPointY, ToPointData(s1), ToPointData(s2), ToPointData(s3), ToPointData(s4), ToPointData(m1), ToPointData(m2), ToPointData(m3), ToPointData(m4)); return staticPoint; } private static PointData ToPointData(DoublePoint p) { return new PointData() { X = p.X, Y = p.Y }; } /// /// 자재 좌표에 얼라인 보정량을 적용한다. /// /// 자재 좌표 /// 얼라인 X보정량 /// 얼라인 Y보정량 /// 얼라인 T보정량 /// 얼라인 보정량이 적용된 자재 좌표 public StaticPoint GetAlignedPoint(StaticPoint staticPoint, double offsetX, double offsetY, Angle offsetT) { // 이미지 좌표계가 아닌 경우, 시계 방향으로 회전하기 위해 회전 값을 반전(* -1) var rotAngle = offsetT * (int)_CalRecipe.CoordSystem.FlipY; // 이미지 좌표 기준 시계 방향으로 회전 var rotatedPoint = MathUtil.Rotate(staticPoint, rotAngle, _CalRecipe.ThetaOrigin); var alignedPoint = new StaticPoint(rotatedPoint.X + offsetX, rotatedPoint.Y + offsetY); _Logger.I($"{staticPoint} -> aligned : {alignedPoint}"); return alignedPoint; } /// /// 리스트로 전달된 자재 좌표에 얼라인 보정량을 적용한다. /// /// 자재 좌표 리스트 /// 얼라인 X보정량 /// 얼라인 Y보정량 /// 얼라인 T보정량 /// 얼라인 보정량이 적용된 자재 좌표 리스트 public List GetAlignedPoints(List staticPoints, double offsetX, double offsetY, Angle offsetT) { List alignedStaticPoints = new List(); foreach (var staticPoint in staticPoints) { alignedStaticPoints.Add( GetAlignedPoint(staticPoint, offsetX, offsetY, offsetT)); } return alignedStaticPoints; } /// /// 리스트로 전달된 자재 좌표에 얼라인 보정량을 적용하고 모션 좌표로 변환한다. /// /// 자재 좌표 리스트 /// 얼라인 X보정량 /// 얼라인 Y보정량 /// 얼라인 T보정량 /// 패턴 간의 수평 거리 /// 패턴 간의 수직 거리 /// 수평 Low, 수직 Low 모션 좌표 /// 수평 High, 수직 Low 모션 좌표 /// 수평 Low, 수직 High 모션 좌표 /// 수평 High, 수직 High 모션 좌표 /// 얼라인 보정량이 적용된 모션 좌표 리스트 public List CoordConvertWithAlignOffset( List staticPoints, double offsetX, double offsetY, Angle offsetT, double horiozntalDistance, double verticalDistance, MotionPoint llMotion, MotionPoint hlMotion, MotionPoint lhMotion, MotionPoint hhMotion) { List motionPoints = new List(); foreach (var staticPoint in staticPoints) { motionPoints.Add( CoordConvertWithAlignOffset( staticPoint, offsetX, offsetY, offsetT, horiozntalDistance, verticalDistance, llMotion, hlMotion, lhMotion, hhMotion)); } return motionPoints; } /// /// 자재 좌표에 얼라인 보정량을 적용하고 모션 좌표로 변환한다. /// /// 자재 좌표 리스트 /// 얼라인 X보정량 /// 얼라인 Y보정량 /// 얼라인 T보정량 /// 패턴 간의 수평 거리 /// 패턴 간의 수직 거리 /// 수평 Low, 수직 Low 모션 좌표 /// 수평 High, 수직 Low 모션 좌표 /// 수평 Low, 수직 High 모션 좌표 /// 수평 High, 수직 High 모션 좌표 /// 얼라인 보정량이 적용된 모션 좌표 public MotionPoint CoordConvertWithAlignOffset( StaticPoint staticPoint, double offsetX, double offsetY, Angle offsetT, double horiozntalDistance, double verticalDistance, MotionPoint llMotion, MotionPoint hlMotion, MotionPoint lhMotion, MotionPoint hhMotion) { var alignedPoint = GetAlignedPoint(staticPoint, offsetX, offsetY, offsetT); return CoordConvert( alignedPoint.X, alignedPoint.Y, horiozntalDistance, verticalDistance, llMotion, hlMotion, lhMotion, hhMotion); } private void UpdateRecipe() { _CalRecipe = VisionRecipeManager.GetCalRecipe(_SubSysInfo); _CoordConvRecipe = VisionRecipeManager.GetCoordConvRecipe(_SubSysInfo); } } }