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

364 lines
12 KiB
C#

using Aurora;
using Aurora.Api;
using Aurora.Api.Manager;
using Aurora.View;
using AuroraLaser;
using AuroraLaserScanner;
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;
// 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;
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()
{
// TODO: Limit 값을 Min, Max 로 따로 Setting 입력값으로 가져와야 할 수도 있음. 우선 현상태 유지
CommandPosLimitMinX = -1 * _ScannerConfig.ScanXSize / 2;
CommandPosLimitMaxX = _ScannerConfig.ScanXSize / 2;
CommandPosLimitMinY = -1 * _ScannerConfig.ScanYSize / 2;
CommandPosLimitMaxY = _ScannerConfig.ScanYSize / 2;
//CommandPosXLimit = string.Format($"{-1 * _ScannerConfig.ScanXSize / 2} ~ {_ScannerConfig.ScanXSize / 2}");
//CommandPosYLimit = string.Format($"{-1 * _ScannerConfig.ScanYSize / 2} ~ {_ScannerConfig.ScanYSize / 2}");
}
private void OnMonitoring(object sender, EventArgs e)
{
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;
}
}
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)
{
// TODO: Left, Right, Up, Down 은 장비 Scanner 의 방향에 따라 달라질 수 있다
// 양산중에는 동작 하면 안됨
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;
}
}
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;
default:
break;
}
// 현재 Curruent Pos 기준으로, 입력방향으로 입력값이 Limit 를 넘어 서는지 확인 (Rel 임)
if (CheckOverLimitPos(ScannerXPos + xPos, ScannerYPos + yPos)) {
Log.E(string.Format("움직이려는 범위가 스캐너 범위를 초과하였습니다."));
return;
}
double finalVelocity = _ScannerConfig.JumpSpeed * _VelocityRate;
_Scanner.SetJumpSpeedCtrl(finalVelocity);
_Scanner.JumpRel(xPos, yPos);
//Jump 후 Speed 원복
_Scanner.SetJumpSpeedCtrl(_ScannerConfig.JumpSpeed);
}
private void MoveJogHome()
{
double finalVelocity = _ScannerConfig.JumpSpeed * _VelocityRate;
_Scanner.SetJumpSpeedCtrl(finalVelocity);
_Scanner.JumpAbs(0, 0);
//Jump 후 Speed 원복
_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;
if (_MotionMode == eMotionMode.ABS) {
yPos = _Scanner.GetCommandPosY();
} else {
yPos = 0.0;
}
}
break;
case eAxisType.AXIS_Y: {
if (_MotionMode == eMotionMode.ABS) {
xPos = _Scanner.GetCommandPosX();
} else {
xPos = 0.0;
}
yPos = CommandPosY;
}
break;
default:
break;
}
// 현재 Curruent Pos 기준으로, 입력방향으로 입력값이 Limit 를 넘어 서는지 확인
if (_MotionMode == eMotionMode.ABS) {
if (CheckOverLimitPos(xPos, yPos)) {
Log.E(string.Format("움직이려는 범위가 스캐너 범위를 초과하였습니다."));
return;
}
} else {
if (CheckOverLimitPos(ScannerXPos + xPos, ScannerYPos + yPos)) {
Log.E(string.Format("움직이려는 범위가 스캐너 범위를 초과하였습니다."));
return;
}
}
double finalVelocity = _ScannerConfig.JumpSpeed * _VelocityRate;
_Scanner.SetJumpSpeedCtrl(finalVelocity);
if (_MotionMode == eMotionMode.ABS) {
_Scanner.JumpAbs(xPos, yPos);
} else {
_Scanner.JumpRel(xPos, yPos);
}
//Jump 후 Speed 원복
_Scanner.SetJumpSpeedCtrl(_ScannerConfig.JumpSpeed);
}
private bool CheckOverLimitPos(double calcPosX, double calcPosY)
{
if (calcPosX < CommandPosLimitMinX || calcPosX > CommandPosLimitMaxX) {
return true;
} else if (calcPosY < CommandPosLimitMinY || calcPosY > CommandPosLimitMaxY) {
return true;
}
return false;
}
}
}