diff --git a/Cs_HMI/AGVLogic/AGVNavigationCore/AGVNavigationCore.csproj b/Cs_HMI/AGVLogic/AGVNavigationCore/AGVNavigationCore.csproj
index a5f78e5..d04e3fc 100644
--- a/Cs_HMI/AGVLogic/AGVNavigationCore/AGVNavigationCore.csproj
+++ b/Cs_HMI/AGVLogic/AGVNavigationCore/AGVNavigationCore.csproj
@@ -94,6 +94,7 @@
UnifiedAGVCanvas.cs
+
diff --git a/Cs_HMI/AGVLogic/AGVNavigationCore/Controls/UnifiedAGVCanvas.Events.cs b/Cs_HMI/AGVLogic/AGVNavigationCore/Controls/UnifiedAGVCanvas.Events.cs
index c8d8fe4..8cd8a4d 100644
--- a/Cs_HMI/AGVLogic/AGVNavigationCore/Controls/UnifiedAGVCanvas.Events.cs
+++ b/Cs_HMI/AGVLogic/AGVNavigationCore/Controls/UnifiedAGVCanvas.Events.cs
@@ -207,6 +207,9 @@ namespace AGVNavigationCore.Controls
{
DrawPath(g, _currentPath, Color.Purple);
+ // 경로 내 교차로 강조 표시
+ HighlightJunctionsInPath(g, _currentPath);
+
// AGVPathResult의 모터방향 정보가 있다면 향상된 경로 그리기
// 현재는 기본 PathResult를 사용하므로 향후 AGVPathResult로 업그레이드 시 활성화
// TODO: AGVPathfinder 사용시 AGVPathResult로 업그레이드
@@ -282,7 +285,96 @@ namespace AGVNavigationCore.Controls
pathPen.Dispose();
}
-
+ ///
+ /// 경로에 포함된 교차로(3개 이상의 노드가 연결된 노드)를 파란색으로 강조 표시
+ ///
+ private void HighlightJunctionsInPath(Graphics g, AGVPathResult path)
+ {
+ if (path?.Path == null || _nodes == null || _nodes.Count == 0)
+ return;
+
+ const int JUNCTION_CONNECTIONS = 3; // 교차로 판정 기준: 3개 이상의 연결
+
+ foreach (var nodeId in path.Path)
+ {
+ var node = _nodes.FirstOrDefault(n => n.NodeId == nodeId);
+ if (node == null) continue;
+
+ // 교차로 판정: 3개 이상의 노드가 연결된 경우
+ if (node.ConnectedNodes != null && node.ConnectedNodes.Count >= JUNCTION_CONNECTIONS)
+ {
+ DrawJunctionHighlight(g, node);
+ }
+ }
+ }
+
+ ///
+ /// 교차로 노드를 파란색 반투명 배경으로 강조 표시
+ ///
+ private void DrawJunctionHighlight(Graphics g, MapNode junctionNode)
+ {
+ if (junctionNode == null) return;
+
+ const int JUNCTION_HIGHLIGHT_RADIUS = 25; // 강조 표시 반경
+
+ // 파란색 반투명 브러시로 배경 원 그리기
+ using (var highlightBrush = new SolidBrush(Color.FromArgb(80, 70, 130, 200))) // 파란색 (70, 130, 200) 알파 80
+ using (var highlightPen = new Pen(Color.FromArgb(150, 100, 150, 220), 2)) // 파란 테두리
+ {
+ g.FillEllipse(
+ highlightBrush,
+ junctionNode.Position.X - JUNCTION_HIGHLIGHT_RADIUS,
+ junctionNode.Position.Y - JUNCTION_HIGHLIGHT_RADIUS,
+ JUNCTION_HIGHLIGHT_RADIUS * 2,
+ JUNCTION_HIGHLIGHT_RADIUS * 2
+ );
+
+ g.DrawEllipse(
+ highlightPen,
+ junctionNode.Position.X - JUNCTION_HIGHLIGHT_RADIUS,
+ junctionNode.Position.Y - JUNCTION_HIGHLIGHT_RADIUS,
+ JUNCTION_HIGHLIGHT_RADIUS * 2,
+ JUNCTION_HIGHLIGHT_RADIUS * 2
+ );
+ }
+
+ // 교차로 라벨 추가
+ DrawJunctionLabel(g, junctionNode);
+ }
+
+ ///
+ /// 교차로 라벨을 표시 (선택사항)
+ ///
+ private void DrawJunctionLabel(Graphics g, MapNode junctionNode)
+ {
+ if (junctionNode == null) return;
+
+ using (var font = new Font("Arial", 9, FontStyle.Bold))
+ using (var brush = new SolidBrush(Color.Blue))
+ {
+ var text = "교차로";
+ var textSize = g.MeasureString(text, font);
+
+ // 노드 위쪽에 라벨 표시
+ var labelX = junctionNode.Position.X - textSize.Width / 2;
+ var labelY = junctionNode.Position.Y - 35;
+
+ // 배경 박스 그리기
+ using (var bgBrush = new SolidBrush(Color.FromArgb(220, 255, 255, 200)))
+ {
+ g.FillRectangle(
+ bgBrush,
+ labelX - 3,
+ labelY - 3,
+ textSize.Width + 6,
+ textSize.Height + 6
+ );
+ }
+
+ g.DrawString(text, font, brush, labelX, labelY);
+ }
+ }
+
private void DrawNodesOnly(Graphics g)
diff --git a/Cs_HMI/AGVLogic/AGVNavigationCore/PathFinding/Core/AGVPathResult.cs b/Cs_HMI/AGVLogic/AGVNavigationCore/PathFinding/Core/AGVPathResult.cs
index 5db3f63..f7e5295 100644
--- a/Cs_HMI/AGVLogic/AGVNavigationCore/PathFinding/Core/AGVPathResult.cs
+++ b/Cs_HMI/AGVLogic/AGVNavigationCore/PathFinding/Core/AGVPathResult.cs
@@ -91,6 +91,11 @@ namespace AGVNavigationCore.PathFinding.Core
///
public string DirectionChangeNode { get; set; }
+ ///
+ /// 경로계산시 사용했던 최초 이전 포인트 이전의 노드
+ ///
+ public MapNode PrevNode { get; set; }
+
///
/// 기본 생성자
///
@@ -110,6 +115,7 @@ namespace AGVNavigationCore.PathFinding.Core
RequiredDirectionChange = false;
DirectionChangeNode = string.Empty;
DockingValidation = DockingValidationResult.CreateNotRequired();
+ PrevNode = null;
}
///
@@ -135,29 +141,7 @@ namespace AGVNavigationCore.PathFinding.Core
return result;
}
- ///
- /// 성공 결과 생성 (노드별 모터방향 정보 포함)
- ///
- /// 경로
- /// AGV 명령어 목록
- /// 노드별 모터방향 정보
- /// 총 거리
- /// 계산 시간
- /// 성공 결과
- public static AGVPathResult CreateSuccess(List path, List commands, List nodeMotorInfos, float totalDistance, long calculationTimeMs)
- {
- var result = new AGVPathResult
- {
- Success = true,
- Path = new List(path),
- Commands = new List(commands),
- TotalDistance = totalDistance,
- CalculationTimeMs = calculationTimeMs
- };
-
- result.CalculateMetrics();
- return result;
- }
+
///
/// 실패 결과 생성
@@ -193,37 +177,6 @@ namespace AGVNavigationCore.PathFinding.Core
};
}
- ///
- /// 성공 결과 생성 (상세 경로용)
- ///
- /// 상세 경로
- /// 총 거리
- /// 계산 시간
- /// 탐색된 노드 수
- /// 계획 설명
- /// 방향 전환 여부
- /// 방향 전환 노드
- /// 성공 결과
- public static AGVPathResult CreateSuccess(List detailedPath, float totalDistance, long calculationTimeMs, int exploredNodes, string planDescription, bool directionChange = false, string changeNode = null)
- {
- var path = detailedPath?.Select(n => n.NodeId).ToList() ?? new List();
-
- var result = new AGVPathResult
- {
- Success = true,
- Path = path,
- DetailedPath = detailedPath ?? new List(),
- TotalDistance = totalDistance,
- CalculationTimeMs = calculationTimeMs,
- ExploredNodes = exploredNodes,
- PlanDescription = planDescription ?? string.Empty,
- RequiredDirectionChange = directionChange,
- DirectionChangeNode = changeNode ?? string.Empty
- };
-
- result.CalculateMetrics();
- return result;
- }
///
/// 경로 메트릭 계산
diff --git a/Cs_HMI/AGVLogic/AGVNavigationCore/PathFinding/Core/AStarPathfinder.cs b/Cs_HMI/AGVLogic/AGVNavigationCore/PathFinding/Core/AStarPathfinder.cs
index 39057c4..bd66618 100644
--- a/Cs_HMI/AGVLogic/AGVNavigationCore/PathFinding/Core/AStarPathfinder.cs
+++ b/Cs_HMI/AGVLogic/AGVNavigationCore/PathFinding/Core/AStarPathfinder.cs
@@ -403,6 +403,7 @@ namespace AGVNavigationCore.PathFinding.Core
// DetailedPath 설정
result.DetailedPath = combinedDetailedPath;
+ result.PrevNode = previousResult.PrevNode;
return result;
}
diff --git a/Cs_HMI/AGVLogic/AGVNavigationCore/PathFinding/Planning/AGVPathfinder.cs b/Cs_HMI/AGVLogic/AGVNavigationCore/PathFinding/Planning/AGVPathfinder.cs
index 0b63d8c..f0c5833 100644
--- a/Cs_HMI/AGVLogic/AGVNavigationCore/PathFinding/Planning/AGVPathfinder.cs
+++ b/Cs_HMI/AGVLogic/AGVNavigationCore/PathFinding/Planning/AGVPathfinder.cs
@@ -122,9 +122,15 @@ namespace AGVNavigationCore.PathFinding.Planning
//1.목적지까지의 최단거리 경로를 찾는다.
var pathResult = _basicPathfinder.FindPath(startNode.NodeId, targetNode.NodeId);
+ pathResult.PrevNode = prevNode;
if (!pathResult.Success || pathResult.Path == null || pathResult.Path.Count == 0)
return AGVPathResult.CreateFailure("각 노드간 최단 경로 계산이 실패되었습니다", 0, 0);
+ //정방향/역방향 이동 시 다음 노드 확인
+ var nextNodeForward = DirectionalHelper.GetNextNodeByDirection(startNode, prevNode, currentDirection, _mapNodes);
+ var nextNodeBackward = DirectionalHelper.GetNextNodeByDirection(startNode, prevNode, ReverseDirection, _mapNodes);
+
+
//2.AGV방향과 목적지에 설정된 방향이 일치하면 그대로 진행하면된다.(목적지에 방향이 없는 경우에도 그대로 진행)
if (targetNode.DockDirection == DockingDirection.DontCare ||
(targetNode.DockDirection == DockingDirection.Forward && currentDirection == AgvDirection.Forward) ||
@@ -135,6 +141,7 @@ namespace AGVNavigationCore.PathFinding.Planning
return pathResult;
}
+
//2-1 현재위치의 반대방향과 대상의 방향이 맞는 경우에도 그대로 사용가능하다.
//if (targetNode.DockDirection == DockingDirection.DontCare ||
// (targetNode.DockDirection == DockingDirection.Forward && currentDirection == AgvDirection.Backward) ||
@@ -147,17 +154,20 @@ namespace AGVNavigationCore.PathFinding.Planning
// return pathResult;
//}
- //2-2 정방향/역방향 이동 시 다음 노드 확인
- var nextNodeForward = GetNextNodeByDirection(startNode, prevNode, currentDirection, _mapNodes);
- var nextNodeBackward = GetNextNodeByDirection(startNode, prevNode, ReverseDirection, _mapNodes);
-
+
//뒤로 이동시 경로상의 처음 만나는 노드가 같다면 그 방향으로 이동하면 된다.
- if (nextNodeBackward.NodeId == pathResult.Path[1])
+ if (nextNodeBackward.NodeId == pathResult.Path[1] && targetNode.DockDirection == DockingDirection.Backward)
{
MakeDetailData(pathResult, ReverseDirection);
MakeMagnetDirection(pathResult);
return pathResult;
}
+ if(nextNodeForward.NodeId == pathResult.Path[1] && targetNode.DockDirection == DockingDirection.Forward)
+ {
+ MakeDetailData(pathResult, currentDirection);
+ MakeMagnetDirection(pathResult);
+ return pathResult;
+ }
//if(nextNodeForward.NodeId == pathResult.Path[1])
//{
@@ -184,12 +194,27 @@ namespace AGVNavigationCore.PathFinding.Planning
//1.시작위치 - 교차로(여기까지는 현재 방향으로 그대로 이동을 한다)
var path1 = _basicPathfinder.FindPath(startNode.NodeId, JunctionInPath.NodeId);
+ path1.PrevNode = prevNode;
+
+ //다음좌표를 보고 정방향인지 역방향인지 체크한다.
+ if( nextNodeForward.NodeId.Equals( path1.Path[1]))
+ {
+ MakeDetailData(path1, currentDirection); // path1의 상세 경로 정보 채우기 (모터 방향 설정)
+ }
+ else if(nextNodeBackward.NodeId.Equals(path1.Path[1]))
+ {
+ MakeDetailData(path1, ReverseDirection); // path1의 상세 경로 정보 채우기 (모터 방향 설정)
+ }
+ else return AGVPathResult.CreateFailure("교차로까지 계산된 경로에 현재 위치정보로 추측을 할 수 없습니다", 0, 0);
+
+
+
+
- // path1의 상세 경로 정보 채우기 (모터 방향 설정)
- MakeDetailData(path1, currentDirection);
//2.교차로 - 종료위치
var path2 = _basicPathfinder.FindPath(JunctionInPath.NodeId, targetNode.NodeId);
+ path2.PrevNode = prevNode;
MakeDetailData(path2, ReverseDirection);
//3.방향전환을 위환 대체 노드찾기
@@ -265,100 +290,6 @@ namespace AGVNavigationCore.PathFinding.Planning
}
}
- ///
- /// 현재 노드에서 주어진 방향(Forward/Backward)으로 이동할 때 다음 노드를 반환
- ///
- /// 현재 노드
- /// 이전 노드 (진행 방향 기준점)
- /// 이동 방향 (Forward 또는 Backward)
- /// 모든 맵 노드
- /// 다음 노드 (또는 null)
- private MapNode GetNextNodeByDirection(MapNode currentNode, MapNode prevNode, AgvDirection direction, List allNodes)
- {
- if (currentNode == null || prevNode == null || allNodes == null)
- return null;
-
- // 현재 노드에 연결된 노드들 중 이전 노드가 아닌 노드들만 필터링
- var connectedNodeIds = currentNode.ConnectedNodes;
- if (connectedNodeIds == null || connectedNodeIds.Count == 0)
- return null;
-
- var candidateNodes = allNodes.Where(n =>
- connectedNodeIds.Contains(n.NodeId)
- ).ToList();
-
- if (candidateNodes.Count == 0)
- return null;
-
- // Forward인 경우: 이전→현재 방향으로 계속 직진하는 노드 우선
- // Backward인 경우: 이전→현재 방향의 반대로 이동하는 노드 우선
- var movementVector = new PointF(
- currentNode.Position.X - prevNode.Position.X,
- currentNode.Position.Y - prevNode.Position.Y
- );
-
- var movementLength = (float)Math.Sqrt(
- movementVector.X * movementVector.X +
- movementVector.Y * movementVector.Y
- );
-
- if (movementLength < 0.001f)
- return candidateNodes[0];
-
- var normalizedMovement = new PointF(
- movementVector.X / movementLength,
- movementVector.Y / movementLength
- );
-
- // 각 후보 노드에 대해 점수 계산
- MapNode bestNode = null;
- float bestScore = float.MinValue;
-
- foreach (var candidate in candidateNodes)
- {
- var toNextVector = new PointF(
- candidate.Position.X - currentNode.Position.X,
- candidate.Position.Y - currentNode.Position.Y
- );
-
- var toNextLength = (float)Math.Sqrt(
- toNextVector.X * toNextVector.X +
- toNextVector.Y * toNextVector.Y
- );
-
- if (toNextLength < 0.001f)
- continue;
-
- var normalizedToNext = new PointF(
- toNextVector.X / toNextLength,
- toNextVector.Y / toNextLength
- );
-
- // 내적 계산 (유사도: -1 ~ 1)
- float dotProduct = (normalizedMovement.X * normalizedToNext.X) +
- (normalizedMovement.Y * normalizedToNext.Y);
-
- float score;
- if (direction == AgvDirection.Forward)
- {
- // Forward: 진행 방향과 유사한 방향 선택 (높은 내적 = 좋음)
- score = dotProduct;
- }
- else // Backward
- {
- // Backward: 진행 방향과 반대인 방향 선택 (낮은 내적 = 좋음)
- score = -dotProduct;
- }
-
- if (score > bestScore)
- {
- bestScore = score;
- bestNode = candidate;
- }
- }
-
- return bestNode;
- }
///
/// Path에 등록된 방향을 확인하여 마그넷정보를 업데이트 합니다
diff --git a/Cs_HMI/AGVLogic/AGVNavigationCore/Utils/DirectionalHelper.cs b/Cs_HMI/AGVLogic/AGVNavigationCore/Utils/DirectionalHelper.cs
new file mode 100644
index 0000000..d79c0fe
--- /dev/null
+++ b/Cs_HMI/AGVLogic/AGVNavigationCore/Utils/DirectionalHelper.cs
@@ -0,0 +1,114 @@
+using System;
+using System.Collections.Generic;
+using System.Drawing;
+using System.Linq;
+using AGVNavigationCore.Models;
+
+namespace AGVNavigationCore.Utils
+{
+ ///
+ /// AGV 방향 계산 헬퍼 유틸리티
+ /// 현재 위치에서 주어진 모터 방향으로 이동할 때 다음 노드를 계산
+ ///
+ public static class DirectionalHelper
+ {
+ ///
+ /// 현재 노드에서 주어진 방향(Forward/Backward)으로 이동할 때 다음 노드를 반환
+ ///
+ /// 현재 노드
+ /// 이전 노드 (진행 방향 기준점)
+ /// 이동 방향 (Forward 또는 Backward)
+ /// 모든 맵 노드
+ /// 다음 노드 (또는 null)
+ public static MapNode GetNextNodeByDirection(
+ MapNode currentNode,
+ MapNode prevNode,
+ AgvDirection direction,
+ List allNodes)
+ {
+ if (currentNode == null || prevNode == null || allNodes == null)
+ return null;
+
+ // 현재 노드에 연결된 노드들 중 이전 노드가 아닌 노드들만 필터링
+ var connectedNodeIds = currentNode.ConnectedNodes;
+ if (connectedNodeIds == null || connectedNodeIds.Count == 0)
+ return null;
+
+ var candidateNodes = allNodes.Where(n =>
+ connectedNodeIds.Contains(n.NodeId)
+ ).ToList();
+
+ if (candidateNodes.Count == 0)
+ return null;
+
+ // Forward인 경우: 이전→현재 방향으로 계속 직진하는 노드 우선
+ // Backward인 경우: 이전→현재 방향의 반대로 이동하는 노드 우선
+ var movementVector = new PointF(
+ currentNode.Position.X - prevNode.Position.X,
+ currentNode.Position.Y - prevNode.Position.Y
+ );
+
+ var movementLength = (float)Math.Sqrt(
+ movementVector.X * movementVector.X +
+ movementVector.Y * movementVector.Y
+ );
+
+ if (movementLength < 0.001f)
+ return candidateNodes[0];
+
+ var normalizedMovement = new PointF(
+ movementVector.X / movementLength,
+ movementVector.Y / movementLength
+ );
+
+ // 각 후보 노드에 대해 점수 계산
+ MapNode bestNode = null;
+ float bestScore = float.MinValue;
+
+ foreach (var candidate in candidateNodes)
+ {
+ var toNextVector = new PointF(
+ candidate.Position.X - currentNode.Position.X,
+ candidate.Position.Y - currentNode.Position.Y
+ );
+
+ var toNextLength = (float)Math.Sqrt(
+ toNextVector.X * toNextVector.X +
+ toNextVector.Y * toNextVector.Y
+ );
+
+ if (toNextLength < 0.001f)
+ continue;
+
+ var normalizedToNext = new PointF(
+ toNextVector.X / toNextLength,
+ toNextVector.Y / toNextLength
+ );
+
+ // 내적 계산 (유사도: -1 ~ 1)
+ float dotProduct = (normalizedMovement.X * normalizedToNext.X) +
+ (normalizedMovement.Y * normalizedToNext.Y);
+
+ float score;
+ if (direction == AgvDirection.Forward)
+ {
+ // Forward: 진행 방향과 유사한 방향 선택 (높은 내적 = 좋음)
+ score = dotProduct;
+ }
+ else // Backward
+ {
+ // Backward: 진행 방향과 반대인 방향 선택 (낮은 내적 = 좋음)
+ score = -dotProduct;
+ }
+
+ if (score > bestScore)
+ {
+ bestScore = score;
+ bestNode = candidate;
+ }
+ }
+
+ return bestNode;
+ }
+ }
+}
diff --git a/Cs_HMI/AGVLogic/AGVNavigationCore/Utils/DockingValidator.cs b/Cs_HMI/AGVLogic/AGVNavigationCore/Utils/DockingValidator.cs
index 6e86211..1869bdb 100644
--- a/Cs_HMI/AGVLogic/AGVNavigationCore/Utils/DockingValidator.cs
+++ b/Cs_HMI/AGVLogic/AGVNavigationCore/Utils/DockingValidator.cs
@@ -41,6 +41,59 @@ namespace AGVNavigationCore.Utils
System.Diagnostics.Debug.WriteLine($"[DockingValidator] 목적지 노드: {targetNodeId} 타입:{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;
+
+ var curNode = mapNodes?.FirstOrDefault(n => n.NodeId == curNodeId);
+ var nextNode = mapNodes?.FirstOrDefault(n => n.NodeId == nextNodeId);
+
+ if (curNode != null && nextNode != null)
+ {
+ MapNode prevNode = null;
+ if (i == 0) prevNode = pathResult.PrevNode;
+ else
+ {
+ var prevNodeId = pathResult.DetailedPath[i - 1].NodeId;
+ prevNode = mapNodes?.FirstOrDefault(n => n.NodeId == prevNodeId);
+ }
+
+
+ if (prevNode != null)
+ {
+ // DirectionalHelper를 사용하여 예상되는 다음 노드 확인
+ var expectedNextNode = DirectionalHelper.GetNextNodeByDirection(
+ curNode,
+ prevNode,
+ pathResult.DetailedPath[i].MotorDirection,
+ mapNodes
+ );
+
+ if (expectedNextNode != null && !expectedNextNode.NodeId.Equals(nextNode.NodeId))
+ {
+
+
+ string error =
+ $"[DockingValidator] ⚠️ 경로 방향 불일치: " +
+ $"현재={curNode.RfidId}[{curNodeId}] 이전={prevNode.RfidId}[{(prevNode?.NodeId ?? string.Empty)}] " +
+ $"예상다음={expectedNextNode.RfidId}[{expectedNextNode.NodeId}] 실제다음={nextNode.RfidId}[{nextNodeId}]";
+ System.Diagnostics.Debug.WriteLine($"[DockingValidator] ❌ 도킹 검증 실패: {error}");
+ return DockingValidationResult.CreateInvalid(
+ targetNodeId,
+ LastNode.Type,
+ pathResult.DetailedPath[i].MotorDirection,
+ pathResult.DetailedPath[i].MotorDirection,
+ error);
+
+
+ }
+ }
+ }
+ }
+
+
// 도킹이 필요한 노드인지 확인 (DockDirection이 DontCare가 아닌 경우)
if (LastNode.DockDirection == DockingDirection.DontCare)
{
diff --git a/Cs_HMI/AGVLogic/ANALYSIS_AGV_Direction_Storage.md b/Cs_HMI/AGVLogic/ANALYSIS_AGV_Direction_Storage.md
deleted file mode 100644
index d9a4995..0000000
--- a/Cs_HMI/AGVLogic/ANALYSIS_AGV_Direction_Storage.md
+++ /dev/null
@@ -1,276 +0,0 @@
-# AGV 방향 정보 저장 위치 분석
-
-## 개요
-AGV의 이동 방향을 계산하기 위해 **이전 RFID 위치 정보**와 **현재 모터 방향(전/후진)**을 함께 저장하고 관리하는 시스템
-
----
-
-## 📍 저장 위치: VirtualAGV.cs (AGVSimulator\Models\VirtualAGV.cs)
-
-### 핵심 필드 (Field) 구조
-
-#### 현재 상태 (Current State)
-```csharp
-private Point _currentPosition; // 현재 AGV 위치 (픽셀 좌표)
-private MapNode _currentNode; // 현재 노드 (RFID ID 포함)
-private AgvDirection _currentDirection; // 현재 모터 방향 (Forward/Backward)
-```
-
-#### 이전 상태 (Previous State - 리프트 방향 계산용)
-```csharp
-private Point _targetPosition; // 이전 위치 (previousPos 역할)
-private MapNode _targetNode; // 이전 노드 (이전 RFID)
-private AgvDirection _targetDirection; // 이전 모터 방향
-```
-
-### 데이터 구조 시각화
-```
-이전 상태 (n-1) 현재 상태 (n)
-────────────────────────────────────
-_targetPosition ─────→ _currentPosition (좌표 이동)
-_targetNode ─────→ _currentNode (RFID 이동)
-_targetDirection ─────→ _currentDirection (모터 방향)
-```
-
----
-
-## 🔄 SetPosition() 메서드 - 위치 및 방향 업데이트
-
-### 위치: VirtualAGV.cs 305~322행
-
-```csharp
-///
-/// AGV 위치 직접 설정 (시뮬레이터용)
-/// TargetPosition을 이전 위치로 저장하여 리프트 방향 계산이 가능하도록 함
-///
-/// 현재 RFID 노드
-/// 새로운 위치
-/// 모터이동방향 (Forward/Backward)
-public void SetPosition(MapNode node, Point newPosition, AgvDirection motorDirection)
-{
- // 현재 위치를 이전 위치로 저장 (리프트 방향 계산용)
- if (_currentPosition != Point.Empty)
- {
- _targetPosition = _currentPosition; // ← 이전 위치 저장
- _targetDirection = _currentDirection; // ← 이전 방향 저장
- _targetNode = node; // ← 이전 노드(RFID) 저장
- }
-
- // 새로운 위치 설정
- _currentPosition = newPosition; // 현재 위치 설정
- _currentDirection = motorDirection; // 현재 모터방향 설정
- _currentNode = node; // 현재 노드(RFID) 설정
-
- // 위치 변경 이벤트 발생
- PositionChanged?.Invoke(this, (_currentPosition, _currentDirection, _currentNode));
-}
-```
-
-### SetPosition() 실행 흐름
-
-| 단계 | 동작 | 데이터 |
-|------|------|--------|
-| **1단계: 이전 상태 백업** | 현재 위치 → 이전 위치로 저장 | _currentPosition → _targetPosition |
-| | 현재 방향 → 이전 방향으로 저장 | _currentDirection → _targetDirection |
-| | 현재 노드 → 이전 노드로 저장 | _currentNode → _targetNode |
-| **2단계: 새 상태 설정** | 새 좌표 저장 | newPosition → _currentPosition |
-| | 새 모터방향 저장 | motorDirection → _currentDirection |
-| | 새 노드(RFID) 저장 | node → _currentNode |
-| **3단계: 이벤트 발생** | 위치 변경 알림 | PositionChanged 이벤트 발생 |
-
----
-
-## 🧭 리프트 방향 계산에 사용되는 정보
-
-### 필요한 정보
-1. **이전 위치**: _targetPosition
-2. **현재 위치**: _currentPosition
-3. **현재 모터 방향**: _currentDirection (Forward/Backward)
-
-### 리프트 방향 계산 로직
-**파일**: `AGVNavigationCore\Utils\LiftCalculator.cs`
-**메서드**: `CalculateLiftAngleRadians(Point currentPos, Point targetPos, AgvDirection motorDirection)`
-
-#### 계산식 (모터 방향 고려)
-```csharp
-if (motorDirection == AgvDirection.Forward)
-{
- // 전진: 현재→목표 벡터 (리프트가 목표 방향 향함)
- var dx = targetPos.X - currentPos.X;
- var dy = targetPos.Y - currentPos.Y;
-}
-else if (motorDirection == AgvDirection.Backward)
-{
- // 후진: 현재→목표 벡터 반대 (리프트가 이동 방향 향함)
- var dx = currentPos.X - targetPos.X;
- var dy = currentPos.Y - targetPos.Y;
-}
-
-// 각도 계산
-var angle = Math.Atan2(dy, dx);
-```
-
-### 계산 예시
-
-#### 상황 1: 전진 모드 (Forward)
-```
-위치: 006 (100, 100) → 005 (150, 100) 이동 중
-
-_targetPosition = (100, 100) // 이전 위치 (006)
-_currentPosition = (150, 100) // 현재 위치 (005)
-_currentDirection = Forward // 전진
-
-벡터: (150-100, 100-100) = (50, 0) ⇒ 오른쪽(0°)
-리프트 방향: 오른쪽(0°)으로 회전
-```
-
-#### 상황 2: 후진 모드 (Backward)
-```
-위치: 006 (100, 100) → 005 (150, 100) 이동 중 (후진)
-
-_targetPosition = (100, 100) // 이전 위치 (006)
-_currentPosition = (150, 100) // 현재 위치 (005)
-_currentDirection = Backward // 후진
-
-벡터: (100-150, 100-100) = (-50, 0) ⇒ 왼쪽(180°)
-리프트 방향: 왼쪽(180°)으로 회전 (이동 방향 반대)
-```
-
----
-
-## 📊 저장된 정보 요약
-
-### VirtualAGV가 저장하는 RFID/방향 정보
-
-| 정보 | 필드명 | 타입 | 설명 |
-|------|--------|------|------|
-| **이전 위치** | _targetPosition | Point | 이전 RFID 감지 위치 |
-| **이전 RFID** | _targetNode | MapNode | 이전 RFID 정보 (RfidId 포함) |
-| **이전 방향** | _targetDirection | AgvDirection | 이전 모터 방향 |
-| **현재 위치** | _currentPosition | Point | 현재 RFID 감지 위치 |
-| **현재 RFID** | _currentNode | MapNode | 현재 RFID 정보 (RfidId 포함) |
-| **현재 방향** | _currentDirection | AgvDirection | 현재 모터 방향 (Forward/Backward) |
-
-### MapNode에 포함된 RFID 정보
-
-```csharp
-public class MapNode
-{
- public string RfidId { get; set; } // 물리적 RFID ID
- public string RfidStatus { get; set; } // RFID 상태
- public string RfidDescription { get; set; } // RFID 설명
-
- // ... 기타 노드 정보
-}
-```
-
----
-
-## 🔍 호출 흐름: SetPosition() 언제 호출되는가?
-
-### 호출 위치들
-
-#### 1. **AGV 시뮬레이션에서의 자동 위치 업데이트**
-**시나리오**: AGV가 경로를 따라 이동 중
-
-```csharp
-// VirtualAGV.cs의 경로 실행 중
-ProcessNextNode()
- ↓
-다음 노드에 도착 후
-SetPosition(nextNode, nextPosition, motorDirection)
- ↓
-_targetPosition ← 이전 위치 저장
-_currentPosition ← 새 위치 설정
-```
-
-#### 2. **시뮬레이터 UI에서의 수동 위치 설정**
-**시나리오**: 사용자가 시뮬레이터에서 AGV를 수동으로 배치
-
-```csharp
-// SimulatorForm에서 사용자 클릭
-userClicksOnCanvas()
- ↓
-SetPosition(selectedNode, clickPosition, currentDirection)
- ↓
-VirtualAGV 위치 업데이트
-```
-
----
-
-## 💾 이 정보가 사용되는 곳들
-
-### 1. **리프트 방향 계산** (LiftCalculator.cs)
-```csharp
-var liftAngle = CalculateLiftAngleRadians(
- _targetPosition, // 이전 위치
- _currentPosition, // 현재 위치
- _currentDirection // 현재 모터 방향
-);
-```
-
-### 2. **경로 방향 검증** (DirectionChangePlanner.cs)
-```csharp
-// 현재 방향이 목표 도킹 방향과 일치하는지 확인
-bool needDirectionChange = (_currentDirection != requiredDockingDirection);
-```
-
-### 3. **UI 렌더링** (UnifiedAGVCanvas.cs)
-```csharp
-// AGV 리프트 그리기 시 방향 정보 사용
-DrawAGVLiftAdvanced(graphics, agv);
- ↓
-agv.CurrentDirection (현재 방향)
-agv.TargetPosition (이전 위치)
-```
-
-### 4. **위치 변경 이벤트 발생**
-```csharp
-PositionChanged?.Invoke(this,
- (_currentPosition, _currentDirection, _currentNode)
-);
-```
-
----
-
-## 🎯 요약: AGV 방향 계산 데이터 흐름
-
-```
-입력: RFID 감지 + 모터 방향 정보
- ↓
-SetPosition(node, newPos, direction) 호출
- ↓
-[이전 상태 백업]
- _targetPosition = 이전 위치
- _targetDirection = 이전 방향
- _targetNode = 이전 RFID
- ↓
-[현재 상태 설정]
- _currentPosition = 새 위치
- _currentDirection = 현재 방향
- _currentNode = 현재 RFID
- ↓
-[리프트 방향 계산에 사용]
- LiftCalculator.CalculateLiftAngleRadians(
- 이전위치, 현재위치, 현재방향
- )
- ↓
-결과: AGV의 정확한 리프트 방향 결정
-```
-
----
-
-## 📌 중요 포인트
-
-✅ **이전 위치 보존**: SetPosition() 호출 시 기존 현재 위치를 이전 위치로 저장
-✅ **방향 정보 포함**: 이전/현재 방향 모두 저장하여 리프트 회전 계산
-✅ **RFID 매핑**: MapNode에 RfidId 포함하여 물리적 RFID와 논리적 위치 연계
-✅ **이벤트 발행**: 위치 변경 시 자동으로 PositionChanged 이벤트 발생
-✅ **파라미터 분리**: motorDirection을 별도 파라미터로 받아 명확한 방향 제어
-
----
-
-## 🔧 현재 상태: 시뮬레이터에서만 구현
-
-현재 이 저장 메커니즘은 **VirtualAGV.cs에 전체 주석처리**되어 있습니다.
-실제 운영 시스템에서는 이와 유사한 메커니즘이 **실제 AGV 하드웨어 제어 모듈**에서 구현될 것으로 예상됩니다.
diff --git a/Cs_HMI/AGVLogic/BACKWARD_FIX_SUMMARY_KO.md b/Cs_HMI/AGVLogic/BACKWARD_FIX_SUMMARY_KO.md
deleted file mode 100644
index bd66e2e..0000000
--- a/Cs_HMI/AGVLogic/BACKWARD_FIX_SUMMARY_KO.md
+++ /dev/null
@@ -1,147 +0,0 @@
-# Backward 방향 로직 수정 - 최종 요약
-
-**수정 완료**: 2025-10-23
-**상태**: 🟢 완료됨
-
----
-
-## 문제점
-
-### 사용자 피드백
-> "002 → 003으로 후진상태로 이동완료한 후. 003위치에서 후진방향으로 다음 노드를 예측하면 004가 아니라 002가 나와.. 잘못되었어."
-
-### 발생한 오류
-```
-이동: 002 → 003 (Backward 모터)
-위치: 003
-다음 노드 예측: GetNextNodeId(Backward)
-
-잘못된 결과: N002 ❌
-올바른 결과: N004 ✅
-```
-
----
-
-## 원인 분석
-
-### Backward 케이스의 잘못된 로직
-```csharp
-case AgvDirection.Backward:
- if (dotProduct < -0.9f) // ❌ 반대 방향만 찾음
- baseScore = 100.0f;
-```
-
-이렇게 하면:
-- 002→003 이동 벡터: (72, 34)
-- Backward에서는 반대 벡터만 선호
-- 결과: (-72, -34) = N002를 선택 ❌
-
-### 사용자의 올바른 이해
-> "역방향모터 구동이든 정방향 모터 구동이든 의미야.. 모터 방향 바꾼다고해서 AGV몸체가 방향을 바꾸는게 아니야."
-
-**해석**:
-- 모터 방향(Forward/Backward)은 단순히 모터가 어느 방향으로 회전하는지
-- **AGV 몸체의 이동 방향은 변하지 않음**
-- 따라서 경로 선택도 동일해야 함
-
----
-
-## 해결책
-
-### 수정된 Backward 로직
-```csharp
-case AgvDirection.Backward:
- // ✅ Forward와 동일하게 같은 경로 방향 선호
- // 모터 방향(역진)은 이미 _currentDirection에 저장됨
- if (dotProduct > 0.9f)
- baseScore = 100.0f;
- else if (dotProduct > 0.5f)
- baseScore = 80.0f;
- // ... Forward와 동일한 로직
-```
-
-### 수정된 파일
-- **파일**: `AGVNavigationCore\Models\VirtualAGV.cs`
-- **라인**: 755-767
-- **변경**: Backward 케이스를 Forward와 동일하게 처리
-
----
-
-## 검증 결과
-
-### 문제였던 시나리오 4: 002 → 003 → Backward
-
-**이동 벡터**: (72, 34)
-
-**후보 N004 (380, 340)**:
-- 벡터: (102, 62) → 정규화: (0.853, 0.519)
-- 내적: 0.901 × 0.853 + 0.426 × 0.519 ≈ **0.989**
-- Forward/Backward 모두: dotProduct > 0.9 → **100점** ✅
-
-**후보 N002 (206, 244)**:
-- 벡터: (-72, -34) → 정규화: (-0.901, -0.426)
-- 내적: 0.901 × (-0.901) + 0.426 × (-0.426) ≈ **-0.934**
-- Forward/Backward 모두: dotProduct < -0.9 하지만... < -0.5 → **20점** ❌
-
-**결과**: N004 선택 ✅ **문제 해결!**
-
----
-
-## 모든 시나리오 검증
-
-| 시나리오 | 이동 경로 | 모터 | 결과 | 예상 | 상태 |
-|---------|---------|------|------|------|------|
-| 1 | 001→002 | Forward | N003 | N003 | ✅ |
-| 2 | 001→002 | Backward | N003 | N003 | ✅ |
-| 3 | 002→003 | Forward | N004 | N004 | ✅ |
-| 4 | 002→003 | Backward | **N004** | **N004** | ✅ **FIXED** |
-
----
-
-## 개념 정리
-
-### Forward vs Backward의 의미
-
-```
-❌ 잘못된 이해:
- Forward = 앞으로 가는 방향
- Backward = 뒤로 가는 방향 (경로도 반대)
-
-✅ 올바른 이해:
- Forward = 모터 정방향 회전 (경로는 그대로)
- Backward = 모터 역방향 회전 (경로는 그대로)
-
- → 경로 선택은 이동 벡터에만 의존
- → Forward/Backward 모두 같은 경로 선호
-```
-
-### AGV 이동의 실제 동작
-
-```
-002에서 003으로 이동: 이동 벡터 = (72, 34)
-
-③에서 다음 노드 선택:
-- Forward 모터: 같은 방향 경로 선호 → N004
-- Backward 모터: 같은 방향 경로 선호 → N004
-
-모터 방향은 모터 회전 방향만 나타낼 뿐,
-경로 선택에는 영향을 주지 않음!
-```
-
----
-
-## 최종 상태
-
-✅ **Backward 로직 수정 완료**
-
-- 파일: VirtualAGV.cs (라인 755-767)
-- 변경: Forward와 동일한 로직으로 수정
-- 결과: 사용자 피드백 "N004가 나와야 한다" 충족
-- 검증: 모든 4가지 시나리오 패스
-
-**다음 단계**: 실제 맵 파일로 통합 테스트
-
----
-
-**완료**: 2025-10-23
-**상태**: 🟢 전체 구현 및 수정 완료
diff --git a/Cs_HMI/AGVLogic/BACKWARD_FIX_VERIFICATION.md b/Cs_HMI/AGVLogic/BACKWARD_FIX_VERIFICATION.md
deleted file mode 100644
index a252e1f..0000000
--- a/Cs_HMI/AGVLogic/BACKWARD_FIX_VERIFICATION.md
+++ /dev/null
@@ -1,277 +0,0 @@
-# Backward 방향 로직 수정 검증 보고서
-
-**수정 완료**: 2025-10-23
-**상태**: ✅ 수정 완료 및 검증 됨
-
----
-
-## 📋 요약
-
-### 발견된 문제
-사용자 피드백: "002 → 003으로 후진상태로 이동완료한 후, 003위치에서 후진방향으로 다음 노드를 예측하면 004가 아니라 002가 나와... 잘못되었어."
-
-**결과**:
-- 실제: N002 (잘못된 결과)
-- 예상: N004 (올바른 결과)
-
-### 근본 원인
-`CalculateDirectionalScore()` 메서드의 `AgvDirection.Backward` 케이스가 반대 방향을 찾도록 구현됨:
-```csharp
-case AgvDirection.Backward:
- if (dotProduct < -0.9f) // ❌ 반대 방향 선호
- baseScore = 100.0f;
-```
-
-### 해결책
-사용자의 올바른 이해에 따라 로직 수정:
-> "역방향모터 구동이든 정방향 모터 구동이든 의미야.. 모터 방향 바꾼다고해서 AGV몸체가 방향을 바꾸는게 아니야."
-
-**Backward를 Forward와 동일하게 처리** (경로 선호도는 동일):
-```csharp
-case AgvDirection.Backward:
- if (dotProduct > 0.9f) // ✅ Forward와 동일하게 같은 방향 선호
- baseScore = 100.0f;
-```
-
----
-
-## 🔧 수정 상세
-
-### 수정 파일
-**파일**: `AGVNavigationCore\Models\VirtualAGV.cs`
-**라인**: 755-767
-
-### 수정 전
-```csharp
-case AgvDirection.Backward:
- // Backward: 역진 방향 선호 (dotProduct ≈ -1)
- if (dotProduct < -0.9f)
- baseScore = 100.0f;
- else if (dotProduct < -0.5f)
- baseScore = 80.0f;
- else if (dotProduct < 0.0f)
- baseScore = 50.0f;
- else if (dotProduct < 0.5f)
- baseScore = 20.0f;
- break;
-```
-
-### 수정 후
-```csharp
-case AgvDirection.Backward:
- // Backward: Forward와 동일하게 같은 경로 방향 선호 (dotProduct ≈ 1)
- // 모터 방향(역진)은 이미 _currentDirection에 저장됨
- // GetNextNodeId의 direction 파라미터는 경로 계속 의도를 나타냄
- if (dotProduct > 0.9f)
- baseScore = 100.0f;
- else if (dotProduct > 0.5f)
- baseScore = 80.0f;
- else if (dotProduct > 0.0f)
- baseScore = 50.0f;
- else if (dotProduct > -0.5f)
- baseScore = 20.0f;
- break;
-```
-
----
-
-## ✅ 검증: 모든 시나리오
-
-### 테스트 맵
-```
-N001 (65, 229)
- ↓
-N002 (206, 244)
- ↓
-N003 (278, 278)
- ↓
-N004 (380, 340)
-```
-
-### 시나리오 1: 001 → 002 → Forward
-```
-이동 벡터: (206-65, 244-229) = (141, 15)
-정규화: (0.987, 0.105)
-
-후보 1 - N001 위치 (65, 229):
- 벡터: (65-206, 229-244) = (-141, -15)
- 정규화: (-0.987, -0.105)
- 내적: 0.987×(-0.987) + 0.105×(-0.105) ≈ -0.985
-
- Forward에서: dotProduct < -0.5 → 20점
-
-후보 2 - N003 위치 (278, 278):
- 벡터: (278-206, 278-244) = (72, 34)
- 정규화: (0.901, 0.426)
- 내적: 0.987×0.901 + 0.105×0.426 ≈ 0.934
-
- Forward에서: dotProduct > 0.9 → 100점 ✅
-
-결과: N003 선택 ✅ PASS
-```
-
-### 시나리오 2: 001 → 002 → Backward
-```
-이동 벡터: (141, 15)
-정규화: (0.987, 0.105)
-
-후보 1 - N001 위치:
- 내적: -0.985
-
- Backward에서 (수정 후): dotProduct > 0.9? No
- dotProduct < -0.5? Yes → 20점
-
-후보 2 - N003 위치:
- 내적: 0.934
-
- Backward에서 (수정 후): dotProduct > 0.9? Yes → 100점 ✅
-
-결과: N003 선택 ✅ PASS
-```
-
-### 시나리오 3: 002 → 003 → Forward
-```
-이동 벡터: (278-206, 278-244) = (72, 34)
-정규화: (0.901, 0.426)
-
-후보 1 - N002 위치:
- 벡터: (-72, -34)
- 정규화: (-0.901, -0.426)
- 내적: -0.934
-
- Forward에서: dotProduct < 0 → 20점
-
-후보 2 - N004 위치 (380, 340):
- 벡터: (380-278, 340-278) = (102, 62)
- 정규화: (0.853, 0.519)
- 내적: 0.901×0.853 + 0.426×0.519 ≈ 0.989
-
- Forward에서: dotProduct > 0.9 → 100점 ✅
-
-결과: N004 선택 ✅ PASS
-```
-
-### 시나리오 4: 002 → 003 → Backward (✨ 수정된 케이스)
-```
-이동 벡터: (72, 34)
-정규화: (0.901, 0.426)
-
-후보 1 - N002 위치:
- 벡터: (-72, -34)
- 정규화: (-0.901, -0.426)
- 내적: -0.934
-
- Backward에서 (수정 후): dotProduct > 0.9? No
- dotProduct > 0.5? No
- dotProduct > 0.0? No
- dotProduct > -0.5? Yes → 20점
-
-후보 2 - N004 위치:
- 벡터: (102, 62)
- 정규화: (0.853, 0.519)
- 내적: 0.989
-
- Backward에서 (수정 후): dotProduct > 0.9? Yes → 100점 ✅
-
-결과: N004 선택 ✅ PASS (사용자 피드백과 일치!)
-```
-
----
-
-## 📊 결과 비교
-
-| 시나리오 | 이동 경로 | 방향 | 수정 전 | 수정 후 | 예상 | 검증 |
-|---------|---------|------|-------|--------|------|------|
-| 1 | 001→002 | Forward | N003 | N003 | N003 | ✅ |
-| 2 | 001→002 | Backward | N002 | N003 | N003 | ✅ |
-| 3 | 002→003 | Forward | N004 | N004 | N004 | ✅ |
-| 4 | 002→003 | Backward | ❌ N002 | ✅ N004 | N004 | ✅ FIXED |
-
----
-
-## 🎯 핵심 개념 정리
-
-### 1. 모터 방향 vs 경로 방향
-- **모터 방향** (_currentDirection): Forward/Backward - 모터가 어느 방향으로 돌아가는지
-- **경로 방향** (direction 파라미터): Forward/Backward - AGV가 계속 같은 경로로 갈 의도
-
-### 2. GetNextNodeId() 파라미터의 의미
-
-#### 이전 (잘못된) 이해
-- Forward: 같은 벡터 방향
-- Backward: 반대 벡터 방향
-- 결과: 방향이 바뀌면 경로도 바뀜 ❌
-
-#### 현재 (올바른) 이해
-- Forward: 같은 벡터 방향 선호
-- Backward: 같은 벡터 방향 선호 (Forward와 동일)
-- 결과: 모터 방향이 바뀌어도 경로는 유지 ✅
-
-### 3. 왜 Forward와 Backward가 같은 로직인가?
-
-AGV가 002에서 003으로 (72, 34) 벡터로 이동했다:
-- 정방향 모터(Forward)라면: 같은 방향으로 계속 → N004
-- 역방향 모터(Backward)라면: 역방향으로 회전하면서 같은 경로 계속 → N004
-
-**모터 방향만 다를 뿐, AGV 몸체는 같은 경로를 따라간다!**
-
----
-
-## 📝 테스트 파일 업데이트
-
-**파일**: `AGVNavigationCore\Utils\GetNextNodeIdTest.cs`
-
-**시나리오 4 수정**:
-```csharp
-// 수정 전
-TestScenario(
- "Backward 이동: 002에서 003으로, 다음은 Backward",
- node002.Position, node003, node002, // 예상: N002 ❌
- AgvDirection.Backward, allNodes,
- "002 (예상)"
-);
-
-// 수정 후
-TestScenario(
- "Backward 이동: 002에서 003으로, 다음은 Backward (경로 계속)",
- node002.Position, node003, node004, // 예상: N004 ✅
- AgvDirection.Backward, allNodes,
- "004 (예상 - 경로 계속)"
-);
-```
-
----
-
-## 🔗 관련 파일
-
-| 파일 | 변경 내용 |
-|------|---------|
-| VirtualAGV.cs | CalculateDirectionalScore() Backward 케이스 수정 |
-| GetNextNodeIdTest.cs | 시나리오 4 예상 결과 업데이트 |
-| BACKWARD_LOGIC_FIX.md | 수정 과정 상세 설명 |
-
----
-
-## ✨ 최종 상태
-
-### 수정 내용
-- ✅ VirtualAGV.cs의 Backward 로직 수정
-- ✅ GetNextNodeIdTest.cs의 테스트 케이스 업데이트
-- ✅ 사용자 피드백 "004가 나와야 한다" 충족
-
-### 동작 검증
-- ✅ 시나리오 1-4 모두 올바른 결과 반환
-- ✅ 모터 방향 변경 시에도 경로 유지
-- ✅ 사용자 의도 "모터 방향은 그냥 모터 방향일 뿐" 반영
-
-### 다음 단계
-1. 프로젝트 컴파일 및 빌드 확인
-2. GetNextNodeIdTest 실행으로 검증
-3. 맵 시뮬레이터로 실제 동작 확인
-4. NewMap.agvmap 파일로 실제 경로 테스트
-
----
-
-**완료 일시**: 2025-10-23
-**상태**: 🟢 수정 및 검증 완료
-**다음 작업**: 컴파일 및 런타임 테스트
diff --git a/Cs_HMI/AGVLogic/BACKWARD_LOGIC_FIX.md b/Cs_HMI/AGVLogic/BACKWARD_LOGIC_FIX.md
deleted file mode 100644
index 280aba2..0000000
--- a/Cs_HMI/AGVLogic/BACKWARD_LOGIC_FIX.md
+++ /dev/null
@@ -1,189 +0,0 @@
-# Backward 방향 로직 수정 완료
-
-## 🎯 핵심 개념
-
-**사용자 피드백**: "역방향모터 구동이든 정방향 모터 구동이든 의미야.. 모터 방향 바꾼다고해서 AGV몸체가 방향을 바꾸는게 아니야."
-
-**번역**: 역방향(Backward) 모터 구동이든 정방향(Forward) 모터 구동이든 동일한 의미입니다. 모터 방향을 바꾼다고 해서 AGV 몸체가 방향을 바꾸는 것은 아닙니다.
-
-## ❌ 문제점 (수정 전)
-
-### 잘못된 이해
-- **Backward**: 반대 방향을 찾는다 (dotProduct < -0.9f)
-- **Forward**: 같은 방향을 찾는다 (dotProduct > 0.9f)
-- 모터 방향 차이가 경로 방향 선택에 영향
-
-### 실제 문제 시나리오
-```
-002 (206, 244) → 003 (278, 278) → Backward 이동
-현재 위치: 003
-이동 벡터: (72, 34) - 002에서 003으로의 방향
-
-GetNextNodeId(Backward) 호출:
-❌ 결과: 002 (반대 방향 선택)
-✅ 예상: 004 (경로 계속)
-```
-
-## ✅ 해결책 (수정 후)
-
-### 올바른 이해
-**Forward와 Backward 모두 동일한 경로를 선호한다**
-- **Forward**: 이동 방향과 같은 경로 선호 (dotProduct > 0.9f)
-- **Backward**: 이동 방향과 같은 경로 선호 (dotProduct > 0.9f) ← 수정됨!
-- 모터 방향(_currentDirection) vs 경로 방향(direction 파라미터) 분리
-
-### 수정 내용
-
-**파일**: `AGVNavigationCore\Models\VirtualAGV.cs` (라인 755-767)
-
-**수정 전**:
-```csharp
-case AgvDirection.Backward:
- // Backward: 역진 방향 선호 (dotProduct ≈ -1) ❌
- if (dotProduct < -0.9f)
- baseScore = 100.0f;
- else if (dotProduct < -0.5f)
- baseScore = 80.0f;
- // ... 반대 방향 선택
-```
-
-**수정 후**:
-```csharp
-case AgvDirection.Backward:
- // Backward: Forward와 동일하게 같은 경로 방향 선호 (dotProduct ≈ 1) ✅
- // 모터 방향(역진)은 이미 _currentDirection에 저장됨
- // GetNextNodeId의 direction 파라미터는 경로 계속 의도를 나타냄
- if (dotProduct > 0.9f)
- baseScore = 100.0f;
- else if (dotProduct > 0.5f)
- baseScore = 80.0f;
- // ... Forward와 동일
-```
-
-## 📐 동작 원리
-
-### 벡터 계산
-```
-이전 → 현재 = 이동 벡터 (AGV 몸체의 이동 방향)
-
-현재 → 다음 후보들 = 후보 벡터들
-
-내적 (Dot Product):
-- 1에 가까움: 같은 방향 (경로 계속)
-- -1에 가까움: 반대 방향 (경로 돌아감)
-
-Forward 선호: dotProduct > 0.9f (같은 방향)
-Backward 선호: dotProduct > 0.9f (같은 방향) ← 수정됨!
-```
-
-### 기본 개념
-
-```
-AGV 몸체는 경로를 따라 이동
-↓
-모터 방향(Forward/Backward)은 MOTOR가 어느 방향으로 회전하는지
-↓
-경로는 변하지 않음, 모터 방향만 변함
-↓
-GetNextNodeId(direction)의 direction은:
-- 모터가 정방향/역방향 중 어느 것으로 회전하는지 나타냄
-- 다음 노드 선택에는 영향을 주지 않음 (경로 선호도는 동일)
-```
-
-## 🧪 검증: 수정된 동작
-
-### 시나리오 1: 001 → 002 → Forward
-```
-이동 벡터: (141, 15)
-후보 1 (N001): (-141, -15) → dot = -0.985 → 20점
-후보 2 (N003): (72, 34) → dot = 0.934 → 100점 ✅
-결과: N003 선택 ✓
-```
-
-### 시나리오 2: 001 → 002 → Backward (이전: 실패, 이제: 성공)
-```
-이동 벡터: (141, 15)
-후보 1 (N001): (-141, -15) → dot = -0.985 → ? (이전엔 100점)
-후보 2 (N003): (72, 34) → dot = 0.934 → ? (이전엔 0점)
-
-수정 후 (Forward와 동일한 로직):
-후보 1 (N001): dot = -0.985 < -0.5 → 20점 (< 0 구간)
-후보 2 (N003): dot = 0.934 > 0.9 → 100점 ✅
-결과: N003 선택... 잠깐, 이건 틀렸다!
-```
-
-### 🚨 새로운 문제 발견
-
-실제로 시나리오 2를 다시 분석해보니, 001 → 002 → **Backward** 이후에는 **001로 돌아가는 것이 맞다**.
-
-왜냐하면:
-- AGV가 001에서 002로 FORWARD 모터로 이동했다
-- 002에서 BACKWARD 모터를 켜면, AGV는 역방향으로 움직인다
-- 역방향이면 다시 001로 돌아간다
-
-따라서 **방향 파라미터는 정말로 의미가 있다**!
-
-### ✅ 올바른 이해
-
-```
-시나리오별 분석:
-
-1️⃣ 001→002 FORWARD 이동
- 이동 벡터: (141, 15)
-
- 다음에 FORWARD? → 같은 벡터 방향 선호 → 003 ✓
- 다음에 BACKWARD? → 반대 벡터 방향 선호 → 001 ✓
-
-2️⃣ 002→003 FORWARD 이동
- 이동 벡터: (72, 34)
-
- 다음에 FORWARD? → 같은 벡터 방향 선호 → 004 ✓
- 다음에 BACKWARD? → 반대 벡터 방향 선호 → 002 ✓
-
-3️⃣ 002→003 BACKWARD 이동
- 이동 벡터: (72, 34)
-
- 다음에 BACKWARD? → 같은 벡터 방향 선호 → 004 ✓
- (모터 방향은 역상이지만, 이동 벡터는 같음)
-```
-
-### 🎯 실제 의미
-
-**사용자의 의도**:
-> "모터 방향(Forward/Backward)은 모터가 어느 방향으로 돌아가는지일 뿐,
-> AGV 몸체의 이동 경로 방향과는 별개다"
-
-**그러나 실제로는**:
-- 모터 방향이 역방향이면, 같은 경로에서도 반대편으로 간다
-- Forward 001→002 후, Backward라면 역진 모터로 002→001이 된다
-- 따라서 direction 파라미터는 "현재 모터 상태"를 나타낸다
-
-### ❓ 사용자 질문과 재확인 필요
-
-현재 혼동된 부분:
-1. 사용자는 "모터 방향은 그냥 모터 방향일 뿐"이라고 했지만
-2. 실제로는 모터 방향이 AGV 이동 방향에 영향을 미친다
-
-**재확인 필요한 사항**:
-- 002→003 BACKWARD 이동 후, 003에서 BACKWARD 방향으로 다음은:
- - 사용자 의도: 004 (경로 계속)?
- - 아니면: 002 (모터 역방향이므로 돌아감)?
-
----
-
-## 📝 임시 결론
-
-수정한 로직에서:
-- **Forward & Backward 모두**: dotProduct > 0.9f 선호
-- 결과적으로 같은 경로를 계속 선호
-
-하지만 **002→003 BACKWARD 이동 후**의 결과는:
-- 002→003 벡터: (72, 34)
-- N004 벡터: (102, 62) → dot ≈ 0.989 > 0.9 → 100점 ✓
-- N002 벡터: (-72, -34) → dot ≈ -0.934 < -0.9 → 0점
-
-따라서 결과: **N004 선택** ✓
-
-이는 사용자 피드백 "004가 나와야 한다"와 일치한다!
-
-**현재 수정 상태: ✅ CORRECT**
diff --git a/Cs_HMI/AGVLogic/CLAUDE.md b/Cs_HMI/AGVLogic/CLAUDE.md
deleted file mode 100644
index 348ca06..0000000
--- a/Cs_HMI/AGVLogic/CLAUDE.md
+++ /dev/null
@@ -1,221 +0,0 @@
-# CLAUDE.md (AGVLogic 폴더)
-
-이 파일은 AGVLogic 폴더에서 개발 중인 AGV 관련 프로젝트들을 위한 개발 가이드입니다.
-
-**현재 폴더 위치**: `C:\Data\Source\(5613#) ENIG AGV\Source\Cs_HMI\AGVLogic\`
-**맵데이터**: `../Data/NewMap.agvmap` 파일을 기준으로 사용
-
----
-
-## 프로젝트 개요
-
-현재 AGVLogic 폴더에서 다음 3개의 독립 프로젝트를 개발 중입니다:
-
-### 1. AGVMapEditor (맵 에디터)
-**위치**: `./AGVMapEditor/`
-**실행파일**: `./AGVMapEditor/bin/Debug/AGVMapEditor.exe`
-
-#### 핵심 기능
-- **맵 노드 관리**: 논리적 노드 생성, 연결, 속성 설정
-- **RFID 매핑**: 물리적 RFID ID ↔ 논리적 노드 ID 매핑
-- **시각적 편집**: 드래그앤드롭으로 노드 배치 및 연결
-- **JSON 저장**: 맵 데이터를 JSON 형식으로 저장/로드
-- **노드 연결 관리**: 연결 목록 표시 및 직접 삭제 기능
-
-#### 핵심 클래스
-- **MapNode**: 논리적 맵 노드 (NodeId, 위치, 타입, 연결 정보)
-- **RfidMapping**: RFID 물리적 ID ↔ 논리적 노드 ID 매핑
-- **NodeResolver**: RFID ID를 통한 노드 해석기
-- **MapCanvas**: 시각적 맵 편집 컨트롤
-
-### 2. AGVNavigationCore (경로 탐색 라이브러리)
-**위치**: `./AGVNavigationCore/`
-
-#### 핵심 기능
-- **A* 경로 탐색**: 최적 경로 계산 알고리즘
-- **방향 제어**: 전진/후진 모터 방향 결정
-- **도킹 검증**: 충전기/장비 도킹 방향 검증
-- **리프트 계산**: AGV 리프트 각도 계산
-- **경로 최적화**: 회전 구간 회피 등 고급 옵션
-
-#### 핵심 클래스
-- **PathFinding/Core/AStarPathfinder.cs**: A* 알고리즘 구현
-- **PathFinding/Planning/AGVPathfinder.cs**: 경로 탐색 메인 클래스
-- **PathFinding/Planning/DirectionChangePlanner.cs**: 방향 변경 계획
-- **Utils/LiftCalculator.cs**: 리프트 각도 계산
-- **Utils/DockingValidator.cs**: 도킹 유효성 검증
-- **Controls/UnifiedAGVCanvas.cs**: 맵 및 AGV 시각화
-
-### 3. AGVSimulator (AGV 시뮬레이터)
-**위치**: `./AGVSimulator/`
-**실행파일**: `./AGVSimulator/bin/Debug/AGVSimulator.exe`
-
-#### 핵심 기능
-- **가상 AGV 시뮬레이션**: 실시간 AGV 움직임 및 상태 관리
-- **맵 시각화**: 맵 에디터에서 생성한 맵 파일 로드 및 표시
-- **경로 실행**: 계산된 경로를 따라 AGV 시뮬레이션
-- **상태 모니터링**: AGV 상태, 위치, 배터리 등 실시간 표시
-
-#### 핵심 클래스
-- **VirtualAGV**: 가상 AGV 동작 시뮬레이션 (이동, 회전, 도킹, 충전)
-- **SimulatorCanvas**: AGV 및 맵 시각화 캔버스
-- **SimulatorForm**: 시뮬레이터 메인 인터페이스
-- **SimulationState**: 시뮬레이션 상태 관리
-
-#### AGV 상태
-- **Idle**: 대기
-- **Moving**: 이동 중
-- **Rotating**: 회전 중
-- **Docking**: 도킹 중
-- **Charging**: 충전 중
-- **Error**: 오류
-
----
-
-## AGV 방향 제어 및 도킹 시스템
-
-### AGV 하드웨어 레이아웃
-```
-LIFT --- AGV --- MONITOR
- ↑ ↑ ↑
-후진시 AGV본체 전진시
-도달위치 도달위치
-```
-
-### 모터 방향과 이동 방향
-- **전진 모터 (Forward)**: AGV가 모니터 방향으로 이동 (→)
-- **후진 모터 (Backward)**: AGV가 리프트 방향으로 이동 (←)
-
-### 도킹 방향 규칙
-- **충전기 (Charging)**: 전진 도킹 (Forward) - 모니터가 충전기 면
-- **장비 (Docking)**: 후진 도킹 (Backward) - 리프트가 장비 면
-
-### 핵심 계산 파일들
-1. **LiftCalculator.cs** - 리프트 방향 계산
- - `CalculateLiftAngleRadians(Point currentPos, Point targetPos, AgvDirection motorDirection)`
-
-2. **DirectionChangePlanner.cs** - 도킹 방향 결정
- - `GetRequiredDockingDirection(string targetNodeId)` - 노드타입별 도킹 방향 반환
-
-3. **VirtualAGV.cs** - AGV 위치/방향 관리
- - `SetPosition(Point newPosition)` - AGV 위치 및 방향 설정
-
----
-
-## AGVNavigationCore 프로젝트 구조
-
-### 📁 폴더 구조
-```
-AGVNavigationCore/
-├── Controls/
-│ ├── UnifiedAGVCanvas.cs # AGV 및 맵 시각화 메인 캔버스
-│ ├── UnifiedAGVCanvas.Events.cs # 그리기 및 이벤트 처리
-│ ├── UnifiedAGVCanvas.Mouse.cs # 마우스 인터랙션
-│ ├── AGVState.cs # AGV 상태 정의
-│ └── IAGV.cs # AGV 인터페이스
-│
-├── Models/
-│ ├── MapNode.cs # 맵 노드 데이터 모델
-│ ├── MapLoader.cs # JSON 맵 파일 로더
-│ └── Enums.cs # 열거형 정의 (NodeType, AgvDirection 등)
-│
-├── Utils/
-│ ├── LiftCalculator.cs # 리프트 각도 계산
-│ └── DockingValidator.cs # 도킹 유효성 검증
-│
-└── PathFinding/
- ├── Analysis/
- │ └── JunctionAnalyzer.cs # 교차점 분석
- │
- ├── Core/
- │ ├── AStarPathfinder.cs # A* 알고리즘
- │ ├── PathNode.cs # 경로 노드
- │ └── AGVPathResult.cs # 경로 계산 결과
- │
- ├── Planning/
- │ ├── AGVPathfinder.cs # 경로 탐색 메인 클래스
- │ ├── AdvancedAGVPathfinder.cs # 고급 경로 탐색
- │ ├── DirectionChangePlanner.cs # 방향 변경 계획
- │ ├── NodeMotorInfo.cs # 노드별 모터 정보
- │ └── PathfindingOptions.cs # 경로 탐색 옵션
- │
- └── Validation/
- ├── DockingValidationResult.cs # 도킹 검증 결과
- └── PathValidationResult.cs # 경로 검증 결과
-```
-
-### 🎯 클래스 배치 원칙
-
-#### PathFinding/Validation/
-- **검증 결과 클래스**: `*ValidationResult.cs` 패턴 사용
-- **패턴**: 정적 팩토리 메서드 (CreateValid, CreateInvalid, CreateNotRequired)
-- **속성**: IsValid, ValidationError, 관련 상세 정보
-
-#### PathFinding/Planning/
-- **경로 계획 클래스**: 실제 경로 탐색 및 계획 로직
-- **방향 변경 로직**: DirectionChangePlanner.cs
-- **경로 최적화**: 경로 생성과 관련된 전략
-
-#### PathFinding/Core/
-- **핵심 알고리즘**: A* 알고리즘 등 기본 경로 탐색
-- **기본 경로 탐색**: 단순한 점-to-점 경로 계산
-
-#### PathFinding/Analysis/
-- **경로 분석**: 생성된 경로의 품질 및 특성 분석
-- **성능 분석**: 경로 효율성 및 최적화 분석
-
----
-
-## 개발 워크플로우
-
-### 권장 개발 순서
-1. **맵 데이터 준비**: AGVMapEditor로 맵 노드 배치 및 RFID 매핑 설정
-2. **경로 탐색 구현**: AGVNavigationCore에서 경로 계산 알고리즘 개발
-3. **시뮬레이션 테스트**: AGVSimulator로 AGV 동작 검증
-4. **메인 프로젝트 통합**: 개발 완료 후 부모 폴더(Cs_HMI)에 병합
-
-### 중요한 개발 패턴
-- **이벤트 기반 아키텍처**: UI 업데이트는 이벤트를 통해 자동화
-- **상태 관리**: _hasChanges 플래그로 변경사항 추적
-- **에러 처리**: 사용자 확인 다이얼로그와 상태바 메시지 활용
-- **코드 재사용**: UnifiedAGVCanvas를 맵에디터와 시뮬레이터에서 공통 사용
-
-### 주의사항
-- **PathFinding 로직 변경시**: 반드시 시뮬레이터에서 테스트 후 적용
-- **노드 연결 관리**: 물리적 RFID와 논리적 노드 ID 분리 원칙 유지
-- **JSON 파일 형식**: 맵 데이터는 MapNodes, RfidMappings 두 섹션으로 구성
-- **좌표 시스템**: 줌/팬 상태에서 좌표 변환 정확성 지속 모니터링
-
----
-
-## 최근 구현 완료 기능
-
-### ✅ 회전 구간 회피 기능 (PathFinding)
-- **목적**: AGV 회전 오류를 피하기 위한 선택적 회전 구간 회피
-- **파일**: `PathFinding/PathfindingOptions.cs`
-- **UI**: AGVSimulator에 "회전 구간 회피" 체크박스
-
-### ✅ 맵 에디터 마우스 좌표 오차 수정
-- **문제**: 줌 인/아웃 시 노드 선택 히트 영역이 너무 작음
-- **해결**: 최소 화면 히트 영역(20픽셀) 보장
-- **파일**: `AGVNavigationCore/Controls/UnifiedAGVCanvas.Mouse.cs`
-
-### ✅ 노드 연결 관리 시스템
-- **기능**: 노드 연결 목록 표시 및 삭제
-- **파일들**:
- - `AGVMapEditor/Forms/MainForm.cs` - UI 및 이벤트 처리
- - `UnifiedAGVCanvas.cs` - 편집 모드 및 이벤트 정의
- - `UnifiedAGVCanvas.Mouse.cs` - 마우스 연결 삭제 기능
-
----
-
-## 향후 개발 우선순위
-
-1. **방향 전환 기능**: AGV 현재 방향과 목표 방향 불일치 시 회전 노드 경유 로직
-2. **맵 검증 기능**: 연결 무결성, 고립된 노드, 순환 경로 등 검증
-3. **성능 최적화**: 대형 맵에서 경로 계산 및 연결 목록 표시 성능 개선
-4. **실시간 동기화**: 맵 에디터와 시뮬레이터 간 실시간 맵 동기화
-
----
-
-**최종 업데이트**: 2025-10-23 - AGVLogic 폴더 기준으로 정리
diff --git a/Cs_HMI/AGVLogic/E2ETEST.md b/Cs_HMI/AGVLogic/E2ETEST.md
deleted file mode 100644
index 743a28c..0000000
--- a/Cs_HMI/AGVLogic/E2ETEST.md
+++ /dev/null
@@ -1,44 +0,0 @@
-# E2E 테스트 계획
-
-AGV 시스템의 종단간 테스트 시나리오 문서
-
-## 테스트 시나리오
-
-### 1. 기본 경로 계산 테스트
-- 시작점과 목적지 설정
-- 경로 계산 수행
-- 경로 유효성 검증
-
-### 2. 방향 전환 테스트
-- 전진/후진 방향 전환이 필요한 경로
-- 갈림길에서의 방향 전환 검증
-- 회전 구간 회피 옵션 테스트
-
-### 3. RFID 매핑 테스트
-- RFID-NodeID 매핑 검증
-- 중복 RFID 감지 테스트
-- 노드 해석 정확성 검증
-
-### 4. 시뮬레이션 테스트
-- AGV 가상 이동 시뮬레이션
-- 경로 추적 정확성
-- 상태 변화 모니터링
-
-### 5. 목적지 선택 기능 테스트
-- 목적지 선택 모드 활성화/비활성화
-- 노드 클릭으로 목적지 설정
-- 자동 경로 계산 수행
-
-## 테스트 데이터
-
-### 맵 데이터
-- NewMap.agvmap 기준 테스트
-- 다양한 노드 타입 검증
-- 복잡한 갈림길 구조 테스트
-
-### 시나리오별 테스트 케이스
-1. 단순 직선 경로
-2. 다중 갈림길 경로
-3. 방향 전환이 필요한 경로
-4. 충전/도킹 노드 경로
-5. 회전 노드 회피 경로
\ No newline at end of file
diff --git a/Cs_HMI/AGVLogic/FINAL_SUMMARY_KO.md b/Cs_HMI/AGVLogic/FINAL_SUMMARY_KO.md
deleted file mode 100644
index 8c19594..0000000
--- a/Cs_HMI/AGVLogic/FINAL_SUMMARY_KO.md
+++ /dev/null
@@ -1,263 +0,0 @@
-# GetNextNodeId() 최종 구현 완료 - 한글 요약
-
-**최종 완료**: 2025-10-23
-**상태**: 🟢 **완전히 완료됨**
-
----
-
-## 📋 사용자 요구사항 확인
-
-### 핵심 요구사항
-> "002 → 003 후진 이동했을때 다시 후진이동을 더하면 004가 나와야하고, 전진으로하면 002가 나와야하는데"
-
-**해석**:
-```
-초기 상태: 002 → 003 Backward 이동 완료
-_currentDirection = Backward
-
-GetNextNodeId(Backward) → 004 (경로 계속)
-GetNextNodeId(Forward) → 002 (경로 반대)
-```
-
----
-
-## ✅ 최종 해결책
-
-### 핵심 개념
-**현재 모터 방향과 요청 방향이 같으면 경로 계속, 다르면 경로 반대**
-
-```
-_currentDirection = 현재 모터가 어느 방향으로 회전 중인지
-direction 파라미터 = 다음 모터를 어느 방향으로 회전시킬 것인지
-
-같음 → 경로 계속 (경로 벡터와 같은 방향)
-다름 → 경로 반대 (경로 벡터와 반대 방향)
-```
-
-### 수정 내용
-
-**파일**: `VirtualAGV.cs` (라인 743-783)
-
-**Forward 케이스**:
-```csharp
-if (_currentDirection == AgvDirection.Forward)
-{
- // Forward → Forward: 경로 계속
- if (dotProduct > 0.9f) baseScore = 100.0f;
-}
-else
-{
- // Backward → Forward: 경로 반대
- if (dotProduct < -0.9f) baseScore = 100.0f;
-}
-```
-
-**Backward 케이스**:
-```csharp
-if (_currentDirection == AgvDirection.Backward)
-{
- // Backward → Backward: 경로 계속
- if (dotProduct > 0.9f) baseScore = 100.0f;
-}
-else
-{
- // Forward → Backward: 경로 반대
- if (dotProduct < -0.9f) baseScore = 100.0f;
-}
-```
-
----
-
-## 🧪 최종 검증
-
-### 6가지 모든 시나리오 검증
-
-#### 시나리오 1-2: 001 → 002 Forward
-```
-현재 모터: Forward
-
-1-1) GetNextNodeId(Forward):
- Forward → Forward = 경로 계속
- 결과: N003 ✅
-
-1-2) GetNextNodeId(Backward):
- Forward → Backward = 경로 반대
- 결과: N001 ✅
-```
-
-#### 시나리오 2-4: 002 → 003 Forward
-```
-현재 모터: Forward
-
-2-1) GetNextNodeId(Forward):
- Forward → Forward = 경로 계속
- 결과: N004 ✅
-
-2-2) GetNextNodeId(Backward):
- Forward → Backward = 경로 반대
- 결과: N002 ✅
-```
-
-#### 시나리오 5-6: 002 → 003 Backward ⭐
-```
-현재 모터: Backward
-
-3-1) GetNextNodeId(Forward) ← 사용자 요구!
- Backward → Forward = 경로 반대
- 결과: N002 ✅ **사용자 피드백 충족!**
-
-3-2) GetNextNodeId(Backward) ← 사용자 요구!
- Backward → Backward = 경로 계속
- 결과: N004 ✅ **사용자 피드백 충족!**
-```
-
----
-
-## 📊 최종 결과
-
-| # | 이동 경로 | 현재 모터 | 요청 | 경로 선택 | 결과 | 예상 |
-|---|---------|---------|------|---------|------|------|
-| 1 | 001→002 | Forward | Forward | 계속 | N003 | ✅ |
-| 2 | 001→002 | Forward | Backward | 반대 | N001 | ✅ |
-| 3 | 002→003 | Forward | Forward | 계속 | N004 | ✅ |
-| 4 | 002→003 | Forward | Backward | 반대 | N002 | ✅ |
-| **5** | **002→003** | **Backward** | **Forward** | **반대** | **N002** | **✅ 완료!** |
-| **6** | **002→003** | **Backward** | **Backward** | **계속** | **N004** | **✅ 완료!** |
-
----
-
-## 💡 핵심 개념 정리
-
-### 모터 방향의 의미
-```
-모터가 정방향 회전 (Forward):
- - 같은 경로로 진행
- - dotProduct > 0.9 선호
-
-모터가 역방향 회전 (Backward):
- - 역시 같은 경로로 진행
- - 단, 모터만 반대로 회전
- - dotProduct > 0.9 선호
-
-모터 방향 전환:
- - 경로가 반대가 됨
- - dotProduct < -0.9 선호
-```
-
-### 사용자의 이해와의 일치
-> "모터 방향은 그냥 모터가 어느 방향으로 회전하는지일 뿐"
-
-✅ 구현에 반영됨:
-- Forward 모터든 Backward 모터든 같은 경로 선호
-- 경로 변경은 **모터 방향 전환**할 때만 발생
-- _currentDirection과 direction 파라미터가 다를 때만 경로 반대
-
----
-
-## 🔧 수정된 파일
-
-### 핵심 수정
-1. **VirtualAGV.cs** (라인 743-783)
- - Forward 케이스: _currentDirection 기반 로직
- - Backward 케이스: _currentDirection 기반 로직
-
-2. **GetNextNodeIdTest.cs**
- - 시나리오 5-6 추가
- - currentMotorDirection 파라미터 추가
-
-### 핵심 파일
-- VirtualAGV.cs: GetNextNodeId() 구현
-- MapLoader.cs: 양방향 연결 자동 설정
-- GetNextNodeIdTest.cs: 6가지 시나리오 검증
-
----
-
-## 📚 주요 문서
-
-- **FINAL_VERIFICATION_CORRECT.md**: 상세 검증 보고서
-- **STATUS_REPORT_FINAL.md**: 전체 구현 보고서
-- **GETNEXTNODEID_LOGIC_ANALYSIS.md**: 벡터 계산 분석
-- **MAP_LOADING_BIDIRECTIONAL_FIX.md**: 양방향 연결 설명
-
----
-
-## ✨ 구현 특징
-
-### 1. 현재 모터 상태 기반 로직
-```csharp
-if (_currentDirection == direction)
- // 모터 방향 유지 → 경로 계속
-else
- // 모터 방향 전환 → 경로 반대
-```
-
-### 2. 벡터 기반 점수 계산
-```
-경로 계속: dotProduct > 0.9 (같은 방향)
-경로 반대: dotProduct < -0.9 (반대 방향)
-```
-
-### 3. 완전한 모터 제어
-```
-Forward/Backward 모두:
-- 같은 모터 상태 유지 시: 경로 계속
-- 다른 모터 상태로 전환 시: 경로 반대
-```
-
----
-
-## 🚀 사용 예시
-
-### 경로 추적 시나리오
-```csharp
-// 002 → 003 Backward 이동
-agv.SetPosition(node003, pos, AgvDirection.Backward);
-
-// 계속 후진으로 진행
-var next = agv.GetNextNodeId(AgvDirection.Backward, allNodes);
-// → N004 (같은 경로, 같은 모터) ✅
-
-// 전진으로 방향 바꾸기
-next = agv.GetNextNodeId(AgvDirection.Forward, allNodes);
-// → N002 (반대 경로, 다른 모터) ✅
-```
-
----
-
-## ✅ 완료 항목
-
-✅ GetNextNodeId() 메서드 구현
-✅ Forward/Backward/Left/Right 지원
-✅ 벡터 기반 방향 계산
-✅ 2-위치 히스토리 관리
-✅ 양방향 연결 자동 설정
-✅ 현재 모터 방향 기반 로직
-✅ 모터 상태 전환 처리
-✅ 6가지 시나리오 모두 검증
-✅ 사용자 요구사항 100% 충족
-✅ 상세 문서화 완료
-
----
-
-## 🎉 최종 상태
-
-**모든 요구사항 충족됨:**
-```
-002 → 003 Backward 이동 후
-
-GetNextNodeId(Backward):
- 현재 Backward, 요청 Backward → 경로 계속
- → N004 ✅
-
-GetNextNodeId(Forward):
- 현재 Backward, 요청 Forward → 경로 반대
- → N002 ✅
-```
-
-**상태**: 🟢 **완전히 완료됨**
-
----
-
-**최종 수정**: 2025-10-23
-**검증**: 6/6 시나리오 패스
-**다음 단계**: 컴파일 및 런타임 테스트
diff --git a/Cs_HMI/AGVLogic/FINAL_VERIFICATION_CORRECT.md b/Cs_HMI/AGVLogic/FINAL_VERIFICATION_CORRECT.md
deleted file mode 100644
index 4291c40..0000000
--- a/Cs_HMI/AGVLogic/FINAL_VERIFICATION_CORRECT.md
+++ /dev/null
@@ -1,230 +0,0 @@
-# GetNextNodeId() 최종 수정 및 검증 - 올바른 로직
-
-**수정 완료**: 2025-10-23
-**상태**: 🟢 **최종 완료**
-
----
-
-## 🎯 사용자 요구사항 (최종 확인)
-
-### 시나리오 분석
-
-**002 → 003 Backward 이동 완료 후** (_currentDirection = Backward):
-
-| 요청 방향 | 현재 모터 상태 | 예상 경로 | 의미 |
-|---------|-------------|---------|------|
-| GetNextNodeId(Forward) | Backward | 002 (반대) | 모터 방향 전환 - 경로 반대 |
-| GetNextNodeId(Backward) | Backward | 004 (계속) | 모터 방향 유지 - 경로 계속 |
-
-### 올바른 이해
-- **요청 방향 = 요청하려는 모터 방향**
-- **_currentDirection = 현재 모터 방향**
-- 같으면: 경로 계속
-- 다르면: 경로 반대
-
----
-
-## 🔧 최종 수정 사항
-
-### 파일: VirtualAGV.cs (라인 743-783)
-
-#### Forward 케이스 (라인 743-771)
-```csharp
-case AgvDirection.Forward:
- if (_currentDirection == AgvDirection.Forward)
- {
- // 이미 Forward → Forward = 경로 계속
- if (dotProduct > 0.9f)
- baseScore = 100.0f; // 같은 방향 선호
- }
- else
- {
- // Backward → Forward = 경로 반대
- if (dotProduct < -0.9f)
- baseScore = 100.0f; // 반대 방향 선호
- }
- break;
-```
-
-#### Backward 케이스 (라인 773-783)
-```csharp
-case AgvDirection.Backward:
- if (_currentDirection == AgvDirection.Backward)
- {
- // 이미 Backward → Backward = 경로 계속
- if (dotProduct > 0.9f)
- baseScore = 100.0f; // 같은 방향 선호
- }
- else
- {
- // Forward → Backward = 경로 반대
- if (dotProduct < -0.9f)
- baseScore = 100.0f; // 반대 방향 선호
- }
- break;
-```
-
----
-
-## ✅ 최종 검증: 모든 시나리오
-
-### 시나리오 1: 001 → 002 Forward → ?
-
-**초기 상태**: _currentDirection = Forward
-
-**Forward 요청** (Forward → Forward = 경로 계속):
-- 이동 벡터: (141, 15)
-- N001: dot = -0.985 → dotProduct > 0.9? No → 20점
-- N003: dot = 0.934 → dotProduct > 0.9? Yes → **100점** ✅
-- **결과: N003** ✓
-
-**Backward 요청** (Forward → Backward = 경로 반대):
-- N001: dot = -0.985 → dotProduct < -0.9? No, < -0.5? Yes → **80점** ✅
-- N003: dot = 0.934 → dotProduct < -0.9? No → 20점 이하
-- **결과: N001** ✓
-
----
-
-### 시나리오 2: 002 → 003 Forward → ?
-
-**초기 상태**: _currentDirection = Forward
-
-**Forward 요청** (Forward → Forward = 경로 계속):
-- 이동 벡터: (72, 34)
-- N002: dot = -0.934 → dotProduct > 0.9? No → 20점 이하
-- N004: dot = 0.989 → dotProduct > 0.9? Yes → **100점** ✅
-- **결과: N004** ✓
-
-**Backward 요청** (Forward → Backward = 경로 반대):
-- N002: dot = -0.934 → dotProduct < -0.9? No, < -0.5? Yes → **80점** ✅
-- N004: dot = 0.989 → dotProduct < -0.9? No → 20점 이하
-- **결과: N002** ✓
-
----
-
-### 시나리오 3: 002 → 003 Backward → ? ⭐ 중요
-
-**초기 상태**: _currentDirection = Backward
-
-**Forward 요청** (Backward → Forward = 경로 반대):
-- 이동 벡터: (72, 34)
-- N002: dot = -0.934 → dotProduct < -0.9? No, < -0.5? Yes → **80점** ✅
-- N004: dot = 0.989 → dotProduct < -0.9? No → 20점 이하
-- **결과: N002** ✅ **사용자 요구 충족!**
-
-**Backward 요청** (Backward → Backward = 경로 계속):
-- N002: dot = -0.934 → dotProduct > 0.9? No → 20점 이하
-- N004: dot = 0.989 → dotProduct > 0.9? Yes → **100점** ✅
-- **결과: N004** ✅ **사용자 요구 충족!**
-
----
-
-## 📊 최종 결과 표
-
-| 시나리오 | 이동 | 현재 모터 | 요청 | 경로 | 결과 | 예상 | 상태 |
-|---------|-----|---------|------|------|------|------|------|
-| 1-1 | 001→002 | Forward | Forward | 계속 | N003 | N003 | ✅ |
-| 1-2 | 001→002 | Forward | Backward | 반대 | N001 | N001 | ✅ |
-| 2-1 | 002→003 | Forward | Forward | 계속 | N004 | N004 | ✅ |
-| 2-2 | 002→003 | Forward | Backward | 반대 | N002 | N002 | ✅ |
-| 3-1 | 002→003 | Backward | Forward | 반대 | N002 | N002 | ✅ FIXED |
-| 3-2 | 002→003 | Backward | Backward | 계속 | N004 | N004 | ✅ FIXED |
-
----
-
-## 💡 핵심 개념 정리
-
-### 모터 방향의 역할
-
-```
-현재 모터 상태 (_currentDirection):
- ├─ Forward: 모터 정방향 회전 중
- └─ Backward: 모터 역방향 회전 중
-
-요청 방향 (direction 파라미터):
- ├─ Forward: Forward 모터로 진행하고 싶음
- └─ Backward: Backward 모터로 진행하고 싶음
-
-같을 때:
- → 모터 방향 유지
- → 경로 계속 (같은 벡터 방향 선호)
- → dotProduct > 0.9
-
-다를 때:
- → 모터 방향 전환
- → 경로 반대 (반대 벡터 방향 선호)
- → dotProduct < -0.9
-```
-
-### 실제 동작 흐름
-
-```
-시나리오: 002→003 Backward 이동
-
-1. SetPosition(node003, pos, Backward)
- _currentDirection ← Backward
-
-2. GetNextNodeId(Forward) 호출
- - 현재는 Backward인데, Forward 요청
- - 모터 방향 전환 필요!
- - 경로는 반대 방향 선호
- - 결과: N002 (반대 경로)
-
-3. GetNextNodeId(Backward) 호출
- - 현재 Backward, Backward 요청
- - 모터 방향 유지!
- - 경로는 같은 방향 선호
- - 결과: N004 (같은 경로)
-```
-
----
-
-## 🚀 사용 패턴
-
-### 경로 추적
-```csharp
-// 002 → 003 Backward 이동
-agv.SetPosition(node003, pos003, AgvDirection.Backward);
-_currentDirection = AgvDirection.Backward;
-
-// 계속 Backward로 진행
-string next = agv.GetNextNodeId(AgvDirection.Backward, allNodes);
-// dotProduct > 0.9 선호 → N004
-
-// 모터 방향 전환해서 진행
-next = agv.GetNextNodeId(AgvDirection.Forward, allNodes);
-// dotProduct < -0.9 선호 → N002
-```
-
-### 경로 방향 이해
-```
-Backward 모터 상태:
-- Backward 요청 = 모터 유지 = 경로 계속 = dotProduct > 0.9 ✅
-- Forward 요청 = 모터 전환 = 경로 반대 = dotProduct < -0.9 ✅
-```
-
----
-
-## ✨ 최종 상태
-
-### 수정 완료
-✅ Forward 케이스: _currentDirection 기반 로직 추가
-✅ Backward 케이스: _currentDirection 기반 로직 추가
-✅ 모터 상태 추적: _currentDirection 사용
-✅ 경로 선택: 현재/요청 모터 상태 비교
-
-### 검증 완료
-✅ 모든 6가지 시나리오 (1-1, 1-2, 2-1, 2-2, 3-1, 3-2)
-✅ 사용자 요구사항 100% 충족
-✅ 모터 전환 시나리오 모두 작동
-
-### 요구사항 충족
-✅ 002→003 Backward 후 Forward → N002
-✅ 002→003 Backward 후 Backward → N004
-✅ 기존 모든 시나리오 유지
-
----
-
-**최종 수정**: 2025-10-23
-**상태**: 🟢 **완료 및 검증됨**
-**다음**: 테스트 및 빌드 가능
diff --git a/Cs_HMI/AGVLogic/GETNEXTNODEID_LOGIC_ANALYSIS.md b/Cs_HMI/AGVLogic/GETNEXTNODEID_LOGIC_ANALYSIS.md
deleted file mode 100644
index eab75c5..0000000
--- a/Cs_HMI/AGVLogic/GETNEXTNODEID_LOGIC_ANALYSIS.md
+++ /dev/null
@@ -1,367 +0,0 @@
-# GetNextNodeId() 로직 분석 및 검증
-
-## 🎯 검증 대상
-
-사용자 요구사항:
-```
-001 (65, 229) → 002 (206, 244) → Forward → 003 ✓
-001 (65, 229) → 002 (206, 244) → Backward → 001 ✓
-
-002 (206, 244) → 003 (278, 278) → Forward → 004 ✓
-002 (206, 244) → 003 (278, 278) → Backward → 002 ✓
-```
-
----
-
-## 📐 벡터 계산 논리
-
-### 기본 개념
-
-```
-이전 위치: prevPos = (x1, y1)
-현재 위치: currentPos = (x2, y2)
-
-이동 벡터: v_movement = (x2-x1, y2-y1)
- → 이 벡터의 방향이 "AGV가 이동한 방향"
-
-다음 노드 위치: nextPos = (x3, y3)
-
-다음 벡터: v_next = (x3-x2, y3-y2)
- → 이 벡터의 방향이 "다음 노드로 가는 방향"
-```
-
-### 내적 (Dot Product)
-```
-dot = v_movement · v_next = v_m.x * v_n.x + v_m.y * v_n.y
-
-의미:
- dot ≈ 1 : 거의 같은 방향 (0°) → Forward에 적합
- dot ≈ 0 : 직각 (90°) → Left/Right
- dot ≈ -1 : 거의 반대 방향 (180°) → Backward에 적합
-```
-
-### 외적 (Cross Product)
-```
-cross = v_movement × v_next (Z 성분) = v_m.x * v_n.y - v_m.y * v_n.x
-
-의미:
- cross > 0 : 반시계 방향 (좌측)
- cross < 0 : 시계 방향 (우측)
-```
-
----
-
-## 🧪 실제 시나리오 계산
-
-### 시나리오 1: 001 → 002 → Forward → ?
-
-#### 초기 조건
-```
-001: (65, 229)
-002: (206, 244)
-003: (278, 278)
-
-이동 벡터: v_m = (206-65, 244-229) = (141, 15)
-정규화: n_m = (141/142.79, 15/142.79) ≈ (0.987, 0.105)
-```
-
-#### 002의 ConnectedNodes: [N001, N003]
-
-**후보 1: N001**
-```
-다음 벡터: v_n = (65-206, 229-244) = (-141, -15)
-정규화: n_n = (-141/142.79, -15/142.79) ≈ (-0.987, -0.105)
-
-내적: dot = 0.987*(-0.987) + 0.105*(-0.105)
- = -0.974 - 0.011
- ≈ -0.985 (매우 반대 방향)
-
-외적: cross = 0.987*(-0.105) - 0.105*(-0.987)
- = -0.104 + 0.104
- ≈ 0
-
-Forward 모드에서:
- dotProduct < -0.5 → baseScore = 20.0 (낮은 점수)
-```
-
-**후보 2: N003** ⭐
-```
-다음 벡터: v_n = (278-206, 278-244) = (72, 34)
-정규화: n_n = (72/79.88, 34/79.88) ≈ (0.901, 0.426)
-
-내적: dot = 0.987*0.901 + 0.105*0.426
- = 0.889 + 0.045
- ≈ 0.934 (거의 같은 방향)
-
-외적: cross = 0.987*0.426 - 0.105*0.901
- = 0.421 - 0.095
- ≈ 0.326
-
-Forward 모드에서:
- dotProduct > 0.9 → baseScore = 100.0 ✓ (최고 점수!)
-```
-
-#### 결과: N003 선택 ✅
-
----
-
-### 시나리오 2: 001 → 002 → Backward → ?
-
-#### 초기 조건
-```
-001: (65, 229)
-002: (206, 244)
-
-이동 벡터: v_m = (141, 15) (같음)
-정규화: n_m = (0.987, 0.105) (같음)
-```
-
-#### 002의 ConnectedNodes: [N001, N003]
-
-**후보 1: N001** ⭐
-```
-다음 벡터: v_n = (-141, -15) (같음)
-정규화: n_n = (-0.987, -0.105) (같음)
-
-내적: dot ≈ -0.985 (매우 반대 방향)
-
-Backward 모드에서:
- dotProduct < -0.9 → baseScore = 100.0 ✓ (최고 점수!)
-```
-
-**후보 2: N003**
-```
-다음 벡터: v_n = (72, 34) (같음)
-정규화: n_n = (0.901, 0.426) (같음)
-
-내적: dot ≈ 0.934 (거의 같은 방향)
-
-Backward 모드에서:
- dotProduct > 0.5 → baseScore = 0 (점수 없음)
-```
-
-#### 결과: N001 선택 ✅
-
----
-
-### 시나리오 3: 002 → 003 → Forward → ?
-
-#### 초기 조건
-```
-002: (206, 244)
-003: (278, 278)
-004: (380, 340)
-
-이동 벡터: v_m = (278-206, 278-244) = (72, 34)
-정규화: n_m ≈ (0.901, 0.426)
-```
-
-#### 003의 ConnectedNodes: [N002, N004]
-
-**후보 1: N002**
-```
-다음 벡터: v_n = (206-278, 244-278) = (-72, -34)
-정규화: n_n ≈ (-0.901, -0.426)
-
-내적: dot ≈ -0.934 (거의 반대)
-
-Forward 모드에서:
- dotProduct < 0 → baseScore ≤ 50.0
-```
-
-**후보 2: N004** ⭐
-```
-다음 벡터: v_n = (380-278, 340-278) = (102, 62)
-정규화: n_n = (102/119.54, 62/119.54) ≈ (0.853, 0.519)
-
-내적: dot = 0.901*0.853 + 0.426*0.519
- = 0.768 + 0.221
- ≈ 0.989 (거의 같은 방향)
-
-Forward 모드에서:
- dotProduct > 0.9 → baseScore = 100.0 ✓
-```
-
-#### 결과: N004 선택 ✅
-
----
-
-### 시나리오 4: 002 → 003 → Backward → ?
-
-#### 초기 조건
-```
-002: (206, 244)
-003: (278, 278)
-
-이동 벡터: v_m = (72, 34)
-정규화: n_m = (0.901, 0.426)
-```
-
-#### 003의 ConnectedNodes: [N002, N004]
-
-**후보 1: N002** ⭐
-```
-다음 벡터: v_n = (-72, -34)
-정규화: n_n = (-0.901, -0.426)
-
-내적: dot ≈ -0.934 (거의 반대)
-
-Backward 모드에서:
- dotProduct < -0.9 → baseScore = 100.0 ✓
-```
-
-**후보 2: N004**
-```
-다음 벡터: v_n = (102, 62)
-정규화: n_n = (0.853, 0.519)
-
-내적: dot ≈ 0.989 (거의 같은)
-
-Backward 모드에서:
- dotProduct > 0 → baseScore = 0 (점수 없음)
-```
-
-#### 결과: N002 선택 ✅
-
----
-
-## ✅ 검증 결과
-
-| 시나리오 | 이전→현재 | 방향 | 예상 | 계산 결과 | 검증 |
-|---------|----------|------|------|----------|------|
-| 1 | 001→002 | Forward | 003 | 003 (100.0) | ✅ |
-| 2 | 001→002 | Backward | 001 | 001 (100.0) | ✅ |
-| 3 | 002→003 | Forward | 004 | 004 (100.0) | ✅ |
-| 4 | 002→003 | Backward | 002 | 002 (100.0) | ✅ |
-
----
-
-## 🔍 핵심 로직 검토
-
-### VirtualAGV.GetNextNodeId() - 라인 628-719
-
-```csharp
-public string GetNextNodeId(AgvDirection direction, List allNodes)
-{
- // 1️⃣ 히스토리 검증
- if (_prevPosition == Point.Empty || _currentPosition == Point.Empty)
- return null; // ← 2개 위치 필수
-
- // 2️⃣ 연결된 노드 필터링
- var candidateNodes = allNodes.Where(n =>
- _currentNode.ConnectedNodes.Contains(n.NodeId)
- ).ToList();
-
- // 3️⃣ 이동 벡터 계산
- var movementVector = new PointF(
- _currentPosition.X - _prevPosition.X,
- _currentPosition.Y - _prevPosition.Y
- );
-
- // 4️⃣ 정규화
- var normalizedMovement = new PointF(
- movementVector.X / movementLength,
- movementVector.Y / movementLength
- );
-
- // 5️⃣ 각 후보에 대해 점수 계산
- foreach (var candidate in candidateNodes)
- {
- float score = CalculateDirectionalScore(
- normalizedMovement,
- normalizedToNext,
- direction // ← Forward/Backward/Left/Right
- );
-
- if (score > bestCandidate.score)
- bestCandidate = (candidate, score);
- }
-
- return bestCandidate.node?.NodeId;
-}
-```
-
-### CalculateDirectionalScore() - 라인 721-821
-
-```csharp
-private float CalculateDirectionalScore(
- PointF movementDirection, // 정규화된 이동 벡터
- PointF nextDirection, // 정규화된 다음 벡터
- AgvDirection requestedDir) // 요청된 방향
-{
- // 내적: 유사도 계산
- float dotProduct = (movementDirection.X * nextDirection.X) +
- (movementDirection.Y * nextDirection.Y);
-
- // 외적: 좌우 판별
- float crossProduct = (movementDirection.X * nextDirection.Y) -
- (movementDirection.Y * nextDirection.X);
-
- // 방향에 따라 점수 계산
- switch (requestedDir)
- {
- case AgvDirection.Forward:
- // Forward: dotProduct > 0.9 → 100점 ✓
- break;
-
- case AgvDirection.Backward:
- // Backward: dotProduct < -0.9 → 100점 ✓
- break;
-
- case AgvDirection.Left:
- // Left: crossProduct 양수 선호 ✓
- break;
-
- case AgvDirection.Right:
- // Right: crossProduct 음수 선호 ✓
- break;
- }
-
- return baseScore;
-}
-```
-
----
-
-## 📊 최종 결론
-
-### ✅ 로직이 정확함
-
-모든 시나리오에서:
-- **Forward 이동**: 이동 벡터와 방향이 거의 같은 노드 선택 (dotProduct > 0.9)
-- **Backward 이동**: 이동 벡터와 반대 방향인 노드 선택 (dotProduct < -0.9)
-
-### 🎯 동작 원리
-
-1. **이동 벡터**: "AGV가 이동한 방향"을 나타냄
-2. **Forward**: 같은 방향으로 계속 진행
-3. **Backward**: 반대 방향으로 돌아감
-
-```
-Forward 논리:
- 001→002 이동 벡터 방향으로
- → 002에서 Forward 선택
- → 같은 방향인 003 선택 ✓
-
-Backward 논리:
- 001→002 이동 벡터 방향으로
- → 002에서 Backward 선택
- → 반대 방향인 001 선택 ✓
-```
-
----
-
-## 🧪 테스트 클래스
-
-**파일**: `GetNextNodeIdTest.cs`
-
-실행하면:
-1. 각 시나리오별 벡터 계산 출력
-2. 내적/외적 값 표시
-3. 후보 노드별 점수 계산
-4. 선택된 노드 및 검증 결과
-
----
-
-**분석 완료**: 2025-10-23
-**상태**: 🟢 로직 정확 검증 완료
diff --git a/Cs_HMI/AGVLogic/IMPLEMENTATION_CHECKLIST.md b/Cs_HMI/AGVLogic/IMPLEMENTATION_CHECKLIST.md
deleted file mode 100644
index 97d6e2f..0000000
--- a/Cs_HMI/AGVLogic/IMPLEMENTATION_CHECKLIST.md
+++ /dev/null
@@ -1,227 +0,0 @@
-# GetNextNodeId() 구현 - 최종 체크리스트
-
-**완료 일시**: 2025-10-23
-**상태**: 🟢 **모두 완료**
-
----
-
-## ✅ 구현 완료 항목
-
-### 핵심 메서드
-- [x] GetNextNodeId() 메서드 구현 (VirtualAGV.cs)
-- [x] CalculateDirectionalScore() 메서드 구현
-- [x] Forward 케이스 (현재 모터 상태 기반 로직)
-- [x] Backward 케이스 (현재 모터 상태 기반 로직)
-- [x] Left 케이스 (좌측 회전)
-- [x] Right 케이스 (우측 회전)
-
-### 지원 기능
-- [x] 벡터 정규화
-- [x] 내적 계산
-- [x] 외적 계산
-- [x] 2-위치 히스토리 검증
-- [x] 이동 거리 검증
-- [x] ConnectedNodes 필터링
-
-### 맵 로드 기능
-- [x] EnsureBidirectionalConnections() 구현 (MapLoader.cs)
-- [x] 단방향 저장 → 양방향 메모리 로드
-- [x] LoadMapFromFile()에 통합
-
-### 테스트 및 검증
-- [x] GetNextNodeIdTest.cs 구현
-- [x] TestScenario() 메서드
-- [x] 6가지 시나리오 테스트
-- [x] currentMotorDirection 파라미터 추가
-- [x] 모든 시나리오 검증 완료
-
-### 문서화
-- [x] GETNEXTNODEID_LOGIC_ANALYSIS.md
-- [x] MAP_LOADING_BIDIRECTIONAL_FIX.md
-- [x] VERIFICATION_COMPLETE.md
-- [x] BACKWARD_LOGIC_FIX.md
-- [x] BACKWARD_FIX_VERIFICATION.md
-- [x] BACKWARD_FIX_SUMMARY_KO.md
-- [x] FINAL_VERIFICATION_CORRECT.md
-- [x] STATUS_REPORT_FINAL.md
-- [x] QUICK_REFERENCE.md
-- [x] FINAL_SUMMARY_KO.md
-
----
-
-## ✅ 사용자 요구사항 충족
-
-### 초기 요구사항
-- [x] GetNextNodeId() 메서드 구현
-- [x] 이전 위치 + 현재 위치로 방향 계산
-- [x] Forward/Backward/Left/Right 지원
-- [x] 벡터 기반 계산
-- [x] 2-위치 히스토리 필요
-
-### 개선 요구사항
-- [x] 양방향 연결 자동 설정
-- [x] MapLoader에 통합
-- [x] JSON 저장은 단방향
-- [x] 메모리는 양방향
-
-### 최종 피드백
-- [x] 002→003 Backward 후 Backward → N004
-- [x] 002→003 Backward 후 Forward → N002
-- [x] 모터 방향에 따른 경로 선택
-- [x] 모터 전환 시 경로 반대
-
----
-
-## ✅ 검증 결과
-
-### 6가지 시나리오
-| # | 시나리오 | 상태 |
-|---|---------|------|
-| 1 | 001→002 Forward → Forward | ✅ PASS |
-| 2 | 001→002 Forward → Backward | ✅ PASS |
-| 3 | 002→003 Forward → Forward | ✅ PASS |
-| 4 | 002→003 Forward → Backward | ✅ PASS |
-| 5 | 002→003 Backward → Forward | ✅ PASS |
-| 6 | 002→003 Backward → Backward | ✅ PASS |
-
-### 특수 검증
-- [x] 벡터 내적 계산 정확성
-- [x] 벡터 외적 계산 정확성
-- [x] 점수 계산 정확성
-- [x] 최고 점수 노드 선택
-- [x] 경로 반대 감지
-- [x] 경로 계속 감지
-
----
-
-## ✅ 코드 품질
-
-### 코드 구조
-- [x] 메서드 분리 (GetNextNodeId + CalculateDirectionalScore)
-- [x] 가독성 있는 변수명
-- [x] 주석 추가 (한글)
-- [x] 로직 명확성
-
-### 에러 처리
-- [x] null 체크
-- [x] 2-위치 히스토리 검증
-- [x] ConnectedNodes 검증
-- [x] 이동 거리 검증 (< 0.001f)
-
-### 성능
-- [x] 벡터 정규화 효율성
-- [x] 루프 최소화
-- [x] 메모리 사용 최적화
-
----
-
-## ✅ 통합 준비
-
-### 빌드 준비
-- [x] 문법 오류 없음
-- [x] 컴파일 가능 (수동 확인)
-- [x] 의존성 명확
-- [x] 네임스페이스 올바름
-
-### 실행 준비
-- [x] 테스트 클래스 준비
-- [x] 테스트 시나리오 정의
-- [x] 예상 결과 문서화
-- [x] 검증 기준 명확
-
-### 배포 준비
-- [x] 핵심 파일 수정 완료
-- [x] 테스트 파일 업데이트
-- [x] 문서 작성 완료
-- [x] 버전 관리 가능
-
----
-
-## 📋 다음 단계
-
-### 즉시 작업
-- [ ] 프로젝트 빌드
-- [ ] 컴파일 오류 확인
-- [ ] 기본 테스트 실행
-
-### 후속 작업
-- [ ] GetNextNodeIdTest 실행
-- [ ] 6가지 시나리오 검증
-- [ ] 실제 맵 파일로 테스트
-- [ ] AGVSimulator 통합 테스트
-
-### 최종 확인
-- [ ] 메인 애플리케이션 통합
-- [ ] 실시간 경로 계산 검증
-- [ ] 사용자 피드백 수집
-- [ ] 안정성 확인
-
----
-
-## 📊 파일 변경 요약
-
-### 수정된 파일 (2개)
-1. **VirtualAGV.cs**
- - GetNextNodeId() 메서드 추가 (628-821라인)
- - CalculateDirectionalScore() 메서드 추가 (725-821라인)
- - Forward/Backward 케이스 _currentDirection 기반 로직
-
-2. **GetNextNodeIdTest.cs**
- - 시나리오 5-6 추가
- - currentMotorDirection 파라미터 추가
- - TestScenario() 메서드 서명 업데이트
-
-### 통합 수정 (1개)
-3. **MapLoader.cs**
- - EnsureBidirectionalConnections() 메서드 추가
- - LoadMapFromFile()에 통합
-
-### 생성된 파일 (정보 목적)
-- 10개 이상의 상세 문서
-
----
-
-## 🎯 최종 성과
-
-### 기능 완성도
-```
-GetNextNodeId() 메서드: 100% ✅
-테스트 및 검증: 100% ✅
-사용자 요구사항: 100% ✅
-문서화: 100% ✅
-```
-
-### 코드 품질
-```
-컴파일 가능: ✅
-오류 처리: ✅
-가독성: ✅
-유지보수성: ✅
-```
-
-### 검증 상태
-```
-로직 정확성: ✅ (6/6 시나리오)
-모터 상태 관리: ✅
-경로 선택 정확도: ✅
-엣지 케이스 처리: ✅
-```
-
----
-
-## 🟢 최종 상태
-
-**모든 항목 완료 - 프로덕션 준비 완료**
-
-```
-구현: ✅ 완료
-검증: ✅ 완료
-문서: ✅ 완료
-테스트: ✅ 준비됨
-```
-
----
-
-**완료 일시**: 2025-10-23
-**최종 상태**: 🟢 **전부 완료**
-**다음 단계**: 빌드 및 런타임 테스트 진행
diff --git a/Cs_HMI/AGVLogic/IMPLEMENTATION_COMPLETE.md b/Cs_HMI/AGVLogic/IMPLEMENTATION_COMPLETE.md
deleted file mode 100644
index bdc48ec..0000000
--- a/Cs_HMI/AGVLogic/IMPLEMENTATION_COMPLETE.md
+++ /dev/null
@@ -1,333 +0,0 @@
-# GetNextNodeId() 구현 완료 및 Backward 로직 수정 완료
-
-**최종 완료**: 2025-10-23
-**상태**: 🟢 전체 구현 및 수정 완료
-**검증**: ✅ 모든 시나리오 패스
-
----
-
-## 📋 전체 요약
-
-### 초기 요청
-사용자가 AGV 방향 결정 알고리즘을 요청:
-```
-현재 위치 + 이전 위치 + 방향 파라미터
- ↓
-다음 노드 ID 반환
-```
-
-### 구현된 기능
-1. **GetNextNodeId()** - VirtualAGV.cs에 구현
- - 벡터 기반 방향 계산
- - Forward/Backward/Left/Right 지원
- - 2-위치 히스토리 필요
-
-2. **EnsureBidirectionalConnections()** - MapLoader.cs에 추가
- - 단방향 맵 저장 → 양방향 메모리 로드
- - 자동 양방향 연결 복원
-
-3. **테스트 및 검증 클래스**
- - GetNextNodeIdTest.cs
- - TestRunner.cs
- - 4가지 시나리오 검증
-
-### 발견 및 수정된 문제
-**문제**: Backward 로직이 반대 방향을 찾도록 구현됨
-```csharp
-// 수정 전 (❌ 잘못됨)
-case AgvDirection.Backward:
- if (dotProduct < -0.9f) // 반대 방향 선호
- baseScore = 100.0f;
-
-// 수정 후 (✅ 올바름)
-case AgvDirection.Backward:
- if (dotProduct > 0.9f) // Forward와 동일하게 같은 방향 선호
- baseScore = 100.0f;
-```
-
-**결과**: 002→003 Backward 후 004를 올바르게 반환
-
----
-
-## 🎯 최종 검증 결과
-
-### 모든 4가지 시나리오 검증 완료
-
-| 시나리오 | 이동 | 방향 | 결과 | 예상 | 상태 |
-|---------|-----|------|------|------|------|
-| 1 | 001→002 | Forward | N003 | N003 | ✅ PASS |
-| 2 | 001→002 | Backward | N003 | N003 | ✅ PASS |
-| 3 | 002→003 | Forward | N004 | N004 | ✅ PASS |
-| 4 | 002→003 | Backward | N004 | N004 | ✅ PASS (FIXED) |
-
-### 핵심 검증 - 시나리오 4 (수정된 케이스)
-
-**문제 상황** (사용자 피드백):
-```
-002 → 003 Backward 이동 완료
-003에서 GetNextNodeId(Backward) 호출
-
-수정 전: N002 반환 ❌
-수정 후: N004 반환 ✅
-```
-
-**동작 원리**:
-- 이동 벡터: (72, 34) [002→003 방향]
-- N004 벡터: (102, 62) [003→004 방향]
-- 내적: 0.989 > 0.9 → 100점 (경로 계속 선호) ✅
-- N002 벡터: (-72, -34) [003→002 방향]
-- 내적: -0.934 < -0.9 → 20점 (경로 반대) ❌
-
----
-
-## 📁 전체 파일 목록
-
-### 핵심 구현 파일
-
-#### 1. VirtualAGV.cs (AGVNavigationCore\Models\)
-- **메서드**: GetNextNodeId() - 라인 628-821
-- **메서드**: CalculateDirectionalScore() - 라인 725-821
-- **수정**: Backward 케이스 로직 (라인 755-767)
-- **용도**: AGV 시뮬레이터의 가상 AGV 동작 관리
-
-#### 2. MapLoader.cs (AGVNavigationCore\Models\)
-- **메서드**: EnsureBidirectionalConnections() - 라인 341-389
-- **호출처**: LoadMapFromFile() - 라인 85
-- **용도**: 맵 로드 시 양방향 연결 자동 복원
-
-### 테스트 및 검증 파일
-
-#### 3. GetNextNodeIdTest.cs (AGVNavigationCore\Utils\)
-- **메서드**: TestGetNextNodeId() - 테스트 실행
-- **메서드**: TestScenario() - 개별 시나리오 검증
-- **메서드**: CalculateScoreAndPrint() - 점수 계산 및 출력
-- **시나리오**: 4가지 모두 포함 (수정됨)
-- **용도**: GetNextNodeId() 동작 검증
-
-#### 4. TestRunner.cs (AGVNavigationCore\Utils\)
-- **용도**: 테스트 클래스 실행
-
-### 독립적 구현 파일
-
-#### 5. DirectionalPathfinder.cs (AGVNavigationCore\PathFinding\Planning\)
-- **목적**: GetNextNodeId()와 독립적인 경로 탐색 엔진
-- **메서드**: FindNextNode()
-- **용도**: 향후 다른 방향 기반 로직에서 재사용 가능
-
-#### 6. AGVDirectionCalculator.cs (AGVNavigationCore\Utils\)
-- **목적**: DirectionalPathfinder 통합 레이어
-- **메서드**: CalculateNextNodeId()
-- **용도**: VirtualAGV와 독립적으로 테스트 가능
-
-### 문서 파일
-
-#### 7. GETNEXTNODEID_LOGIC_ANALYSIS.md
-- **내용**: 4가지 시나리오 상세 벡터 계산
-- **포함**: 수학 원리, 예시 계산
-
-#### 8. MAP_LOADING_BIDIRECTIONAL_FIX.md
-- **내용**: 양방향 연결 자동 설정 설명
-- **포함**: 문제 분석, 해결책
-
-#### 9. BACKWARD_LOGIC_FIX.md
-- **내용**: Backward 로직 수정 설명
-- **포함**: 문제, 해결책, 개념 정리
-
-#### 10. BACKWARD_FIX_VERIFICATION.md
-- **내용**: Backward 수정 검증 보고서
-- **포함**: 모든 시나리오 검증, 결과 비교
-
-#### 11. VERIFICATION_COMPLETE.md
-- **내용**: 초기 구현의 검증 보고서
-- **포함**: 4가지 시나리오, 점수 계산
-
----
-
-## 🔧 기술 상세
-
-### 벡터 계산 원리
-
-```
-이전 위치 P1 → 현재 위치 P2: 이동 벡터 V_m
-현재 위치 P2 → 다음 후보 P3: 후보 벡터 V_n
-
-내적 (Dot Product):
- dot = V_m · V_n
- 범위: -1 (완전 반대) ~ 1 (완전 같음)
-
-Forward 점수:
- dot > 0.9 → 100점 (거의 같은 방향)
- dot > 0.5 → 80점
- dot > 0 → 50점
- dot > -0.5 → 20점
- else → 0점
-
-Backward 점수 (수정 후):
- Forward과 동일 (경로 선호도는 동일)
-```
-
-### Left/Right 처리
-
-```
-crossProduct = V_m × V_n (Z 성분)
-
-Forward 상태 (dot > 0):
- Left: cross > 0.5 선호
- Right: cross < -0.5 선호
-
-Backward 상태 (dot < 0):
- Left와 Right 반전
- Left: cross < -0.5 선호 (반시계 반전)
- Right: cross > 0.5 선호 (시계 반전)
-```
-
----
-
-## ✨ 주요 특징
-
-### 1. 벡터 기반 방향 계산
-- 단순 각도 계산이 아닌 벡터 유사도 사용
-- 수학적으로 정확한 방향 판별
-
-### 2. 2-위치 히스토리 기반
-- 최소 2개 위치 필요 (_prevPosition, _currentPosition)
-- 이동 방향을 정확히 파악
-
-### 3. 양방향 연결 자동 보장
-- 맵 로드 시 자동으로 역방향 연결 추가
-- 현재 노드에서만 모든 다음 노드 찾을 수 있음
-
-### 4. Forward/Backward 동일 경로 선호
-- 모터 방향은 단순히 회전 방향
-- 경로 선택에는 영향 없음
-- 사용자 피드백 반영: "모터 방향 바꾼다고 해서 AGV 몸체 방향이 바뀌지 않아"
-
----
-
-## 🚀 사용 방법
-
-### 기본 사용
-
-```csharp
-// VirtualAGV 인스턴스
-var agv = new VirtualAGV("AGV001");
-
-// 최소 2번 위치 설정
-agv.SetPosition(node001, new Point(65, 229), AgvDirection.Forward);
-agv.SetPosition(node002, new Point(206, 244), AgvDirection.Forward);
-
-// 다음 노드 계산
-string nextNodeId = agv.GetNextNodeId(AgvDirection.Forward, allNodes);
-// 결과: "N003"
-
-// 방향 변경
-nextNodeId = agv.GetNextNodeId(AgvDirection.Backward, allNodes);
-// 결과: "N003" (경로는 동일하지만 모터 방향만 변경)
-```
-
-### 테스트 실행
-
-```csharp
-var tester = new GetNextNodeIdTest();
-tester.TestGetNextNodeId();
-// 모든 시나리오 검증 출력
-```
-
----
-
-## 📊 변경 이력
-
-### 1차 구현 (초기)
-- GetNextNodeId() 메서드 추가
-- Forward/Backward/Left/Right 지원
-- 4가지 테스트 시나리오 정의
-
-### 2차 개선 (양방향 연결)
-- EnsureBidirectionalConnections() 추가
-- MapLoader.LoadMapFromFile()에 통합
-- 맵 로드 시 자동 양방향 복원
-
-### 3차 수정 (Backward 로직)
-- Backward 케이스 로직 수정
-- Forward와 동일한 경로 선호 로직으로 변경
-- 테스트 케이스 업데이트
-
----
-
-## ✅ 검증 체크리스트
-
-- [x] 001→002 Forward→003
-- [x] 001→002 Backward→003
-- [x] 002→003 Forward→004
-- [x] 002→003 Backward→004 ← **FIXED**
-- [x] 양방향 연결 자동 설정
-- [x] 벡터 정규화 로직
-- [x] 점수 계산 로직
-- [x] Left/Right 처리
-- [x] CS1026 오류 수정
-- [x] 테스트 클래스 구현
-- [x] Backward 로직 수정
-
----
-
-## 🎓 개념 정리
-
-### AGV 방향의 의미
-
-```
-모터 방향 (Motor Direction):
-- Forward: 모터가 정방향으로 회전
-- Backward: 모터가 역방향으로 회전
-
-경로 방향 (Path Direction):
-- GetNextNodeId()의 direction 파라미터
-- 경로 계속 의도를 나타냄
-- Forward/Backward 모두 같은 경로 선호
-
-AGV 몸체 이동:
-- 이전 위치 + 현재 위치로 계산된 벡터
-- 모터 방향이 바뀌어도 경로 벡터는 동일
-```
-
-### 왜 같은 경로를 선호하는가?
-
-```
-시나리오: 002→003 Backward 이동
-
-모터 역방향이면:
-1. 재장비 시스템은 역방향 모터로 AGV를 뒤로 밀어낸다
-2. AGV 몸체는 여전히 002→003 방향으로 이동한다
-3. 다음 노드는 여전히 004여야 한다
-
-따라서:
-- 모터 방향은 단순히 모터 회전 방향
-- 경로 선택은 이동 벡터 기반
-- Forward/Backward 모두 같은 경로 선호
-```
-
----
-
-## 🎉 최종 상태
-
-### 구현 완료
-- ✅ GetNextNodeId() 메서드 완전 구현
-- ✅ 4가지 시나리오 검증 완료
-- ✅ 양방향 연결 자동 설정 완료
-- ✅ Backward 로직 수정 완료
-
-### 동작 확인
-- ✅ 벡터 계산 정확성 검증
-- ✅ 점수 계산 로직 검증
-- ✅ 모든 방향 지원 확인
-- ✅ 사용자 피드백 반영 완료
-
-### 문서화
-- ✅ 상세 기술 문서 작성
-- ✅ 검증 보고서 작성
-- ✅ 개념 설명 문서 작성
-
----
-
-**완료 일시**: 2025-10-23
-**최종 상태**: 🟢 **전체 구현, 수정, 검증 완료**
-**다음 단계**: 실제 맵 파일(NewMap.agvmap)로 통합 테스트 진행
diff --git a/Cs_HMI/AGVLogic/IMPLEMENTATION_DirectionalPathfinder.md b/Cs_HMI/AGVLogic/IMPLEMENTATION_DirectionalPathfinder.md
deleted file mode 100644
index 1f4c7a8..0000000
--- a/Cs_HMI/AGVLogic/IMPLEMENTATION_DirectionalPathfinder.md
+++ /dev/null
@@ -1,472 +0,0 @@
-# 방향 기반 경로 탐색 (DirectionalPathfinder) 구현 문서
-
-## 📋 개요
-
-**이전 위치 + 현재 위치 + 진행 방향**을 기반으로 **다음 노드 ID**를 반환하는 시스템 구현
-
-### 핵심 요구사항
-- ✅ VirtualAGV에 최소 **2개 위치 히스토리** 필요 (prev/current)
-- ✅ 방향별 가중치 시스템 (Forward/Backward/Left/Right)
-- ✅ Backward 시 좌/우 방향 **반전** 처리
-- ✅ NewMap.agvmap 파일 기반 동작
-
----
-
-## 🏗️ 구현 아키텍처
-
-### 클래스 다이어그램
-
-```
-┌─────────────────────────────────────────┐
-│ AGVDirectionCalculator │
-│ (메인 인터페이스) │
-│ │
-│ GetNextNodeId( │
-│ prevPos, currentNode, currentPos, │
-│ direction, allNodes │
-│ ) │
-└──────────────┬──────────────────────────┘
- │ uses
- ▼
-┌─────────────────────────────────────────┐
-│ DirectionalPathfinder │
-│ (핵심 알고리즘) │
-│ │
-│ - DirectionWeights 설정 │
-│ - 벡터 기반 방향 계산 │
-│ - 방향별 점수 계산 │
-└─────────────────────────────────────────┘
-
-┌─────────────────────────────────────────┐
-│ DirectionalPathfinderTest │
-│ (NewMap.agvmap 기반 테스트) │
-│ │
-│ - 맵 파일 로드 │
-│ - 테스트 시나리오 실행 │
-│ - 결과 검증 │
-└─────────────────────────────────────────┘
-```
-
----
-
-## 🔧 구현 상세
-
-### 1. DirectionalPathfinder.cs (PathFinding/Planning/)
-
-**목적**: 벡터 기반 방향 계산 엔진
-
-#### 핵심 메서드: `GetNextNodeId()`
-
-```csharp
-public string GetNextNodeId(
- Point previousPos, // 이전 RFID 감지 위치
- MapNode currentNode, // 현재 RFID 노드
- Point currentPos, // 현재 위치
- AgvDirection direction, // 요청된 이동 방향
- List allNodes // 맵의 모든 노드
-)
-```
-
-#### 실행 순서
-
-1️⃣ **입력 검증**
-```csharp
-if (previousPos == Point.Empty || currentPos == Point.Empty)
- return null; // 2개 위치 히스토리 필수
-```
-
-2️⃣ **연결된 노드 필터링**
-```csharp
-var candidateNodes = allNodes.Where(n =>
- currentNode.ConnectedNodes.Contains(n.NodeId)
-).ToList();
-```
-
-3️⃣ **이동 벡터 계산**
-```csharp
-var movementVector = new PointF(
- currentPos.X - previousPos.X, // Δx
- currentPos.Y - previousPos.Y // Δy
-);
-```
-
-4️⃣ **벡터 정규화** (길이 1로 만듦)
-```csharp
-float length = √(Δx² + Δy²);
-normalizedMovement = (Δx/length, Δy/length);
-```
-
-5️⃣ **각 후보 노드에 대해 방향 점수 계산**
-```
-for each candidate in candidateNodes:
- score = CalculateDirectionalScore(
- 이동방향,
- 현재→다음 벡터,
- 요청된 방향
- )
-```
-
-6️⃣ **가장 높은 점수 선택**
-```csharp
-return scoredCandidates
- .OrderByDescending(x => x.score)
- .First()
- .node.NodeId;
-```
-
-#### 방향 점수 계산 로직 (CalculateDirectionalScore)
-
-**사용하는 벡터 연산:**
-- **내적 (Dot Product)**: 두 벡터의 유사도 (-1 ~ 1)
-- **외적 (Cross Product)**: 좌우 판별 (양수 = 좌, 음수 = 우)
-
-```
-내적 = v1.x * v2.x + v1.y * v2.y
-외적 = v1.x * v2.y - v1.y * v2.x
-```
-
-##### 🔄 Forward (전진) 모드
-
-```
-직진(dotProduct ≈ 1) → 점수 100 * 1.0
-비슷한 방향(0.5~0.9) → 점수 80 * 1.0
-약간 다른(0~0.5) → 점수 50 * 1.0
-거의 반대(-0.5~0) → 점수 20 * 2.0 (후진 가중치)
-완전 반대(< -0.5) → 점수 0
-```
-
-##### ↩️ Backward (후진) 모드
-
-```
-반대 방향(dotProduct < -0.9) → 점수 100 * 2.0
-비슷하게 반대(-0.5~-0.9) → 점수 80 * 2.0
-약간 다른(-0~0.5) → 점수 50 * 2.0
-거의 같은(0~0.5) → 점수 20 * 1.0
-완전 같은(> 0.5) → 점수 0
-```
-
-##### ⬅️ Left (좌측) 모드
-
-**Forward 상태 (dotProduct > 0):**
-```
-좌측(crossProduct > 0.5) → 점수 100 * 1.5
-약간 좌측(0~0.5) → 점수 70 * 1.5
-직진(-0.5~0) → 점수 50 * 1.0
-우측 방향(-0.5~-1) → 점수 30 * 1.5
-```
-
-**Backward 상태 (dotProduct < 0) - 좌우 반전:**
-```
-좌측(crossProduct < -0.5) → 점수 100 * 1.5
-약간 좌측(-0.5~0) → 점수 70 * 1.5
-역진(0~0.5) → 점수 50 * 2.0
-우측 방향(> 0.5) → 점수 30 * 1.5
-```
-
-##### ➡️ Right (우측) 모드
-
-**Forward 상태 (dotProduct > 0):**
-```
-우측(crossProduct < -0.5) → 점수 100 * 1.5
-약간 우측(-0.5~0) → 점수 70 * 1.5
-직진(0~0.5) → 점수 50 * 1.0
-좌측 방향(> 0.5) → 점수 30 * 1.5
-```
-
-**Backward 상태 (dotProduct < 0) - 좌우 반전:**
-```
-우측(crossProduct > 0.5) → 점수 100 * 1.5
-약간 우측(0~0.5) → 점수 70 * 1.5
-역진(-0.5~0) → 점수 50 * 2.0
-좌측 방향(< -0.5) → 점수 30 * 1.5
-```
-
-#### 방향 가중치 (DirectionWeights)
-
-```csharp
-public class DirectionWeights
-{
- public float ForwardWeight { get; set; } = 1.0f; // 직진
- public float LeftWeight { get; set; } = 1.5f; // 좌측 (비직진이므로 높음)
- public float RightWeight { get; set; } = 1.5f; // 우측 (비직진이므로 높음)
- public float BackwardWeight { get; set; } = 2.0f; // 후진 (거리 페널티)
-}
-```
-
----
-
-### 2. AGVDirectionCalculator.cs (Utils/)
-
-**목적**: VirtualAGV 또는 실제 AGV와의 통합 인터페이스
-
-```csharp
-public class AGVDirectionCalculator
-{
- public string GetNextNodeId(
- Point previousRfidPos, // 이전 RFID 위치
- MapNode currentNode, // 현재 노드
- Point currentRfidPos, // 현재 RFID 위치
- AgvDirection direction, // 이동 방향
- List allNodes // 모든 노드
- )
- {
- return _pathfinder.GetNextNodeId(
- previousRfidPos,
- currentNode,
- currentRfidPos,
- direction,
- allNodes
- );
- }
-
- // 추가: 선택된 방향 역추적
- public AgvDirection AnalyzeSelectedDirection(
- Point previousPos,
- Point currentPos,
- MapNode selectedNextNode,
- List connectedNodes
- )
- {
- // 벡터 비교로 실제 선택된 방향 분석
- }
-}
-```
-
----
-
-### 3. DirectionalPathfinderTest.cs (Utils/)
-
-**목적**: NewMap.agvmap 파일 기반 테스트
-
-#### 기능
-
-```csharp
-public class DirectionalPathfinderTest
-{
- // 맵 파일 로드
- public bool LoadMapFile(string filePath)
-
- // 테스트 실행
- public void TestDirectionalMovement(
- string previousRfidId,
- string currentRfidId,
- AgvDirection direction
- )
-
- // 정보 출력
- public void PrintAllNodes()
- public void PrintNodeInfo(string rfidId)
-}
-```
-
----
-
-## 📊 테스트 시나리오
-
-### 테스트 케이스 1: 직선 경로 전진
-```
-001 → 002 → Forward
-예상: 003
-이유: 직진 이동 (직진 가중치 1.0)
-```
-
-### 테스트 케이스 2: 역진
-```
-002 → 001 → Backward
-예상: 이전 노드 또는 null (001이 002의 유일한 연결)
-이유: 역진 방향 (후진 가중치 2.0)
-```
-
-### 테스트 케이스 3: 좌회전
-```
-002 → 003 → Forward
-예상: 004
-이유: 직진 계속
-```
-
-### 테스트 케이스 4: 분기점에서 우회전
-```
-003 → 004 → Right
-예상: 030 (또는 N022)
-이유: 우측 방향 가중치 1.5
-```
-
-### 테스트 케이스 5: Backward 시 좌우 반전
-```
-004 → 003 → Backward → Left
-예상: 002
-이유: Backward 상태에서 Left = 반전되어 원래는 우측 방향
- (Backward 기준 좌측 = Forward 기준 우측)
-```
-
----
-
-## 🔍 벡터 연산 예시
-
-### 예시 1: 001 → 002 → Forward
-
-```
-이동 벡터: (206-65, 244-229) = (141, 15)
-정규화: (141/142, 15/142) ≈ (0.993, 0.106)
-
-003 위치: (278, 278)
-002→003 벡터: (278-206, 278-244) = (72, 34)
-정규화: (72/80, 34/80) ≈ (0.9, 0.425)
-
-내적 = 0.993*0.9 + 0.106*0.425 ≈ 0.939 (매우 유사)
-→ Forward 점수: 100 * 1.0 = 100.0 ✓ 최고 점수
-→ 결과: 003 반환
-```
-
-### 예시 2: 003 → 004 → Right
-
-```
-이동 벡터: (380-278, 340-278) = (102, 62)
-정규화: (102/119, 62/119) ≈ (0.857, 0.521)
-
-N022 위치: (?, ?)
-N031 위치: (?, ?)
-(실제 맵 데이터에 따라 계산)
-
-Right 선택 → crossProduct 음수 선호
-→ N031 선택 가능성 높음
-```
-
----
-
-## 📁 파일 구조
-
-```
-AGVNavigationCore/
-├── PathFinding/
-│ └── Planning/
-│ └── DirectionalPathfinder.cs ← 핵심 알고리즘
-├── Utils/
-│ ├── AGVDirectionCalculator.cs ← 통합 인터페이스
-│ ├── DirectionalPathfinderTest.cs ← 테스트 클래스
-│ └── TestRunner.cs ← 실행 프로그램
-└── AGVNavigationCore.csproj ← 프로젝트 파일 (수정됨)
-```
-
----
-
-## 🚀 사용 방법
-
-### 기본 사용
-
-```csharp
-// 1. 계산기 생성
-var calculator = new AGVDirectionCalculator();
-
-// 2. 맵 노드 로드
-List allNodes = LoadMapFromFile("NewMap.agvmap");
-
-// 3. 다음 노드 계산
-string nextNodeId = calculator.GetNextNodeId(
- previousRfidPos: new Point(65, 229), // 001 위치
- currentNode: node002, // 현재 노드
- currentRfidPos: new Point(206, 244), // 002 위치
- direction: AgvDirection.Forward, // 전진
- allNodes: allNodes
-);
-
-Console.WriteLine($"다음 노드: {nextNodeId}"); // 003
-```
-
-### VirtualAGV 통합
-
-```csharp
-public class VirtualAGV
-{
- private AGVDirectionCalculator _directionCalc;
-
- public void OnPositionChanged()
- {
- // SetPosition() 호출 후
- string nextNodeId = _directionCalc.GetNextNodeId(
- _targetPosition, // 이전 위치
- _currentNode, // 현재 노드
- _currentPosition, // 현재 위치
- _currentDirection, // 현재 방향
- _allNodes
- );
- }
-}
-```
-
-### 테스트 실행
-
-```csharp
-var tester = new DirectionalPathfinderTest();
-tester.LoadMapFile(@"C:\Data\...\NewMap.agvmap");
-tester.TestDirectionalMovement("001", "002", AgvDirection.Forward);
-```
-
----
-
-## ✅ 검증 체크리스트
-
-- [x] 2개 위치 히스토리 검증 로직
-- [x] Forward/Backward/Left/Right 방향 처리
-- [x] Backward 시 좌우 반전 구현
-- [x] 방향별 가중치 시스템
-- [x] 벡터 기반 방향 계산
-- [x] NewMap.agvmap 파일 로드 지원
-- [x] 테스트 프레임워크
-
----
-
-## 🔗 관련 클래스
-
-| 클래스 | 파일 | 용도 |
-|--------|------|------|
-| DirectionalPathfinder | PathFinding/Planning/ | 핵심 알고리즘 |
-| AGVDirectionCalculator | Utils/ | 통합 인터페이스 |
-| DirectionalPathfinderTest | Utils/ | 테스트 |
-| TestRunner | Utils/ | 실행 프로그램 |
-| MapNode | Models/ | 노드 데이터 |
-| AgvDirection | Models/Enums.cs | 방향 열거형 |
-
----
-
-## 📝 주의사항
-
-⚠️ **2개 위치 히스토리 필수**
-- previousPos가 Point.Empty이면 null 반환
-- VirtualAGV.SetPosition() 호출 시 이전 위치를 _targetPosition에 저장
-
-⚠️ **벡터 정규화**
-- 매우 작은 이동(< 0.001)은 거리 0으로 처리
-
-⚠️ **방향 가중치**
-- 기본값: Forward=1.0, Left/Right=1.5, Backward=2.0
-- 프로젝트별로 조정 가능
-
-⚠️ **점수 시스템**
-- 100점 = 완벽한 방향
-- 0점 = 방향 불가
-- 낮은 점수도 반환됨 (대안 경로)
-
----
-
-## 🎯 향후 개선사항
-
-1. **A* 알고리즘 통합**
- - 현재는 직접 연결된 노드만 고려
- - A* 알고리즘으로 확장 가능
-
-2. **경로 캐싱**
- - 자주 이동하는 경로 캐시
- - 성능 향상
-
-3. **동적 가중치 조정**
- - AGV 상태(배터리, 속도)에 따라 가중치 변경
-
-4. **3D 좌표 지원**
- - 현재 2D Point만 지원
- - 3D 좌표 추가 가능
-
----
-
-**작성일**: 2025-10-23
-**상태**: 구현 완료, 테스트 대기
diff --git a/Cs_HMI/AGVLogic/IMPLEMENTATION_SUMMARY.md b/Cs_HMI/AGVLogic/IMPLEMENTATION_SUMMARY.md
deleted file mode 100644
index 0d7eb3d..0000000
--- a/Cs_HMI/AGVLogic/IMPLEMENTATION_SUMMARY.md
+++ /dev/null
@@ -1,311 +0,0 @@
-# 방향 기반 경로 탐색 구현 완료 요약
-
-## ✅ 구현 완료
-
-사용자 요구사항에 따라 **이전 위치 + 현재 위치 + 진행 방향**을 기반으로 **다음 노드를 계산하는 시스템**을 완전히 구현했습니다.
-
----
-
-## 📦 구현된 컴포넌트
-
-### 1. **VirtualAGV.GetNextNodeId()** (핵심 메서드)
-**파일**: `AGVNavigationCore\Models\VirtualAGV.cs` (라인 613~823)
-
-```csharp
-public string GetNextNodeId(AgvDirection direction, List allNodes)
-```
-
-#### 특징:
-- ✅ VirtualAGV의 `_prevPosition`, `_currentPosition`, `_currentNode` 사용
-- ✅ 최소 2개 위치 히스토리 검증 (prev/current 모두 설정되어야 함)
-- ✅ 벡터 기반 방향 계산 (내적, 외적)
-- ✅ Forward/Backward/Left/Right 모든 방향 지원
-- ✅ Backward 시 좌우 방향 자동 반전
-
-#### 동작 방식:
-```
-입력: direction (Forward/Backward/Left/Right), allNodes
- ↓
-1️⃣ 히스토리 검증: _prevPosition, _currentPosition 확인
-2️⃣ 연결된 노드 필터링: currentNode의 ConnectedNodes에서 후보 선택
-3️⃣ 이동 벡터 계산: _currentPosition - _prevPosition
-4️⃣ 벡터 정규화: 길이를 1로 만듦
-5️⃣ 각 후보에 대해 점수 계산:
- - 내적: 진행 방향과의 유사도
- - 외적: 좌우 판별
- - direction에 따라 가중치 적용
-6️⃣ 최고 점수 노드 반환
-```
-
----
-
-## 🧮 방향 점수 계산 로직
-
-### Forward (전진) 모드
-```
-내적 값 (dotProduct) 점수
-────────────────────────────
-> 0.9 (거의 같은 방향) 100
-0.5~0.9 (비슷한 방향) 80
-0~0.5 (약간 다른 방향) 50
--0.5~0 (거의 반대) 20
-< -0.5 (완전 반대) 0
-```
-
-### Backward (후진) 모드
-```
-내적 값 (dotProduct) 점수
-────────────────────────────
-< -0.9 (거의 반대) 100
--0.5~-0.9 (비슷하게 반대) 80
--0.5~0 (약간 다른) 50
-0~0.5 (거의 같은 방향) 20
-> 0.5 (완전 같은 방향) 0
-```
-
-### Left (좌측) 모드
-```
-Forward 상태 (dotProduct > 0): Backward 상태 (dotProduct < 0):
-─────────────────────────────────────────────────────────────────────
-crossProduct > 0.5 → 100 (좌측) crossProduct < -0.5 → 100 (좌측 반전)
-0~0.5 → 70 -0.5~0 → 70
--0.5~0 → 50 0~0.5 → 50
-< -0.5 → 30 > 0.5 → 30
-```
-
-### Right (우측) 모드
-```
-Forward 상태 (dotProduct > 0): Backward 상태 (dotProduct < 0):
-─────────────────────────────────────────────────────────────────────
-crossProduct < -0.5 → 100 (우측) crossProduct > 0.5 → 100 (우측 반전)
--0.5~0 → 70 0~0.5 → 70
-0~0.5 → 50 -0.5~0 → 50
-> 0.5 → 30 < -0.5 → 30
-```
-
----
-
-## 📋 테스트 시나리오
-
-### 시나리오 1: 직선 경로 전진
-```
-001 (65, 229) → 002 (206, 244) → GetNextNodeId(Forward)
-이동 벡터: (141, 15)
-002→003: (72, 34)
-내적: 0.939 → Forward 점수: 100 ✓
-결과: 003
-```
-
-### 시나리오 2: 좌회전
-```
-002 (206, 244) → 003 (278, 278) → GetNextNodeId(Left)
-이동 벡터에 대해 Left 가중치 적용
-외적: crossProduct 양수 선호
-```
-
-### 시나리오 3: 우회전
-```
-003 (278, 278) → 004 (380, 340) → GetNextNodeId(Right)
-이동 벡터에 대해 Right 가중치 적용
-외적: crossProduct 음수 선호
-결과: 030 또는 N022 (맵 구조에 따라)
-```
-
-### 시나리오 4: 후진
-```
-004 → 003 → GetNextNodeId(Backward)
-역진 가중치 적용 (dotProduct < -0.9 = 100점)
-결과: 002
-```
-
-### 시나리오 5: Backward 시 좌우 반전
-```
-004 → 003 (Backward) → GetNextNodeId(Left)
-Backward 상태에서 Left = 원래 Right 방향
-좌우 자동 반전으로 올바른 방향 계산
-```
-
----
-
-## 🏗️ 추가 구현 파일들
-
-### 1. **DirectionalPathfinder.cs**
-**파일**: `PathFinding\Planning\DirectionalPathfinder.cs`
-- 독립적인 벡터 기반 경로 탐색 엔진
-- VirtualAGV와 분리된 재사용 가능한 컴포넌트
-- 방향 가중치 커스터마이징 지원
-
-### 2. **AGVDirectionCalculator.cs**
-**파일**: `Utils\AGVDirectionCalculator.cs`
-- VirtualAGV와 실제 AGV 시스템을 위한 통합 인터페이스
-- RFID 위치 기반 계산
-- 선택된 방향 역추적 기능
-
-### 3. **DirectionalPathfinderTest.cs**
-**파일**: `Utils\DirectionalPathfinderTest.cs`
-- NewMap.agvmap 파일 로드 및 파싱
-- 테스트 시나리오 실행
-- 결과 검증 및 출력
-
-### 4. **TestRunner.cs**
-**파일**: `Utils\TestRunner.cs`
-- 전체 테스트 프로그램 실행
-- 모든 시나리오 자동 테스트
-
----
-
-## 📊 .csproj 수정 사항
-
-**파일**: `AGVNavigationCore\AGVNavigationCore.csproj`
-
-추가된 항목:
-```xml
-
-
-
-
-```
-
----
-
-## 🚀 사용 방법
-
-### 기본 사용 (VirtualAGV)
-
-```csharp
-// VirtualAGV 인스턴스
-var agv = new VirtualAGV("AGV001");
-
-// 위치 설정 (최소 2번)
-agv.SetPosition(node001, new Point(65, 229), AgvDirection.Forward);
-agv.SetPosition(node002, new Point(206, 244), AgvDirection.Forward);
-
-// 다음 노드 계산
-string nextNodeId = agv.GetNextNodeId(AgvDirection.Forward, allNodes);
-Console.WriteLine($"다음 노드: {nextNodeId}"); // 003
-```
-
-### 고급 사용 (독립적인 계산기)
-
-```csharp
-var calculator = new AGVDirectionCalculator();
-
-string nextNodeId = calculator.GetNextNodeId(
- previousRfidPos: new Point(206, 244),
- currentNode: node003,
- currentRfidPos: new Point(278, 278),
- direction: AgvDirection.Right,
- allNodes: allNodes
-);
-
-// 실제 선택된 방향 분석
-AgvDirection selectedDir = calculator.AnalyzeSelectedDirection(
- new Point(206, 244),
- new Point(278, 278),
- selectedNextNode,
- connectedNodes
-);
-```
-
----
-
-## ⚠️ 중요 주의사항
-
-### 1. 2개 위치 히스토리 필수
-```csharp
-// ❌ 잘못된 사용 (처음 호출 시)
-string next = agv.GetNextNodeId(direction, allNodes); // null 반환
-
-// ✅ 올바른 사용
-agv.SetPosition(node1, pos1, AgvDirection.Forward); // 첫 번째
-agv.SetPosition(node2, pos2, AgvDirection.Forward); // 두 번째
-string next = agv.GetNextNodeId(direction, allNodes); // 결과 반환
-```
-
-### 2. 벡터 정규화
-- 매우 작은 이동(<0.001px)은 거리 0으로 간주
-- 이 경우 첫 번째 연결 노드 반환
-
-### 3. 좌표계 유지
-- 모든 좌표는 맵 기준 (화면 좌표가 아님)
-- 줌/팬 상태에서는 별도 변환 필요
-
-### 4. 내적/외적 이해
-```
-내적 (Dot Product):
- = v1.x * v2.x + v1.y * v2.y
- 범위: -1 ~ 1
- 1 = 같은 방향, 0 = 직각, -1 = 반대 방향
-
-외적 (Cross Product):
- = v1.x * v2.y - v1.y * v2.x
- 양수 = 좌측, 음수 = 우측
-```
-
----
-
-## 📁 최종 파일 구조
-
-```
-AGVNavigationCore/
-├── Models/
-│ └── VirtualAGV.cs ⭐ (GetNextNodeId 추가)
-├── PathFinding/
-│ └── Planning/
-│ ├── DirectionalPathfinder.cs (NEW)
-│ ├── AGVPathfinder.cs
-│ └── ...
-├── Utils/
-│ ├── AGVDirectionCalculator.cs (NEW)
-│ ├── DirectionalPathfinderTest.cs (NEW)
-│ ├── TestRunner.cs (NEW)
-│ └── ...
-└── AGVNavigationCore.csproj (MODIFIED)
-```
-
----
-
-## 🎯 핵심 요구사항 검증
-
-| 요구사항 | 상태 | 구현 위치 |
-|---------|------|----------|
-| GetNextNodeID(direction) 메서드 | ✅ 완료 | VirtualAGV:628 |
-| 2개 위치 히스토리 검증 | ✅ 완료 | VirtualAGV:630-634 |
-| Forward/Backward/Left/Right 지원 | ✅ 완료 | VirtualAGV:743-817 |
-| 좌우 반전 로직 | ✅ 완료 | VirtualAGV:780, 806 |
-| 벡터 기반 계산 | ✅ 완료 | VirtualAGV:658-678 |
-| NewMap.agvmap 테스트 지원 | ✅ 완료 | DirectionalPathfinderTest |
-
----
-
-## 📝 다음 단계 (선택사항)
-
-1. **실제 맵에서 테스트**
- - TestRunner로 NewMap.agvmap 검증
- - 실제 RFID 번호로 시나리오 테스트
-
-2. **성능 최적화**
- - 벡터 계산 캐싱
- - 점수 계산 병렬화
-
-3. **기능 확장**
- - 3D 좌표 지원
- - A* 알고리즘 통합
- - 동적 가중치 조정
-
-4. **시뮬레이터 통합**
- - AGVSimulator에 GetNextNodeId 연결
- - 실시간 경로 변경 시연
-
----
-
-## 📚 관련 문서
-
-- `ANALYSIS_AGV_Direction_Storage.md` - VirtualAGV 필드 분석
-- `IMPLEMENTATION_DirectionalPathfinder.md` - 상세 구현 가이드
-
----
-
-**완료 일시**: 2025-10-23
-**상태**: 🟢 구현 완료, 테스트 대기
-**다음 작업**: NewMap.agvmap으로 실제 테스트
diff --git a/Cs_HMI/AGVLogic/MAP_LOADING_BIDIRECTIONAL_FIX.md b/Cs_HMI/AGVLogic/MAP_LOADING_BIDIRECTIONAL_FIX.md
deleted file mode 100644
index aff1986..0000000
--- a/Cs_HMI/AGVLogic/MAP_LOADING_BIDIRECTIONAL_FIX.md
+++ /dev/null
@@ -1,285 +0,0 @@
-# 맵 로딩 양방향 연결 자동 설정 수정
-
-## 🔍 문제 현상
-
-### 원래 문제
-```
-맵 에디터에서 002 → 003 연결 생성
- ↓
-NewMap.agvmap 저장:
- 002.ConnectedNodes = ["001", "003"]
- 003.ConnectedNodes = ["002"]
- ↓
-맵 로드 후 GetNextNodeId(Forward) 호출:
- 002의 ConnectedNodes 확인 → [001, 003] 있음 ✓
- 003의 ConnectedNodes 확인 → [002] 있음 ✓ (문제 없음)
- ↓
- 004에서 002로 이동한 경우:
- 002의 ConnectedNodes = ["001", "003"] ✓
- 003의 ConnectedNodes = ["002"] (004가 없음!) ✗
-```
-
-### 근본 원인
-`CleanupDuplicateConnections()` 메서드가 양방향 연결을 **단방향으로 축약**했습니다.
-
-```csharp
-// 기존 로직 (라인 303-314)
-if (connectedNode.ConnectedNodes.Contains(node.NodeId))
-{
- // 양방향 연결인 경우 사전순으로 더 작은 노드에만 유지
- if (string.Compare(node.NodeId, connectedNodeId, StringComparison.Ordinal) > 0)
- {
- connectionsToRemove.Add(connectedNodeId); // ← 역방향 제거!
- }
- else
- {
- connectedNode.RemoveConnection(node.NodeId); // ← 역방향 제거!
- }
-}
-```
-
-이로 인해 N003 → N002 같은 역방향 연결이 삭제되었습니다.
-
----
-
-## ✅ 해결 방법
-
-### 추가된 메서드: `EnsureBidirectionalConnections()`
-
-**파일**: `MapLoader.cs` (라인 341-389)
-
-**목적**: 모든 연결을 양방향으로 보장
-
-#### 동작 흐름
-
-```
-1단계: 모든 노드의 명시적 연결 수집
- 002.ConnectedNodes = ["001", "003"]
- 003.ConnectedNodes = ["002"]
- allConnections = {
- "N002": {"N001", "N003"},
- "N003": {"N002"}
- }
-
-2단계: 역방향 연결 추가
- 각 노드에 대해:
- "다른 노드가 나를 연결하고 있는가?" 확인
-
- N003의 경우:
- - N002가 N003을 연결? YES → N003.ConnectedNodes에 N002 추가
-
- N002의 경우:
- - N001이 N002를 연결? YES → N002.ConnectedNodes에 N001 추가
- - N003이 N002를 연결? YES → N002.ConnectedNodes에 N003 추가 (이미 있음)
-
-결과:
- 002.ConnectedNodes = ["001", "003"] ✓
- 003.ConnectedNodes = ["002"] ← ["002"]로 유지 (N002는 이미 명시적)
-```
-
-#### 코드 예시
-
-```csharp
-private static void EnsureBidirectionalConnections(List mapNodes)
-{
- // 1단계: 모든 명시적 연결 수집
- var allConnections = new Dictionary>();
- foreach (var node in mapNodes)
- {
- if (!allConnections.ContainsKey(node.NodeId))
- allConnections[node.NodeId] = new HashSet();
-
- if (node.ConnectedNodes != null)
- {
- foreach (var connectedId in node.ConnectedNodes)
- allConnections[node.NodeId].Add(connectedId);
- }
- }
-
- // 2단계: 역방향 연결 추가
- foreach (var node in mapNodes)
- {
- if (node.ConnectedNodes == null)
- node.ConnectedNodes = new List();
-
- // 이 노드를 연결하는 모든 노드 찾기
- foreach (var otherNodeId in allConnections.Keys)
- {
- if (otherNodeId == node.NodeId) continue;
-
- // 다른 노드가 이 노드를 연결하고 있다면
- if (allConnections[otherNodeId].Contains(node.NodeId))
- {
- // 이 노드의 ConnectedNodes에 그 노드를 추가
- if (!node.ConnectedNodes.Contains(otherNodeId))
- node.ConnectedNodes.Add(otherNodeId);
- }
- }
- }
-}
-```
-
----
-
-## 🔄 맵 로딩 순서 (수정된)
-
-```
-LoadMapFromFile()
- ↓
-JSON 역직렬화
- ↓
-MigrateDescriptionToName()
- ↓
-MigrateDockingDirection()
- ↓
-FixDuplicateNodeIds()
- ↓
-CleanupDuplicateConnections() ← 중복만 제거 (양방향 연결 유지)
- ↓
-✨ EnsureBidirectionalConnections() ← NEW: 양방향 자동 설정
- ↓
-LoadImageNodes()
- ↓
-Success = true
-```
-
----
-
-## 📊 결과 비교
-
-### 수정 전
-```
-002.ConnectedNodes = ["001", "003"]
-003.ConnectedNodes = ["002"]
-004.ConnectedNodes = ["003", "022", "031"]
-
-002에서 GetNextNodeId(Forward)
- → 003 계산 ✓
- → 001 계산 ✓
-
-003에서 GetNextNodeId(Forward)
- → 002 계산 ✓
- → (004 없음!) ✗ ← 004로 진행 불가
-
-004에서 GetNextNodeId(Backward)
- → 003 계산 ✓
- → 022, 031 계산 ✓
-```
-
-### 수정 후 ✅
-```
-002.ConnectedNodes = ["001", "003"]
-003.ConnectedNodes = ["002", "004"]
-004.ConnectedNodes = ["003", "022", "031"]
-
-002에서 GetNextNodeId(Forward)
- → 003 계산 ✓
- → 001 계산 ✓
-
-003에서 GetNextNodeId(Forward)
- → 002 계산 ✓
- → 004 계산 ✓ ← 이제 404로 진행 가능!
-
-004에서 GetNextNodeId(Backward)
- → 003 계산 ✓
- → 022, 031 계산 ✓
-```
-
----
-
-## 🎯 GetNextNodeId() 동작 원리
-
-이제 모든 노드의 `ConnectedNodes`에 양방향 연결이 포함되어 있으므로:
-
-```csharp
-public string GetNextNodeId(AgvDirection direction, List allNodes)
-{
- // 현재 노드의 ConnectedNodes에 모든 가능한 다음 노드가 포함됨 ✓
- var candidateNodes = allNodes.Where(n =>
- _currentNode.ConnectedNodes.Contains(n.NodeId)
- ).ToList();
-
- // 벡터 기반 점수 계산으로 최적 노드 선택
- return bestCandidate.node?.NodeId;
-}
-```
-
----
-
-## 🔗 관계도
-
-```
-맵 에디터
- ↓ (002→003 연결 생성 및 저장)
- ↓
-NewMap.agvmap
- ↓ (파일 로드)
- ↓
-LoadMapFromFile()
- ↓
-[CleanupDuplicateConnections]
- 002: ["001", "003"]
- 003: ["002"]
- ↓
-[EnsureBidirectionalConnections] ← NEW!
- 002: ["001", "003"]
- 003: ["002", "004"] ← 004 추가!
- ↓
-VirtualAGV.GetNextNodeId()
- 가능한 다음 노드 모두 찾을 수 있음 ✓
-```
-
----
-
-## 📋 체크리스트
-
-- [x] `EnsureBidirectionalConnections()` 메서드 추가
-- [x] `LoadMapFromFile()` 호출 순서 업데이트
-- [x] 모든 연결이 양방향으로 보장됨
-- [x] VirtualAGV.GetNextNodeId()에서 모든 가능한 다음 노드 찾을 수 있음
-- [x] RFID 002 → 003 → Forward → 004 경로 가능
-- [x] RFID 004 → 003 → Backward → 002 경로 가능
-
----
-
-## 🧪 테스트 시나리오
-
-### 시나리오 1: 직선 경로
-```
-002 → 003 → Forward → 004
-검증: 003.ConnectedNodes에 004가 포함되어야 함
-```
-
-### 시나리오 2: 분기점
-```
-004 → 003 → Left → ?
-검증: 003.ConnectedNodes에 가능한 모든 노드 포함
-```
-
-### 시나리오 3: 역진
-```
-004 → 003 → Backward → 002
-검증: 003.ConnectedNodes에 002가 포함되어야 함
-```
-
----
-
-## 📌 중요 포인트
-
-✅ **맵 로딩 시 자동으로 양방향 설정**
-- 사용자(맵 에디터)는 단방향만 그으면 됨
-- 시스템이 자동으로 역방향 추가
-
-✅ **GetNextNodeId() 완벽 지원**
-- 현재 노드의 ConnectedNodes만으로 모든 가능한 다음 노드 찾음
-- 벡터 기반 점수 계산으로 최적 경로 선택
-
-✅ **기존 맵 호환성 유지**
-- 기존 저장된 맵도 로드 시 자동으로 양방향 설정됨
-- 새로운 맵도 동일 방식으로 처리됨
-
----
-
-**수정 완료일**: 2025-10-23
-**상태**: 🟢 완료
-**다음 단계**: NewMap.agvmap 로드하여 검증
diff --git a/Cs_HMI/AGVLogic/PATHSCENARIO.md b/Cs_HMI/AGVLogic/PATHSCENARIO.md
deleted file mode 100644
index 6af5bb0..0000000
--- a/Cs_HMI/AGVLogic/PATHSCENARIO.md
+++ /dev/null
@@ -1,100 +0,0 @@
-## 경로시뮬레이션 설명
-## AGV는 같은경로상에서 방향을 전환할 수 없음
-## 경로계산을 위해서는 반드시 AGV는 2개 이상의 RFID를 읽어야 한다. (최소 2개를 읽어야 모터방향과 RFID의 읽히는 순서를 가지고 현재 AGV의 방향을 결정지을 수 있다)
-## 하기 케이스의 경우 케이스 설명전에 AGV가 어떻게 이동했는지 최소 2개의 RFID정보를 제공한다.
-## AGV의 RFID로 위치이동하는 것은 시뮬레이터폼의 SetAGVPositionByRfid 함수를 참고하면 됨
-## 방향전환이 필요할 때에 갈림길은 AGV와 가장 가까운 갈림길을 사용한다.
-
-## case 1 (AGV가 전진방향으로 이동하는 경우)
-## AGV는 모터전진방향으로 008 -> 007 로 이동 (최종위치는 007)
-
-Q1.목적지 : 015 (충전기 이므로 전진 방향 도킹해야하는 곳)
- A. 목적지 도킹방향과 현재 AGV도킹 방향이 동일하므로 방향전환이 필요없다. 목적지 까지의 최단거리를 계산한 후 그대로 이동하면됨
- 007 - 006 - 005 - 004 - 012 - 013 - 014 - 015
-
-Q2.목적지 : 019 (충전기 이므로 전진 방향 도킹해야하는 곳)
- A. 목적지 도킹방향과 현재 AGV도킹 방향이 동일하므로 방향전환이 필요없다. 목적지 까지의 최단거리를 계산한 후 그대로 이동하면됨
- 007 - 006 - 005 - 004 - 012 - 016 - 017 - 018 - 019
-
-Q3.목적지 : 001 (장비 이므로 후진 방향 도킹해야하는 곳)
- A. 목적지 도킹방향과 현재 AGV도킹 방향이 일치하지 않으니 방향전환이 필요하다,
- 목적지까의 RFID목록은 007 - 006 - 005 - 004 - 003 - 002 - 001
- 갈림길은 005 , 004 총 2개가 있으나 AGV 이동 방향상 가장 가까운 갈림길은 005이다. 전환은 005에서 하기로 한다.
- 005갈림길은 내경로상의 006 과 037이 있다. 내 경로상에서 방향전환은 할 수 없으니 005 갈림길에서는 037로 방향을 틀어서 (Magnet Left) 전진이동을 한후
- 037이 발견되면 방향을 후진으로 전환하면서 005를 거쳐 004방향으로 가도록 (Magnet Right) 로 유도해서 진행한다.
- 그렇게하면 005를 지나 004를 갈때에는 후진방향으로 이동하게 된다. 후진시에는 전진과 magtnet 방향전환이 반대로 필요하다,
- 037 -> 005 -> 004 의 경우 후진이동으로 좌회전을 해야하는데. 후진이기때문에 magnet 은 right 로 유도한다.
-
- 최종 경로는 아래와 같다
-
- 007(F) - 006(F) - 005(F) - 037(B) - 005(B) - 004(B) - 003(B) - 002(B) - 001(B)
-
-Q4.목적지 : 011 (장비 이므로 후진 방향 도킹해야하는 곳)
- A. 목적지 도킹방향과 현재 AGV도킹 방향이 일치하지 않으니 방향전환이 필요하다,
- 목적지까의 RFID목록은 007 - 006 - 005 - 004 - 030 - 009 - 010 - 011
- 갈림길은 005 , 004 총 2개가 있으나 AGV 이동 방향상 가장 가까운 갈림길은 005이다. 전환은 005에서 하기로 한다.
- 005갈림길은 내 경로상의 006 과 037이 있다. 내 경로상에서 방향전환은 할 수 없으니 005 갈림길에서는 037로 방향을 틀어서 (Magnet Left) 전진이동을 한후
- 037이 발견되면 방향을 후진으로 전환하면서 005를 거쳐 004방향으로 가도록 (Magnet Right) 로 유도해서 진행한다.
- 그렇게하면 005를 지나 004를 갈때에는 후진방향으로 이동하게 된다. 후진시에는 전진과 magtnet 방향전환이 반대로 필요하다,
- 037 -> 005 -> 004 의 경우 후진이동으로 좌회전을 해야하는데. 후진이기때문에 magnet 은 right 로 유도한다.
-
- 최종 경로는 아래와 같다
-
- 007(F) - 006(F) - 005(F) - 037(B) - 005(B) - 004(B) - 030(B) - 009(B) - 010(B) - 011(B)
-
-Q.목적지 : 041 (장비 이므로 후진 방향 도킹해야하는 곳)
- A. 목적지 도킹방향과 현재 AGV도킹 방향이 일치하지 않으니 방향전환이 필요하다,
- 목적지까의 RFID목록은 007 - 006 - 005 - 037 - 036 - 035 - 034 - 033 - 032 - 031 - 041
- 경로상 갈림길은 005 총 1개가 있으므로 전환은 005에서 하기로 한다.
- 005갈림길은 내 경로상의 006 과 037(이 경우엔 037도 내 경로는 맞다)
- 이 경우에는 006도 037도 내 경로이므로 005에 연결된 004포인트로 이동하면서 방향전환이 필요하다
- 005 갈림길에서는 004까지 전진으로 진행하고 004도착시 후진을 하고 005에서 037로 방향을 틀도록 마그넷을(left)로 유도한다
- 그렇게하면 005를 지나 037를 갈때에는 후진방향으로 이동하게 된다.
-
- 최종 경로는 아래와 같다
-
- 007(F) - 006(F) - 005(F) - 004(F) - 005(B) - 037(B) - 036(B) - 035(B) - 034(B) - 033(B) - 032(B) - 031(B) - 041(B)
-
-Q5.8 (장비 이므로 후진 방향 도킹해야하는 곳)
- A. 목적지 도킹방향과 현재 AGV도킹 방향이 일치하지 않으니 방향전환이 필요하다,
- 목적지까의 RFID목록은 007 - 006 - 005 - 037 - 036 - 035 - 034 - 038
- 경로상 갈림길은 005 총 1개가 있으므로 전환은 005에서 하기로 한다.
- 005갈림길은 내 경로상의 006 과 037(이 경우엔 037도 내 경로는 맞다)
- 이 경우에는 006도 037도 내 경로이므로 005에 연결된 004포인트로 이동하면서 방향전환이 필요하다
- 005 갈림길에서는 004까지 전진으로 진행하고 004도착시 후진을 하고 005에서 037로 방향을 틀도록 마그넷을(left)로 유도한다
- 그렇게하면 005를 지나 037를 갈때에는 후진방향으로 이동하게 된다.
-
- 최종 경로는 아래와 같다
-
- 007(F) - 006(F) - 005(F) - 004(F) - 005(B) - 037(B) - 036(B) - 035(B) - 034(B) - 038(B)
-
-
-## AGV는 모터전진방향으로 037 -> 036 로 이동 (최종위치는 036)
-Q6.목적지 : 038 (장비 이므로 후진 방향 도킹해야하는 곳)
- A. 목적지 도킹방향과 현재 AGV도킹 방향이 일치하지 않으니 방향전환이 필요하다,
- 목적지까의 RFID목록은 036 - 035 - 034 - 038
- 경로상 갈림길이 없다, 가장 가까운 갈림길은 005이므로 전환은 005에서 하기로 한다.
- 005갈림길은 내 경로상 포인트가 없으니 전환은 004 혹은 006 어떤쪽이던 상관없다.
- 다만 이러한 경우 일관성을 위해 Magnet 유도를 Left를 사용한다
- 036에서 후진으로 이동을 시작하면 037 -> 005 순으로 후진 이동을 한다. 여기서 방향전환을 해야하고 마그넷이 left로 유도가 되면
- AGV는 006방향으로 틀게된다. 이제 이러면 바로위의 Q5와 동일한 조건이 완성된다. 위치 006에서는 005 037 모두 목적지까지 포함되므로 004로
- 이동해서 전환을 해야한다. 005(f), 004(f) 까지 이동을 한 후 이제 방향전환을 해서 후진으로 005까지 이동이 필요하다. 후진이므로
- magnet을 left유도하여 037로 이동할 수 있게한다
-
- 최종 경로는 아래와 같다
-
- 036(B) - 037(B) - 005(B) - 006(B) - 005(F) - 004(F) - 005(F) - 037(B) - 036(B) - 035(B) - 034(B) - 038(B)
-
-
-## case 2 (AGV가 후진방향으로 이동하는 경우)
-AGV는 모터후진방향으로 008 -> 007 로 이동 (최종위치는 007)
-Q7.목적지 : 015 (충전기는 전진 도킹해야합니다.)
- A. 목적지 도킹방향과 현재 AGV도킹 방향이 일치하지 않으니 방향전환이 필요하다,
- 목적지까의 RFID목록은 007 - 006 - 005 - 004 - 012 - 013 -014 -015
- 경로상 갈림길은 005, 004, 012 총 3개가 있다, 가장 가까운 갈림길은 005이므로 전환은 005에서 하기로 한다.
- 005 갈림길은 내 경로상 포인트 (006,004)가 있으니 037 포인트를 이용하여 전환을 하면 된다.
- 006(B) -> 005(B - 마그넷유도 RIGHT) -> 037(F) -> 그런후 방향전화을 해서 005까지 전진으로 이동을 하고 004로 방향을 틀면된다.
-
- 최종 경로는 아래와 같다
-
- 007(B) - 006(B) - 005(B-maget right) - 037(에 B로 도착하면 F로 전환한다) - 005(F) - 004(F) - 012(F) - 013(F) - 014(F) - 015(F)
\ No newline at end of file
diff --git a/Cs_HMI/AGVLogic/PROJECT_SUMMARY.md b/Cs_HMI/AGVLogic/PROJECT_SUMMARY.md
deleted file mode 100644
index 0114fe6..0000000
--- a/Cs_HMI/AGVLogic/PROJECT_SUMMARY.md
+++ /dev/null
@@ -1,353 +0,0 @@
-# 프로젝트 요약 (AGVMapEditor, AGVNavigationCore, AGVSimulator)
-
-## 📊 프로젝트 개요
-
-3개의 주요 프로젝트가 **AGVNavigationCore** 라이브러리를 공유하며 연동되는 구조입니다.
-
-```
-┌─────────────────────────────────────────────────────────────┐
-│ AGVNavigationCore (공유 라이브러리) │
-├─────────────────────────────────────────────────────────────┤
-│ • Models: MapNode, MapLoader, Enums, IMovableAGV, VirtualAGV
-│ • Controls: UnifiedAGVCanvas (통합 UI 렌더링)
-│ • PathFinding: A*, AGVPathfinder, DirectionChangePlanner
-└─────────────────────────────────────────────────────────────┘
- ▲ ▲ ▲
- │ 참조 │ 참조 │ 참조
- │ │ │
- ┌──────────────┐ ┌──────────────┐ ┌──────────────┐
- │ AGVMapEditor │ │ AGVSimulator │ │ AGV4 (미사용)
- │ (맵 편집) │ │ (시뮬레이션) │ │ (메인앱)
- └──────────────┘ └──────────────┘ └──────────────┘
-```
-
----
-
-## 🎯 각 프로젝트의 기능
-
-### 1️⃣ **AGVMapEditor** (맵 편집 도구)
-
-**목적**: AGV 맵 데이터를 시각적으로 생성/편집
-
-#### 제공 기능
-| 기능 | 설명 |
-|------|------|
-| **노드 생성** | 맵 상에 AGV 네비게이션 노드 추가 |
-| **노드 편집** | 노드 이름, RFID, 타입, 도킹방향 설정 |
-| **노드 이동** | 드래그로 노드 위치 변경 (그리드 스냅 지원) |
-| **연결 관리** | 노드 간 경로 연결 생성/삭제 |
-| **노드 삭제** | 선택된 노드 제거 |
-| **라벨 추가** | 맵에 텍스트 라벨 추가 |
-| **이미지 추가** | 맵에 배경 이미지 추가 |
-| **맵 저장/로드** | JSON 형식 맵 파일 저장/로드 |
-
-#### 기술 구성
-```
-MainForm (WinForms)
-└─ UnifiedAGVCanvas (UI 렌더링)
- ├─ MapNode 목록 관리
- ├─ 편집 모드 (Select, Move, AddNode, Connect, Delete, DeleteConnection, AddLabel, AddImage)
- └─ MapLoader 사용 (JSON 저장/로드)
-```
-
-#### 주요 UI 요소
-- **메뉴바**: File (Open/Save), Edit, View
-- **툴바**: 편집 모드 전환 버튼 (선택, 이동, 노드추가, 연결, 삭제, 라벨, 이미지)
-- **속성 패널**: 선택된 노드 정보 표시/편집
-- **캔버스**: 맵 시각화 및 편집
-
----
-
-### 2️⃣ **AGVNavigationCore** (경로 계산 엔진 라이브러리)
-
-**목적**: AGV 경로 계산 및 네비게이션 핵심 로직 제공
-
-#### 제공 기능
-| 영역 | 모듈 | 기능 |
-|------|------|------|
-| **Models** | MapNode | AGV 네비게이션 노드 데이터 |
-| | MapLoader | 맵 파일 로드/저장 |
-| | IMovableAGV | AGV 동작 인터페이스 |
-| | VirtualAGV | 가상 AGV 시뮬레이션 로직 ⚠️ **미완성** |
-| **Controls** | UnifiedAGVCanvas | 맵 렌더링/편집/모니터링 UI |
-| **PathFinding** | AStarPathfinder | 기본 A* 경로 탐색 |
-| | AGVPathfinder | AGV 제약 고려 경로 계산 ⚠️ **미완성** |
-| | DirectionChangePlanner | 방향 전환 경로 계획 ⚠️ **미완성** |
-
-#### 핵심 기능 (구현 상태)
-```
-✅ 완성
-├─ MapNode 데이터 모델
-├─ MapLoader (파일 I/O)
-├─ UnifiedAGVCanvas (UI 렌더링/편집)
-└─ AStarPathfinder (기본 경로 탐색)
-
-❌ 미완성 (개발 대상)
-├─ VirtualAGV.ExecutePath() - 경로 실행
-├─ VirtualAGV.Update() - 프레임 업데이트
-├─ AGVPathfinder 핵심 로직 - 경로 상세화, 마그넷 방향 계산
-└─ DirectionChangePlanner - 4단계 방향 전환 알고리즘
-```
-
-#### 기술 구성
-```
-AGVNavigationCore (Class Library)
-├── Models/
-│ ├── MapNode.cs
-│ ├── MapLoader.cs
-│ ├── VirtualAGV.cs (← 경로 추적 미완성)
-│ ├── IMovableAGV.cs
-│ └── Enums.cs
-├── Controls/
-│ ├── UnifiedAGVCanvas.cs (메인 UI)
-│ ├── UnifiedAGVCanvas.Designer.cs
-│ ├── UnifiedAGVCanvas.Events.cs
-│ ├── UnifiedAGVCanvas.Mouse.cs (← 줌 기능)
-│ ├── UnifiedAGVCanvas.Rendering.cs
-│ └── UnifiedAGVCanvas.Utilities.cs
-├── PathFinding/
-│ ├── Core/
-│ │ ├── AStarPathfinder.cs ✅
-│ │ ├── PathNode.cs
-│ │ └── AGVPathResult.cs
-│ ├── Planning/
-│ │ ├── AGVPathfinder.cs (❌ 미완성)
-│ │ ├── DirectionChangePlanner.cs (❌ 미완성)
-│ │ └── NodeMotorInfo.cs
-│ ├── Analysis/
-│ │ └── JunctionAnalyzer.cs
-│ └── Validation/
-│ ├── PathValidationResult.cs
-│ └── DockingValidationResult.cs
-└── Utils/
- └── LiftCalculator.cs
-```
-
----
-
-### 3️⃣ **AGVSimulator** (AGV 시뮬레이터)
-
-**목적**: AGV 경로 계산 및 동작을 시각적으로 검증
-
-#### 제공 기능
-| 기능 | 설명 |
-|------|------|
-| **맵 로드** | 저장된 맵 파일 로드 |
-| **AGV 시뮬레이션** | 가상 AGV 생성 및 경로 따라 이동 |
-| **경로 계산** | 시작점/목적지 선택 후 경로 자동 계산 |
-| **경로 시각화** | 계산된 경로 맵에 표시 |
-| **실시간 상태 모니터링** | AGV 위치, 방향, 상태 실시간 표시 |
-| **도킹 검증** | AGV 도킹 방향 검증 |
-
-#### 기술 구성
-```
-SimulatorForm (WinForms)
-├─ UnifiedAGVCanvas (맵 렌더링)
-├─ VirtualAGV 리스트 (가상 AGV들)
-├─ MapLoader (맵 파일 로드)
-├─ AGVPathfinder (경로 계산)
-└─ 시뮬레이션 타이머 (매 프레임 AGV 업데이트)
-```
-
-#### 주요 UI 요소
-- **메뉴바**: File (Open Map)
-- **경로 제어 그룹**: 시작RFID, 목적지RFID, 타겟계산 버튼
-- **시뮬레이션 제어**: 시작, 일시정지, 정지 버튼
-- **캔버스**: 맵 + AGV + 경로 시각화
-
----
-
-## 🎨 UnifiedAGVCanvas (통합 UI 컨트롤)
-
-**위치**: `AGVNavigationCore/Controls/UnifiedAGVCanvas.cs` (4개 파일)
-
-### 핵심 기능
-| 기능 | 설명 |
-|------|------|
-| **맵 렌더링** | 노드, 연결선, 그리드, AGV, 경로 표시 |
-| **편집 기능** | 노드 추가/이동/삭제, 연결 관리 (AGVMapEditor) |
-| **모니터링** | 실시간 AGV 상태 표시 (AGVSimulator) |
-| **줌/팬** | 마우스 휠 줌, 좌클릭 드래그 팬 |
-| **선택/호버** | 노드 선택, 호버 표시 |
-| **경로 시각화** | 계산된 경로를 색상으로 표시 |
-
-### 모드 및 상태
-```csharp
-// CanvasMode
-Edit // 편집 모드 (맵 에디터)
-
-// EditMode (Edit 모드에서만 적용)
-Select // 노드 선택
-Move // 노드 이동
-AddNode // 노드 추가
-Connect // 연결 생성
-Delete // 노드/연결 삭제
-DeleteConnection // 연결 삭제
-AddLabel // 라벨 추가
-AddImage // 이미지 추가
-```
-
----
-
-## 🖱️ 줌/팬 기능 (현재 상태)
-
-### 현재 구현
-```csharp
-// UnifiedAGVCanvas.Mouse.cs : 171-188
-
-private void UnifiedAGVCanvas_MouseWheel(object sender, MouseEventArgs e)
-{
- // 줌 처리
- var mouseWorldPoint = ScreenToWorld(e.Location);
- var oldZoom = _zoomFactor;
-
- if (e.Delta > 0)
- _zoomFactor = Math.Min(_zoomFactor * 1.2f, 5.0f); // 확대 (1.2배)
- else
- _zoomFactor = Math.Max(_zoomFactor / 1.2f, 0.1f); // 축소 (1.2배)
-
- // 마우스 위치를 중심으로 줌
- var zoomRatio = _zoomFactor / oldZoom;
- _panOffset.X = (int)(e.X - (e.X - _panOffset.X) * zoomRatio);
- _panOffset.Y = (int)(e.Y - (e.Y - _panOffset.Y) * zoomRatio);
-
- Invalidate();
-}
-```
-
-### 문제점 및 개선 사항
-
-#### ⚠️ 현재 문제
-1. **줌 계산 로직**: 수식이 복잡하고 정확하지 않을 수 있음
-2. **좌표계 혼동**: 스크린 좌표와 월드 좌표 변환이 일관성 없음
-3. **매끄러움**: 줌 비율 계산에서 부자연스러운 동작 가능
-
-#### ✅ 개선 방안
-마우스 커서 위치를 기준점으로 하는 스무스한 줌을 구현:
-
-```csharp
-private void UnifiedAGVCanvas_MouseWheel(object sender, MouseEventArgs e)
-{
- // 현재 마우스 위치를 월드 좌표로 변환
- var mouseWorldBefore = ScreenToWorld(e.Location);
-
- float oldZoom = _zoomFactor;
-
- // 줌 팩터 계산 (휠 델타 기반)
- if (e.Delta > 0)
- _zoomFactor = Math.Min(_zoomFactor * 1.15f, 5.0f); // 확대 (부드러움)
- else
- _zoomFactor = Math.Max(_zoomFactor / 1.15f, 0.1f); // 축소 (부드러움)
-
- // 마우스 위치가 같은 월드 좌표를 가리키도록 팬 오프셋 조정
- var mouseWorldAfter = ScreenToWorld(e.Location);
-
- _panOffset.X += (int)((mouseWorldBefore.X - mouseWorldAfter.X) * _zoomFactor);
- _panOffset.Y += (int)((mouseWorldBefore.Y - mouseWorldAfter.Y) * _zoomFactor);
-
- Invalidate();
-}
-```
-
-#### 주요 개선점
-1. **더 부드러운 줌**: 1.2배 → 1.15배로 조정
-2. **명확한 로직**: 마우스 위치 기준으로 명시적으로 계산
-3. **정확한 좌표 변환**: ScreenToWorld() 사용으로 일관성 보장
-4. **자연스러운 동작**: 마우스 아래의 점이 같은 위치를 가리킴
-
----
-
-## 📂 파일 구조 (48개 C# 파일)
-
-### AGVMapEditor (10개 파일)
-```
-AGVMapEditor/
-├── Forms/
-│ ├── MainForm.cs (메인 폼, 편집 로직)
-│ └── MainForm.Designer.cs (UI 디자인)
-├── Models/
-│ ├── EditorSettings.cs (에디터 설정)
-│ ├── MapImage.cs (맵 이미지 데이터)
-│ ├── MapLabel.cs (맵 라벨 데이터)
-│ └── NodePropertyWrapper.cs (노드 속성 래퍼)
-├── Program.cs (진입점)
-└── Properties/
- └── AssemblyInfo.cs (어셈블리 정보)
-```
-
-### AGVNavigationCore (30개 파일)
-```
-AGVNavigationCore/
-├── Models/ (8개)
-│ ├── MapNode.cs, MapLoader.cs, VirtualAGV.cs, IMovableAGV.cs, etc.
-├── Controls/ (6개)
-│ ├── UnifiedAGVCanvas.cs, UnifiedAGVCanvas.Designer.cs, etc.
-├── PathFinding/ (13개)
-│ ├── Core/ (AStarPathfinder, PathNode, AGVPathResult)
-│ ├── Planning/ (AGVPathfinder, DirectionChangePlanner, etc.)
-│ ├── Analysis/ (JunctionAnalyzer)
-│ └── Validation/ (PathValidationResult, DockingValidationResult)
-└── Utils/ (3개)
- ├── LiftCalculator.cs, DockingValidator.cs, etc.
-```
-
-### AGVSimulator (8개 파일)
-```
-AGVSimulator/
-├── Forms/
-│ ├── SimulatorForm.cs (시뮬레이터 메인 폼)
-│ └── SimulatorForm.Designer.cs
-├── Models/
-│ └── (VirtualAGV는 AGVNavigationCore에서 참조)
-├── Program.cs
-└── Properties/
- └── AssemblyInfo.cs
-```
-
----
-
-## 🔄 데이터 흐름
-
-### 맵 편집 → 저장 흐름
-```
-AGVMapEditor.MainForm
- ↓
-UnifiedAGVCanvas (편집 모드)
- ↓
-MapLoader.SaveMapToFile()
- ↓
-NewMap.agvmap (JSON 파일)
-```
-
-### 맵 로드 → 시뮬레이션 흐름
-```
-NewMap.agvmap (JSON 파일)
- ↓
-MapLoader.LoadMapFromFile()
- ↓
-AGVSimulator.SimulatorForm
- ↓
-UnifiedAGVCanvas (모니터링 모드)
- ↓
-VirtualAGV (경로 실행) ⚠️ 미완성
-```
-
----
-
-## ⚠️ 현재 미완성 부분
-
-### 🔴 우선순위 높음
-1. **VirtualAGV.ExecutePath()** - 경로 실행 로직
-2. **VirtualAGV.Update()** - 매 프레임 위치 업데이트
-3. **AGVPathfinder 핵심** - 경로 상세화, 마그넷 방향 계산
-
-### 🟡 우선순위 중간
-4. **DirectionChangePlanner** - 4단계 방향 전환 알고리즘
-5. **UnifiedAGVCanvas 줌 개선** - 마우스 기준 스무스 줌
-
----
-
-## 📝 참고 문서
-- `CLAUDE.md` - 개발 가이드 및 AGV 하드웨어 설명
-- `CHANGELOG.md` - 변경 로그
-- `Data/NewMap.agvmap` - 실제 맵 데이터 샘플
diff --git a/Cs_HMI/AGVLogic/QUICK_REFERENCE.md b/Cs_HMI/AGVLogic/QUICK_REFERENCE.md
deleted file mode 100644
index d79a7a2..0000000
--- a/Cs_HMI/AGVLogic/QUICK_REFERENCE.md
+++ /dev/null
@@ -1,233 +0,0 @@
-# GetNextNodeId() 구현 - 빠른 참조 가이드
-
-**최종 업데이트**: 2025-10-23
-**상태**: 🟢 완료
-
----
-
-## 🎯 핵심 정보
-
-### 구현 메서드
-```csharp
-public string GetNextNodeId(AgvDirection direction, List allNodes)
-```
-
-**위치**: `AGVNavigationCore\Models\VirtualAGV.cs` (라인 628-821)
-
-### 사용 방법
-```csharp
-// 위치 설정 (최소 2회)
-agv.SetPosition(node001, new Point(65, 229), AgvDirection.Forward);
-agv.SetPosition(node002, new Point(206, 244), AgvDirection.Forward);
-
-// 다음 노드 조회
-string nextNodeId = agv.GetNextNodeId(AgvDirection.Forward, allNodes);
-// 결과: "N003"
-```
-
----
-
-## ⚡ 핵심 수정사항
-
-### Backward 로직 수정
-**파일**: `VirtualAGV.cs` (라인 755-767)
-
-**변경 전**:
-```csharp
-if (dotProduct < -0.9f) // ❌ 반대 방향
- baseScore = 100.0f;
-```
-
-**변경 후**:
-```csharp
-if (dotProduct > 0.9f) // ✅ 같은 방향
- baseScore = 100.0f;
-```
-
-### 이유
-모터 방향(Forward/Backward)은 경로 선택에 영향을 주지 않음
-→ Forward/Backward 모두 같은 경로 선호
-
----
-
-## 🧪 검증 결과
-
-### 4가지 시나리오 - 모두 패스 ✅
-
-| # | 이동 | 방향 | 결과 | 상태 |
-|---|-----|------|------|------|
-| 1 | 001→002 | Forward | N003 | ✅ |
-| 2 | 001→002 | Backward | N003 | ✅ |
-| 3 | 002→003 | Forward | N004 | ✅ |
-| 4 | 002→003 | Backward | N004 | ✅ FIXED |
-
----
-
-## 📊 기술 개요
-
-### 벡터 계산
-```
-1. 이동 벡터 = 현재 위치 - 이전 위치
-2. 정규화
-3. 각 후보와 내적/외적 계산
-4. 방향별 점수 결정
-5. 최고 점수 노드 반환
-```
-
-### 점수 기준
-```
-Forward/Backward (수정 후 동일):
- dot > 0.9 → 100점
- dot > 0.5 → 80점
- dot > 0 → 50점
- dot > -0.5 → 20점
- else → 0점
-```
-
----
-
-## 🔧 관련 파일
-
-### 핵심 파일
-- **VirtualAGV.cs** - GetNextNodeId() 구현
-- **MapLoader.cs** - 양방향 연결 자동 설정
-- **GetNextNodeIdTest.cs** - 테스트 코드
-
-### 문서 파일
-- **BACKWARD_FIX_SUMMARY_KO.md** - 수정 요약 (한글)
-- **STATUS_REPORT_FINAL.md** - 최종 보고서
-- **BACKWARD_FIX_VERIFICATION.md** - 검증 보고서
-
----
-
-## 📝 요구사항 충족 현황
-
-### 사용자 요청
-✅ Forward/Backward 지원
-✅ Left/Right 지원
-✅ 벡터 기반 계산
-✅ 2-위치 히스토리 필요
-✅ 양방향 연결 자동 설정
-✅ 002→003 Backward → 004 반환
-
-### 테스트
-✅ 4가지 시나리오 모두 패스
-✅ 사용자 피드백 반영 완료
-✅ 버그 수정 완료
-
----
-
-## 💬 주요 개념
-
-### Forward vs Backward
-```
-❌ 틀림: Forward(앞) vs Backward(뒤) - 경로 방향
-✅ 맞음: Forward(정방향) vs Backward(역방향) - 모터 방향
- 경로 선택은 동일!
-```
-
-### 양방향 연결
-```
-맵 저장: 단방향 (002→003)
-메모리: 양방향 (002↔003)
- 자동 복원됨!
-```
-
----
-
-## 🚀 사용 시나리오
-
-### 경로 계산
-```csharp
-// AGV가 002에서 003으로 이동 (Forward 모터)
-agv.SetPosition(node002, new Point(206, 244), AgvDirection.Forward);
-agv.SetPosition(node003, new Point(278, 278), AgvDirection.Forward);
-
-// 다음 노드 조회
-string nextForward = agv.GetNextNodeId(AgvDirection.Forward, allNodes);
-// 결과: N004 (경로 계속)
-
-string nextBackward = agv.GetNextNodeId(AgvDirection.Backward, allNodes);
-// 결과: N004 (경로 계속, 모터만 역방향)
-```
-
-### 방향 확인
-```csharp
-// 이전 모터 방향
-AgvDirection prev = agv._currentDirection; // Forward/Backward
-
-// 현재 위치 확인
-Point current = agv._currentPosition;
-
-// 이동 벡터 계산 가능
-// 다음 노드 결정 가능
-```
-
----
-
-## ⚙️ 내부 동작
-
-### SetPosition() 호출 시
-1. _prevPosition ← _currentPosition
-2. _currentPosition ← newPosition
-3. _prevNode ← _currentNode
-4. _currentNode ← newNode
-5. _currentDirection ← direction
-
-### GetNextNodeId() 호출 시
-1. 2-위치 히스토리 검증
-2. 이동 벡터 계산
-3. 정규화
-4. 각 후보 노드에 대해:
- - 벡터 계산
- - 정규화
- - 내적/외적 계산
- - 점수 결정
-5. 최고 점수 노드 반환
-
----
-
-## 🔍 디버깅 팁
-
-### 예상과 다른 결과가 나올 때
-1. ConnectedNodes 확인
- ```csharp
- var connected = currentNode.ConnectedNodes;
- // 모든 이웃 노드가 포함되어 있나?
- ```
-
-2. 위치 좌표 확인
- ```csharp
- var pos = agv._currentPosition;
- var prevPos = agv._prevPosition;
- // 좌표가 올바른가?
- ```
-
-3. 벡터 계산 확인
- ```csharp
- var vec = (prevPos.X - currentPos.X, prevPos.Y - currentPos.Y);
- // 벡터가 맞는 방향인가?
- ```
-
----
-
-## 📚 추가 리소스
-
-**상세 분석**: `GETNEXTNODEID_LOGIC_ANALYSIS.md`
-**검증 결과**: `BACKWARD_FIX_VERIFICATION.md`
-**전체 보고서**: `STATUS_REPORT_FINAL.md`
-
----
-
-## ✅ 체크리스트
-
-프로젝트 통합 시:
-- [ ] VirtualAGV.cs 확인 (GetNextNodeId 메서드)
-- [ ] MapLoader.cs 확인 (양방향 연결 설정)
-- [ ] 테스트 실행 (GetNextNodeIdTest)
-- [ ] 맵 파일 확인 (NewMap.agvmap)
-- [ ] 실제 경로 테스트
-
----
-
-**최종 상태**: 🟢 **준비 완료**
diff --git a/Cs_HMI/AGVLogic/README_FINAL.md b/Cs_HMI/AGVLogic/README_FINAL.md
deleted file mode 100644
index c5a1c05..0000000
--- a/Cs_HMI/AGVLogic/README_FINAL.md
+++ /dev/null
@@ -1,366 +0,0 @@
-# GetNextNodeId() 구현 최종 완료 보고서
-
-**보고 일시**: 2025-10-23
-**최종 상태**: 🟢 **완전히 완료됨**
-
----
-
-## 📌 개요
-
-### 프로젝트 목표
-AGV의 현재 위치와 이전 위치를 기반으로 다음 노드를 결정하는 `GetNextNodeId()` 메서드 구현
-
-### 최종 결과
-✅ 메서드 완전 구현
-✅ 모든 요구사항 충족
-✅ 6/6 시나리오 검증 완료
-✅ 사용자 피드백 100% 반영
-
----
-
-## 🎯 핵심 기능
-
-### GetNextNodeId() 메서드
-```csharp
-public string GetNextNodeId(AgvDirection direction, List allNodes)
-```
-
-**파라미터**:
-- `direction`: 요청하려는 모터 방향 (Forward/Backward/Left/Right)
-- `allNodes`: 모든 맵 노드 목록
-
-**반환값**:
-- 다음 노드의 ID
-- 또는 null (연결된 노드 없음)
-
-**필수 조건**:
-- 최소 2번의 SetPosition() 호출 필요 (_prevPosition, _currentPosition)
-
-### 동작 원리
-```
-1. 이동 벡터 계산 (현재 - 이전)
-2. 정규화
-3. 각 후보 노드와 내적/외적 계산
-4. 현재 모터 상태(_currentDirection) 기반 점수 결정
-5. 최고 점수 노드 반환
-```
-
----
-
-## 💡 핵심 개념
-
-### 모터 방향과 경로 선택
-```
-현재 모터 방향 = _currentDirection
-요청 모터 방향 = direction 파라미터
-
-같음 → 경로 계속 (dotProduct > 0.9)
-다름 → 경로 반대 (dotProduct < -0.9)
-```
-
-### 실제 의미
-```
-002 → 003 Backward 이동 후:
-
-GetNextNodeId(Backward):
- Backward → Backward: 모터 방향 유지
- 경로 계속 → N004 ✅
-
-GetNextNodeId(Forward):
- Backward → Forward: 모터 방향 전환
- 경로 반대 → N002 ✅
-```
-
----
-
-## 📂 수정된 파일
-
-### 1. VirtualAGV.cs
-**위치**: `AGVNavigationCore\Models\VirtualAGV.cs`
-**라인**: 628-821
-
-**추가된 메서드**:
-- GetNextNodeId() - 라인 628-719
-- CalculateDirectionalScore() - 라인 725-821
-
-**핵심 로직**:
-```csharp
-case AgvDirection.Forward:
- if (_currentDirection == AgvDirection.Forward)
- // 경로 계속
- else
- // 경로 반대
- break;
-
-case AgvDirection.Backward:
- if (_currentDirection == AgvDirection.Backward)
- // 경로 계속
- else
- // 경로 반대
- break;
-```
-
-### 2. MapLoader.cs
-**위치**: `AGVNavigationCore\Models\MapLoader.cs`
-**라인**: 341-389
-
-**추가된 메서드**:
-- EnsureBidirectionalConnections() - 라인 341-389
-
-**기능**:
-- 맵 로드 시 자동으로 양방향 연결 복원
-- LoadMapFromFile()에서 라인 85에서 호출
-
-### 3. GetNextNodeIdTest.cs
-**위치**: `AGVNavigationCore\Utils\GetNextNodeIdTest.cs`
-
-**변경 사항**:
-- 시나리오 5-6 추가
-- currentMotorDirection 파라미터 추가
-- TestScenario() 메서드 오버로드
-
----
-
-## ✅ 검증 결과
-
-### 6가지 모든 시나리오 검증 완료
-
-```
-시나리오 1: 001→002 Forward → Forward
- 현재: Forward, 요청: Forward
- 경로: 계속
- 결과: N003 ✅
-
-시나리오 2: 001→002 Forward → Backward
- 현재: Forward, 요청: Backward
- 경로: 반대
- 결과: N001 ✅
-
-시나리오 3: 002→003 Forward → Forward
- 현재: Forward, 요청: Forward
- 경로: 계속
- 결과: N004 ✅
-
-시나리오 4: 002→003 Forward → Backward
- 현재: Forward, 요청: Backward
- 경로: 반대
- 결과: N002 ✅
-
-시나리오 5: 002→003 Backward → Forward ⭐
- 현재: Backward, 요청: Forward
- 경로: 반대
- 결과: N002 ✅ 사용자 요구 충족!
-
-시나리오 6: 002→003 Backward → Backward ⭐
- 현재: Backward, 요청: Backward
- 경로: 계속
- 결과: N004 ✅ 사용자 요구 충족!
-```
-
----
-
-## 📚 문서 목록
-
-### 상세 문서
-1. **FINAL_VERIFICATION_CORRECT.md**
- - 최종 검증 보고서
- - 6가지 시나리오 상세 분석
-
-2. **STATUS_REPORT_FINAL.md**
- - 전체 구현 상태 보고서
- - 완성도 통계
-
-3. **FINAL_SUMMARY_KO.md**
- - 최종 요약 (한글)
- - 사용자 요구사항 확인
-
-### 기술 문서
-4. **GETNEXTNODEID_LOGIC_ANALYSIS.md**
- - 벡터 계산 상세 분석
- - 수학 원리 설명
-
-5. **MAP_LOADING_BIDIRECTIONAL_FIX.md**
- - 양방향 연결 설정 설명
- - 구현 방식
-
-### 참고 문서
-6. **QUICK_REFERENCE.md**
- - 빠른 참조 가이드
- - 핵심 정보
-
-7. **IMPLEMENTATION_CHECKLIST.md**
- - 완료 항목 체크리스트
- - 다음 단계
-
----
-
-## 🚀 사용 방법
-
-### 기본 사용법
-```csharp
-// VirtualAGV 인스턴스
-var agv = new VirtualAGV("AGV001");
-
-// 최소 2번 위치 설정
-agv.SetPosition(node002, new Point(206, 244), AgvDirection.Backward);
-agv.SetPosition(node003, new Point(278, 278), AgvDirection.Backward);
-
-// 다음 노드 조회
-string nextNodeId = agv.GetNextNodeId(AgvDirection.Backward, allNodes);
-// 결과: "N004" (경로 계속)
-
-nextNodeId = agv.GetNextNodeId(AgvDirection.Forward, allNodes);
-// 결과: "N002" (경로 반대)
-```
-
-### 테스트 실행
-```csharp
-var tester = new GetNextNodeIdTest();
-tester.TestGetNextNodeId();
-// 6가지 시나리오 모두 검증
-```
-
----
-
-## 🔧 기술 사양
-
-### 벡터 계산
-```
-이동 벡터 = 현재 위치 - 이전 위치
-정규화: 벡터 / |벡터|
-
-내적: 방향 유사도 (-1 ~ 1)
- > 0.9: 매우 유사 (100점)
- > 0.5: 유사 (80점)
- > 0: 약간 유사 (50점)
- > -0.5: 약간 반대 (20점)
- ≤ -0.5: 반대 (0점)
-
-외적: 좌우 판별
- > 0: 좌측 (반시계)
- < 0: 우측 (시계)
-```
-
-### 점수 결정
-```
-Forward 모터 상태에서 Forward 요청:
- dotProduct > 0.9 → 100점 (경로 계속)
-
-Forward 모터 상태에서 Backward 요청:
- dotProduct < -0.9 → 100점 (경로 반대)
-
-Backward 모터 상태에서 Backward 요청:
- dotProduct > 0.9 → 100점 (경로 계속)
-
-Backward 모터 상태에서 Forward 요청:
- dotProduct < -0.9 → 100점 (경로 반대)
-```
-
----
-
-## ✨ 주요 특징
-
-### 1. 현재 모터 상태 기반 로직
-- _currentDirection과 direction 파라미터 비교
-- 자동으로 경로 계속/반대 판별
-
-### 2. 벡터 기반 정확한 계산
-- 내적으로 방향 유사도 계산
-- 외적으로 좌우 판별
-- 수학적으로 정확한 방향 결정
-
-### 3. 안전한 에러 처리
-- null 검증
-- 2-위치 히스토리 검증
-- 이동 거리 검증
-- ConnectedNodes 필터링
-
-### 4. 완전한 테스트 커버리지
-- 6가지 시나리오 모두 검증
-- 모터 상태 전환 시나리오 포함
-- 경로 계속/반대 모두 검증
-
----
-
-## 📊 구현 통계
-
-```
-추가된 코드 라인: ~200 (GetNextNodeId + CalculateDirectionalScore)
-보조 메서드: 1개 (EnsureBidirectionalConnections)
-테스트 시나리오: 6개
-문서 파일: 10개 이상
-
-코드 품질:
-- 컴파일 가능: ✅
-- 오류 처리: ✅
-- 가독성: ✅
-- 유지보수성: ✅
-
-검증 상태:
-- 시나리오 통과: 6/6 (100%)
-- 사용자 요구사항: 100% 충족
-- 엣지 케이스: 처리 완료
-```
-
----
-
-## ✅ 완료 항목
-
-### 구현
-- [x] GetNextNodeId() 메서드
-- [x] CalculateDirectionalScore() 메서드
-- [x] 현재 모터 상태 기반 로직
-- [x] 벡터 계산 (정규화, 내적, 외적)
-- [x] 점수 결정 로직
-
-### 통합
-- [x] VirtualAGV.cs에 추가
-- [x] MapLoader.cs 양방향 연결 설정
-- [x] GetNextNodeIdTest.cs 통합
-
-### 검증
-- [x] 6가지 시나리오 모두 검증
-- [x] 모터 상태 전환 검증
-- [x] 경로 계속/반대 검증
-- [x] 사용자 피드백 확인
-
-### 문서
-- [x] 상세 기술 문서
-- [x] 검증 보고서
-- [x] 사용 가이드
-- [x] 참고 자료
-
----
-
-## 🎉 최종 상태
-
-```
-상태: 🟢 완전히 완료됨
-
-구현: 100%
-검증: 100%
-문서: 100%
-사용자 요구사항: 100%
-```
-
----
-
-## 📞 문의 사항
-
-### 구현 관련
-- VirtualAGV.cs 라인 628-821 참고
-- GETNEXTNODEID_LOGIC_ANALYSIS.md 참고
-
-### 검증 관련
-- FINAL_VERIFICATION_CORRECT.md 참고
-- GetNextNodeIdTest.cs 실행
-
-### 사용 관련
-- QUICK_REFERENCE.md 참고
-- FINAL_SUMMARY_KO.md 참고
-
----
-
-**최종 완료**: 2025-10-23
-**상태**: 🟢 **프로덕션 준비 완료**
-**다음 단계**: 빌드 및 런타임 테스트
diff --git a/Cs_HMI/AGVLogic/STATUS_REPORT_FINAL.md b/Cs_HMI/AGVLogic/STATUS_REPORT_FINAL.md
deleted file mode 100644
index a8c885d..0000000
--- a/Cs_HMI/AGVLogic/STATUS_REPORT_FINAL.md
+++ /dev/null
@@ -1,335 +0,0 @@
-# GetNextNodeId() 구현 및 Backward 로직 수정 - 최종 상태 보고서
-
-**보고 일시**: 2025-10-23
-**전체 상태**: 🟢 **완료 및 검증됨**
-
----
-
-## 📋 작업 완료 현황
-
-### ✅ 1단계: GetNextNodeId() 메서드 구현
-- **상태**: 완료
-- **파일**: `AGVNavigationCore\Models\VirtualAGV.cs` (628-821라인)
-- **기능**:
- - 이전 위치 + 현재 위치 + 방향으로 다음 노드 ID 반환
- - Forward/Backward/Left/Right 4가지 방향 지원
- - 벡터 기반 방향 계산 (내적/외적)
- - 2-위치 히스토리 필요
-
-### ✅ 2단계: 양방향 연결 자동 설정
-- **상태**: 완료
-- **파일**: `AGVNavigationCore\Models\MapLoader.cs` (341-389라인)
-- **기능**:
- - 맵 로드 시 자동으로 양방향 연결 복원
- - 단방향 저장 → 양방향 메모리 로드
- - `EnsureBidirectionalConnections()` 메서드 추가
-
-### ✅ 3단계: Backward 로직 수정 (최신 수정)
-- **상태**: 완료
-- **파일**: `AGVNavigationCore\Models\VirtualAGV.cs` (755-767라인)
-- **수정 내용**:
- - Backward를 Forward와 동일하게 처리
- - dotProduct < -0.9f → **dotProduct > 0.9f로 변경**
- - 경로 선택은 이동 벡터에만 의존
-
-### ✅ 4단계: 테스트 및 검증
-- **상태**: 완료
-- **파일**:
- - `GetNextNodeIdTest.cs` - 4가지 시나리오 검증
- - `TestRunner.cs` - 테스트 실행 클래스
-- **결과**: 모든 시나리오 패스 (4/4 ✅)
-
----
-
-## 🎯 핵심 수정 사항
-
-### 문제 상황
-```
-사용자 피드백: 002→003 Backward 이동 후,
-003에서 GetNextNodeId(Backward) 호출 시
-예상: N004 (경로 계속)
-실제: N002 (경로 반대) ❌
-```
-
-### 원인
-Backward 로직이 반대 방향을 찾도록 구현되어 있었음:
-```csharp
-case AgvDirection.Backward:
- if (dotProduct < -0.9f) // ❌ 반대 방향만 선호
-```
-
-### 해결책
-Backward를 Forward와 동일하게 처리:
-```csharp
-case AgvDirection.Backward:
- if (dotProduct > 0.9f) // ✅ 같은 방향 선호
-```
-
-### 이유
-> "모터 방향을 바꾼다고 해서 AGV 몸체 방향이 바뀌는 게 아니야"
->
-> 모터 방향(Forward/Backward)은 단순히 모터 회전 방향
-> AGV 이동 경로는 변하지 않음
-> 따라서 경로 선택은 Forward/Backward 구분 없이 동일해야 함
-
----
-
-## ✅ 검증 결과
-
-### 모든 4가지 시나리오 검증 완료
-
-```
-시나리오 1: 001(65,229) → 002(206,244) → Forward
- 이동 벡터: (141, 15)
- 후보 N001: dot = -0.985 → 20점
- 후보 N003: dot = 0.934 → 100점 ✅
- 결과: N003 선택 ✅ PASS
-
-시나리오 2: 001(65,229) → 002(206,244) → Backward
- 이동 벡터: (141, 15)
- 후보 N001: dot = -0.985 → 20점
- 후보 N003: dot = 0.934 → 100점 ✅
- 결과: N003 선택 ✅ PASS
-
-시나리오 3: 002(206,244) → 003(278,278) → Forward
- 이동 벡터: (72, 34)
- 후보 N002: dot = -0.934 → 20점
- 후보 N004: dot = 0.989 → 100점 ✅
- 결과: N004 선택 ✅ PASS
-
-시나리오 4: 002(206,244) → 003(278,278) → Backward ⭐ FIXED
- 이동 벡터: (72, 34)
- 후보 N002: dot = -0.934 → 20점
- 후보 N004: dot = 0.989 → 100점 ✅
- 결과: N004 선택 ✅ PASS (사용자 피드백 충족!)
-```
-
-### 수정 전후 비교
-| 시나리오 | 수정 전 | 수정 후 | 예상 | 상태 |
-|---------|--------|--------|------|------|
-| 4번 | N002 ❌ | N004 ✅ | N004 | FIXED |
-
----
-
-## 📊 구현 통계
-
-### 작성된 코드
-- **핵심 메서드**: 2개 (GetNextNodeId, CalculateDirectionalScore)
-- **메서드 라인 수**: 약 200라인
-- **보조 메서드**: EnsureBidirectionalConnections (약 50라인)
-
-### 테스트 코드
-- **테스트 시나리오**: 4개
-- **검증 메서드**: 5개
-- **테스트 라인 수**: 약 300라인
-
-### 문서
-- **기술 문서**: 5개
-- **검증 보고서**: 2개
-- **요약 문서**: 2개
-
----
-
-## 🔍 기술 상세
-
-### 벡터 계산 방식
-```
-1. 이동 벡터 계산
- v_movement = currentPos - prevPos
-
-2. 벡터 정규화
- normalized = v_movement / |v_movement|
-
-3. 후보별 점수 계산
- v_next = candidatePos - currentPos
- normalized_next = v_next / |v_next|
-
- 내적: dot = normalized · normalized_next
- 외적: cross = normalized × normalized_next (Z)
-
-4. 방향별 점수 결정
- Forward/Backward: 내적 값 기반 (수정 후 동일)
- Left/Right: 외적 값 기반 (dotProduct 상태에 따라 달라짐)
-
-5. 최고 점수 노드 선택
- return max(scores).node
-```
-
-### 점수 기준
-```
-Forward 모드:
- dot > 0.9 → 100점 (거의 같은 방향)
- dot > 0.5 → 80점
- dot > 0 → 50점
- dot > -0.5 → 20점
- else → 0점
-
-Backward 모드 (수정 후 - Forward와 동일):
- dot > 0.9 → 100점 ✅
- dot > 0.5 → 80점
- dot > 0 → 50점
- dot > -0.5 → 20점
- else → 0점
-```
-
----
-
-## 📁 최종 파일 목록
-
-### 수정된 핵심 파일
-1. **VirtualAGV.cs**
- - GetNextNodeId() 메서드 추가 (628-821라인)
- - CalculateDirectionalScore() 메서드 추가 (725-821라인)
- - **Backward 케이스 수정 (755-767라인)**
-
-2. **MapLoader.cs**
- - EnsureBidirectionalConnections() 메서드 추가 (341-389라인)
- - LoadMapFromFile()에 통합 (85라인)
-
-3. **GetNextNodeIdTest.cs**
- - **시나리오 4 업데이트** (70-72라인)
- - 예상값 N002 → **N004로 변경**
-
-### 테스트 파일
-4. **TestRunner.cs** - 테스트 실행 클래스
-
-### 문서 파일
-5. GETNEXTNODEID_LOGIC_ANALYSIS.md - 상세 로직 분석
-6. MAP_LOADING_BIDIRECTIONAL_FIX.md - 양방향 연결 설명
-7. VERIFICATION_COMPLETE.md - 초기 구현 검증
-8. **BACKWARD_LOGIC_FIX.md** - Backward 수정 설명
-9. **BACKWARD_FIX_VERIFICATION.md** - 수정 검증 보고서
-10. **BACKWARD_FIX_SUMMARY_KO.md** - 수정 요약 (한글)
-11. IMPLEMENTATION_COMPLETE.md - 전체 구현 완료 보고서
-12. **STATUS_REPORT_FINAL.md** - 이 파일
-
----
-
-## 💡 주요 개념
-
-### 1. Forward vs Backward
-
-**❌ 잘못된 이해**:
-- Forward = 앞으로 가는 방향
-- Backward = 뒤로 가는 방향
-
-**✅ 올바른 이해**:
-- Forward = 모터 정방향 회전
-- Backward = 모터 역방향 회전
-- **경로 선택은 동일** (이동 벡터 기반)
-
-### 2. 2-위치 히스토리의 의미
-
-```
-_prevPosition: 이전 RFID 위치
-_currentPosition: 현재 RFID 위치
-
-이동 벡터 = currentPosition - prevPosition
- = AGV의 실제 이동 방향
-
-이 벡터를 기반으로 다음 노드 결정
-```
-
-### 3. 양방향 연결이 필요한 이유
-
-```
-맵 저장: 002 → 003 (단방향)
-메모리 로드:
- - 002.ConnectedNodes = [001, 003]
- - 003.ConnectedNodes = [002, 004] ← 자동 추가
-
-GetNextNodeId()는 현재 노드의 ConnectedNodes만 사용
-따라서 양방향 연결이 필수
-```
-
----
-
-## 🚀 다음 단계
-
-### 1. 컴파일 및 빌드
-```bash
-cd AGVLogic
-build.bat
-→ AGVNavigationCore.dll 생성
-```
-
-### 2. 런타임 테스트
-```csharp
-var tester = new GetNextNodeIdTest();
-tester.TestGetNextNodeId();
-```
-
-### 3. 실제 맵 테스트
-```
-NewMap.agvmap 파일로 AGVSimulator 실행
-→ 실제 경로 계산 및 검증
-```
-
-### 4. 통합 테스트
-```
-메인 애플리케이션(AGV4.exe)에서
-실제 RFID 기반 경로 계산 검증
-```
-
----
-
-## ✨ 구현 특징
-
-### 1. 수학적 정확성
-- 벡터 내적/외적 활용
-- 정규화를 통한 방향 계산
-- 부동소수점 오차 처리
-
-### 2. 확장성
-- Left/Right 방향 지원
-- DirectionalPathfinder로 독립적 구현
-- 향후 복잡한 경로 전략 추가 가능
-
-### 3. 견고성
-- 2-위치 히스토리 검증
-- 이동 거리 검증 (< 0.001f 처리)
-- ConnectedNodes 검증
-
-### 4. 사용자 의도 반영
-- "모터 방향은 모터 방향일 뿐" 개념 적용
-- 경로 선택과 모터 방향 분리
-- Forward/Backward 대칭적 처리
-
----
-
-## 📈 성과 요약
-
-| 항목 | 결과 |
-|------|------|
-| 기능 구현 | ✅ 100% |
-| 버그 수정 | ✅ 100% |
-| 테스트 커버리지 | ✅ 100% (4/4 시나리오) |
-| 사용자 피드백 반영 | ✅ 100% |
-| 문서화 | ✅ 완벽함 |
-| 검증 | ✅ 완료됨 |
-
----
-
-## 🎉 최종 결론
-
-### 구현 완료
-✅ GetNextNodeId() 메서드 완전 구현
-✅ 모든 요구 사항 충족
-✅ 모든 시나리오 검증 완료
-
-### Backward 버그 수정
-✅ 사용자 피드백 "N004가 나와야 한다" 충족
-✅ 모터 방향 개념 올바르게 적용
-✅ Forward/Backward 대칭 로직 구현
-
-### 품질 보증
-✅ 상세한 기술 문서 작성
-✅ 완전한 검증 보고서 작성
-✅ 코드 주석 추가 (한글)
-✅ 테스트 케이스 포함
-
----
-
-**보고서 작성**: 2025-10-23
-**최종 상태**: 🟢 **전체 완료**
-**프로젝트 상태**: 다음 단계(빌드/테스트)로 진행 가능
diff --git a/Cs_HMI/AGVLogic/TODO.md b/Cs_HMI/AGVLogic/TODO.md
deleted file mode 100644
index e5d491e..0000000
--- a/Cs_HMI/AGVLogic/TODO.md
+++ /dev/null
@@ -1,191 +0,0 @@
-# AGV 네비게이션 시스템 개발 현황
-
-## 📊 프로젝트 개요
-**AGV 이동 시스템 설계 및 개발 - RFID 기반 네비게이션 시스템**
-
-최근 리팩토링을 통해 전문 라이브러리 **AGVNavigationCore** 중심의 현대적 아키텍처로 재구성됨.
-
----
-
-## ✅ **완료된 핵심 시스템**
-
-### 🏗️ **AGVNavigationCore 라이브러리** (완료)
-**전문 AGV 네비게이션 라이브러리 - 상업적 수준 완성도**
-
-#### **Models 패키지** ✅
-- **MapNode.cs**: 고도화된 노드 모델
- - RFID 매핑 통합, 라벨/이미지 지원
- - 도킹 방향, 장비 타입, 회전 가능 여부
- - 이미지 자동 리사이즈, 투명도, 회전 지원
-- **RfidMapping.cs**: RFID ↔ NodeId 매핑 시스템
-- **Enums.cs**: 완전한 열거형 (NodeType, AgvDirection, DockingDirection, StationType)
-
-#### **PathFinding 패키지** ✅
-- **AStarPathfinder.cs**: 표준 A* 알고리즘 완전 구현
- - 양방향 연결 자동 생성
- - 휴리스틱 가중치, 최대 탐색 노드 제한
- - 다중 목표 최단 경로 탐색
-- **AGVPathfinder.cs**: AGV 특화 제약사항 완전 반영
- - 방향성 제약 (전진/후진만 가능)
- - 회전 제약 (특정 지점에서만 180도 회전)
- - 도킹 방향 강제 (충전기:전진, 장비:후진)
- - 실행 가능한 AGV 명령어 생성
-- **RfidBasedPathfinder.cs**: 현장 운영 완전 대응
- - RFID 기반 실시간 경로 계산
- - 물리적 RFID와 논리적 노드 분리
- - 현장 유지보수성 극대화
-- **PathResult/AGVPathResult/RfidPathResult**: 계층적 결과 시스템
-
-#### **Controls 패키지** ✅
-- **UnifiedAGVCanvas.cs**: 통합 캔버스 컨트롤
- - 맵 편집, 시뮬레이션, 모니터링 통합
- - ViewOnly/Edit 모드 분리
- - 그리드, 줌, 패닝 지원
-
-### 🎯 **개발 도구들** (리팩토링 완료)
-
-#### **AGVMapEditor** ✅ (현대화됨)
-- UnifiedAGVCanvas 기반 리팩토링
-- RFID 매핑 분리 아키텍처 적용
-- 라벨/이미지 추가 기능 강화
-- JSON 파일 형식 개선
-
-#### **AGVSimulator** ✅ (개선됨)
-- VirtualAGV 클래스 고도화
-- UnifiedAGVCanvas 통합
-- 실시간 상태 시뮬레이션
-
----
-
-## 🚀 **현재 개발 진척도**
-
-### **Phase 1: 기반 시스템** ✅ **100% 완료**
-1. **맵 에디터** ✅ **완료 + 현대화**
- - [x] UnifiedAGVCanvas 기반 리팩토링
- - [x] RFID 매핑 분리 아키텍처 적용
- - [x] 라벨/이미지 고급 기능 (투명도, 회전, 스케일)
- - [x] JSON 저장/로드 개선
-
-2. **경로 계산 엔진** ✅ **100% 완료**
- - [x] **A* 알고리즘** - AStarPathfinder 완전 구현
- - [x] **방향성 고려 라우팅** - AGVPathfinder 완전 구현
- - [x] **도킹 방향 고려** - 충전기(전진), 장비(후진) 강제
- - [x] **동적 경로 재계산** - 실시간 RFID 기반 검증
-
-### **Phase 2: 이동 제어 시스템** ✅ **90% 완료**
-3. **AGV 모션 컨트롤러** ✅ **완료**
- - [x] **실행 가능한 명령어 생성** - [전진, 후진, 좌회전, 우회전, 정지]
- - [x] **방향 전환 로직** - 회전 지점에서만 180도 회전
- - [x] **도킹 시퀀스 제어** - 방향별 자동 접근 전략
-
-4. **위치 추적 시스템** ✅ **80% 완료**
- - [x] **RFID 기반 위치 인식** - RfidBasedPathfinder
- - [x] **실시간 경로 검증** - ValidatePath 기능
- - [ ] **하드웨어 RFID 리더 연동** (메인 애플리케이션 통합 필요)
-
-### **Phase 3: 통합 및 테스트** ✅ **70% 완료**
-5. **시뮬레이션 도구** ✅ **완료**
- - [x] **가상 AGV 시뮬레이터** - VirtualAGV 클래스
- - [x] **경로 시각화** - UnifiedAGVCanvas 통합
- - [x] **실시간 디버깅** - 상태별 색상 표시
-
----
-
-## 🏗️ **현재 시스템 아키텍처**
-
-### 📊 **실제 구현된 컴포넌트 구조**
-```
-AGVNavigationCore (전문 라이브러리)
-├── PathFinding Engine
-│ ├── AStarPathfinder ✅ // 표준 A* 알고리즘
-│ ├── AGVPathfinder ✅ // AGV 제약사항 특화
-│ └── RfidBasedPathfinder ✅ // 현장 운영 최적화
-├── Data Models
-│ ├── MapNode ✅ // 고도화된 노드 모델
-│ ├── RfidMapping ✅ // RFID 매핑 시스템
-│ └── Result Classes ✅ // 계층적 결과 체계
-└── UI Controls
- └── UnifiedAGVCanvas ✅ // 통합 캔버스
-
-AGVMapEditor ✅ // 맵 편집 도구
-└── UnifiedAGVCanvas 기반 현대화
-
-AGVSimulator ✅ // AGV 시뮬레이터
-└── VirtualAGV + UnifiedAGVCanvas
-
-메인 애플리케이션 (AGV4)
-└── AGVNavigationCore 참조 (통합 예정)
-```
-
----
-
-## 🎯 **AGV 동작 제약사항 (완전 반영됨)**
-
-### **물리적 제약사항** ✅
-- **전진**: 모니터 방향으로만 이동 가능
-- **후진**: 리프트 방향으로만 이동 가능
-- **회전**: 특정 회전 지점에서만 180도 회전 가능
-- **좌우 이동**: 불가능 (실제 AGV 한계 반영)
-
-### **도킹 제약사항** ✅
-```
-장비별 도킹 방향 (강제 적용):
-├── 로더, 클리너, 오프로더, 버퍼 (8대) → 후진 도킹
-└── 충전기 1, 충전기 2 (2대) → 전진 도킹
-```
-
-### **RFID 매핑 시스템** ✅
-```csharp
-// 실제 구현된 매핑 시스템
-RFID: "1234567890" → NodeId: "LOADER1" → 실제 의미: "1번 로더"
-RFID: "9876543210" → NodeId: "CHARGE1" → 실제 의미: "1번 충전기"
-
-// 현장 작업자용 정보
-RfidDescription: "로더1번 입구", "충전기2번 도킹 지점"
-Status: "정상", "손상", "교체예정"
-```
-
----
-
-## 📋 **다음 단계 (우선순위별)**
-
-### 🔥 **우선순위 1: 메인 애플리케이션 통합**
-- [ ] **AGV4 프로젝트에 AGVNavigationCore 통합**
-- [ ] **기존 AGV 컨트롤러와 인터페이스 연동**
-- [ ] **실제 RFID 리더 하드웨어 연동**
-
-### ⚡ **우선순위 2: 현장 검증**
-- [ ] **실제 맵 데이터 생성 및 검증** (NewMap.agvmap 활용)
-- [ ] **실제 AGV로 경로 추적 테스트**
-- [ ] **RFID 태그 현장 설치 및 매핑**
-
-### 🛠️ **우선순위 3: 운영 최적화**
-- [ ] **성능 최적화** (대규모 맵 대응)
-- [ ] **에러 처리 강화** (RFID 인식 실패, 경로 차단 등)
-- [ ] **로깅 및 모니터링 시스템**
-
----
-
-## 🌟 **주요 성과 및 차별화 포인트**
-
-### **기술적 성과**
-1. **3단계 API 아키텍처**: Basic(A*) → AGV특화 → RFID기반
-2. **실행 가능한 명령어 생성**: 경로가 아닌 AGV 제어 명령어 직접 출력
-3. **현장 친화적 설계**: RFID 물리/논리 분리로 유지보수성 극대화
-4. **통합 캔버스**: 편집/시뮬레이션/모니터링 단일 컨트롤
-
-### **실용적 가치**
-- **즉시 운영 가능**: 상업적 수준의 완성된 네비게이션 엔진
-- **확장성**: 새로운 AGV 타입이나 장비 쉽게 추가
-- **안정성**: 실제 AGV 제약사항 완전 반영으로 안전한 경로 생성
-
----
-
-## 📖 **참고 문서**
-- **AGVNavigationCore/README.md**: 상세 기능 설명 및 사용법
-- **Data/NewMap.agvmap**: 실제 맵 데이터 샘플
-- **CLAUDE.md**: 개발 환경 및 빌드 정보
-
----
-
-*최종 업데이트: 2024.09.12 - AGVNavigationCore 리팩토링 완료 기준*
\ No newline at end of file
diff --git a/Cs_HMI/AGVLogic/VERIFICATION_COMPLETE.md b/Cs_HMI/AGVLogic/VERIFICATION_COMPLETE.md
deleted file mode 100644
index 9b04366..0000000
--- a/Cs_HMI/AGVLogic/VERIFICATION_COMPLETE.md
+++ /dev/null
@@ -1,340 +0,0 @@
-# GetNextNodeId() 구현 완료 및 검증 보고서
-
-## ✅ 최종 검증 결과
-
-### 사용자 요구사항 달성 100%
-
-```
-요구 사항 1: 001 → 002 (Forward) → 003
-검증: ✅ PASS - dotProduct: 0.934 (100.0점)
-
-요구 사항 2: 001 → 002 (Backward) → 001
-검증: ✅ PASS - dotProduct: -0.985 (100.0점)
-
-요구 사항 3: 002 → 003 (Forward) → 004
-검증: ✅ PASS - dotProduct: 0.989 (100.0점)
-
-요구 사항 4: 002 → 003 (Backward) → 002
-검증: ✅ PASS - dotProduct: -0.934 (100.0점)
-```
-
----
-
-## 🔧 구현 상세
-
-### 1. VirtualAGV.GetNextNodeId() 메서드
-
-**파일**: `AGVNavigationCore\Models\VirtualAGV.cs` (라인 628-719)
-
-**기능**:
-- 이전 위치 + 현재 위치 + 진행 방향으로 다음 노드 ID 반환
-- 2개 위치 히스토리 필수 (`_prevPosition`, `_currentPosition`)
-- 벡터 기반 방향 계산
-
-**핵심 로직**:
-```csharp
-// 1단계: 이동 벡터 계산
-var movementVector = new PointF(
- _currentPosition.X - _prevPosition.X,
- _currentPosition.Y - _prevPosition.Y
-);
-
-// 2단계: 벡터 정규화
-var normalizedMovement = new PointF(
- movementVector.X / movementLength,
- movementVector.Y / movementLength
-);
-
-// 3단계: 각 후보에 대해 점수 계산
-float score = CalculateDirectionalScore(
- normalizedMovement,
- normalizedToNext,
- direction
-);
-
-// 4단계: 최고 점수 노드 반환
-return bestCandidate.node?.NodeId;
-```
-
-### 2. CalculateDirectionalScore() 메서드
-
-**파일**: `VirtualAGV.cs` (라인 721-821)
-
-**점수 계산**:
-
-#### Forward 모드
-```
-dotProduct > 0.9 → 100점 (거의 같은 방향)
-0.5 ~ 0.9 → 80점 (비슷한 방향)
-0 ~ 0.5 → 50점 (약간 다른 방향)
--0.5 ~ 0 → 20점 (거의 반대)
-< -0.5 → 0점 (완전 반대)
-```
-
-#### Backward 모드
-```
-dotProduct < -0.9 → 100점 (거의 반대 방향)
--0.5 ~ -0.9 → 80점 (비슷하게 반대)
--0.5 ~ 0 → 50점 (약간 다른)
-0 ~ 0.5 → 20점 (거의 같은 방향)
-> 0.5 → 0점 (완전 같은 방향)
-```
-
-#### Left/Right 모드
-```
-forward 상태 (dotProduct > 0):
- crossProduct > 0.5 → 100점 (좌측) / 0점 (우측)
- 0 ~ 0.5 → 70점 / 70점
- -0.5 ~ 0 → 50점 / 50점
- < -0.5 → 30점 / 30점
-
-backward 상태 (dotProduct < 0): 좌우 반전
- crossProduct < -0.5 → 100점 (좌측 반전) / 0점
- -0.5 ~ 0 → 70점 / 70점
- 0 ~ 0.5 → 50점 / 50점
- > 0.5 → 30점 / 30점
-```
-
----
-
-## 📐 벡터 수학 원리
-
-### 내적 (Dot Product)
-```
-dot = v1.x * v2.x + v1.y * v2.y
-범위: -1 ~ 1
-
-의미:
- +1 : 같은 방향 (0°)
- 0 : 직각 (90°)
- -1 : 반대 방향 (180°)
-
-Forward: dot > 0.9 선호
-Backward: dot < -0.9 선호
-```
-
-### 외적 (Cross Product)
-```
-cross = v1.x * v2.y - v1.y * v2.x
-
-의미:
- > 0 : 좌측 (반시계)
- < 0 : 우측 (시계)
-
-Left: cross > 0 선호
-Right: cross < 0 선호
-```
-
----
-
-## 🎯 동작 흐름 예시
-
-### 예시 1: 001 → 002 → Forward → ?
-
-```
-이전: (65, 229) 현재: (206, 244) 다음 후보: (65, 229), (278, 278)
-
-이동 벡터: (141, 15) - 오른쪽 위 방향
-
-후보 분석:
- ① (65, 229): (-141, -15) 벡터
- → 반대 방향 (dot ≈ -0.985)
- → Forward에서 20점
-
- ② (278, 278): (72, 34) 벡터
- → 같은 방향 (dot ≈ 0.934)
- → Forward에서 100점 ✓
-
-선택: (278, 278) = N003
-```
-
-### 예시 2: 001 → 002 → Backward → ?
-
-```
-같은 이동 벡터: (141, 15)
-
-후보 분석:
- ① (65, 229): (-141, -15) 벡터
- → 반대 방향 (dot ≈ -0.985)
- → Backward에서 100점 ✓
-
- ② (278, 278): (72, 34) 벡터
- → 같은 방향 (dot ≈ 0.934)
- → Backward에서 0점
-
-선택: (65, 229) = N001
-```
-
----
-
-## 📊 추가 구현 파일
-
-### 1. GetNextNodeIdTest.cs
-- 실제 테스트 시나리오 4가지 검증
-- 벡터 계산 과정 상세 출력
-- 내적/외적 값 표시
-- 각 후보 노드별 점수 계산
-
-### 2. GETNEXTNODEID_LOGIC_ANALYSIS.md
-- 4가지 시나리오 상세 수학 계산
-- 벡터 정규화 과정
-- 최종 점수 계산 과정
-- 검증 결과표
-
-### 3. MAP_LOADING_BIDIRECTIONAL_FIX.md
-- 양방향 연결 자동 설정
-- MapLoader.LoadMapFromFile() 수정
-- EnsureBidirectionalConnections() 메서드
-
----
-
-## 🔄 시스템 흐름
-
-```
-맵 로드
- ↓
-MapLoader.LoadMapFromFile()
- ├─ JSON 파일 읽기 (단방향 연결만 저장)
- ├─ CleanupDuplicateConnections()
- └─ ✨ EnsureBidirectionalConnections() ← 양방향으로 복원
- ↓
-VirtualAGV._prevPosition, _currentPosition 설정
- (SetPosition() 호출 2회 이상)
- ↓
-GetNextNodeId(direction, allNodes) 호출
- ├─ 이동 벡터 계산
- ├─ 벡터 정규화
- ├─ 각 후보에 대해 방향 점수 계산
- └─ 최고 점수 노드 반환
- ↓
-다음 목표 노드 결정 ✓
-```
-
----
-
-## ✨ 핵심 특징
-
-### 1. 벡터 기반 방향 계산
-- 이동 방향과 다음 벡터 비교
-- 내적으로 진행 방향 판별
-- 외적으로 좌우 판별
-
-### 2. Forward/Backward 자동 처리
-- Forward: dotProduct > 0 선호 (같은 방향)
-- Backward: dotProduct < 0 선호 (반대 방향)
-
-### 3. Left/Right 방향 반전
-- Backward 상태에서는 좌우 자동 반전
-- 사용자가 명시적으로 반전할 필요 없음
-
-### 4. 양방향 연결 자동 보장
-- 맵 로드 시 모든 연결을 양방향으로 설정
-- 현재 노드의 ConnectedNodes만으로 모든 다음 노드 찾을 수 있음
-
----
-
-## 📝 사용 방법
-
-### 기본 사용
-```csharp
-// VirtualAGV 인스턴스
-var agv = new VirtualAGV("AGV001");
-
-// 최소 2번 위치 설정 필요
-agv.SetPosition(node001, new Point(65, 229), AgvDirection.Forward);
-agv.SetPosition(node002, new Point(206, 244), AgvDirection.Forward);
-
-// 다음 노드 계산
-string nextNodeId = agv.GetNextNodeId(AgvDirection.Forward, allNodes);
-// 결과: "N003"
-
-// Backward로 변경
-nextNodeId = agv.GetNextNodeId(AgvDirection.Backward, allNodes);
-// 결과: "N001"
-```
-
-### 로직 검증
-```csharp
-// GetNextNodeIdTest 클래스 사용
-var tester = new GetNextNodeIdTest();
-tester.TestGetNextNodeId();
-// 모든 시나리오 검증 출력
-```
-
----
-
-## 🎓 이해하기 쉬운 설명
-
-### Forward (전진)
-```
-AGV가 001에서 002로 이동한 방향으로 계속 진행
-→ 같은 방향인 003을 선택
-```
-
-### Backward (후진)
-```
-AGV가 001에서 002로 이동한 방향의 반대로 진행
-→ 반대 방향인 001을 선택 (되돌아감)
-```
-
-### Left (좌측)
-```
-AGV가 이동 중인 방향에서 좌측으로 회전
-Forward 중: 좌측 선호
-Backward 중: 우측 선호 (반전됨)
-```
-
-### Right (우측)
-```
-AGV가 이동 중인 방향에서 우측으로 회전
-Forward 중: 우측 선호
-Backward 중: 좌측 선호 (반전됨)
-```
-
----
-
-## 🔗 관련 파일
-
-| 파일 | 목적 |
-|------|------|
-| VirtualAGV.cs | GetNextNodeId() 메서드 구현 |
-| MapLoader.cs | 양방향 연결 자동 설정 |
-| GetNextNodeIdTest.cs | 테스트 및 검증 |
-| DirectionalPathfinder.cs | 독립 경로 탐색 엔진 |
-| GETNEXTNODEID_LOGIC_ANALYSIS.md | 상세 수학 분석 |
-| MAP_LOADING_BIDIRECTIONAL_FIX.md | 양방향 연결 설명 |
-
----
-
-## ✅ 검증 체크리스트
-
-- [x] 001 → 002 → Forward → 003 (검증: 100.0점)
-- [x] 001 → 002 → Backward → 001 (검증: 100.0점)
-- [x] 002 → 003 → Forward → 004 (검증: 100.0점)
-- [x] 002 → 003 → Backward → 002 (검증: 100.0점)
-- [x] 양방향 연결 자동 설정
-- [x] 벡터 정규화 로직
-- [x] 점수 계산 로직
-- [x] Left/Right 방향 반전
-- [x] CS1026 오류 수정 (switch expression)
-- [x] 테스트 클래스 구현
-
----
-
-## 🎉 완료 상태
-
-**모든 요구사항이 검증되었습니다!**
-
-```
-✅ GetNextNodeId() 메서드: 완료
-✅ Forward/Backward 동작: 검증 완료
-✅ 벡터 계산 로직: 검증 완료
-✅ 양방향 연결: 완료
-✅ 테스트 프레임워크: 완료
-```
-
----
-
-**완료 일시**: 2025-10-23
-**상태**: 🟢 전체 구현 및 검증 완료
-**다음 단계**: NewMap.agvmap으로 실제 테스트 실행