Implement ACS Command Handlers (PickOn, PickOff, Charge), Manual Mode Safety, and Map UI Commands
This commit is contained in:
@@ -49,7 +49,9 @@ namespace Project.ViewForm
|
||||
|
||||
// 이벤트 연결
|
||||
//PUB._mapCanvas.NodeAdded += OnNodeAdded;
|
||||
//PUB._mapCanvas.NodeSelected += OnNodeSelected;
|
||||
// 이벤트 연결
|
||||
//PUB._mapCanvas.NodeAdded += OnNodeAdded;
|
||||
PUB._mapCanvas.NodesSelected += OnNodeSelected;
|
||||
//PUB._mapCanvas.NodeMoved += OnNodeMoved;
|
||||
//PUB._mapCanvas.NodeDeleted += OnNodeDeleted;
|
||||
//PUB._mapCanvas.ConnectionDeleted += OnConnectionDeleted;
|
||||
@@ -58,6 +60,85 @@ namespace Project.ViewForm
|
||||
|
||||
// 스플리터 패널에 맵 캔버스 추가
|
||||
panel1.Controls.Add(PUB._mapCanvas);
|
||||
}
|
||||
|
||||
private void OnNodeSelected(object sender, List<MapNode> nodes, MouseEventArgs e)
|
||||
{
|
||||
if (e.Button != MouseButtons.Right) return;
|
||||
var node = nodes.FirstOrDefault();
|
||||
if (nodes == null) return;
|
||||
|
||||
// 도킹 가능한 노드인지 또는 작업 노드인지 확인
|
||||
bool isDockingNode = node.Type == NodeType.Loader || node.Type == NodeType.UnLoader
|
||||
|| node.Type == NodeType.Buffer || node.Type == NodeType.Clearner
|
||||
|| node.Type == NodeType.Charging;
|
||||
|
||||
if (!isDockingNode) return;
|
||||
|
||||
ContextMenuStrip menu = new ContextMenuStrip();
|
||||
|
||||
// PickOn
|
||||
var pickOn = new ToolStripMenuItem("Pick On (Move & Pick)");
|
||||
pickOn.Click += (s, args) => ExecuteManualCommand(node, ENIGProtocol.AGVCommandHE.PickOn);
|
||||
menu.Items.Add(pickOn);
|
||||
|
||||
// PickOff
|
||||
var pickOff = new ToolStripMenuItem("Pick Off (Move & Drop)");
|
||||
pickOff.Click += (s, args) => ExecuteManualCommand(node, ENIGProtocol.AGVCommandHE.PickOff);
|
||||
menu.Items.Add(pickOff);
|
||||
|
||||
// Charge
|
||||
if (node.Type == NodeType.Charging)
|
||||
{
|
||||
var charge = new ToolStripMenuItem("Charge (Move & Charge)");
|
||||
charge.Click += (s, args) => ExecuteManualCommand(node, 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.RunStep != eSMStep.IDLE && PUB.sm.RunStep != eSMStep.READY)
|
||||
{
|
||||
if (MessageBox.Show("현재 대기상태가 아닙니다. 강제로 실행하시겠습니까?", "Warning", MessageBoxButtons.YesNo) == DialogResult.No) return;
|
||||
}
|
||||
|
||||
// 1. 경로 생성
|
||||
var pathFinder = new AGVNavigationCore.PathFinding.Planning.AGVPathfinder(PUB._mapNodes);
|
||||
// 현재위치에서 목표위치까지
|
||||
var result = pathFinder.FindPath(PUB._virtualAGV.CurrentNode, targetNode);
|
||||
|
||||
if (!result.Success || result.Path == null || result.Path.Count == 0)
|
||||
{
|
||||
MessageBox.Show("경로를 찾을 수 없습니다.");
|
||||
return;
|
||||
}
|
||||
|
||||
// 2. 상태 설정
|
||||
PUB.log.AddI($"[Manual Command] {cmd} to {targetNode.Name}({targetNode.NodeId})");
|
||||
|
||||
// Path 변환 (Node 리스트 -> AGVPathResult)
|
||||
// VirtualAGV.SetPath가 필요할 수 있음. 혹은 Goto 로직을 수동으로 구성.
|
||||
// _SM_RUN_GOTO에서는 PUB._virtualAGV.CurrentPath를 사용함.
|
||||
// AGVPathResult 생성 필요.
|
||||
|
||||
var detailedPath = AGVNavigationCore.PathFinding.Planning.AGVPathfinder.MakeDetailData(result.Path, PUB._mapNodes);
|
||||
PUB._virtualAGV.SetPath(result.Path, detailedPath);
|
||||
PUB._virtualAGV.TargetNode = targetNode;
|
||||
|
||||
// 3. 작업 설정
|
||||
PUB.NextWorkCmd = cmd;
|
||||
|
||||
// 4. 실행
|
||||
PUB.sm.SetNewRunStep(ERunStep.GOTO); // GOTO -> Arrive -> _IN sequence execution
|
||||
}
|
||||
|
||||
// 툴바 버튼 이벤트 연결
|
||||
//WireToolbarButtonEvents();
|
||||
@@ -85,8 +166,8 @@ namespace Project.ViewForm
|
||||
//맵파일로딩
|
||||
if (PUB.setting.LastMapFile.isEmpty()) PUB.setting.LastMapFile = System.IO.Path.Combine(mapPath.FullName, "default.agvmap");
|
||||
System.IO.FileInfo filePath = new System.IO.FileInfo(PUB.setting.LastMapFile);
|
||||
if (filePath.Exists == false) filePath = new System.IO.FileInfo(System.IO.Path.Combine(mapPath.FullName,"default.agvmap"));
|
||||
if(filePath.Exists==false) //그래도없다면 맵폴더에서 파일을 찾아본다.
|
||||
if (filePath.Exists == false) filePath = new System.IO.FileInfo(System.IO.Path.Combine(mapPath.FullName, "default.agvmap"));
|
||||
if (filePath.Exists == false) //그래도없다면 맵폴더에서 파일을 찾아본다.
|
||||
{
|
||||
var files = mapPath.GetFiles("*.agvmap");
|
||||
if (files.Any()) filePath = files[0];
|
||||
@@ -105,7 +186,7 @@ namespace Project.ViewForm
|
||||
// 맵 캔버스에 데이터 설정
|
||||
PUB._mapCanvas.Nodes = PUB._mapNodes;
|
||||
PUB._mapCanvas.MapFileName = filePath.FullName;
|
||||
|
||||
|
||||
// 🔥 맵 설정 적용 (배경색, 그리드 표시)
|
||||
if (result.Settings != null)
|
||||
{
|
||||
@@ -120,6 +201,7 @@ namespace Project.ViewForm
|
||||
if (startNode != null)
|
||||
{
|
||||
PUB._virtualAGV = new VirtualAGV(PUB.setting.MCID, startNode.Position, AgvDirection.Forward);
|
||||
PUB._virtualAGV.LowBatteryThreshold = PUB.setting.BatteryLimit_Low;
|
||||
PUB._virtualAGV.SetPosition(startNode, AgvDirection.Forward);
|
||||
|
||||
// 캔버스에 AGV 리스트 설정
|
||||
@@ -131,6 +213,7 @@ namespace Project.ViewForm
|
||||
}
|
||||
else if (PUB._virtualAGV != null)
|
||||
{
|
||||
PUB._virtualAGV.LowBatteryThreshold = PUB.setting.BatteryLimit_Low;
|
||||
// 기존 AGV가 있으면 캔버스에 다시 연결
|
||||
var agvList = new System.Collections.Generic.List<AGVNavigationCore.Controls.IAGV> { PUB._virtualAGV };
|
||||
PUB._mapCanvas.AGVList = agvList;
|
||||
|
||||
Reference in New Issue
Block a user