..
This commit is contained in:
@@ -93,8 +93,8 @@ namespace AGVSimulator.Forms
|
||||
this._agvCountLabel = new System.Windows.Forms.Label();
|
||||
this._simulationStatusLabel = new System.Windows.Forms.Label();
|
||||
this._pathGroup = new System.Windows.Forms.GroupBox();
|
||||
this.btPath2 = new System.Windows.Forms.Button();
|
||||
this._clearPathButton = new System.Windows.Forms.Button();
|
||||
this.btPath1 = new System.Windows.Forms.Button();
|
||||
this._targetCalcButton = new System.Windows.Forms.Button();
|
||||
this._avoidRotationCheckBox = new System.Windows.Forms.CheckBox();
|
||||
this._targetNodeCombo = new System.Windows.Forms.ComboBox();
|
||||
@@ -120,7 +120,6 @@ namespace AGVSimulator.Forms
|
||||
this._liftDirectionLabel = new System.Windows.Forms.Label();
|
||||
this._motorDirectionLabel = new System.Windows.Forms.Label();
|
||||
this.timer1 = new System.Windows.Forms.Timer(this.components);
|
||||
this.btPath2 = new System.Windows.Forms.Button();
|
||||
this._menuStrip.SuspendLayout();
|
||||
this._toolStrip.SuspendLayout();
|
||||
this._statusStrip.SuspendLayout();
|
||||
@@ -142,7 +141,7 @@ namespace AGVSimulator.Forms
|
||||
this.helpToolStripMenuItem});
|
||||
this._menuStrip.Location = new System.Drawing.Point(0, 0);
|
||||
this._menuStrip.Name = "_menuStrip";
|
||||
this._menuStrip.Size = new System.Drawing.Size(1034, 24);
|
||||
this._menuStrip.Size = new System.Drawing.Size(1248, 24);
|
||||
this._menuStrip.TabIndex = 0;
|
||||
this._menuStrip.Text = "menuStrip";
|
||||
//
|
||||
@@ -310,7 +309,7 @@ namespace AGVSimulator.Forms
|
||||
this.btMakeMap});
|
||||
this._toolStrip.Location = new System.Drawing.Point(0, 24);
|
||||
this._toolStrip.Name = "_toolStrip";
|
||||
this._toolStrip.Size = new System.Drawing.Size(1034, 25);
|
||||
this._toolStrip.Size = new System.Drawing.Size(1248, 25);
|
||||
this._toolStrip.TabIndex = 1;
|
||||
this._toolStrip.Text = "toolStrip";
|
||||
//
|
||||
@@ -436,7 +435,7 @@ namespace AGVSimulator.Forms
|
||||
this.prb1});
|
||||
this._statusStrip.Location = new System.Drawing.Point(0, 689);
|
||||
this._statusStrip.Name = "_statusStrip";
|
||||
this._statusStrip.Size = new System.Drawing.Size(1034, 22);
|
||||
this._statusStrip.Size = new System.Drawing.Size(1248, 22);
|
||||
this._statusStrip.TabIndex = 2;
|
||||
this._statusStrip.Text = "statusStrip";
|
||||
//
|
||||
@@ -464,7 +463,7 @@ namespace AGVSimulator.Forms
|
||||
this._controlPanel.Controls.Add(this._pathGroup);
|
||||
this._controlPanel.Controls.Add(this._agvControlGroup);
|
||||
this._controlPanel.Dock = System.Windows.Forms.DockStyle.Right;
|
||||
this._controlPanel.Location = new System.Drawing.Point(801, 49);
|
||||
this._controlPanel.Location = new System.Drawing.Point(1015, 49);
|
||||
this._controlPanel.Name = "_controlPanel";
|
||||
this._controlPanel.Size = new System.Drawing.Size(233, 640);
|
||||
this._controlPanel.TabIndex = 3;
|
||||
@@ -532,7 +531,6 @@ namespace AGVSimulator.Forms
|
||||
//
|
||||
this._pathGroup.Controls.Add(this.btPath2);
|
||||
this._pathGroup.Controls.Add(this._clearPathButton);
|
||||
this._pathGroup.Controls.Add(this.btPath1);
|
||||
this._pathGroup.Controls.Add(this._targetCalcButton);
|
||||
this._pathGroup.Controls.Add(this._avoidRotationCheckBox);
|
||||
this._pathGroup.Controls.Add(this._targetNodeCombo);
|
||||
@@ -547,6 +545,16 @@ namespace AGVSimulator.Forms
|
||||
this._pathGroup.TabStop = false;
|
||||
this._pathGroup.Text = "경로 제어";
|
||||
//
|
||||
// btPath2
|
||||
//
|
||||
this.btPath2.Location = new System.Drawing.Point(12, 201);
|
||||
this.btPath2.Name = "btPath2";
|
||||
this.btPath2.Size = new System.Drawing.Size(106, 25);
|
||||
this.btPath2.TabIndex = 10;
|
||||
this.btPath2.Text = "경로 계산2";
|
||||
this.btPath2.UseVisualStyleBackColor = true;
|
||||
this.btPath2.Click += new System.EventHandler(this.btPath2_Click);
|
||||
//
|
||||
// _clearPathButton
|
||||
//
|
||||
this._clearPathButton.Location = new System.Drawing.Point(121, 177);
|
||||
@@ -557,16 +565,6 @@ namespace AGVSimulator.Forms
|
||||
this._clearPathButton.UseVisualStyleBackColor = true;
|
||||
this._clearPathButton.Click += new System.EventHandler(this.OnClearPath_Click);
|
||||
//
|
||||
// btPath1
|
||||
//
|
||||
this.btPath1.Location = new System.Drawing.Point(12, 174);
|
||||
this.btPath1.Name = "btPath1";
|
||||
this.btPath1.Size = new System.Drawing.Size(106, 25);
|
||||
this.btPath1.TabIndex = 4;
|
||||
this.btPath1.Text = "경로 계산";
|
||||
this.btPath1.UseVisualStyleBackColor = true;
|
||||
this.btPath1.Click += new System.EventHandler(this.OnCalculatePath_Click);
|
||||
//
|
||||
// _targetCalcButton
|
||||
//
|
||||
this._targetCalcButton.Location = new System.Drawing.Point(10, 148);
|
||||
@@ -741,7 +739,7 @@ namespace AGVSimulator.Forms
|
||||
this._canvasPanel.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||
this._canvasPanel.Location = new System.Drawing.Point(0, 129);
|
||||
this._canvasPanel.Name = "_canvasPanel";
|
||||
this._canvasPanel.Size = new System.Drawing.Size(801, 560);
|
||||
this._canvasPanel.Size = new System.Drawing.Size(1015, 560);
|
||||
this._canvasPanel.TabIndex = 4;
|
||||
//
|
||||
// lbPredict
|
||||
@@ -749,7 +747,7 @@ namespace AGVSimulator.Forms
|
||||
this.lbPredict.Dock = System.Windows.Forms.DockStyle.Bottom;
|
||||
this.lbPredict.Location = new System.Drawing.Point(0, 513);
|
||||
this.lbPredict.Name = "lbPredict";
|
||||
this.lbPredict.Size = new System.Drawing.Size(801, 47);
|
||||
this.lbPredict.Size = new System.Drawing.Size(1015, 47);
|
||||
this.lbPredict.TabIndex = 0;
|
||||
this.lbPredict.Text = "";
|
||||
//
|
||||
@@ -764,7 +762,7 @@ namespace AGVSimulator.Forms
|
||||
this._agvInfoPanel.Dock = System.Windows.Forms.DockStyle.Top;
|
||||
this._agvInfoPanel.Location = new System.Drawing.Point(0, 49);
|
||||
this._agvInfoPanel.Name = "_agvInfoPanel";
|
||||
this._agvInfoPanel.Size = new System.Drawing.Size(801, 80);
|
||||
this._agvInfoPanel.Size = new System.Drawing.Size(1015, 80);
|
||||
this._agvInfoPanel.TabIndex = 5;
|
||||
//
|
||||
// _pathDebugLabel
|
||||
@@ -775,7 +773,7 @@ namespace AGVSimulator.Forms
|
||||
this._pathDebugLabel.Location = new System.Drawing.Point(10, 30);
|
||||
this._pathDebugLabel.Multiline = true;
|
||||
this._pathDebugLabel.Name = "_pathDebugLabel";
|
||||
this._pathDebugLabel.Size = new System.Drawing.Size(947, 43);
|
||||
this._pathDebugLabel.Size = new System.Drawing.Size(947, 45);
|
||||
this._pathDebugLabel.TabIndex = 4;
|
||||
this._pathDebugLabel.Text = "경로: 설정되지 않음";
|
||||
//
|
||||
@@ -814,21 +812,11 @@ namespace AGVSimulator.Forms
|
||||
this.timer1.Interval = 500;
|
||||
this.timer1.Tick += new System.EventHandler(this.timer1_Tick);
|
||||
//
|
||||
// btPath2
|
||||
//
|
||||
this.btPath2.Location = new System.Drawing.Point(12, 201);
|
||||
this.btPath2.Name = "btPath2";
|
||||
this.btPath2.Size = new System.Drawing.Size(106, 25);
|
||||
this.btPath2.TabIndex = 10;
|
||||
this.btPath2.Text = "경로 계산2";
|
||||
this.btPath2.UseVisualStyleBackColor = true;
|
||||
this.btPath2.Click += new System.EventHandler(this.btPath2_Click);
|
||||
//
|
||||
// SimulatorForm
|
||||
//
|
||||
this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 12F);
|
||||
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
|
||||
this.ClientSize = new System.Drawing.Size(1034, 711);
|
||||
this.ClientSize = new System.Drawing.Size(1248, 711);
|
||||
this.Controls.Add(this._canvasPanel);
|
||||
this.Controls.Add(this._agvInfoPanel);
|
||||
this.Controls.Add(this._controlPanel);
|
||||
@@ -901,7 +889,6 @@ namespace AGVSimulator.Forms
|
||||
private System.Windows.Forms.ComboBox _startNodeCombo;
|
||||
private System.Windows.Forms.Label targetNodeLabel;
|
||||
private System.Windows.Forms.ComboBox _targetNodeCombo;
|
||||
private System.Windows.Forms.Button btPath1;
|
||||
private System.Windows.Forms.Button _clearPathButton;
|
||||
private System.Windows.Forms.Button _targetCalcButton;
|
||||
private System.Windows.Forms.CheckBox _avoidRotationCheckBox;
|
||||
|
||||
@@ -422,8 +422,6 @@ namespace AGVSimulator.Forms
|
||||
var displayText = GetDisplayName(selectedNode.Id);
|
||||
_statusLabel.Text = $"타겟계산 - 목적지: {displayText}";
|
||||
|
||||
// 자동으로 경로 계산 수행
|
||||
OnCalculatePath_Click(this, EventArgs.Empty);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
@@ -1009,8 +1007,8 @@ namespace AGVSimulator.Forms
|
||||
_stopSimulationButton.Enabled = _simulationState.IsRunning;
|
||||
|
||||
_removeAgvButton.Enabled = _agvListCombo.SelectedItem != null;
|
||||
btPath1.Enabled = _startNodeCombo.SelectedItem != null &&
|
||||
_targetNodeCombo.SelectedItem != null;
|
||||
// btPath1.Enabled = _startNodeCombo.SelectedItem != null &&
|
||||
// _targetNodeCombo.SelectedItem != null;
|
||||
|
||||
// RFID 위치 설정 관련
|
||||
var hasSelectedAGV = _agvListCombo.SelectedItem != null;
|
||||
@@ -1577,7 +1575,7 @@ namespace AGVSimulator.Forms
|
||||
MotorDirection = directionName,
|
||||
CurrentPosition = GetNodeDisplayName(currentNode),
|
||||
TargetPosition = GetNodeDisplayName(targetNode),
|
||||
DockingPosition = targetNode.StationType == StationType.Charger ? "충전기" : "장비"
|
||||
DockingPosition = (targetNode.StationType == StationType.Charger1 || targetNode.StationType == StationType.Charger2) ? "충전기" : "장비"
|
||||
};
|
||||
|
||||
if (calcResult.result)
|
||||
@@ -1750,19 +1748,19 @@ namespace AGVSimulator.Forms
|
||||
SetTargetNodeComboBox(dockingTarget.Id);
|
||||
|
||||
// 경로 계산 버튼 클릭 (실제 사용자 동작)
|
||||
var calcResult = CalcPath();
|
||||
//var calcResult = CalcPath();
|
||||
|
||||
// 테스트 결과 생성
|
||||
testResult = CreateTestResultFromUI(nodeA, dockingTarget, directionName, calcResult);
|
||||
//// 테스트 결과 생성
|
||||
//testResult = CreateTestResultFromUI(nodeA, dockingTarget, directionName, calcResult);
|
||||
|
||||
// 로그 추가
|
||||
logForm.AddLogItem(testResult);
|
||||
//// 로그 추가
|
||||
//logForm.AddLogItem(testResult);
|
||||
|
||||
// 실패한 경우에만 경로를 화면에 표시 (시각적 확인)
|
||||
if (!testResult.Success && _simulatorCanvas.CurrentPath != null)
|
||||
{
|
||||
_simulatorCanvas.Invalidate();
|
||||
}
|
||||
//// 실패한 경우에만 경로를 화면에 표시 (시각적 확인)
|
||||
//if (!testResult.Success && _simulatorCanvas.CurrentPath != null)
|
||||
//{
|
||||
// _simulatorCanvas.Invalidate();
|
||||
//}
|
||||
|
||||
Application.DoEvents();
|
||||
});
|
||||
@@ -2414,94 +2412,94 @@ namespace AGVSimulator.Forms
|
||||
return hex.PadLeft(2, '0');
|
||||
}
|
||||
|
||||
(bool result, string message) CalcPath()
|
||||
{
|
||||
// 시작 RFID가 없으면 AGV 현재 위치로 설정
|
||||
if (_startNodeCombo.SelectedItem == null || _startNodeCombo.Text == "선택하세요")
|
||||
{
|
||||
SetStartNodeFromAGVPosition();
|
||||
}
|
||||
//(bool result, string message) CalcPath()
|
||||
//{
|
||||
// // 시작 RFID가 없으면 AGV 현재 위치로 설정
|
||||
// if (_startNodeCombo.SelectedItem == null || _startNodeCombo.Text == "선택하세요")
|
||||
// {
|
||||
// SetStartNodeFromAGVPosition();
|
||||
// }
|
||||
|
||||
if (_startNodeCombo.SelectedItem == null || _targetNodeCombo.SelectedItem == null)
|
||||
{
|
||||
return (false, "시작 RFID와 목표 RFID를 선택해주세요.");
|
||||
}
|
||||
// if (_startNodeCombo.SelectedItem == null || _targetNodeCombo.SelectedItem == null)
|
||||
// {
|
||||
// return (false, "시작 RFID와 목표 RFID를 선택해주세요.");
|
||||
// }
|
||||
|
||||
var startItem = _startNodeCombo.SelectedItem as ComboBoxItem<MapNode>;
|
||||
var targetItem = _targetNodeCombo.SelectedItem as ComboBoxItem<MapNode>;
|
||||
var startNode = startItem?.Value;
|
||||
var targetNode = targetItem?.Value;
|
||||
// var startItem = _startNodeCombo.SelectedItem as ComboBoxItem<MapNode>;
|
||||
// var targetItem = _targetNodeCombo.SelectedItem as ComboBoxItem<MapNode>;
|
||||
// var startNode = startItem?.Value;
|
||||
// var targetNode = targetItem?.Value;
|
||||
|
||||
if (startNode == null || targetNode == null)
|
||||
{
|
||||
return (false, "선택한 노드 정보가 올바르지 않습니다.");
|
||||
}
|
||||
// if (startNode == null || targetNode == null)
|
||||
// {
|
||||
// return (false, "선택한 노드 정보가 올바르지 않습니다.");
|
||||
// }
|
||||
|
||||
|
||||
if (_advancedPathfinder == null)
|
||||
{
|
||||
_advancedPathfinder = new AGVPathfinder(_simulatorCanvas.Nodes);
|
||||
}
|
||||
// if (_advancedPathfinder == null)
|
||||
// {
|
||||
// _advancedPathfinder = new AGVPathfinder(_simulatorCanvas.Nodes);
|
||||
// }
|
||||
|
||||
// 현재 AGV 방향 가져오기
|
||||
var selectedAGV = _agvListCombo.SelectedItem as VirtualAGV;
|
||||
if (selectedAGV == null)
|
||||
{
|
||||
return (false, "Virtual AGV 가 없습니다");
|
||||
}
|
||||
var currentDirection = selectedAGV.CurrentDirection;
|
||||
// // 현재 AGV 방향 가져오기
|
||||
// var selectedAGV = _agvListCombo.SelectedItem as VirtualAGV;
|
||||
// if (selectedAGV == null)
|
||||
// {
|
||||
// return (false, "Virtual AGV 가 없습니다");
|
||||
// }
|
||||
// var currentDirection = selectedAGV.CurrentDirection;
|
||||
|
||||
// AGV의 이전 위치에서 가장 가까운 노드 찾기
|
||||
var prevNode = selectedAGV.PrevNode;
|
||||
var prevDir = selectedAGV.PrevDirection;
|
||||
// // AGV의 이전 위치에서 가장 가까운 노드 찾기
|
||||
// var prevNode = selectedAGV.PrevNode;
|
||||
// var prevDir = selectedAGV.PrevDirection;
|
||||
|
||||
// 고급 경로 계획 사용 (노드 객체 직접 전달)
|
||||
var advancedResult = _advancedPathfinder.FindPath(startNode, targetNode, prevNode, prevDir, currentDirection);
|
||||
// // 고급 경로 계획 사용 (노드 객체 직접 전달)
|
||||
// var advancedResult = _advancedPathfinder.FindPath(startNode, targetNode, prevNode, prevDir, currentDirection);
|
||||
|
||||
_simulatorCanvas.FitToNodes();
|
||||
if (advancedResult.Success)
|
||||
{
|
||||
// 도킹 검증이 없는 경우 추가 검증 수행
|
||||
if (advancedResult.DockingValidation == null || !advancedResult.DockingValidation.IsValidationRequired)
|
||||
{
|
||||
advancedResult.DockingValidation = DockingValidator.ValidateDockingDirection(advancedResult, _simulatorCanvas.Nodes);
|
||||
}
|
||||
// _simulatorCanvas.FitToNodes();
|
||||
// if (advancedResult.Success)
|
||||
// {
|
||||
// // 도킹 검증이 없는 경우 추가 검증 수행
|
||||
// if (advancedResult.DockingValidation == null || !advancedResult.DockingValidation.IsValidationRequired)
|
||||
// {
|
||||
// advancedResult.DockingValidation = DockingValidator.ValidateDockingDirection(advancedResult, _simulatorCanvas.Nodes);
|
||||
// }
|
||||
|
||||
//마지막대상이 버퍼라면 시퀀스처리를 해야한다
|
||||
if (targetNode.StationType == StationType.Buffer)
|
||||
{
|
||||
var lastDetailPath = advancedResult.DetailedPath.Last();
|
||||
if (lastDetailPath.NodeId == targetNode.Id) //마지막노드 재확인
|
||||
{
|
||||
//버퍼에 도킹할때에는 마지막 노드에서 멈추고 시퀀스를 적용해야한다
|
||||
advancedResult.DetailedPath = advancedResult.DetailedPath.Take(advancedResult.DetailedPath.Count - 1).ToList();
|
||||
Console.WriteLine("최종위치가 버퍼이므로 마지막 RFID에서 멈추도록 합니다");
|
||||
}
|
||||
}
|
||||
// //마지막대상이 버퍼라면 시퀀스처리를 해야한다
|
||||
// if (targetNode.StationType == StationType.Buffer)
|
||||
// {
|
||||
// var lastDetailPath = advancedResult.DetailedPath.Last();
|
||||
// if (lastDetailPath.NodeId == targetNode.Id) //마지막노드 재확인
|
||||
// {
|
||||
// //버퍼에 도킹할때에는 마지막 노드에서 멈추고 시퀀스를 적용해야한다
|
||||
// advancedResult.DetailedPath = advancedResult.DetailedPath.Take(advancedResult.DetailedPath.Count - 1).ToList();
|
||||
// Console.WriteLine("최종위치가 버퍼이므로 마지막 RFID에서 멈추도록 합니다");
|
||||
// }
|
||||
// }
|
||||
|
||||
|
||||
_simulatorCanvas.CurrentPath = advancedResult;
|
||||
_pathLengthLabel.Text = $"경로 길이: {advancedResult.TotalDistance:F1}";
|
||||
_statusLabel.Text = $"경로 계산 완료 ({advancedResult.CalculationTimeMs}ms)";
|
||||
// _simulatorCanvas.CurrentPath = advancedResult;
|
||||
// _pathLengthLabel.Text = $"경로 길이: {advancedResult.TotalDistance:F1}";
|
||||
// _statusLabel.Text = $"경로 계산 완료 ({advancedResult.CalculationTimeMs}ms)";
|
||||
|
||||
// 🔥 VirtualAGV에도 경로 설정 (Predict()가 동작하려면 필요)
|
||||
selectedAGV.SetPath(advancedResult);
|
||||
// // 🔥 VirtualAGV에도 경로 설정 (Predict()가 동작하려면 필요)
|
||||
// selectedAGV.SetPath(advancedResult);
|
||||
|
||||
// 도킹 검증 결과 확인 및 UI 표시
|
||||
CheckAndDisplayDockingValidation(advancedResult);
|
||||
// // 도킹 검증 결과 확인 및 UI 표시
|
||||
// CheckAndDisplayDockingValidation(advancedResult);
|
||||
|
||||
// 고급 경로 디버깅 정보 표시
|
||||
UpdateAdvancedPathDebugInfo(advancedResult);
|
||||
return (true, string.Empty);
|
||||
}
|
||||
else
|
||||
{
|
||||
// 경로 실패시 디버깅 정보 초기화
|
||||
_pathDebugLabel.Text = $"경로: 실패 - {advancedResult.ErrorMessage}";
|
||||
// // 고급 경로 디버깅 정보 표시
|
||||
// UpdateAdvancedPathDebugInfo(advancedResult);
|
||||
// return (true, string.Empty);
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// // 경로 실패시 디버깅 정보 초기화
|
||||
// _pathDebugLabel.Text = $"경로: 실패 - {advancedResult.ErrorMessage}";
|
||||
|
||||
return (false, $"경로를 찾을 수 없습니다:\n{advancedResult.ErrorMessage}");
|
||||
}
|
||||
}
|
||||
// return (false, $"경로를 찾을 수 없습니다:\n{advancedResult.ErrorMessage}");
|
||||
// }
|
||||
//}
|
||||
#endregion
|
||||
|
||||
private void btPath2_Click(object sender, EventArgs e)
|
||||
@@ -2569,17 +2567,31 @@ namespace AGVSimulator.Forms
|
||||
_simulatorCanvas.HighlightNodeId = gatewayNode.Id; // Gateway 강조 설정
|
||||
|
||||
// 4. Start -> Gateway 경로 계산 (A*)
|
||||
var pathToGateway = _advancedPathfinder.FindPath(startNode, gatewayNode, prevNode, prevDir, currentAgvDir);
|
||||
var pathToGateway = _advancedPathfinder.FindBasicPath(startNode, gatewayNode, prevNode, prevDir);
|
||||
|
||||
if (!pathToGateway.Success) return (false, $"Gateway({gatewayNode.ID2})까지 경로 실패: {pathToGateway.ErrorMessage}");
|
||||
|
||||
// 5. Gateway -> Target 경로 계산 (회차 패턴 및 최종 진입 포함)
|
||||
var arrivalOrientation = pathToGateway.DetailedPath.Last().MotorDirection;
|
||||
AGVPathResult finalPath = pathToGateway;
|
||||
//마지막경로는 게이트웨이이므로 제거하낟.
|
||||
if(pathToGateway.Path.Count > 1)
|
||||
{
|
||||
pathToGateway.Path.RemoveAt(pathToGateway.Path.Count - 1);
|
||||
pathToGateway.DetailedPath.RemoveAt(pathToGateway.DetailedPath.Count - 1);
|
||||
}
|
||||
|
||||
var gatewayPathResult = GetPathFromGateway(gatewayNode, targetNode, pathToGateway.Path.Last(), arrivalOrientation);
|
||||
// 5. Gateway -> Target 경로 계산 (회차 패턴 및 최종 진입 포함)
|
||||
|
||||
|
||||
MapNode GateprevNode = pathToGateway.Path.Last();
|
||||
NodeMotorInfo GatePrevDetail = pathToGateway.DetailedPath.Last();
|
||||
|
||||
|
||||
var arrivalOrientation = GatePrevDetail.MotorDirection;
|
||||
|
||||
//아래코드오류발생함
|
||||
var gatewayPathResult = GetPathFromGateway(gatewayNode, targetNode, GateprevNode, arrivalOrientation);
|
||||
|
||||
if (!gatewayPathResult.Success) return (false, $"{gatewayPathResult.ErrorMessage}");
|
||||
AGVPathResult finalPath = pathToGateway;
|
||||
|
||||
finalPath = CombinePaths(finalPath, gatewayPathResult);
|
||||
|
||||
@@ -2617,59 +2629,57 @@ namespace AGVSimulator.Forms
|
||||
/// <summary>
|
||||
/// Gateway 도착 후, Target까지의 경로(회차 및 최종진입 포함)를 계산합니다.
|
||||
/// </summary>
|
||||
/// <param name="gatewayNode">게이트웨이 노드값</param>
|
||||
/// <param name="GTNode">게이트웨이 노드값(현재노드값)</param>
|
||||
/// <param name="targetNode">최종 목표값</param>
|
||||
/// <param name="GTprevNode">게이트웨이 진입 전 노드</param>
|
||||
/// <param name="GTprevDirection">게이트웨이 진입 전 모터방향</param>
|
||||
/// <param name="PrevNode">게이트웨이 진입 전 노드</param>
|
||||
/// <param name="PrevDirection">게이트웨이 진입 전 모터방향</param>
|
||||
/// <returns></returns>
|
||||
private AGVPathResult GetPathFromGateway(MapNode gatewayNode, MapNode targetNode, MapNode GTprevNode, AgvDirection GTprevDirection)
|
||||
private AGVPathResult GetPathFromGateway(MapNode GTNode, MapNode targetNode, MapNode PrevNode, AgvDirection PrevDirection)
|
||||
{
|
||||
AGVPathResult resultPath = null;
|
||||
|
||||
MapNode currentNode = gatewayNode;
|
||||
MapNode currentPrev = GTprevNode; // Gateway 바로 이전 노드 (방향 계산용)
|
||||
AgvDirection currentDir = GTprevDirection;
|
||||
|
||||
//게이트웨이 진입 한 방향을 보고. 목적지와 도킹방향이 일치하는지 결정한다.
|
||||
var deltaX = gatewayNode.Position.X - GTprevNode.Position.X;
|
||||
|
||||
var deltaX = GTNode.Position.X - PrevNode.Position.X;
|
||||
var isMonitorLeft = false;
|
||||
bool requiredDir = false;
|
||||
|
||||
switch (targetNode.StationType)
|
||||
{
|
||||
case StationType.Charger1:
|
||||
case StationType.UnLoader:
|
||||
case StationType.Clearner:
|
||||
case StationType.Buffer:
|
||||
|
||||
//버퍼는 게이트웨이가 6번이고 좌/우로 판단한다
|
||||
if (deltaX > 0) //게이트웨이가 더 오른쪽에있으니 좌->우 이동을 한경우이다. 이떄 모터방향이 후진이라면 모니터는 왼쪽이고, 반대는 오른쪽이다
|
||||
if (deltaX > 0) //게이트웨이가 우측에 있다
|
||||
{
|
||||
isMonitorLeft = GTprevDirection == AgvDirection.Backward;
|
||||
//이떄 모터방향이 후진이라면 모니터는 왼쪽이고, 반대는 오른쪽이다
|
||||
isMonitorLeft = PrevDirection == AgvDirection.Backward;
|
||||
}
|
||||
else
|
||||
{
|
||||
isMonitorLeft = GTprevDirection == AgvDirection.Forward;
|
||||
isMonitorLeft = PrevDirection == AgvDirection.Forward;
|
||||
}
|
||||
|
||||
//버퍼는 모니터가 왼쪽에 있으면 안된다.
|
||||
//충전기1만 전진 도킹을 한다.
|
||||
List<string> turnPatterns = new List<string>();
|
||||
AGVPathResult rlt1 = new AGVPathResult();
|
||||
rlt1.Success = true;
|
||||
|
||||
//목적지까지 바로 계산한다
|
||||
var pathtarget = _advancedPathfinder.FindBasicPath(gatewayNode, targetNode, GTprevNode, AgvDirection.Backward);
|
||||
var pathtarget = _advancedPathfinder.FindBasicPath(GTNode, targetNode, PrevNode, AgvDirection.Backward);
|
||||
|
||||
if (isMonitorLeft)
|
||||
if (targetNode.DockDirection == DockingDirection.Backward && isMonitorLeft)
|
||||
{
|
||||
//턴을 하는
|
||||
turnPatterns = GetTurnaroundPattern(gatewayNode, targetNode);
|
||||
if (turnPatterns == null || turnPatterns.Any() == false) return new AGVPathResult { Success = false, ErrorMessage = $"회차 패턴 없음: Dir {currentDir}" };
|
||||
turnPatterns = GetTurnaroundPattern(GTNode, targetNode);
|
||||
if (turnPatterns == null || turnPatterns.Any() == false) return new AGVPathResult { Success = false, ErrorMessage = $"회차 패턴 없음: Dir {PrevDirection}" };
|
||||
foreach (var item in turnPatterns)
|
||||
{
|
||||
var rfidvalue = ushort.Parse(item.Substring(0, 4));
|
||||
var node = _simulatorCanvas.Nodes.FirstOrDefault(t => t.RfidId == rfidvalue);
|
||||
|
||||
//경로노드추가
|
||||
rlt1.Path.Add(node);
|
||||
rlt1.Path.Add(node);
|
||||
|
||||
//Detail 정보도 추가한다.
|
||||
AgvDirection nodedir = item.Substring(4, 1) == "F" ? AgvDirection.Forward : AgvDirection.Backward;
|
||||
@@ -2685,7 +2695,7 @@ namespace AGVSimulator.Forms
|
||||
|
||||
//시작위치가 겹치므로 제거해줘야하낟.
|
||||
if (pathtarget.DetailedPath.First().NodeId != rlt1.DetailedPath.Last().NodeId ||
|
||||
pathtarget.DetailedPath.First().MotorDirection != rlt1.DetailedPath.Last().MotorDirection )
|
||||
pathtarget.DetailedPath.First().MotorDirection != rlt1.DetailedPath.Last().MotorDirection)
|
||||
{
|
||||
new AGVPathResult { Success = false, ErrorMessage = $"게이트웨이 턴 마지막 주소와, 이 후 주소의 시작 노드ID가 일치하지 않습니다" };
|
||||
}
|
||||
@@ -2817,7 +2827,7 @@ namespace AGVSimulator.Forms
|
||||
//게이트웨이까지 후진으로 이동했다면 모니터방향이 오른쪽이다 => 방향전환필요
|
||||
var gateToTarget = GetPathFromGateway(GateWayNode, target, lastPrev, lastDir);
|
||||
|
||||
escPath.Path.RemoveAt(escPath.Path.Count-1);
|
||||
escPath.Path.RemoveAt(escPath.Path.Count - 1);
|
||||
escPath.DetailedPath.RemoveAt(escPath.DetailedPath.Count - 1);
|
||||
|
||||
|
||||
@@ -2888,15 +2898,15 @@ namespace AGVSimulator.Forms
|
||||
var res = new AGVPathResult();
|
||||
res.Success = true;
|
||||
|
||||
foreach(var item in p1.Path)
|
||||
foreach (var item in p1.Path)
|
||||
{
|
||||
res.Path.Add(item);
|
||||
}
|
||||
foreach(var item in p2.Path)
|
||||
foreach (var item in p2.Path)
|
||||
{
|
||||
res.Path.Add(item);
|
||||
}
|
||||
|
||||
|
||||
foreach (var item in p1.DetailedPath)
|
||||
{
|
||||
var maxseq = res.DetailedPath.Count == 0 ? 0 : res.DetailedPath.Max(t => t.seq);
|
||||
@@ -2905,7 +2915,7 @@ namespace AGVSimulator.Forms
|
||||
}
|
||||
foreach (var item in p2.DetailedPath)
|
||||
{
|
||||
var maxseq = res.DetailedPath.Count == 0 ? 0 : res.DetailedPath.Max(t => t.seq);
|
||||
var maxseq = res.DetailedPath.Count == 0 ? 0 : res.DetailedPath.Max(t => t.seq);
|
||||
item.seq = maxseq + 1;
|
||||
res.DetailedPath.Add(item);
|
||||
}
|
||||
@@ -2922,13 +2932,6 @@ namespace AGVSimulator.Forms
|
||||
_simulatorCanvas.FitToNodes();
|
||||
}
|
||||
|
||||
private void OnCalculatePath_Click(object sender, EventArgs e)
|
||||
{
|
||||
var rlt = CalcPath();
|
||||
if (rlt.result == false) MessageBox.Show(rlt.message, "알림", MessageBoxButtons.OK, MessageBoxIcon.Information);
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user