diff --git a/Cs_HMI/AGVLogic/AGVNavigationCore/Controls/UnifiedAGVCanvas.Events.cs b/Cs_HMI/AGVLogic/AGVNavigationCore/Controls/UnifiedAGVCanvas.Events.cs index fe97a93..fc1cc7b 100644 --- a/Cs_HMI/AGVLogic/AGVNavigationCore/Controls/UnifiedAGVCanvas.Events.cs +++ b/Cs_HMI/AGVLogic/AGVNavigationCore/Controls/UnifiedAGVCanvas.Events.cs @@ -99,8 +99,21 @@ namespace AGVNavigationCore.Controls //예측문자는 디버깅시에만 표시한다. if (string.IsNullOrEmpty(PredictMessage) == false && System.Diagnostics.Debugger.IsAttached) { - g.DrawString(this.PredictMessage, this.Font, Brushes.White, 10, 10); + g.DrawString(this.PredictMessage, this.Font, Brushes.White, 10, 100); } + DrawAlertMessage(g); + + } + + void DrawAlertMessage(Graphics g) + { + if (showalert == false) return; + + //상단에 경고 메세지를 추가한다 + if (String.IsNullOrEmpty(this._alertmesage)) return; + + + g.DrawString(this._alertmesage, this.Font, Brushes.Gold, 10, 10); } private void DrawSyncScreen(Graphics g) diff --git a/Cs_HMI/AGVLogic/AGVNavigationCore/Controls/UnifiedAGVCanvas.cs b/Cs_HMI/AGVLogic/AGVNavigationCore/Controls/UnifiedAGVCanvas.cs index 305c3ea..bfc27ef 100644 --- a/Cs_HMI/AGVLogic/AGVNavigationCore/Controls/UnifiedAGVCanvas.cs +++ b/Cs_HMI/AGVLogic/AGVNavigationCore/Controls/UnifiedAGVCanvas.cs @@ -135,6 +135,14 @@ namespace AGVNavigationCore.Controls private float _syncProgress = 0.0f; private string _syncDetail = ""; + string _alertmesage = ""; + bool showalert = false; + public void SetAlertMessage(string m) + { + _alertmesage = m; + showalert = !string.IsNullOrEmpty(m); + } + // 브러쉬 및 펜 private Brush _normalNodeBrush; private Brush _rotationNodeBrush; @@ -643,7 +651,7 @@ namespace AGVNavigationCore.Controls _pathPen = new Pen(Color.Purple, 3); _agvPen = new Pen(Color.Red, 3); _highlightedConnectionPen = new Pen(Color.Red, 4) { DashStyle = DashStyle.Solid }; - _magnetPen = new Pen(Color.FromArgb(100,Color.LightSkyBlue), 15) { DashStyle = DashStyle.Solid }; + _magnetPen = new Pen(Color.FromArgb(100, Color.LightSkyBlue), 15) { DashStyle = DashStyle.Solid }; _markPen = new Pen(Color.White, 3); // 마크는 흰색 선으로 표시 } diff --git a/Cs_HMI/AGVLogic/AGVNavigationCore/PathFinding/Planning/AGVPathfinder.cs b/Cs_HMI/AGVLogic/AGVNavigationCore/PathFinding/Planning/AGVPathfinder.cs index 6514dd5..9556516 100644 --- a/Cs_HMI/AGVLogic/AGVNavigationCore/PathFinding/Planning/AGVPathfinder.cs +++ b/Cs_HMI/AGVLogic/AGVNavigationCore/PathFinding/Planning/AGVPathfinder.cs @@ -131,12 +131,15 @@ namespace AGVNavigationCore.PathFinding.Planning return AGVPathResult.CreateFailure("이동 가능한 노드가 아닙니다", 0, 0); var tnode = targetNode as MapNode; + + //시작노드와 종료노드가 동일위치이고 도킹방향도 맞다면 그대로 OK 한다 if (startNode.Id == targetNode.Id && tnode.DockDirection.MatchAGVDirection(prevDirection)) return AGVPathResult.CreateSuccess(new List { startNode, startNode }, new List(), 0, 0); + //반대방향값 지정 var ReverseDirection = (currentDirection == AgvDirection.Forward ? AgvDirection.Backward : AgvDirection.Forward); - //1.목적지까지의 최단거리 경로를 찾는다. + //1.목적지까지의 최단거리 경로를 찾는다.(AStar 방식) var pathResult = _basicPathfinder.FindPathAStar(startNode.Id, targetNode.Id); pathResult.PrevNode = prevNode; pathResult.PrevDirection = prevDirection; @@ -201,9 +204,7 @@ namespace AGVNavigationCore.PathFinding.Planning } if (nextNodeForward != null && pathResult.Path.Count > 1 && - nextNodeForward.Id == pathResult.Path[1].Id && - tnode.DockDirection == DockingDirection.Forward && - currentDirection == AgvDirection.Forward) // ✅ 추가: 현재도 Forward여야 함 + nextNodeForward.Id == pathResult.Path[1].Id) // ✅ 추가: 현재도 Forward여야 함 { if (tnode.DockDirection == DockingDirection.Forward && currentDirection == AgvDirection.Forward || tnode.DockDirection == DockingDirection.Backward && currentDirection == AgvDirection.Backward) diff --git a/Cs_HMI/AGVLogic/AGVNavigationCore/Utils/DockingValidator.cs b/Cs_HMI/AGVLogic/AGVNavigationCore/Utils/DockingValidator.cs index fdfd752..ae9aa76 100644 --- a/Cs_HMI/AGVLogic/AGVNavigationCore/Utils/DockingValidator.cs +++ b/Cs_HMI/AGVLogic/AGVNavigationCore/Utils/DockingValidator.cs @@ -46,94 +46,122 @@ namespace AGVNavigationCore.Utils System.Diagnostics.Debug.WriteLine($"[DockingValidator] 목적지 노드: {LastNode.Id} 타입:{LastNode.Type} ({(int)LastNode.Type})"); - //detail 경로 이동 예측 검증 - for (int i = 0; i < pathResult.DetailedPath.Count - 1; i++) - { - var curNodeId = pathResult.DetailedPath[i].NodeId; - var nextNodeId = pathResult.DetailedPath[i + 1].NodeId; + ////detail 경로 이동 예측 검증 + //for (int i = 0; i < pathResult.DetailedPath.Count - 1; i++) + //{ + // var curNodeId = pathResult.DetailedPath[i].NodeId; + // var nextNodeId = pathResult.DetailedPath[i + 1].NodeId; - var curNode = mapNodes?.FirstOrDefault(n => n.Id == curNodeId); - var nextNode = mapNodes?.FirstOrDefault(n => n.Id == nextNodeId); + // var curNode = mapNodes?.FirstOrDefault(n => n.Id == curNodeId); + // var nextNode = mapNodes?.FirstOrDefault(n => n.Id == nextNodeId); - if (curNode != null && nextNode != null) - { - MapNode prevNode = null; - AgvDirection prevDir = AgvDirection.Stop; - if (i == 0) - { - prevNode = pathResult.PrevNode; - prevDir = pathResult.PrevDirection; - } - else - { - var prevNodeId = pathResult.DetailedPath[i - 1].NodeId; - prevNode = mapNodes?.FirstOrDefault(n => n.Id == prevNodeId); - prevDir = pathResult.DetailedPath[i - 1].MotorDirection; - } + // if (curNode != null && nextNode != null) + // { + // MapNode prevNode = null; + // AgvDirection prevDir = AgvDirection.Stop; + // if (i == 0) + // { + // prevNode = pathResult.PrevNode; + // prevDir = pathResult.PrevDirection; + // } + // else + // { + // var prevNodeId = pathResult.DetailedPath[i - 1].NodeId; + // prevNode = mapNodes?.FirstOrDefault(n => n.Id == prevNodeId); + // prevDir = pathResult.DetailedPath[i - 1].MotorDirection; + // } - if (prevNode != null) - { - // DirectionalHelper를 사용하여 예상되는 다음 노드 확인 - Console.WriteLine( - $"\n[ValidateDockingDirection] 경로 검증 단계 {i}:"); - Console.WriteLine( - $" 이전→현재→다음: {prevNode.Id}({prevNode.RfidId}) → {curNode.Id}({curNode.RfidId}) → {nextNode.Id}({nextNode.RfidId})"); - Console.WriteLine( - $" 현재 노드 위치: ({curNode.Position.X:F1}, {curNode.Position.Y:F1})"); - Console.WriteLine( - $" 이전 모터방향: {prevDir}, 현재 모터방향: {pathResult.DetailedPath[i].MotorDirection}"); - Console.WriteLine( - $" 마그넷방향: {pathResult.DetailedPath[i].MagnetDirection}"); + // if (prevNode != null) + // { + // // DirectionalHelper를 사용하여 예상되는 다음 노드 확인 + // Console.WriteLine( + // $"\n[ValidateDockingDirection] 경로 검증 단계 {i}:"); + // Console.WriteLine( + // $" 이전→현재→다음: {prevNode.Id}({prevNode.RfidId}) → {curNode.Id}({curNode.RfidId}) → {nextNode.Id}({nextNode.RfidId})"); + // Console.WriteLine( + // $" 현재 노드 위치: ({curNode.Position.X:F1}, {curNode.Position.Y:F1})"); + // Console.WriteLine( + // $" 이전 모터방향: {prevDir}, 현재 모터방향: {pathResult.DetailedPath[i].MotorDirection}"); + // Console.WriteLine( + // $" 마그넷방향: {pathResult.DetailedPath[i].MagnetDirection}"); - var expectedNextNode = DirectionalHelper.GetNextNodeByDirection( - curNode, - prevNode, - prevDir, - pathResult.DetailedPath[i].MotorDirection, - pathResult.DetailedPath[i].MagnetDirection, - mapNodes - ); + // var expectedNextNode = DirectionalHelper.GetNextNodeByDirection( + // curNode, + // prevNode, + // prevDir, + // pathResult.DetailedPath[i].MotorDirection, + // pathResult.DetailedPath[i].MagnetDirection, + // mapNodes + // ); - Console.WriteLine( - $" [예상] GetNextNodeByDirection 결과: {expectedNextNode?.Id ?? "null"}"); - Console.WriteLine( - $" [실제] DetailedPath 다음 노드: {nextNode.RfidId}[{nextNode.Id}]"); + // var expectedNextNodeL = DirectionalHelper.GetNextNodeByDirection( + // curNode, + // prevNode, + // prevDir, + // pathResult.DetailedPath[i].MotorDirection, + // PathFinding.Planning.MagnetDirection.Left, + // mapNodes + // ); - if (expectedNextNode != null && !expectedNextNode.Id.Equals(nextNode.Id)) - { - string error = - $"[DockingValidator] ⚠️ 경로 방향 불일치" + - $"\n현재={curNode.RfidId}[{curNodeId}] 이전={prevNode.RfidId}[{(prevNode?.Id ?? string.Empty)}] " + - $"\n예상다음={expectedNextNode.RfidId}[{expectedNextNode.Id}] 실제다음={nextNode.RfidId}[{nextNodeId}]"; - Console.WriteLine( - $"[ValidateDockingDirection] ❌ 경로 방향 불일치 검출!"); - Console.WriteLine( - $" 이동 벡터:"); - Console.WriteLine( - $" 이전→현재: ({(curNode.Position.X - prevNode.Position.X):F2}, {(curNode.Position.Y - prevNode.Position.Y):F2})"); - Console.WriteLine( - $" 현재→예상: ({(expectedNextNode.Position.X - curNode.Position.X):F2}, {(expectedNextNode.Position.Y - curNode.Position.Y):F2})"); - Console.WriteLine( - $" 현재→실제: ({(nextNode.Position.X - curNode.Position.X):F2}, {(nextNode.Position.Y - curNode.Position.Y):F2})"); - Console.WriteLine($"[ValidateDockingDirection] 에러메시지: {error}"); - return DockingValidationResult.CreateInvalid( - LastNode.Id, - LastNode.Type, - pathResult.DetailedPath[i].MotorDirection, - pathResult.DetailedPath[i].MotorDirection, - error); + // var expectedNextNodeR = DirectionalHelper.GetNextNodeByDirection( + // curNode, + // prevNode, + // prevDir, + // pathResult.DetailedPath[i].MotorDirection, + // PathFinding.Planning.MagnetDirection.Right, + // mapNodes + // ); + + // var expectedNextNodeS = DirectionalHelper.GetNextNodeByDirection( + // curNode, + // prevNode, + // prevDir, + // pathResult.DetailedPath[i].MotorDirection, + // PathFinding.Planning.MagnetDirection.Straight, + // mapNodes + // ); - } - else - { - Console.WriteLine( - $" ✅ 경로 방향 일치!"); - } - } - } - } + // Console.WriteLine( + // $" [예상] GetNextNodeByDirection 결과: {expectedNextNode?.Id ?? "null"}"); + // Console.WriteLine( + // $" [실제] DetailedPath 다음 노드: {nextNode.RfidId}[{nextNode.Id}]"); + + // if (expectedNextNode != null && !expectedNextNode.Id.Equals(nextNode.Id)) + // { + // string error = + // $"[DockingValidator] ⚠️ 경로 방향 불일치" + + // $"\n현재={curNode.RfidId}[{curNodeId}] 이전={prevNode.RfidId}[{(prevNode?.Id ?? string.Empty)}] " + + // $"\n예상다음={expectedNextNode.RfidId}[{expectedNextNode.Id}] 실제다음={nextNode.RfidId}[{nextNodeId}]"; + // Console.WriteLine( + // $"[ValidateDockingDirection] ❌ 경로 방향 불일치 검출!"); + // Console.WriteLine( + // $" 이동 벡터:"); + // Console.WriteLine( + // $" 이전→현재: ({(curNode.Position.X - prevNode.Position.X):F2}, {(curNode.Position.Y - prevNode.Position.Y):F2})"); + // Console.WriteLine( + // $" 현재→예상: ({(expectedNextNode.Position.X - curNode.Position.X):F2}, {(expectedNextNode.Position.Y - curNode.Position.Y):F2})"); + // Console.WriteLine( + // $" 현재→실제: ({(nextNode.Position.X - curNode.Position.X):F2}, {(nextNode.Position.Y - curNode.Position.Y):F2})"); + // Console.WriteLine($"[ValidateDockingDirection] 에러메시지: {error}"); + // return DockingValidationResult.CreateInvalid( + // LastNode.Id, + // LastNode.Type, + // pathResult.DetailedPath[i].MotorDirection, + // pathResult.DetailedPath[i].MotorDirection, + // error); + + + // } + // else + // { + // Console.WriteLine( + // $" ✅ 경로 방향 일치!"); + // } + // } + // } + //} // 도킹이 필요한 노드인지 확인 (DockDirection이 DontCare가 아닌 경우) diff --git a/Cs_HMI/Project/StateMachine/Step/_SM_RUN.cs b/Cs_HMI/Project/StateMachine/Step/_SM_RUN.cs index 5100d7e..b405854 100644 --- a/Cs_HMI/Project/StateMachine/Step/_SM_RUN.cs +++ b/Cs_HMI/Project/StateMachine/Step/_SM_RUN.cs @@ -134,6 +134,7 @@ namespace Project //마지막위치가 아닌 다른 위치에 있으니 버퍼 작업을 할 수없다 PUB.XBE.StepBuffer = Device.eDocStep.NotSet; PUB.log.AddE($"목적지가 버퍼이나 노드가 불일치 한다 오류사항"); + PUB._mapCanvas.SetAlertMessage("목적지가 버퍼이나 노드 불일치 오류"); PUB.sm.SetNewRunStep(ERunStep.ERROR); } break; diff --git a/Cs_HMI/Project/StateMachine/Step/_SM_RUN_BUFFER_IN.cs b/Cs_HMI/Project/StateMachine/Step/_SM_RUN_BUFFER_IN.cs index e1a947f..adbc4e9 100644 --- a/Cs_HMI/Project/StateMachine/Step/_SM_RUN_BUFFER_IN.cs +++ b/Cs_HMI/Project/StateMachine/Step/_SM_RUN_BUFFER_IN.cs @@ -84,6 +84,7 @@ namespace Project //5초동안 AGV까 움직이지 않았다면 오류 처리한다. PUB.AGV.AGVMoveStop($"[bufferin] {overtime}초이내 턴 감지 안됨"); PUB.log.AddE($"[{funcname}] {overtime}초이내 턴 감지 안됨"); + PUB._mapCanvas.SetAlertMessage("턴 완료 확인 불가"); PUB.sm.SetNewRunStep(ERunStep.ERROR); return false; } @@ -129,6 +130,7 @@ namespace Project { PUB.log.AddE($"[{funcname}] 리프트가 내려가지 않습니다"); PUB.AGV.LiftControl(arDev.Narumi.LiftCommand.STP); + PUB._mapCanvas.SetAlertMessage("리프트가 내려가지 않음"); PUB.sm.SetNewRunStep(ERunStep.ERROR); } return false; @@ -162,6 +164,7 @@ namespace Project { PUB.AGV.AGVMoveStop(funcname); PUB.log.AddE($"[{funcname}] AGV속도설정이 완료되지 않았습니다"); + PUB._mapCanvas.SetAlertMessage("agv속도설정 실패"); PUB.sm.SetNewRunStep(ERunStep.ERROR); } return false; @@ -187,6 +190,7 @@ namespace Project { PUB.AGV.AGVMoveStop(funcname); PUB.log.AddE($"[{funcname}] MARK STOP신호가 확인되지 않습니다"); + PUB._mapCanvas.SetAlertMessage("mark stop 신호 확인 안됨"); PUB.sm.SetNewRunStep(ERunStep.ERROR); return false; } @@ -205,6 +209,7 @@ namespace Project { PUB.AGV.AGVMoveStop(funcname); PUB.log.AddE($"[{funcname}] AGV가 멈추지 않아 강제종료 합니다"); + PUB._mapCanvas.SetAlertMessage("agv가 멈추지 않아 강제 종료"); PUB.sm.SetNewRunStep(ERunStep.ERROR); return false; } diff --git a/Cs_HMI/Project/StateMachine/Step/_SM_RUN_BUFFER_OUT.cs b/Cs_HMI/Project/StateMachine/Step/_SM_RUN_BUFFER_OUT.cs index 6e7bf8f..83610eb 100644 --- a/Cs_HMI/Project/StateMachine/Step/_SM_RUN_BUFFER_OUT.cs +++ b/Cs_HMI/Project/StateMachine/Step/_SM_RUN_BUFFER_OUT.cs @@ -72,6 +72,7 @@ namespace Project { PUB.log.AddE($"[{funcname}] 리프트가 동작하지 않습니다"); PUB.AGV.LiftControl(arDev.Narumi.LiftCommand.STP); + PUB._mapCanvas.SetAlertMessage("LIft 동작오류"); PUB.sm.SetNewRunStep(ERunStep.ERROR); } return false; @@ -96,6 +97,7 @@ namespace Project { PUB.AGV.AGVMoveStop(funcname); PUB.log.AddE($"[{funcname}] AGV속도설정이 완료되지 않았습니다"); + PUB._mapCanvas.SetAlertMessage("agv 속도설정실패"); PUB.sm.SetNewRunStep(ERunStep.ERROR); } return false; diff --git a/Cs_HMI/Project/StateMachine/Step/_SM_RUN_CLEANER_IN.cs b/Cs_HMI/Project/StateMachine/Step/_SM_RUN_CLEANER_IN.cs index 38e4e01..65cdc32 100644 --- a/Cs_HMI/Project/StateMachine/Step/_SM_RUN_CLEANER_IN.cs +++ b/Cs_HMI/Project/StateMachine/Step/_SM_RUN_CLEANER_IN.cs @@ -89,6 +89,7 @@ namespace Project { PUB.AGV.AGVMoveStop(funcname); PUB.log.AddE($"[{funcname}] AGV속도설정이 완료되지 않았습니다"); + PUB._mapCanvas.SetAlertMessage("agv 속도 설정 오류"); PUB.sm.SetNewRunStep(ERunStep.ERROR); } return false; @@ -110,6 +111,7 @@ namespace Project { PUB.AGV.AGVMoveStop(funcname); PUB.log.AddE("MARK STOP신호가 확인되지 않습니다"); + PUB._mapCanvas.SetAlertMessage("mark stop 신호 확인 안됨"); PUB.sm.SetNewRunStep(ERunStep.ERROR); return false; } @@ -128,6 +130,7 @@ namespace Project { PUB.AGV.AGVMoveStop(funcname); PUB.log.AddE("AGV가 멈추지 않아 강제종료 합니다"); + PUB._mapCanvas.SetAlertMessage("agv 가 멈추지 않아 강제 종료"); PUB.sm.SetNewRunStep(ERunStep.ERROR); return false; } diff --git a/Cs_HMI/Project/StateMachine/Step/_SM_RUN_CLEANER_OUT.cs b/Cs_HMI/Project/StateMachine/Step/_SM_RUN_CLEANER_OUT.cs index a92c947..2442332 100644 --- a/Cs_HMI/Project/StateMachine/Step/_SM_RUN_CLEANER_OUT.cs +++ b/Cs_HMI/Project/StateMachine/Step/_SM_RUN_CLEANER_OUT.cs @@ -42,6 +42,7 @@ namespace Project { PUB.AGV.AGVMoveStop(funcname); PUB.log.AddE($"[{funcname}] AGV속도설정이 완료되지 않았습니다"); + PUB._mapCanvas.SetAlertMessage("agv 속도 설정 실패"); PUB.sm.SetNewRunStep(ERunStep.ERROR); } return false; diff --git a/Cs_HMI/Project/StateMachine/Step/_SM_RUN_GOCHARGE.cs b/Cs_HMI/Project/StateMachine/Step/_SM_RUN_GOCHARGE.cs index 4fdee1d..738ad62 100644 --- a/Cs_HMI/Project/StateMachine/Step/_SM_RUN_GOCHARGE.cs +++ b/Cs_HMI/Project/StateMachine/Step/_SM_RUN_GOCHARGE.cs @@ -126,6 +126,7 @@ namespace Project { PUB.log.AddE($"[{funcname}] AGV속도설정 실패"); PUB.AGV.AGVMoveStop("err"); + PUB._mapCanvas.SetAlertMessage("agv 속더 설정 실패"); PUB.sm.SetNewRunStep(ERunStep.ERROR); } return false; diff --git a/Cs_HMI/Project/StateMachine/Step/_SM_RUN_LOADER_IN.cs b/Cs_HMI/Project/StateMachine/Step/_SM_RUN_LOADER_IN.cs index cc5fd0d..7bff4af 100644 --- a/Cs_HMI/Project/StateMachine/Step/_SM_RUN_LOADER_IN.cs +++ b/Cs_HMI/Project/StateMachine/Step/_SM_RUN_LOADER_IN.cs @@ -95,6 +95,7 @@ namespace Project { PUB.AGV.AGVMoveStop(funcname); PUB.log.AddE("AGV속도설정이 완료되지 않았습니다"); + PUB._mapCanvas.SetAlertMessage("agv 속도 설정 실패"); PUB.sm.SetNewRunStep(ERunStep.ERROR); } return false; @@ -115,6 +116,7 @@ namespace Project { PUB.AGV.AGVMoveStop(funcname); PUB.log.AddE("MARK STOP신호가 확인되지 않습니다"); + PUB._mapCanvas.SetAlertMessage("mark stop 신호 확인 불가"); PUB.sm.SetNewRunStep(ERunStep.ERROR); return false; } @@ -133,6 +135,7 @@ namespace Project { PUB.AGV.AGVMoveStop(funcname); PUB.log.AddE("AGV가 멈추지 않아 강제종료 합니다"); + PUB._mapCanvas.SetAlertMessage("agv 가 멈추지 않아 강제 종료"); PUB.sm.SetNewRunStep(ERunStep.ERROR); return false; } diff --git a/Cs_HMI/Project/StateMachine/Step/_SM_RUN_LOADER_OUT.cs b/Cs_HMI/Project/StateMachine/Step/_SM_RUN_LOADER_OUT.cs index 1b39129..7943d2b 100644 --- a/Cs_HMI/Project/StateMachine/Step/_SM_RUN_LOADER_OUT.cs +++ b/Cs_HMI/Project/StateMachine/Step/_SM_RUN_LOADER_OUT.cs @@ -41,6 +41,7 @@ namespace Project { PUB.AGV.AGVMoveStop(funcname); PUB.log.AddE($"[{funcname}] AGV속도설정이 완료되지 않았습니다"); + PUB._mapCanvas.SetAlertMessage("agv 속도 설정 실패"); PUB.sm.SetNewRunStep(ERunStep.ERROR); } return false; diff --git a/Cs_HMI/Project/StateMachine/Step/_SM_RUN_UNLOADER_IN.cs b/Cs_HMI/Project/StateMachine/Step/_SM_RUN_UNLOADER_IN.cs index 5ccd751..c3c9190 100644 --- a/Cs_HMI/Project/StateMachine/Step/_SM_RUN_UNLOADER_IN.cs +++ b/Cs_HMI/Project/StateMachine/Step/_SM_RUN_UNLOADER_IN.cs @@ -90,6 +90,7 @@ namespace Project { PUB.AGV.AGVMoveStop(funcname); PUB.log.AddE($"[{funcname}] AGV속도설정이 완료되지 않았습니다"); + PUB._mapCanvas.SetAlertMessage("agv속도설정오류"); PUB.sm.SetNewRunStep(ERunStep.ERROR); } return false; @@ -112,6 +113,7 @@ namespace Project { PUB.AGV.AGVMoveStop(funcname); PUB.log.AddE("MARK STOP신호가 확인되지 않습니다"); + PUB._mapCanvas.SetAlertMessage("mark stop 신호 확인 불가"); PUB.sm.SetNewRunStep(ERunStep.ERROR); return false; } @@ -130,6 +132,7 @@ namespace Project { PUB.AGV.AGVMoveStop(funcname); PUB.log.AddE("AGV가 멈추지 않아 강제종료 합니다"); + PUB._mapCanvas.SetAlertMessage("agv 가 멈추지 않아 강제 종료 합니다"); PUB.sm.SetNewRunStep(ERunStep.ERROR); return false; } diff --git a/Cs_HMI/Project/StateMachine/Step/_SM_RUN_UNLOADER_OUT.cs b/Cs_HMI/Project/StateMachine/Step/_SM_RUN_UNLOADER_OUT.cs index e57ab00..832a57d 100644 --- a/Cs_HMI/Project/StateMachine/Step/_SM_RUN_UNLOADER_OUT.cs +++ b/Cs_HMI/Project/StateMachine/Step/_SM_RUN_UNLOADER_OUT.cs @@ -41,6 +41,7 @@ namespace Project { PUB.AGV.AGVMoveStop(funcname); PUB.log.AddE($"[{funcname}] AGV속도설정이 완료되지 않았습니다"); + PUB._mapCanvas.SetAlertMessage($"[{funcname}] AGV속도설정이 완료되지 않았습니다"); PUB.sm.SetNewRunStep(ERunStep.ERROR); } return false; diff --git a/Cs_HMI/Project/StateMachine/Step/_Util.cs b/Cs_HMI/Project/StateMachine/Step/_Util.cs index 9ff11f7..88e0d15 100644 --- a/Cs_HMI/Project/StateMachine/Step/_Util.cs +++ b/Cs_HMI/Project/StateMachine/Step/_Util.cs @@ -101,8 +101,7 @@ namespace Project } //경로 생성(경로정보가 없거나 현재노드가 경로에 없는경우) - if (PUB._virtualAGV.CurrentPath == null || - PUB._virtualAGV.CurrentPath.DetailedPath.Any() == false || + if (PUB._virtualAGV.HasPath() == false || PUB._virtualAGV.CurrentPath.DetailedPath.Where(t => t.NodeId.Equals(currentNode.Id)).Any() == false) { if (PUB.AGV.system1.agv_run) @@ -112,6 +111,15 @@ namespace Project } var PathResult = CalcPath(PUB._virtualAGV.StartNode, PUB._virtualAGV.TargetNode); + if(PathResult.result !=null && + PathResult.result.Success == true && + PathResult.result.DetailedPath.Where(t => t.NodeId == currentNode.Id).Any() == false) + { + PUB._virtualAGV.StartNode = PUB._virtualAGV.CurrentNode; + PathResult = CalcPath(PUB._virtualAGV.StartNode, PUB._virtualAGV.TargetNode); + } + + if (PathResult.result == null) { PUB.log.AddE($"경로가 계산되지 않았습니다"); @@ -120,9 +128,10 @@ namespace Project } else { - //계산은 되었으나 현재위치가 전체 경로 없다면 시작노드를 현재로 변경해야한다. - PUB._mapCanvas.CurrentPath = PathResult.result; - PUB._virtualAGV.SetPath(PathResult.result); + + PUB._mapCanvas.CurrentPath = PathResult.result; + PUB._virtualAGV.SetPath(PathResult.result); + } PUB.log.AddI($"경로생성 {PUB._virtualAGV.StartNode.RfidId} -> {PUB._virtualAGV.TargetNode.RfidId}"); @@ -136,12 +145,12 @@ namespace Project PUB.AGV.AGVMoveStop("Path Integrity Fail"); } PUB.log.AddE($"경로 무결성 오류로 인해 경로를 삭제 합니다"); - Console.WriteLine($"경로 무결성 오류로 인해 경로를 삭제 합니다"); PUB._virtualAGV.SetPath(null); VAR.I32[eVarInt32.PathValidationError] += 1; if (VAR.I32[eVarInt32.PathValidationError] > 50) { PUB.log.AddE($"연속 경로 무결성 오류로 인해 중지 합니다"); + PUB._mapCanvas.SetAlertMessage($"연속 경로 무결성 오류로 인해 중지 합니다"); PUB.sm.SetNewRunStep(ERunStep.ERROR); } return false; @@ -182,16 +191,6 @@ namespace Project return false; } - var message = $"[다음 행동 예측]\n\n" + - $"모터: {nextAction.Motor}\n" + - $"마그넷: {nextAction.Magnet}\n" + - $"속도: {nextAction.Speed}\n" + - $"이유: {nextAction.Message}\n\n" + - $"---\n" + - $"현재 상태: {PUB._virtualAGV.CurrentState}\n" + - $"현재 방향: {PUB._virtualAGV.CurrentDirection}\n" + - $"위치 확정: {PUB._virtualAGV.IsPositionConfirmed} (RFID {PUB._virtualAGV.DetectedRfidCount}개)\n" + - $"현재 노드: {PUB._virtualAGV.CurrentNodeID2}"; //모터에서 정지를 요청했다 if (nextAction.Motor == AGVNavigationCore.Models.MotorCommand.Stop) diff --git a/Cs_HMI/Project/StateMachine/_AGV.cs b/Cs_HMI/Project/StateMachine/_AGV.cs index 8c4a593..c53d070 100644 --- a/Cs_HMI/Project/StateMachine/_AGV.cs +++ b/Cs_HMI/Project/StateMachine/_AGV.cs @@ -226,12 +226,23 @@ namespace Project var message = $"[다음 행동 예측]\n\n"; if (VAR.BOOL[eVarBool.FLAG_AUTORUN] == false) - message += "[수동모드]\n\n"; + message += "[X] 수동모드\n"; + + if (PUB._virtualAGV.TargetNode == null) message += "[X] 목표노드없음\n"; + if (PUB._virtualAGV.CurrentNode == null) message += "[X] 현재노드없음\n"; + else if (PUB._virtualAGV.HasPath() == false) message += "[X] 경로계산안됨\n"; + if (PUB._virtualAGV.PrevNode == null) message += "[X] 이전노드없음\n"; + else message += $"이전노드: {PUB._virtualAGV.PrevNode.ID2} : {PUB._virtualAGV.PrevDirection}\n"; + message += $"현재노드: {PUB._virtualAGV.CurrentNode.ID2} : {PUB._virtualAGV.CurrentDirection}\n"; + + message += "-------------\n"; var node = PUB._virtualAGV.CurrentNode; var curpos = PUB._virtualAGV.CurrentNodeID2; var targetpos = PUB._virtualAGV.TargetNode?.ID2 ?? "(X)"; + + var pathdetail = ""; if (PUB._virtualAGV.CurrentPath != null && PUB._virtualAGV.CurrentPath.DetailedPath.Any()) { @@ -250,13 +261,13 @@ namespace Project $"마그넷: {nextAction.Magnet}\n" + $"속도: {nextAction.Speed}\n" + $"이유: {nextAction.Message}\n" + - $"상태머신:{PUB.sm.Step}:{PUB.sm.RunStep}:{PUB.sm.RunStepSeq}\n"+ + $"상태머신:{PUB.sm.Step}:{PUB.sm.RunStep}:{PUB.sm.RunStepSeq}\n" + $"---\n" + $"현재 상태: {PUB._virtualAGV.CurrentState}\n" + $"현재 방향: {PUB._virtualAGV.CurrentDirection}\n" + $"턴: {PUB._virtualAGV.Turn}\n" + $"위치 확정: {PUB._virtualAGV.IsPositionConfirmed} (RFID {PUB._virtualAGV.DetectedRfidCount}개)\n" + - $"현재 노드: {curpos}\n" + + $"대상 노드: {targetpos}\n" + $"상세 경로: {pathdetail}"; diff --git a/Cs_HMI/Project/fMain.cs b/Cs_HMI/Project/fMain.cs index 77ee9ef..0c2dfdb 100644 --- a/Cs_HMI/Project/fMain.cs +++ b/Cs_HMI/Project/fMain.cs @@ -437,6 +437,7 @@ namespace Project PUB.Speak(Lang.자동전환, addlog: false); PUB.log.Add($"자동전환 이전스텝:{PUB.sm.RunStep},IDX:{PUB.sm.RunStepSeq}]"); + PUB._mapCanvas.SetAlertMessage("START"); } else {