Files
ENIG/Cs_HMI/AGVLogic/IMPLEMENTATION_SUMMARY.md
backuppc d932b8d332 fix: Add motor direction parameter to magnet direction calculation in pathfinding
- 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>
2025-10-24 15:46:16 +09:00

312 lines
8.9 KiB
Markdown
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 방향 기반 경로 탐색 구현 완료 요약
## ✅ 구현 완료
사용자 요구사항에 따라 **이전 위치 + 현재 위치 + 진행 방향**을 기반으로 **다음 노드를 계산하는 시스템**을 완전히 구현했습니다.
---
## 📦 구현된 컴포넌트
### 1. **VirtualAGV.GetNextNodeId()** (핵심 메서드)
**파일**: `AGVNavigationCore\Models\VirtualAGV.cs` (라인 613~823)
```csharp
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`
추가된 항목:
```xml
<Compile Include="PathFinding\Planning\DirectionalPathfinder.cs" />
<Compile Include="Utils\AGVDirectionCalculator.cs" />
<Compile Include="Utils\DirectionalPathfinderTest.cs" />
<Compile Include="Utils\TestRunner.cs" />
```
---
## 🚀 사용 방법
### 기본 사용 (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으로 실제 테스트