에뮬레이터 개발 전.
This commit is contained in:
54
Cs_HMI/AGVLogic/AGVNavigationCore/Models/AGVCommand.cs
Normal file
54
Cs_HMI/AGVLogic/AGVNavigationCore/Models/AGVCommand.cs
Normal file
@@ -0,0 +1,54 @@
|
||||
namespace AGVNavigationCore.Models
|
||||
{
|
||||
/// <summary>
|
||||
/// AGV 제어 명령 클래스 (실제 AGV 제어용)
|
||||
/// Predict() 메서드가 반환하는 다음 동작 명령
|
||||
/// </summary>
|
||||
public class AGVCommand
|
||||
{
|
||||
/// <summary>모터 명령 (정지/전진/후진)</summary>
|
||||
public MotorCommand Motor { get; set; }
|
||||
|
||||
/// <summary>마그넷 위치 (직진/왼쪽/오른쪽)</summary>
|
||||
public MagnetPosition Magnet { get; set; }
|
||||
|
||||
/// <summary>속도 레벨 (저속/중속/고속)</summary>
|
||||
public SpeedLevel Speed { get; set; }
|
||||
|
||||
/// <summary>명령 이유 메세지- (디버깅/로깅용)</summary>
|
||||
public string Message { get; set; }
|
||||
|
||||
/// <summary>명령 이유- (디버깅/로깅용)</summary>
|
||||
public eAGVCommandReason Reason { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 생성자
|
||||
/// </summary>
|
||||
public AGVCommand(MotorCommand motor, MagnetPosition magnet, SpeedLevel speed, eAGVCommandReason reason, string reasonmessage = "")
|
||||
{
|
||||
Motor = motor;
|
||||
Magnet = magnet;
|
||||
Speed = speed;
|
||||
Reason = reason;
|
||||
Message = reasonmessage;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 기본 생성자
|
||||
/// </summary>
|
||||
public AGVCommand()
|
||||
{
|
||||
Motor = MotorCommand.Stop;
|
||||
Magnet = MagnetPosition.S;
|
||||
Speed = SpeedLevel.L;
|
||||
Message = "";
|
||||
Reason = eAGVCommandReason.Normal;
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return $"Motor:{Motor}, Magnet:{Magnet}, Speed:{Speed},Reason:{Reason}" +
|
||||
(string.IsNullOrEmpty(Message) ? "" : $" ({Message})");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2,7 +2,7 @@ using System;
|
||||
|
||||
namespace AGVNavigationCore.Models
|
||||
{
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 노드 타입 열거형
|
||||
@@ -141,50 +141,42 @@ namespace AGVNavigationCore.Models
|
||||
H
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// AGV 제어 명령 클래스 (실제 AGV 제어용)
|
||||
/// Predict() 메서드가 반환하는 다음 동작 명령
|
||||
/// </summary>
|
||||
public class AGVCommand
|
||||
{
|
||||
/// <summary>모터 명령 (정지/전진/후진)</summary>
|
||||
public MotorCommand Motor { get; set; }
|
||||
|
||||
/// <summary>마그넷 위치 (직진/왼쪽/오른쪽)</summary>
|
||||
public MagnetPosition Magnet { get; set; }
|
||||
|
||||
/// <summary>속도 레벨 (저속/중속/고속)</summary>
|
||||
public SpeedLevel Speed { get; set; }
|
||||
|
||||
/// <summary>명령 이유 (디버깅/로깅용)</summary>
|
||||
public string Reason { get; set; }
|
||||
public enum eAGVCommandReason
|
||||
{
|
||||
/// <summary>
|
||||
/// 초기 미지정
|
||||
/// </summary>
|
||||
Normal,
|
||||
|
||||
/// <summary>
|
||||
/// 생성자
|
||||
/// 위치 미확정
|
||||
/// </summary>
|
||||
public AGVCommand(MotorCommand motor, MagnetPosition magnet, SpeedLevel speed, string reason = "")
|
||||
{
|
||||
Motor = motor;
|
||||
Magnet = magnet;
|
||||
Speed = speed;
|
||||
Reason = reason;
|
||||
}
|
||||
UnknownPosition,
|
||||
|
||||
/// <summary>
|
||||
/// 기본 생성자
|
||||
/// 대상경로없음
|
||||
/// </summary>
|
||||
public AGVCommand()
|
||||
{
|
||||
Motor = MotorCommand.Stop;
|
||||
Magnet = MagnetPosition.S;
|
||||
Speed = SpeedLevel.L;
|
||||
Reason = "";
|
||||
}
|
||||
NoTarget,
|
||||
|
||||
/// <summary>
|
||||
/// 경로없음
|
||||
/// </summary>
|
||||
NoPath,
|
||||
|
||||
/// <summary>
|
||||
/// 경로이탈
|
||||
/// </summary>
|
||||
PathOut,
|
||||
|
||||
/// <summary>
|
||||
/// 마크스탑을 해야한다
|
||||
/// </summary>
|
||||
MarkStop,
|
||||
|
||||
/// <summary>
|
||||
/// 완료
|
||||
/// </summary>
|
||||
Complete,
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return $"Motor:{Motor}, Magnet:{Magnet}, Speed:{Speed}" +
|
||||
(string.IsNullOrEmpty(Reason) ? "" : $" ({Reason})");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -140,7 +140,7 @@ namespace AGVNavigationCore.Models
|
||||
/// <summary>
|
||||
/// 현재 노드 ID 조회
|
||||
/// </summary>
|
||||
string GetCurrentNodeId();
|
||||
MapNode GetCurrentNode();
|
||||
|
||||
/// <summary>
|
||||
/// AGV 상태 정보 문자열 조회
|
||||
|
||||
@@ -43,7 +43,7 @@ namespace AGVNavigationCore.Models
|
||||
/// </summary>
|
||||
public event EventHandler<string> ErrorOccurred;
|
||||
|
||||
|
||||
|
||||
|
||||
#endregion
|
||||
|
||||
@@ -217,6 +217,8 @@ namespace AGVNavigationCore.Models
|
||||
_currentPosition = position;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 감지된 RFID 설정 (실제 RFID 센서에서)
|
||||
/// </summary>
|
||||
@@ -259,6 +261,19 @@ namespace AGVNavigationCore.Models
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 현재 노드id의 개체를 IsPass 로 설정합니다
|
||||
/// </summary>
|
||||
public bool SetCurrentNodeMarkStop()
|
||||
{
|
||||
if (_currentNode == null) return false;
|
||||
var 미완료된처음노드 = _currentPath.DetailedPath.Where(t => t.IsPass == false).OrderBy(t => t.seq).FirstOrDefault();
|
||||
if (미완료된처음노드 == null) return false;
|
||||
미완료된처음노드.IsPass = true;
|
||||
Console.WriteLine($"미완료된처음노드를 true러치합니다");
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 다음 동작 예측 (실제 AGV 제어용)
|
||||
/// AGV가 지속적으로 호출하여 현재 상태와 예측 상태를 일치시킴
|
||||
@@ -273,7 +288,8 @@ namespace AGVNavigationCore.Models
|
||||
return new AGVCommand(
|
||||
MotorCommand.Forward,
|
||||
MagnetPosition.S, // 직진
|
||||
SpeedLevel.L, // 저속
|
||||
SpeedLevel.L, // 저속
|
||||
eAGVCommandReason.UnknownPosition,
|
||||
$"위치 미확정 (RFID {_detectedRfids.Count}/2) - 전진하여 RFID 탐색"
|
||||
);
|
||||
}
|
||||
@@ -285,6 +301,7 @@ namespace AGVNavigationCore.Models
|
||||
MotorCommand.Stop,
|
||||
MagnetPosition.S,
|
||||
SpeedLevel.L,
|
||||
eAGVCommandReason.NoPath,
|
||||
$"위치 확정 완료 (목적지 미설정) - 현재:{_currentNode?.NodeId ?? "알수없음"}"
|
||||
);
|
||||
}
|
||||
@@ -293,12 +310,32 @@ namespace AGVNavigationCore.Models
|
||||
var lastNode = _currentPath.DetailedPath.Last();
|
||||
if (_currentPath.DetailedPath.Where(t => t.seq < lastNode.seq && t.IsPass == false).Any() == false)
|
||||
{
|
||||
return new AGVCommand(
|
||||
MotorCommand.Stop,
|
||||
MagnetPosition.S,
|
||||
SpeedLevel.L,
|
||||
$"목적지 도착 - 최종:{_currentNode?.NodeId ?? "알수없음"}"
|
||||
);
|
||||
// 마지막 노드에 도착했는지 확인 (현재 노드가 마지막 노드와 같은지)
|
||||
if (_currentNode != null && _currentNode.NodeId == lastNode.NodeId)
|
||||
{
|
||||
if (lastNode.IsPass) //이미완료되었다.
|
||||
{
|
||||
return new AGVCommand(
|
||||
MotorCommand.Stop,
|
||||
MagnetPosition.S,
|
||||
SpeedLevel.L,
|
||||
eAGVCommandReason.Complete,
|
||||
$"목적지 도착 - 최종:{_currentNode?.NodeId ?? "알수없음"}"
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
//마지막노드는 일혔지만 완료되지 않았다. 마크스탑필요
|
||||
return new AGVCommand(
|
||||
MotorCommand.Stop,
|
||||
MagnetPosition.S,
|
||||
SpeedLevel.L,
|
||||
eAGVCommandReason.MarkStop,
|
||||
$"목적지 도착 전(MarkStop) - 최종:{_currentNode?.NodeId ?? "알수없음"}"
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// 4. 경로이탈
|
||||
@@ -309,120 +346,14 @@ namespace AGVNavigationCore.Models
|
||||
MotorCommand.Stop,
|
||||
MagnetPosition.S,
|
||||
SpeedLevel.L,
|
||||
eAGVCommandReason.PathOut,
|
||||
$"(재탐색요청)경로이탈 현재위치:{_currentNode.NodeId}"
|
||||
);
|
||||
}
|
||||
|
||||
// 5. 방향체크
|
||||
//if(CurrentDirection != TargetNode.MotorDirection)
|
||||
//{
|
||||
// return new AGVCommand(
|
||||
// MotorCommand.Stop,
|
||||
// MagnetPosition.S,
|
||||
// SpeedLevel.L,
|
||||
// $"(재탐색요청)모터방향 불일치 현재위치:{_currentNode.NodeId}"
|
||||
// );
|
||||
//}
|
||||
|
||||
|
||||
//this.CurrentNodeId
|
||||
|
||||
return GetCommandFromPath(CurrentNodeId, "경로 실행 시작");
|
||||
|
||||
// 4. 위치 확정 + 경로 실행 중 → 현재 상태에 따른 명령 예측
|
||||
switch (_currentState)
|
||||
{
|
||||
case AGVState.Idle:
|
||||
// 🔥 경로가 있다면 이동 시작 (경로 실행 대기 중)
|
||||
if (_currentPath != null && _remainingNodes != null && _remainingNodes.Count > 0)
|
||||
{
|
||||
// DetailedPath에서 다음 노드 정보 가져오기
|
||||
return GetCommandFromPath(_remainingNodes[0], "경로 실행 시작");
|
||||
}
|
||||
|
||||
// 경로가 없으면 대기
|
||||
return new AGVCommand(
|
||||
MotorCommand.Stop,
|
||||
MagnetPosition.S,
|
||||
SpeedLevel.L,
|
||||
"대기 중 (경로 없음)"
|
||||
);
|
||||
|
||||
case AGVState.Moving:
|
||||
{
|
||||
// 이동 중 - DetailedPath에서 현재/다음 노드 정보 가져오기
|
||||
if (_currentPath != null && _remainingNodes != null && _remainingNodes.Count > 0)
|
||||
{
|
||||
return GetCommandFromPath(_remainingNodes[0], "이동 중");
|
||||
}
|
||||
|
||||
// 경로 정보가 없으면 기본 명령 (fallback)
|
||||
var motorCmd = _currentDirection == AgvDirection.Forward
|
||||
? MotorCommand.Forward
|
||||
: MotorCommand.Backward;
|
||||
|
||||
return new AGVCommand(
|
||||
motorCmd,
|
||||
MagnetPosition.S,
|
||||
SpeedLevel.M,
|
||||
$"이동 중 (DetailedPath 없음)"
|
||||
);
|
||||
}
|
||||
|
||||
case AGVState.Rotating:
|
||||
// 회전 중 - 정지 상태에서 마그넷만 조정
|
||||
MagnetPosition magnetPos = MagnetPosition.S;
|
||||
if (_currentDirection == AgvDirection.Left)
|
||||
magnetPos = MagnetPosition.L;
|
||||
else if (_currentDirection == AgvDirection.Right)
|
||||
magnetPos = MagnetPosition.R;
|
||||
|
||||
return new AGVCommand(
|
||||
MotorCommand.Stop, // 회전은 정지 상태에서
|
||||
magnetPos,
|
||||
SpeedLevel.L,
|
||||
$"회전 중 ({_currentDirection})"
|
||||
);
|
||||
|
||||
case AGVState.Docking:
|
||||
{
|
||||
// 도킹 중 - 저속으로 전진 또는 후진
|
||||
var dockingMotor = _dockingDirection == DockingDirection.Forward
|
||||
? MotorCommand.Forward
|
||||
: MotorCommand.Backward;
|
||||
|
||||
return new AGVCommand(
|
||||
dockingMotor,
|
||||
MagnetPosition.S,
|
||||
SpeedLevel.L, // 도킹은 항상 저속
|
||||
$"도킹 중 ({_dockingDirection})"
|
||||
);
|
||||
}
|
||||
|
||||
case AGVState.Charging:
|
||||
return new AGVCommand(
|
||||
MotorCommand.Stop,
|
||||
MagnetPosition.S,
|
||||
SpeedLevel.L,
|
||||
"충전 중"
|
||||
);
|
||||
|
||||
case AGVState.Error:
|
||||
return new AGVCommand(
|
||||
MotorCommand.Stop,
|
||||
MagnetPosition.S,
|
||||
SpeedLevel.L,
|
||||
"오류 발생"
|
||||
);
|
||||
|
||||
default:
|
||||
return new AGVCommand(
|
||||
MotorCommand.Stop,
|
||||
MagnetPosition.S,
|
||||
SpeedLevel.L,
|
||||
"알 수 없는 상태"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
@@ -442,7 +373,7 @@ namespace AGVNavigationCore.Models
|
||||
/// <summary>
|
||||
/// 현재 노드 ID 조회
|
||||
/// </summary>
|
||||
public string GetCurrentNodeId() => _currentNode?.NodeId;
|
||||
public MapNode GetCurrentNode() => _currentNode;
|
||||
|
||||
/// <summary>
|
||||
/// AGV 정보 조회
|
||||
@@ -682,6 +613,7 @@ namespace AGVNavigationCore.Models
|
||||
defaultMotor,
|
||||
MagnetPosition.S,
|
||||
SpeedLevel.M,
|
||||
eAGVCommandReason.NoPath,
|
||||
$"{actionDescription} (DetailedPath 없음)"
|
||||
);
|
||||
}
|
||||
@@ -701,6 +633,7 @@ namespace AGVNavigationCore.Models
|
||||
defaultMotor,
|
||||
MagnetPosition.S,
|
||||
SpeedLevel.M,
|
||||
eAGVCommandReason.NoTarget,
|
||||
$"{actionDescription} (노드 {targetNodeId} 정보 없음)"
|
||||
);
|
||||
}
|
||||
@@ -745,6 +678,7 @@ namespace AGVNavigationCore.Models
|
||||
motorCmd,
|
||||
magnetPos,
|
||||
speed,
|
||||
eAGVCommandReason.Normal,
|
||||
$"{actionDescription} → {targetNodeId} (Motor:{motorCmd}, Magnet:{magnetPos})"
|
||||
);
|
||||
}
|
||||
@@ -817,7 +751,27 @@ namespace AGVNavigationCore.Models
|
||||
}
|
||||
|
||||
public MapNode StartNode { get; set; } = null;
|
||||
public MapNode TargetNode { get; set; } = null;
|
||||
|
||||
private MapNode _targetnode = null;
|
||||
|
||||
/// <summary>
|
||||
/// 목적지를 설정합니다. 목적지가 변경되면 경로계산정보가 삭제 됩니다.
|
||||
/// </summary>
|
||||
public MapNode TargetNode
|
||||
{
|
||||
get
|
||||
{
|
||||
return _targetnode;
|
||||
}
|
||||
set
|
||||
{
|
||||
if (_targetnode != value)
|
||||
{
|
||||
_currentPath = null;
|
||||
_targetnode = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void ProcessNextNode()
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user