307 lines
11 KiB
C#
307 lines
11 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.ComponentModel;
|
|
using System.Data;
|
|
using System.Drawing;
|
|
using System.Linq;
|
|
using System.Text;
|
|
using System.Threading.Tasks;
|
|
using System.Windows.Forms;
|
|
using Project.StateMachine;
|
|
using COMM;
|
|
using AR;
|
|
using AGVNavigationCore.Models;
|
|
|
|
namespace Project.ViewForm
|
|
{
|
|
public partial class fAuto : Form
|
|
{
|
|
|
|
public fAuto()
|
|
{
|
|
InitializeComponent();
|
|
this.FormClosed += FAuto_FormClosed;
|
|
PUB.sm.StepChanged += Sm_StepChanged;
|
|
this.ctlAuto1.ButtonClick += CtlAuto1_ButtonClick;
|
|
if (PUB.sm.Step == eSMStep.INIT || PUB.sm.Step == eSMStep.SYNC)
|
|
this.ctlAuto1.Scean = CtlAuto.eScean.Progress;
|
|
else
|
|
this.ctlAuto1.Scean = CtlAuto.eScean.Normal;
|
|
|
|
InitializeMapCanvas();
|
|
|
|
}
|
|
|
|
private void InitializeMapCanvas()
|
|
{
|
|
PUB._mapCanvas.NodeSelect += OnNodeSelected;;
|
|
|
|
// 스플리터 패널에 맵 캔버스 추가
|
|
panel1.Controls.Add(PUB._mapCanvas);
|
|
}
|
|
|
|
|
|
private void OnNodeSelected(object sender, NodeBase node, MouseEventArgs e)
|
|
{
|
|
if (node == null) return;
|
|
var mapnode = node as MapNode;
|
|
if (mapnode == null) return;
|
|
|
|
// [Run Mode] Left Click: AGV Operation
|
|
if (PUB._mapCanvas.Mode == AGVNavigationCore.Controls.UnifiedAGVCanvas.CanvasMode.Run && e.Button == MouseButtons.Left)
|
|
{
|
|
HandleRunModeClick(mapnode);
|
|
return;
|
|
}
|
|
|
|
if (e.Button != MouseButtons.Right) return;
|
|
|
|
// 도킹 가능한 노드인지 또는 작업 노드인지 확인
|
|
if (mapnode.isDockingNode == false) return;
|
|
|
|
ContextMenuStrip menu = new ContextMenuStrip();
|
|
|
|
// PickOn
|
|
var pickOn = new ToolStripMenuItem("Pick On (Move & Pick)");
|
|
pickOn.Click += (s, args) => ExecuteManualCommand(mapnode, ENIGProtocol.AGVCommandHE.PickOn);
|
|
menu.Items.Add(pickOn);
|
|
|
|
// PickOff
|
|
var pickOff = new ToolStripMenuItem("Pick Off (Move & Drop)");
|
|
pickOff.Click += (s, args) => ExecuteManualCommand(mapnode, ENIGProtocol.AGVCommandHE.PickOff);
|
|
menu.Items.Add(pickOff);
|
|
|
|
// Charge
|
|
if (mapnode.StationType == StationType.Charger)
|
|
{
|
|
var charge = new ToolStripMenuItem("Charge (Move & Charge)");
|
|
charge.Click += (s, args) => ExecuteManualCommand(mapnode, ENIGProtocol.AGVCommandHE.Charger);
|
|
menu.Items.Add(charge);
|
|
}
|
|
|
|
menu.Show(Cursor.Position);
|
|
|
|
|
|
|
|
}
|
|
|
|
private void ExecuteManualCommand(MapNode targetNode, ENIGProtocol.AGVCommandHE cmd)
|
|
{
|
|
if (PUB._virtualAGV.CurrentNode == null)
|
|
{
|
|
MessageBox.Show("AGV의 현재 위치를 알 수 없습니다.");
|
|
return;
|
|
}
|
|
if (PUB.sm.Step == eSMStep.IDLE)
|
|
{
|
|
if (MessageBox.Show("현재 대기상태가 아닙니다. 강제로 실행하시겠습니까?", "Warning", MessageBoxButtons.YesNo) == DialogResult.No) return;
|
|
}
|
|
|
|
if (targetNode.isDockingNode == false)
|
|
{
|
|
UTIL.MsgE("이동 가능한 노드가 아닙니다");
|
|
}
|
|
|
|
// 1. 경로 생성
|
|
var pathFinder = new AGVNavigationCore.PathFinding.Planning.AGVPathfinder(PUB._mapCanvas.Nodes);
|
|
|
|
// 현재위치에서 목표위치까지
|
|
var result = pathFinder.FindPath(PUB._virtualAGV.CurrentNode, targetNode);
|
|
|
|
if (!result.Success || result.Path == null || result.Path.Count == 0)
|
|
{
|
|
MessageBox.Show("경로를 찾을 수 없습니다.");
|
|
return;
|
|
}
|
|
|
|
// 2. 상태 설정
|
|
|
|
// 2. 상태 설정
|
|
if (targetNode is MapNode mapno)
|
|
PUB.log.AddI($"[Manual Command] {cmd} to {mapno.RfidId}({targetNode.Id})");
|
|
else
|
|
PUB.log.AddI($"[Manual Command] {cmd} to ({targetNode.Id})");
|
|
|
|
// FindPathResult contains DetailedPath already.
|
|
PUB._virtualAGV.SetPath(result);
|
|
PUB._virtualAGV.TargetNode = targetNode as MapNode;
|
|
|
|
// 3. 작업 설정
|
|
PUB.NextWorkCmd = cmd;
|
|
|
|
// 4. 실행
|
|
PUB.sm.SetNewRunStep(ERunStep.GOTO); // GOTO -> Arrive -> _IN sequence execution
|
|
}
|
|
|
|
|
|
private void fAuto_Load(object sender, EventArgs e)
|
|
{
|
|
ctlAuto1.dev_agv = PUB.AGV;
|
|
// ctlAuto1.dev_plc = PUB.PLC;
|
|
ctlAuto1.dev_bms = PUB.BMS;
|
|
ctlAuto1.dev_xbe = PUB.XBE;
|
|
|
|
PUB.AGV.DataReceive += AGV_DataReceive;
|
|
|
|
|
|
|
|
//var fn = string.Empty;
|
|
//if (files.Any() == false)
|
|
//{
|
|
// fn = AR.UTIL.MakePath("sample.route");
|
|
//}
|
|
//else if (files.Count() == 1)
|
|
//{
|
|
// fn = files.First().FullName;
|
|
//}
|
|
//if (fn.isEmpty() == false)
|
|
//{
|
|
// var fi = new System.IO.FileInfo(AR.UTIL.CurrentPath + "\\sample.route");
|
|
// if (fi.Exists)
|
|
// {
|
|
// PUB.log.Add($"autoload : {fi.FullName}");
|
|
// var rlt = PUB.mapctl.LoadFromFile(fi.FullName, out string errmsg);
|
|
// if (rlt == false) AR.UTIL.MsgE(errmsg);
|
|
// }
|
|
//}
|
|
|
|
this.timer1.Start();
|
|
|
|
// Set Run Mode
|
|
PUB._mapCanvas.Mode = AGVNavigationCore.Controls.UnifiedAGVCanvas.CanvasMode.Run;
|
|
}
|
|
private void AGV_DataReceive(object sender, arDev.Narumi.DataEventArgs e)
|
|
{
|
|
switch (e.DataType)
|
|
{
|
|
case arDev.Narumi.DataType.TAG:
|
|
//_AGV 파일에서 위치조정을 함
|
|
//var tagno = PUB.AGV.data.TagNo;
|
|
//PUB.mapctl.SetCurrentPosition(tagno);
|
|
break;
|
|
}
|
|
}
|
|
|
|
private void CtlAuto1_ButtonClick(CtlAuto.UIButton idx)
|
|
{
|
|
if (idx.cmd.Equals("EMG"))
|
|
{
|
|
PUB.log.Add("ui reset click");
|
|
PUB.AGV.AGVErrorReset();
|
|
}
|
|
}
|
|
|
|
private void Sm_StepChanged(object sender, StateMachine.StateMachine.StepChangeEventArgs e)
|
|
{
|
|
if (e.New == eSMStep.INIT || e.New == eSMStep.SYNC)
|
|
this.ctlAuto1.Scean = CtlAuto.eScean.Progress;
|
|
else
|
|
this.ctlAuto1.Scean = CtlAuto.eScean.Normal;
|
|
}
|
|
|
|
private void FAuto_FormClosed(object sender, FormClosedEventArgs e)
|
|
{
|
|
timer1.Stop();
|
|
PUB.sm.StepChanged -= Sm_StepChanged;
|
|
this.ctlAuto1.ButtonClick -= CtlAuto1_ButtonClick;
|
|
PUB.AGV.DataReceive -= AGV_DataReceive;
|
|
|
|
// Reset Mode to Edit
|
|
PUB._mapCanvas.Mode = AGVNavigationCore.Controls.UnifiedAGVCanvas.CanvasMode.Edit;
|
|
}
|
|
|
|
bool tmrun = false;
|
|
|
|
private void fAuto_VisibleChanged(object sender, EventArgs e)
|
|
{
|
|
this.timer1.Enabled = this.Visible;
|
|
if (timer1.Enabled)
|
|
{
|
|
timer1.Start();
|
|
// 화면이 보일 때 Run 모드로 강제 설정
|
|
if (PUB._mapCanvas.Mode != AGVNavigationCore.Controls.UnifiedAGVCanvas.CanvasMode.Run)
|
|
{
|
|
PUB._mapCanvas.Mode = AGVNavigationCore.Controls.UnifiedAGVCanvas.CanvasMode.Run;
|
|
}
|
|
}
|
|
else timer1.Stop();
|
|
}
|
|
|
|
private void timer1_Tick_1(object sender, EventArgs e)
|
|
{
|
|
//if (this.Visible == false) return;
|
|
//if (tmrun == true) return;
|
|
//tmrun = true;
|
|
|
|
//this.ctlAuto1.OnUpdateMode = true;
|
|
|
|
//if (this.ctlAuto1.Scean == CtlAuto.eScean.Progress)
|
|
//{
|
|
// ctlAuto1.ProgressVal = PUB.Result.SMSG_ProgressValue;
|
|
// ctlAuto1.ProgressMax = PUB.Result.SMSG_ProgressMax;
|
|
// ctlAuto1.StatusMessage = VAR.STR?.Get(eVarString.StatusMessage) ?? string.Empty;
|
|
//}
|
|
//this.ctlAuto1.StopMessage = string.Empty;
|
|
|
|
//if (PUB.sm.Step == StateMachine.eSMStep.RUN)
|
|
//{
|
|
// this.ctlAuto1.runStep = PUB.sm.RunStep;
|
|
//}
|
|
//else
|
|
//{
|
|
// this.ctlAuto1.runStep = ERunStep.READY;
|
|
//}
|
|
//this.ctlAuto1.OnUpdateMode = false;
|
|
//this.ctlAuto1.Invalidate();
|
|
|
|
//PUB.mapctl.PredictNextAction();
|
|
|
|
//tmrun = false;
|
|
}
|
|
|
|
private void HandleRunModeClick(MapNode targetNode)
|
|
{
|
|
if (targetNode == null) return;
|
|
|
|
ENIGProtocol.AGVCommandHE targetCmd = ENIGProtocol.AGVCommandHE.Goto;
|
|
string confirmMsg = "";
|
|
|
|
if (targetNode.StationType == StationType.Charger)
|
|
{
|
|
if (MessageBox.Show($"[{targetNode.Id}] 충전기로 이동하여 충전을 진행하시겠습니까?", "작업 확인", MessageBoxButtons.YesNo) == DialogResult.Yes)
|
|
{
|
|
targetCmd = ENIGProtocol.AGVCommandHE.Charger;
|
|
ExecuteManualCommand(targetNode, targetCmd);
|
|
}
|
|
return;
|
|
}
|
|
else if (targetNode.isDockingNode)
|
|
{
|
|
// Loader, Unloader, Buffer, Cleaner - Pick/Drop Selection
|
|
ContextMenuStrip menu = new ContextMenuStrip();
|
|
|
|
var pickOn = new ToolStripMenuItem("Pick On (Move & Pick)");
|
|
pickOn.Click += (s, args) => ExecuteManualCommand(targetNode, ENIGProtocol.AGVCommandHE.PickOn);
|
|
menu.Items.Add(pickOn);
|
|
|
|
var pickOff = new ToolStripMenuItem("Pick Off (Move & Drop)");
|
|
pickOff.Click += (s, args) => ExecuteManualCommand(targetNode, ENIGProtocol.AGVCommandHE.PickOff);
|
|
menu.Items.Add(pickOff);
|
|
|
|
menu.Show(Cursor.Position);
|
|
return;
|
|
}
|
|
else
|
|
{
|
|
// Normal Node
|
|
if (MessageBox.Show($"[{targetNode.Id}] 노드로 이동하시겠습니까?", "이동 확인", MessageBoxButtons.YesNo) == DialogResult.Yes)
|
|
{
|
|
targetCmd = ENIGProtocol.AGVCommandHE.Goto;
|
|
ExecuteManualCommand(targetNode, targetCmd);
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
}
|