# 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 하드웨어 제어 모듈**에서 구현될 것으로 예상됩니다.