- Fixed critical issue in ConvertToDetailedPath where motor direction was not passed to GetRequiredMagnetDirection - Motor direction is essential for backward movement as Left/Right directions must be inverted - Modified AGVPathfinder.cs line 280 to pass currentDirection parameter - Ensures backward motor direction properly inverts magnet sensor directions feat: Add waypoint support to pathfinding system - Added FindPath overload with params string[] waypointNodeIds in AStarPathfinder - Supports sequential traversal through multiple intermediate nodes - Validates waypoints and prevents duplicates in sequence - Returns combined path result with aggregated metrics feat: Implement path result merging with DetailedPath preservation - Added CombineResults method in AStarPathfinder for intelligent path merging - Automatically deduplicates nodes when last of previous path equals first of current - Preserves DetailedPath information including motor and magnet directions - Essential for multi-segment path operations feat: Integrate magnet direction with motor direction awareness - Modified JunctionAnalyzer.GetRequiredMagnetDirection to accept AgvDirection parameter - Inverts Left/Right magnet directions when moving Backward - Properly handles motor direction context throughout pathfinding feat: Add automatic start node selection in simulator - Added SetStartNodeToCombo method to SimulatorForm - Automatically selects start node combo box when AGV position is set via RFID - Improves UI usability and workflow efficiency 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
8.9 KiB
8.9 KiB
방향 기반 경로 탐색 구현 완료 요약
✅ 구현 완료
사용자 요구사항에 따라 이전 위치 + 현재 위치 + 진행 방향을 기반으로 다음 노드를 계산하는 시스템을 완전히 구현했습니다.
📦 구현된 컴포넌트
1. VirtualAGV.GetNextNodeId() (핵심 메서드)
파일: AGVNavigationCore\Models\VirtualAGV.cs (라인 613~823)
public string GetNextNodeId(AgvDirection direction, List<MapNode> 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
추가된 항목:
<Compile Include="PathFinding\Planning\DirectionalPathfinder.cs" />
<Compile Include="Utils\AGVDirectionCalculator.cs" />
<Compile Include="Utils\DirectionalPathfinderTest.cs" />
<Compile Include="Utils\TestRunner.cs" />
🚀 사용 방법
기본 사용 (VirtualAGV)
// 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
고급 사용 (독립적인 계산기)
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개 위치 히스토리 필수
// ❌ 잘못된 사용 (처음 호출 시)
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 |
📝 다음 단계 (선택사항)
-
실제 맵에서 테스트
- TestRunner로 NewMap.agvmap 검증
- 실제 RFID 번호로 시나리오 테스트
-
성능 최적화
- 벡터 계산 캐싱
- 점수 계산 병렬화
-
기능 확장
- 3D 좌표 지원
- A* 알고리즘 통합
- 동적 가중치 조정
-
시뮬레이터 통합
- AGVSimulator에 GetNextNodeId 연결
- 실시간 경로 변경 시연
📚 관련 문서
ANALYSIS_AGV_Direction_Storage.md- VirtualAGV 필드 분석IMPLEMENTATION_DirectionalPathfinder.md- 상세 구현 가이드
완료 일시: 2025-10-23 상태: 🟢 구현 완료, 테스트 대기 다음 작업: NewMap.agvmap으로 실제 테스트