Files
ENIG/Cs_HMI/AGVNavigationCore/PathFinding/RfidPathResult.cs
ChiKyun Kim de0e39e030 refactor: Consolidate RFID mapping and add bidirectional pathfinding
Major improvements to AGV navigation system:

• Consolidated RFID management into MapNode, removing duplicate RfidMapping class
• Enhanced MapNode with RFID metadata fields (RfidStatus, RfidDescription)
• Added automatic bidirectional connection generation in pathfinding algorithms
• Updated all components to use unified MapNode-based RFID system
• Added command line argument support for AGVMapEditor auto-loading files
• Fixed pathfinding failures by ensuring proper node connectivity

Technical changes:
- Removed RfidMapping class and dependencies across all projects
- Updated AStarPathfinder with EnsureBidirectionalConnections() method
- Modified MapLoader to use AssignAutoRfidIds() for RFID automation
- Enhanced UnifiedAGVCanvas, SimulatorForm, and MainForm for MapNode integration
- Improved data consistency and reduced memory footprint

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-09-11 16:41:52 +09:00

229 lines
7.2 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
using System;
using System.Collections.Generic;
using AGVNavigationCore.Models;
namespace AGVNavigationCore.PathFinding
{
/// <summary>
/// RFID 기반 AGV 경로 계산 결과
/// 실제 현장에서 AGV가 RFID를 기준으로 이동하는 방식에 맞춤
/// </summary>
public class RfidPathResult
{
/// <summary>
/// 경로 찾기 성공 여부
/// </summary>
public bool Success { get; set; }
/// <summary>
/// RFID 경로 목록 (시작 → 목적지 순서)
/// </summary>
public List<string> RfidPath { get; set; }
/// <summary>
/// AGV 명령어 목록 (이동 방향 시퀀스)
/// </summary>
public List<AgvDirection> Commands { get; set; }
/// <summary>
/// 총 거리
/// </summary>
public float TotalDistance { get; set; }
/// <summary>
/// 계산 소요 시간 (밀리초)
/// </summary>
public long CalculationTimeMs { get; set; }
/// <summary>
/// 예상 소요 시간 (초)
/// </summary>
public float EstimatedTimeSeconds { get; set; }
/// <summary>
/// 회전 횟수
/// </summary>
public int RotationCount { get; set; }
/// <summary>
/// 오류 메시지 (실패시)
/// </summary>
public string ErrorMessage { get; set; }
/// <summary>
/// 기본 생성자
/// </summary>
public RfidPathResult()
{
Success = false;
RfidPath = new List<string>();
Commands = new List<AgvDirection>();
TotalDistance = 0;
CalculationTimeMs = 0;
EstimatedTimeSeconds = 0;
RotationCount = 0;
ErrorMessage = string.Empty;
}
/// <summary>
/// 성공 결과 생성
/// </summary>
/// <param name="rfidPath">RFID 경로</param>
/// <param name="commands">AGV 명령어 목록</param>
/// <param name="totalDistance">총 거리</param>
/// <param name="calculationTimeMs">계산 시간</param>
/// <param name="estimatedTimeSeconds">예상 소요 시간</param>
/// <param name="rotationCount">회전 횟수</param>
/// <returns>성공 결과</returns>
public static RfidPathResult CreateSuccess(
List<string> rfidPath,
List<AgvDirection> commands,
float totalDistance,
long calculationTimeMs,
float estimatedTimeSeconds,
int rotationCount)
{
return new RfidPathResult
{
Success = true,
RfidPath = new List<string>(rfidPath),
Commands = new List<AgvDirection>(commands),
TotalDistance = totalDistance,
CalculationTimeMs = calculationTimeMs,
EstimatedTimeSeconds = estimatedTimeSeconds,
RotationCount = rotationCount
};
}
/// <summary>
/// 실패 결과 생성
/// </summary>
/// <param name="errorMessage">오류 메시지</param>
/// <param name="calculationTimeMs">계산 시간</param>
/// <returns>실패 결과</returns>
public static RfidPathResult CreateFailure(string errorMessage, long calculationTimeMs)
{
return new RfidPathResult
{
Success = false,
ErrorMessage = errorMessage,
CalculationTimeMs = calculationTimeMs
};
}
/// <summary>
/// 명령어 요약 생성
/// </summary>
/// <returns>명령어 요약 문자열</returns>
public string GetCommandSummary()
{
if (!Success) return "실패";
var summary = new List<string>();
var currentCommand = AgvDirection.Stop;
var count = 0;
foreach (var command in Commands)
{
if (command == currentCommand)
{
count++;
}
else
{
if (count > 0)
{
summary.Add($"{GetCommandText(currentCommand)}×{count}");
}
currentCommand = command;
count = 1;
}
}
if (count > 0)
{
summary.Add($"{GetCommandText(currentCommand)}×{count}");
}
return string.Join(" → ", summary);
}
/// <summary>
/// 명령어 텍스트 반환
/// </summary>
private string GetCommandText(AgvDirection command)
{
switch (command)
{
case AgvDirection.Forward: return "전진";
case AgvDirection.Backward: return "후진";
case AgvDirection.Left: return "좌회전";
case AgvDirection.Right: return "우회전";
case AgvDirection.Stop: return "정지";
default: return command.ToString();
}
}
/// <summary>
/// RFID 경로 요약 생성
/// </summary>
/// <returns>RFID 경로 요약 문자열</returns>
public string GetRfidPathSummary()
{
if (!Success || RfidPath.Count == 0) return "경로 없음";
if (RfidPath.Count <= 3)
{
return string.Join(" → ", RfidPath);
}
else
{
return $"{RfidPath[0]} → ... ({RfidPath.Count - 2}개 경유) → {RfidPath[RfidPath.Count - 1]}";
}
}
/// <summary>
/// 상세 경로 정보 반환
/// </summary>
/// <returns>상세 정보 문자열</returns>
public string GetDetailedInfo()
{
if (!Success)
{
return $"RFID 경로 계산 실패: {ErrorMessage} (계산시간: {CalculationTimeMs}ms)";
}
return $"RFID 경로: {RfidPath.Count}개 지점, 거리: {TotalDistance:F1}px, " +
$"회전: {RotationCount}회, 예상시간: {EstimatedTimeSeconds:F1}초, " +
$"계산시간: {CalculationTimeMs}ms";
}
/// <summary>
/// AGV 운영자용 실행 정보 반환
/// </summary>
/// <returns>실행 정보 문자열</returns>
public string GetExecutionInfo()
{
if (!Success) return $"실행 불가: {ErrorMessage}";
return $"[실행준비] {GetRfidPathSummary()}\n" +
$"[명령어] {GetCommandSummary()}\n" +
$"[예상시간] {EstimatedTimeSeconds:F1}초";
}
/// <summary>
/// 문자열 표현
/// </summary>
public override string ToString()
{
if (Success)
{
return $"Success: {RfidPath.Count} RFIDs, {TotalDistance:F1}px, {RotationCount} rotations, {EstimatedTimeSeconds:F1}s";
}
else
{
return $"Failed: {ErrorMessage}";
}
}
}
}