This commit is contained in:
backuppc
2026-01-21 17:28:39 +09:00
parent 3044894e5c
commit 00c4663ebc
3 changed files with 335 additions and 42 deletions

View File

@@ -263,7 +263,7 @@ namespace AGVNavigationCore.PathFinding.Core
/// 경로의 노드 정보를 포함
/// </summary>
/// <returns></returns>
public string GetDetailedPathInfo()
public string GetDetailedPathInfo(bool shortmessage = false)
{
if (!Success)
{
@@ -272,7 +272,10 @@ namespace AGVNavigationCore.PathFinding.Core
var data = DetailedPath.Select(t =>
{
return $"{t.RfidId}[{t.NodeId}] {t.MotorDirection.ToString().Substring(0, 1)}-{t.MagnetDirection.ToString().Substring(0, 1)}";
if (shortmessage)
return $"{t.RfidId:00}{t.MotorDirection.ToString().Substring(0, 1)}{t.MagnetDirection.ToString().Substring(0, 1)}";
else
return $"{t.RfidId}[{t.NodeId}] {t.MotorDirection.ToString().Substring(0, 1)}-{t.MagnetDirection.ToString().Substring(0, 1)}";
});
return string.Join(" → ", data);
}

View File

@@ -56,6 +56,11 @@ namespace AGVSimulator.Forms
listItem.BackColor = Color.LightPink;
}
var dockpos = item.DockingPosition ?? string.Empty;
var targerpos = item.TargetPosition ?? string.Empty;
if (dockpos.Equals("충전기") && targerpos.StartsWith("0015"))
listItem.ForeColor = Color.DarkViolet;
_logListView.Items.Add(listItem);
_logListView.EnsureVisible(_logListView.Items.Count - 1);
}

View File

@@ -1539,8 +1539,14 @@ namespace AGVSimulator.Forms
private string GetNodeDisplayName(MapNode node)
{
if (node == null) return "-";
if (node.HasRfid()) return node.RfidId.ToString("0000");
return $"({node.Id})";
var retval = "";
if (node.HasRfid()) retval = node.RfidId.ToString("0000");
else retval = $"({node.Id})";
if (node.DockDirection == DockingDirection.Forward)
retval += "(F)";
else if (node.DockDirection == DockingDirection.Backward)
retval += "(B)";
return retval;
}
/// <summary>
@@ -1606,13 +1612,13 @@ namespace AGVSimulator.Forms
{
logItem.Success = true;
logItem.Message = "성공";
logItem.DetailedPath = currentPath.GetDetailedPathInfo();
logItem.DetailedPath = currentPath.GetDetailedPathInfo(true);
}
else
{
logItem.Success = false;
logItem.Message = $"도킹 검증 실패: {dockingValidation.ValidationError}";
logItem.DetailedPath = currentPath.GetDetailedPathInfo();
logItem.DetailedPath = currentPath.GetDetailedPathInfo(true);
}
}
else
@@ -1694,9 +1700,9 @@ namespace AGVSimulator.Forms
logForm.AppendLog("---");
// 각 연결된 노드 쌍에 대해 테스트
foreach (var (nodeA, nodeB) in nodePairs)
foreach (var (direction, directionName) in directions)
{
foreach (var (direction, directionName) in directions)
foreach (var (nodeA, nodeB) in nodePairs)
{
// 취소 확인
if (logForm.CancelRequested)
@@ -1766,10 +1772,7 @@ namespace AGVSimulator.Forms
var startNode = (_startNodeCombo.SelectedItem as ComboBoxItem<MapNode>)?.Value;
var targetNode = (_targetNodeCombo.SelectedItem as ComboBoxItem<MapNode>)?.Value;
var selectedAGV = _agvListCombo.SelectedItem as VirtualAGV;
var calcResult = CalcPath(startNode, targetNode, this._simulatorCanvas.Nodes,selectedAGV.PrevNode, selectedAGV.PrevDirection);
var calcResult = CalcPath(startNode, targetNode, this._simulatorCanvas.Nodes, selectedAGV.PrevNode, selectedAGV.PrevDirection);
//// 테스트 결과 생성
testResult = CreateTestResultFromUI(nodeA, dockingTarget, directionName, calcResult);
@@ -2111,9 +2114,13 @@ namespace AGVSimulator.Forms
{
try
{
if (_emulatorPort != null && _emulatorPort.IsOpen)
if (_emulatorPort != null)
{
_emulatorPort.Close();
// 이벤트 핸들러 해제 (중복 호출 방지)
_emulatorPort.DataReceived -= OnEmulatorDataReceived;
if (_emulatorPort.IsOpen)
_emulatorPort.Close();
}
_isEmulatorConnected = false;
_connectButton.Text = "Connect";
@@ -2131,6 +2138,8 @@ namespace AGVSimulator.Forms
{
try
{
if (_emulatorPort == null || !_emulatorPort.IsOpen) return;
string data = _emulatorPort.ReadExisting();
_recvBuffer.Append(data);
@@ -2161,6 +2170,11 @@ namespace AGVSimulator.Forms
catch (Exception ex)
{
Console.WriteLine($"Emulator Recv Error: {ex.Message}");
// 수신 중 오류 발생 시 연결 해제 처리 (UI 스레드에서 실행)
this.Invoke(new Action(() =>
{
if (_isEmulatorConnected) DisconnectEmulator();
}));
}
}
@@ -2366,7 +2380,11 @@ namespace AGVSimulator.Forms
private void SendEmulatorStatus()
{
if (_emulatorPort == null || !_emulatorPort.IsOpen) return;
if (_emulatorPort == null || !_emulatorPort.IsOpen)
{
if (_isEmulatorConnected) DisconnectEmulator();
return;
}
var agv = _agvList.FirstOrDefault();
@@ -2419,7 +2437,10 @@ namespace AGVSimulator.Forms
{
_emulatorPort.Write(barr, 0, barr.Length);
}
catch { }
catch
{
if (_isEmulatorConnected) DisconnectEmulator();
}
}
private string CalculateChecksum(string data)
@@ -2545,7 +2566,7 @@ namespace AGVSimulator.Forms
else
{
// 8. 적용
ApplyResultToSimulator(rlt, selectedAGV);
UpdateAdvancedPathDebugInfo(rlt);
}
@@ -2563,7 +2584,7 @@ namespace AGVSimulator.Forms
if (startNode == null || targetNode == null) return AGVPathResult.CreateFailure("시작/종료노드가 지정되지 않음");
try
{
var pathFinder = new AGVPathfinder(nodes);
@@ -2574,13 +2595,19 @@ namespace AGVSimulator.Forms
AGVPathResult LimitPath = null;
if (startNode.ConnectedMapNodes.Count == 1)
{
LimitPath = pathFinder.FindPathAStar(startNode, targetNode);
for(int i = 0; i < LimitPath.Path.Count;i++)
LimitPath = pathFinder.FindPathAStar(startNode, prevNode);
for (int i = 0; i < LimitPath.Path.Count; i++)
{
var nodeinfo = LimitPath.Path[i];
var dir = (prevDir == AgvDirection.Forward ? AgvDirection.Backward : AgvDirection.Forward);
LimitPath.DetailedPath.Add(new NodeMotorInfo(i + 1, nodeinfo.Id, nodeinfo.RfidId, dir));
}
//시작위치 및 방향을변경해준다
var org_start = startNode;
startNode = prevNode;
prevNode = org_start;
prevDir = (prevDir == AgvDirection.Forward ? AgvDirection.Backward : AgvDirection.Forward);
}
@@ -2599,9 +2626,11 @@ namespace AGVSimulator.Forms
_simulatorCanvas.HighlightNodeId = null;
//버퍼구간내에 시작과 종료가 모두 포함되어있다
bool fixpath = false;
if (rlt.Path.Contains(startNode) && rlt.Path.Contains(targetNode))
{
Retval = CalcPathBufferToBuffer(pathFinder, startNode, targetNode, prevNode, prevDir, selectedAGV);
fixpath = true;
}
else
{
@@ -2641,9 +2670,18 @@ namespace AGVSimulator.Forms
}
//경로오류 검사
if (Retval.Success == false) return Retval;
if (LimitPath != null)
{
Retval = CombinePaths(LimitPath, Retval);
}
//해당경로와 대상의 도킹포인트의 방향을 검사합니다
if (targetNode.DockDirection != DockingDirection.DontCare)
{
@@ -2661,7 +2699,7 @@ namespace AGVSimulator.Forms
//6[F][R] → 13[B][L] → 6[F][L] 이런경우를 찾아서 경로를 최적화한다.
//위 예제에서는 6FR 13BL 이 제자리로 오는 경로이므로 6FL만 남기면된다.
//단순히 ID만 같은게 아니라, 실제로 갔다가 되돌아오는 패턴(역방향)인지 확인해야 함.
while (true)
while (fixpath == false && true)
{
var updatecount = 0;
for (int i = 0; i < Retval.DetailedPath.Count - 2; i++)
@@ -2725,8 +2763,126 @@ namespace AGVSimulator.Forms
}
//6[F][R] → 13[B][L] → 6[F][L] 이런경우를 찾아서 경로를 최적화한다.
//위 예제에서는 6FR 13BL 이 제자리로 오는 경로이므로 6FL만 남기면된다.
//최종 목적지를 확인하여 도킹 노드라면 그 도킹노드방향과 모터방향을 체크한다.
var lastnode = Retval.Path.Last();
if (lastnode.StationType != StationType.Normal)
{
var lastnodePath = Retval.DetailedPath.Last();
if (lastnode.DockDirection == DockingDirection.Forward && lastnodePath.MotorDirection != AgvDirection.Forward)
return AGVPathResult.CreateFailure($"목적지의 모터방향({lastnode.DockDirection}) 불일치 경로방향({lastnodePath.MotorDirection}) {Retval.GetDetailedPathInfo(true)}");
if (lastnode.DockDirection == DockingDirection.Backward && lastnodePath.MotorDirection != AgvDirection.Backward)
return AGVPathResult.CreateFailure($"목적지의 모터방향({lastnode.DockDirection}) 불일치 경로방향({lastnodePath.MotorDirection}) {Retval.GetDetailedPathInfo(true)}");
}
//모든 디테일데이터의 실제 위치를 기반으로 전체 노드를 추정한다
for (int i = 0; i < Retval.DetailedPath.Count - 1; i++)
{
var pnode = (i == 0 ? prevNode : Retval.Path[i - 1]);
var pdir = (i == 0 ? prevDir : Retval.DetailedPath[i - 1].MotorDirection);
var cnode = Retval.Path[i];
var nnode = Retval.Path[i + 1];
//연결된 노드에 다음노드 id가 포함되는지 확인한다
if (cnode.ConnectedNodes.Contains(nnode.Id) == false)
{
return AGVPathResult.CreateFailure($"[{cnode.RfidId}] 노드에 연결되지 않은 [{nnode.RfidId}]노드가 지정됨 {Retval.GetDetailedPathInfo(true)}");
}
//왔던방향을 제외한 다른 방향에 다음노드가 있는지
var detail = Retval.DetailedPath[i];
//연결된 모두를 찾아서 온곳
bool existconnnode = false;
//왓던방향을고려해서 다음 노드를 찾아서 일치하는지 본다.
var deltaX = nnode.Position.X - cnode.Position.X;
var deltaY = nnode.Position.Y - cnode.Position.Y;
if (Math.Abs(deltaX) > Math.Abs(deltaY))
{
//x축으로 많이 움직임
if (nnode.Position.X > pnode.Position.X)
{
//장비가 오른쪽으로 움직였다
if (pdir == detail.MotorDirection)
{
//왓던방향으로 게속 이동한다
var nextpredictnode = cnode.ConnectedMapNodes.Where(t => t.Position.X > cnode.Position.X).FirstOrDefault();
if (nextpredictnode.Id != nnode.Id)
return AGVPathResult.CreateFailure($"[{cnode.RfidId}] 노드의 다음[{nnode.RfidId}]노드가 올바르지 않음 {Retval.GetDetailedPathInfo(true)}");
}
else
{
//반대방향으로 이동한다
var nextpredictnode = cnode.ConnectedMapNodes.Where(t => t.Position.X < cnode.Position.X).FirstOrDefault();
if (nextpredictnode.Id != nnode.Id)
return AGVPathResult.CreateFailure($"[{cnode.RfidId}] 노드의 다음[{nnode.RfidId}]노드가 올바르지 않음 {Retval.GetDetailedPathInfo(true)}");
}
}
else
{
//장비가 왼쪽으로 움직였다
if (pdir == detail.MotorDirection) //후진으로 왼쪽이동했으니 모니터가 왼쪽에 있다.
{
//왓던방향으로 게속 이동한다
var nextpredictnode = cnode.ConnectedMapNodes.Where(t => t.Position.X < cnode.Position.X).FirstOrDefault();
if (nextpredictnode.Id != nnode.Id)
return AGVPathResult.CreateFailure($"[{cnode.RfidId}] 노드의 다음[{nnode.RfidId}]노드가 올바르지 않음 {Retval.GetDetailedPathInfo(true)}");
}
else
{
//반대방향으로 이동한다
var nextpredictnode = cnode.ConnectedMapNodes.Where(t => t.Position.X > cnode.Position.X).FirstOrDefault();
if (nextpredictnode.Id != nnode.Id)
return AGVPathResult.CreateFailure($"[{cnode.RfidId}] 노드의 다음[{nnode.RfidId}]노드가 올바르지 않음 {Retval.GetDetailedPathInfo(true)}");
}
}
}
else
{
//y축으로 많이 움직임
if (nnode.Position.Y < pnode.Position.Y)
{
//장비가 위로 움직였다
if (pdir == detail.MotorDirection)
{
//왓던방향으로 게속 이동한다
var nextpredictnode = cnode.ConnectedMapNodes.Where(t => t.Position.Y > cnode.Position.Y).FirstOrDefault();
if (nextpredictnode.Id != nnode.Id)
return AGVPathResult.CreateFailure($"[{cnode.RfidId}] 노드의 다음[{nnode.RfidId}]노드가 올바르지 않음 {Retval.GetDetailedPathInfo(true)}");
}
else
{
//반대방향으로 이동한다
var nextpredictnode = cnode.ConnectedMapNodes.Where(t => t.Position.Y < cnode.Position.Y).FirstOrDefault();
if (nextpredictnode.Id != nnode.Id)
return AGVPathResult.CreateFailure($"[{cnode.RfidId}] 노드의 다음[{nnode.RfidId}]노드가 올바르지 않음 {Retval.GetDetailedPathInfo(true)}");
}
}
else
{
//장비가 아래로 움직였다
if (pdir == detail.MotorDirection) //후진으로 아래로 이동했으니 모니터가 위에 있다.
{
//왓던방향으로 게속 이동한다
var nextpredictnode = cnode.ConnectedMapNodes.Where(t => t.Position.Y > cnode.Position.Y).Select(t => t.Id).ToList();
if (nextpredictnode.Contains(nnode.Id) == false)
return AGVPathResult.CreateFailure($"[{cnode.RfidId}] 노드의 다음[{nnode.RfidId}]노드가 올바르지 않음 {Retval.GetDetailedPathInfo(true)}");
}
else
{
//반대방향으로 이동한다
var nextpredictnode = cnode.ConnectedMapNodes.Where(t => t.Position.Y > cnode.Position.Y).FirstOrDefault();
if (nextpredictnode.Id != nnode.Id)
return AGVPathResult.CreateFailure($"[{cnode.RfidId}] 노드의 다음[{nnode.RfidId}]노드가 올바르지 않음 {Retval.GetDetailedPathInfo(true)}");
}
}
}
}
//최종결과 반환
@@ -2748,18 +2904,26 @@ namespace AGVSimulator.Forms
// 이동 벡터 X 변화량
// prev가 없거나 start와 같으면 이동 방향을 알 수 없음 -> 이 경우 보수적으로 기존 로직(Backward면 탈출) 따름
int deltaX = 0;
int deltaY = 0;
if (prev == null) return AGVPathResult.CreateFailure("이전 노드 정보가 없습니다");
else deltaX = start.Position.X - prev.Position.X;
else
{
deltaX = start.Position.X - prev.Position.X;
deltaY = -(start.Position.Y - prev.Position.Y);
}
if (Math.Abs(deltaY) > Math.Abs(deltaX))
deltaX = deltaY;
bool isMonitorLeft = false;
if (deltaX > 0) // 오른쪽(Forward)으로 이동해 옴 (예: 2 -> 4)
if (deltaX > 0) // 오른쪽(Forward)으로 이동해 옴 (예: 2 -> 4), 위로 이동함
{
// 이동방향(Right) + 전진(F) => Monitor Right (Good)
// 이동방향(Right) + 후진(B) => Monitor Left (Bad)
isMonitorLeft = (prevDir == AgvDirection.Backward);
}
else if (deltaX < 0) // 왼쪽(Reverse)으로 이동해 옴 (예: 4 -> 2)
else if (deltaX < 0) // 왼쪽(Reverse)으로 이동해 옴 (예: 4 -> 2), 아래로 이동함
{
// 이동방향(Left) + 전진(F) => Monitor Left (Bad)
// 이동방향(Left) + 후진(B) => Monitor Right (Good)
@@ -2775,8 +2939,22 @@ namespace AGVSimulator.Forms
{
// Monitor Left 상태 (방향 불일치) -> Gateway로 탈출
var GateWayNode = FindNode(6);
var escPath = pathfinder.FindBasicPath(start, GateWayNode, prev, prevDir);
if (!escPath.Success) return AGVPathResult.CreateFailure("버퍼 탈출 경로 실패");
var reverseDir = prevDir == AgvDirection.Backward ? AgvDirection.Forward : AgvDirection.Backward;
//왼족에서 오른조긍로 이동하면 prevdir 을 그대로 쓰는데.. 오른쪽에서 왼쪽으로 이동했다면 방향을 변경해야한다
AGVPathResult escPath = null;
if (start.Position.X > prev.Position.X)
{
escPath = pathfinder.FindBasicPath(start, GateWayNode, prev, prevDir);
if (!escPath.Success) return AGVPathResult.CreateFailure("버퍼 탈출 경로 실패");
}
else
{
escPath = pathfinder.FindBasicPath(start, GateWayNode, prev, reverseDir);
if (!escPath.Success) return AGVPathResult.CreateFailure("버퍼 탈출 경로 실패");
}
var lastNode = escPath.Path.Last(); // Should be GW6
var lastPrev = escPath.Path[escPath.Path.Count - 2];
@@ -2805,9 +2983,96 @@ namespace AGVSimulator.Forms
else
{
// Monitor Right 상태 (방향 일치) -> 직접 진입 또는 Overshoot
bool isTargetLeft = target.Position.X < start.Position.X;
if (isTargetLeft)
if (target == start)
{
//시작위치랑 종료위치랑 같고, 방향도 같다면 이동할 필요는 없는 조건이다
//오른쪽으로 한번더 이동해서그곳까지 이동한 후 역방향으로 MS 처리한다
//PREV 가 아닌 다른 노드가 이동할 대상이다
//현재위치에서 지정방향으로 이동한다.
var list = new List<MapNode>();
var retval = AGVPathResult.CreateSuccess(list, new List<AgvDirection>(), 0, 0);
var resversedir = prevDir == AgvDirection.Backward ? AgvDirection.Forward : AgvDirection.Backward;
//현재위치에서 반드시 시작해야하낟.
retval.Path.Add(target);
if (deltaX < 0)
{
//장비가 오른쪽에서 왼쪽으로 오는 경우와
var nextNode = start.ConnectedMapNodes.Where(t => t.Id != prev.Id && t.StationType == StationType.Buffer).FirstOrDefault();
if (nextNode != null)
{
//방향결정
retval.DetailedPath.Add(new NodeMotorInfo(1, target.Id, target.RfidId, prevDir));
//다음노드로 이동을한다.
retval.Path.Add(nextNode);
var lastDefailt = retval.DetailedPath.Last();
retval.DetailedPath.Add(new NodeMotorInfo(lastDefailt.seq + 1, nextNode.Id, nextNode.RfidId, AgvDirection.Forward)
{
Speed = SpeedLevel.M,
IsPass = false,
});
////다시원래노드로 이동을해야한다.(반대방향으로)
retval.Path.Add(target);
retval.DetailedPath.Add(new NodeMotorInfo((retval.DetailedPath.Max(t => t.seq) + 1), target.Id, target.RfidId, AgvDirection.Forward));
//최종목적지로 간다
retval.Path.Add(target);
retval.DetailedPath.Add(new NodeMotorInfo(retval.DetailedPath.Max(t => t.seq) + 1, target.Id, target.RfidId, AgvDirection.Backward));
}
else
{
//방향결정(다음노드가 없으니 반대방향으로 들어가야한다)
retval.DetailedPath.Add(new NodeMotorInfo(1, target.Id, target.RfidId, resversedir));
//다음노드가 없으므로 이전노드로 처리를 해야한다.
retval.Path.Add(prev);
retval.DetailedPath.Add(new NodeMotorInfo(retval.DetailedPath.Last().seq + 1, prev.Id, prev.RfidId, prevDir)
{
Speed = SpeedLevel.M,
IsPass = false,
});
//최종목적지로 간다
retval.Path.Add(target);
retval.DetailedPath.Add(new NodeMotorInfo(retval.DetailedPath.Max(t => t.seq) + 1, target.Id, target.RfidId, prevDir));
}
}
else
{
//왼쪽에서 오른쪽으로 오는 경우가 서로 다르다
retval.DetailedPath.Add(new NodeMotorInfo(1, target.Id, target.RfidId, prevDir));
var nextNode = start.ConnectedMapNodes.Where(t => t.Id != prev.Id && t.StationType == StationType.Buffer).FirstOrDefault();
//한번더 이동을한다.(그리고는 반대로 저속 이동을 하게한다)
retval.Path.Add(nextNode);
var lastDefailt = retval.DetailedPath.Last();
retval.DetailedPath.Add(new NodeMotorInfo(lastDefailt.seq + 1, nextNode.Id, nextNode.RfidId, AgvDirection.Backward)
{
Speed = SpeedLevel.L,
IsPass = false,
});
//최종목적지로 간다
retval.Path.Add(target);
retval.DetailedPath.Add(new NodeMotorInfo(retval.DetailedPath.Max(t => t.seq) + 1, target.Id, target.RfidId, AgvDirection.Backward));
}
return retval;
}
else if (isTargetLeft)
{
var directPath = pathfinder.FindBasicPath(start, target, prev, AgvDirection.Backward);
ApplyResultToSimulator(directPath, agv);
@@ -2823,14 +3088,22 @@ namespace AGVSimulator.Forms
// return (false, "Overshoot 공간 부족");
var path1 = pathfinder.FindBasicPath(start, target, prev, AgvDirection.Forward);
if (path1.Path.Count < 2) return AGVPathResult.CreateFailure("Overshoot 경로 생성 실패");
if (path1.Path.Count < 2)
{
return AGVPathResult.CreateFailure("Overshoot 경로 생성 실패");
}
//마지막위치는 제거한다. 바로 방향을 전환하기 위함이다.
var last = path1.Path.Last();
var lastD = path1.DetailedPath.Last();
path1.Path.RemoveAt(path1.Path.Count - 1);
path1.DetailedPath.RemoveAt(path1.DetailedPath.Count - 1);
//목표에서 방향바꿔 마크스탑을 해야한다
path1.Path.Add(path1.Path.Last());
path1.Path.Add(last);
//디테일은 방향바꿔서 추가 필요(속도는 저속처리해준다)
var lastDefailt = path1.DetailedPath.Last();
path1.DetailedPath.Add(new NodeMotorInfo(lastDefailt.seq + 1, lastDefailt.NodeId, lastDefailt.RfidId, AgvDirection.Backward)
path1.DetailedPath.Add(new NodeMotorInfo(lastD.seq + 1, lastD.NodeId, lastD.RfidId, AgvDirection.Backward)
{
Speed = SpeedLevel.L,
IsPass = false,
@@ -2892,8 +3165,6 @@ namespace AGVSimulator.Forms
//게이트웨이 진입 한 방향을 보고. 목적지와 도킹방향이 일치하는지 결정한다.
var deltaX = GTNode.Position.X - PrevNode.Position.X;
var isMonitorLeft = false;
bool requiredDir = false;
if (deltaX > 0) //게이트웨이가 우측에 있다
{
@@ -2932,7 +3203,8 @@ namespace AGVSimulator.Forms
var motdir = targetNode.DockDirection == DockingDirection.Backward ? AgvDirection.Backward : AgvDirection.Forward;
var pathtarget = pathFinder.FindBasicPath(GTNode, targetNode, PrevNode, motdir);
if (targetNode.DockDirection == DockingDirection.Backward && isMonitorLeft)
if ((targetNode.DockDirection == DockingDirection.Backward && isMonitorLeft) ||
(targetNode.DockDirection == DockingDirection.Forward && !isMonitorLeft))
{
//턴을 하는
turnPatterns = GetTurnaroundPattern(GTNode, targetNode);
@@ -2987,12 +3259,13 @@ namespace AGVSimulator.Forms
private MapNode GetGatewayNode(MapNode node)
{
var rfid = 0;
if (node.RfidId == 1) rfid = 10;
if (node.RfidId == 15) rfid = 9;
if (node.RfidId == 11) rfid = 6;
if (node.RfidId == 8) rfid = 13;
if (node.RfidId == 19) rfid = 13;
if (node.StationType == StationType.Buffer) rfid = 6;
if (node.StationType == StationType.UnLoader) rfid = 10; //unloader
else if (node.StationType == StationType.Charger1) rfid = 9; //charger #1
else if (node.StationType == StationType.Clearner) rfid = 6; //cleaner
else if (node.StationType == StationType.Charger2) rfid = 13; //charger #2
else if (node.StationType == StationType.Loader) rfid = 13; //loader
else if (node.StationType == StationType.Buffer) rfid = 6;
if (rfid == 0) return null;
return this._simulatorCanvas.Nodes.FirstOrDefault(t => t.RfidId == rfid);
}
@@ -3048,6 +3321,18 @@ namespace AGVSimulator.Forms
var res = new AGVPathResult();
res.Success = true;
var p1last = p1.DetailedPath.LastOrDefault();
var p2fist = p2.DetailedPath.FirstOrDefault();
//p1의 마지막과 p2의 시작이 같다면 p1의 마지막을 제거한다.
if (p1last != null && p2fist != null &&
(p1last.NodeId == p2fist.NodeId && p1last.MotorDirection == p2fist.MotorDirection && p1last.MagnetDirection == p2fist.MagnetDirection))
{
p1.Path.RemoveAt(p1.Path.Count - 1);
p1.DetailedPath.RemoveAt(p1.DetailedPath.Count - 1);
}
foreach (var item in p1.Path)
{
res.Path.Add(item);