2026-04-14 20:44:08 +09:00

372 lines
14 KiB
C#

using Aurora;
using Aurora.Api;
using Aurora.Api.Devices;
using Aurora.Api.Manager;
using Aurora.View;
using AuroraACS; // 26.04.06 NDY 추가
using AuroraLaser;
using AuroraLaserScanner;
using AuroraMotionBoard.Ajin;
using HarfBuzzSharp;
using Microsoft.Office.Interop.Excel;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Input;
using System.Windows.Threading;
namespace WeldingCommon.Views
{
public enum eAxisType
{
AXIS_X,
AXIS_Y
}
public enum eJogDirection
{
MINUS,
PLUS
}
public enum eMotionMode
{
ABS,
REL
};
public class UCScannerMotionViewModel : NotifyPropertyChangedBase
{
private readonly Logger Log = new Logger("UCScannerMotionViewModel");
public ICommand CMD_VisibleChanged { get; }
public ICommand CMD_SpeedChanged { get; }
public ICommand CMD_MotionModeChanged { get; }
public ICommand CMD_JogMove { get; }
public ICommand CMD_CommandPosMove { get; }
private readonly IAuroraEnvironment _Aurora;
private readonly Scanner _Scanner;
private readonly Laser _Laser;
private readonly ScannerConfig _ScannerConfig;
private double _ScannerXPos;
public double ScannerXPos { get => _ScannerXPos; set => SetProperty(ref _ScannerXPos, value); }
private double _ScannerYPos;
public double ScannerYPos { get => _ScannerYPos; set => SetProperty(ref _ScannerYPos, value); }
private bool _IsScannerBusy;
public bool IsScannerBusy { get => _IsScannerBusy; set => SetProperty(ref _IsScannerBusy, value); }
private double _StepValue;
public double StepValue { get => _StepValue; set => SetProperty(ref _StepValue, value); }
private double _CommandPosX;
public double CommandPosX { get => _CommandPosX; set => SetProperty(ref _CommandPosX, value); }
private double _CommandPosY;
public double CommandPosY { get => _CommandPosY; set => SetProperty(ref _CommandPosY, value); }
private double _CommandPosLimitMinX;
public double CommandPosLimitMinX { get => _CommandPosLimitMinX; set => SetProperty(ref _CommandPosLimitMinX, value); }
private double _CommandPosLimitMaxX;
public double CommandPosLimitMaxX { get => _CommandPosLimitMaxX; set => SetProperty(ref _CommandPosLimitMaxX, value); }
private double _CommandPosLimitMinY;
public double CommandPosLimitMinY { get => _CommandPosLimitMinY; set => SetProperty(ref _CommandPosLimitMinY, value); }
private double _CommandPosLimitMaxY;
public double CommandPosLimitMaxY { get => _CommandPosLimitMaxY; set => SetProperty(ref _CommandPosLimitMaxY, value); }
private double _VelocityRate;
private eMotionMode _MotionMode;
private readonly DispatcherTimer _MonitorTimer;
// 26.04.06 NDY Stage X 관련 필드 추가 ==================
private ACSMotor _MotorX;
private ACSMotor _MotorZ;
private double _StageXPos;
public double StageXPos { get => _StageXPos; set => SetProperty(ref _StageXPos, value); }
private double _StageZPos;
public double StageZPos { get => _StageZPos; set => SetProperty(ref _StageZPos, value); }
private bool _IsStageXActivated;
public bool IsStageXActivated { get => _IsStageXActivated; set => SetProperty(ref _IsStageXActivated, value); }
private bool _IsStageZActivated;
public bool IsStageZActivated { get => _IsStageZActivated; set => SetProperty(ref _IsStageZActivated, value); }
// ========================================================
// PAM, RUW 처럼 2개 이상의 scanner 를 사용하는 경우가 있어, scannerId 를 받는 형태로 생성
public UCScannerMotionViewModel(IAuroraEnvironment aurora, string scannerId)
{
_Aurora = aurora;
_Scanner = _Aurora.DeviceManager[scannerId] as Scanner;
_Laser = _Aurora.DeviceManager[CommonDeviceIds.Laser] as Laser;
_ScannerConfig = _Aurora.DeviceManager.GetDeviceConfig(scannerId) as ScannerConfig;
// 26.04.06 NDY Stage X 모터 연결 추가 ===============
try { _MotorX = _Aurora.DeviceManager["AxisX2"] as ACSMotor; }
catch { _MotorX = null; }
try { _MotorZ = _Aurora.DeviceManager["AxisZ"] as ACSMotor; }
catch { _MotorZ = null; }
// ====================================================
InitVariable();
CMD_VisibleChanged = new DelegateCommand(VisibleChanged);
CMD_SpeedChanged = new DelegateCommand(PerformCmdSpeedChanged);
CMD_MotionModeChanged = new DelegateCommand(PerformCmdMotionModeChanged);
CMD_JogMove = new DelegateCommand(PerformCmdJogMove);
CMD_CommandPosMove = new DelegateCommand(PerformCmdCommandPosMove);
_MonitorTimer = new DispatcherTimer();
_MonitorTimer.Tick += OnMonitoring;
_MonitorTimer.Interval = TimeSpan.FromMilliseconds(100);
}
private void InitVariable()
{
_VelocityRate = 1;
_MotionMode = eMotionMode.ABS;
}
private void VisibleChanged(object obj)
{
bool visible = (bool)obj;
if (visible)
{
Init_XYLimitPos();
_MonitorTimer.Start();
}
else
{
_MonitorTimer.Stop();
}
}
private void Init_XYLimitPos()
{
CommandPosLimitMinX = -1 * _ScannerConfig.ScanXSize / 2;
CommandPosLimitMaxX = _ScannerConfig.ScanXSize / 2;
CommandPosLimitMinY = -1 * _ScannerConfig.ScanYSize / 2;
CommandPosLimitMaxY = _ScannerConfig.ScanYSize / 2;
}
private void OnMonitoring(object sender, EventArgs e)
{
// 기존 Scanner 모니터링
double xPos, yPos;
if (_Scanner != null && _Scanner.IsActivated)
{
_Scanner.GetXYPos(out xPos, out yPos);
ScannerXPos = xPos;
ScannerYPos = yPos;
IsScannerBusy = _Scanner.GetBusyStatus();
}
else
{
ScannerXPos = 0;
ScannerYPos = 0;
IsScannerBusy = false;
}
// 26.04.06 NDY Stage X 모니터링 추가 ================
if (_MotorX != null && _MotorX.IsActivated)
{
StageXPos = _MotorX.GetActualPos();
IsStageXActivated = true;
}
else
{
IsStageXActivated = false;
}
if (_MotorZ != null && _MotorZ.IsActivated)
{
StageZPos = _MotorZ.GetActualPos();
IsStageZActivated = true;
}
else
{
IsStageZActivated = false;
}
// ====================================================
}
private void PerformCmdSpeedChanged(object commandParameter)
{
switch ((string)commandParameter)
{
case "Low": _VelocityRate = 0.5; break;
case "Mid": _VelocityRate = 1; break;
case "High": _VelocityRate = 1.5; break;
}
}
private void PerformCmdMotionModeChanged(object commandParameter)
{
switch ((string)commandParameter)
{
case "ABS": _MotionMode = eMotionMode.ABS; break;
case "REL": _MotionMode = eMotionMode.REL; break;
}
}
private void PerformCmdJogMove(object commandParameter)
{
var MainSequence = _Aurora.SequenceEntry[CommonSequenceIds.SeqAutoRun].RunState;
if (MainSequence == SequenceRunState.Running)
return;
switch ((string)commandParameter)
{
case "Left": MoveJogXYPos(eAxisType.AXIS_X, eJogDirection.MINUS); break;
case "Right": MoveJogXYPos(eAxisType.AXIS_X, eJogDirection.PLUS); break;
case "Up": MoveJogXYPos(eAxisType.AXIS_Y, eJogDirection.PLUS); break;
case "Down": MoveJogXYPos(eAxisType.AXIS_Y, eJogDirection.MINUS); break;
case "Home": MoveJogHome(); break;
// 26.04.06 NDY Stage X 버튼 추가 =================
case "Stage_X_Left": MoveStageX(eJogDirection.MINUS); break;
case "Stage_X_Right": MoveStageX(eJogDirection.PLUS); break;
case "Stage_Z_Left": MoveStageZ(eJogDirection.MINUS); break;
case "Stage_Z_Right": MoveStageZ(eJogDirection.PLUS); break;
// =================================================
}
}
// 26.04.06 NDY Stage X 이동 메서드 추가 ==================
private void MoveStageX(eJogDirection direction)
{
if (_MotorX == null || !_MotorX.IsActivated) return;
// 이미지 기준 방향 반전 적용
double step = direction == eJogDirection.PLUS ? -StepValue : +StepValue;
Log.I($"Stage X Move : {step}mm");
_MotorX.SetTargetPos(step, TargetPosType.REL);
_MotorX.SetVelocityImm(_MotorX.GetJogSpeed(AuroraACS.Speed.L) * _VelocityRate);
_MotorX.Move();
}
private void MoveStageZ(eJogDirection direction)
{
if (_MotorZ == null || !_MotorZ.IsActivated) return;
// 이미지 기준 방향 반전 적용
double step = direction == eJogDirection.PLUS ? -StepValue : +StepValue;
Log.I($"Stage Z Move : {step}mm");
_MotorZ.SetTargetPos(step, TargetPosType.REL);
_MotorZ.SetVelocityImm(_MotorZ.GetJogSpeed(AuroraACS.Speed.L) * _VelocityRate);
_MotorZ.Move();
}
// =========================================================
private void MoveJogXYPos(eAxisType axisType, eJogDirection direction)
{
double xPos = 0.0;
double yPos = 0.0;
switch (axisType)
{
case eAxisType.AXIS_X:
{
if (direction == eJogDirection.MINUS) { xPos = StepValue * -1; yPos = 0; }
else if (direction == eJogDirection.PLUS) { xPos = StepValue; yPos = 0; }
}
break;
case eAxisType.AXIS_Y:
{
if (direction == eJogDirection.MINUS) { xPos = 0; yPos = StepValue * -1; }
else if (direction == eJogDirection.PLUS) { xPos = 0; yPos = StepValue; }
}
break;
}
if (CheckOverLimitPos(ScannerXPos + xPos, ScannerYPos + yPos))
{
Log.E("움직이려는 범위가 스캐너 범위를 초과하였습니다.");
return;
}
double finalVelocity = _ScannerConfig.JumpSpeed * _VelocityRate;
_Scanner.SetJumpSpeedCtrl(finalVelocity);
_Scanner.JumpRel(xPos, yPos);
_Scanner.SetJumpSpeedCtrl(_ScannerConfig.JumpSpeed);
}
private void MoveJogHome()
{
double finalVelocity = _ScannerConfig.JumpSpeed * _VelocityRate;
_Scanner.SetJumpSpeedCtrl(finalVelocity);
_Scanner.JumpAbs(0, 0);
_Scanner.SetJumpSpeedCtrl(_ScannerConfig.JumpSpeed);
}
private void PerformCmdCommandPosMove(object commandParameter)
{
switch ((string)commandParameter)
{
case "X": MoveCommandXYPos(eAxisType.AXIS_X); break;
case "Y": MoveCommandXYPos(eAxisType.AXIS_Y); break;
}
}
private void MoveCommandXYPos(eAxisType axisType)
{
double xPos = 0.0;
double yPos = 0.0;
switch (axisType)
{
case eAxisType.AXIS_X:
{
xPos = CommandPosX;
yPos = _MotionMode == eMotionMode.ABS ? _Scanner.GetCommandPosY() : 0.0;
}
break;
case eAxisType.AXIS_Y:
{
xPos = _MotionMode == eMotionMode.ABS ? _Scanner.GetCommandPosX() : 0.0;
yPos = CommandPosY;
}
break;
}
if (_MotionMode == eMotionMode.ABS)
{
if (CheckOverLimitPos(xPos, yPos))
{
Log.E("움직이려는 범위가 스캐너 범위를 초과하였습니다.");
return;
}
}
else
{
if (CheckOverLimitPos(ScannerXPos + xPos, ScannerYPos + yPos))
{
Log.E("움직이려는 범위가 스캐너 범위를 초과하였습니다.");
return;
}
}
double finalVelocity = _ScannerConfig.JumpSpeed * _VelocityRate;
_Scanner.SetJumpSpeedCtrl(finalVelocity);
if (_MotionMode == eMotionMode.ABS)
_Scanner.JumpAbs(xPos, yPos);
else
_Scanner.JumpRel(xPos, yPos);
_Scanner.SetJumpSpeedCtrl(_ScannerConfig.JumpSpeed);
}
private bool CheckOverLimitPos(double calcPosX, double calcPosY)
{
if (calcPosX < CommandPosLimitMinX || calcPosX > CommandPosLimitMaxX) return true;
if (calcPosY < CommandPosLimitMinY || calcPosY > CommandPosLimitMaxY) return true;
return false;
}
}
}