시스템메세지, 정보메세지개념 추가
This commit is contained in:
@@ -104,6 +104,7 @@ namespace AGVNavigationCore.Controls
|
|||||||
{
|
{
|
||||||
g.DrawString(this.PredictMessage, this.Font, Brushes.White, 10, 100);
|
g.DrawString(this.PredictMessage, this.Font, Brushes.White, 10, 100);
|
||||||
}
|
}
|
||||||
|
DrawSystemMessage(g);
|
||||||
DrawAlertMessage(g);
|
DrawAlertMessage(g);
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -207,9 +208,9 @@ namespace AGVNavigationCore.Controls
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void DrawAlertMessage(Graphics g)
|
void DrawSystemMessage(Graphics g)
|
||||||
{
|
{
|
||||||
if (!showalert || String.IsNullOrEmpty(this._alertmesage)) return;
|
if (!showalertsystem || String.IsNullOrEmpty(this._systemmesage)) return;
|
||||||
|
|
||||||
// 상단 중앙에 반투명 빨간색 배경 바 표시
|
// 상단 중앙에 반투명 빨간색 배경 바 표시
|
||||||
int barHeight = 40;
|
int barHeight = 40;
|
||||||
@@ -239,13 +240,12 @@ namespace AGVNavigationCore.Controls
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 텍스트 깜박임 효과 (배경은 유지하고 텍스트만 깜박임)
|
// 텍스트 깜박임 효과 (배경은 유지하고 텍스트만 깜박임)
|
||||||
if (_isAlertBlinkOn)
|
|
||||||
{
|
|
||||||
using (var font = new Font("Malgun Gothic", 12, FontStyle.Bold))
|
using (var font = new Font("Malgun Gothic", 12, FontStyle.Bold))
|
||||||
using (var brush = new SolidBrush(Color.White))
|
using (var brush = new SolidBrush(Color.White))
|
||||||
{
|
{
|
||||||
var textSize = g.MeasureString(_alertmesage, font);
|
var textSize = g.MeasureString(_systemmesage, font);
|
||||||
g.DrawString(_alertmesage, font, brush,
|
g.DrawString(_systemmesage, font, brush,
|
||||||
barX + (barWidth - textSize.Width) / 2,
|
barX + (barWidth - textSize.Width) / 2,
|
||||||
barY + (barHeight - textSize.Height) / 2);
|
barY + (barHeight - textSize.Height) / 2);
|
||||||
}
|
}
|
||||||
@@ -259,9 +259,61 @@ namespace AGVNavigationCore.Controls
|
|||||||
g.FillEllipse(brush, iconX - 2, iconY - 8, 4, 16); // body
|
g.FillEllipse(brush, iconX - 2, iconY - 8, 4, 16); // body
|
||||||
g.FillEllipse(brush, iconX - 2, iconY + 10, 4, 4); // dot
|
g.FillEllipse(brush, iconX - 2, iconY + 10, 4, 4); // dot
|
||||||
}
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
void DrawAlertMessage(Graphics g)
|
||||||
|
{
|
||||||
|
if (!showinfo || String.IsNullOrEmpty(this._infomessage)) return;
|
||||||
|
|
||||||
|
// 상단 중앙에 반투명 빨간색 배경 바 표시
|
||||||
|
int barHeight = 40;
|
||||||
|
int barWidth = Math.Min(600, this.Width - 40); // 최대 600px, 좌우 여백 20px
|
||||||
|
int barX = (this.Width - barWidth) / 2;
|
||||||
|
int barY = 20+50;
|
||||||
|
|
||||||
|
// 둥근 사각형 배경
|
||||||
|
using (var path = new GraphicsPath())
|
||||||
|
{
|
||||||
|
int radius = 10;
|
||||||
|
path.AddArc(barX, barY, radius * 2, radius * 2, 180, 90);
|
||||||
|
path.AddArc(barX + barWidth - radius * 2, barY, radius * 2, radius * 2, 270, 90);
|
||||||
|
path.AddArc(barX + barWidth - radius * 2, barY + barHeight - radius * 2, radius * 2, radius * 2, 0, 90);
|
||||||
|
path.AddArc(barX, barY + barHeight - radius * 2, radius * 2, radius * 2, 90, 90);
|
||||||
|
path.CloseFigure();
|
||||||
|
|
||||||
|
using (var brush = new SolidBrush(Color.FromArgb(255, Color.Lime)))
|
||||||
|
{
|
||||||
|
g.FillPath(brush, path);
|
||||||
|
}
|
||||||
|
|
||||||
|
using (var pen = new Pen(Color.FromArgb(255, 255, 255), 2))
|
||||||
|
{
|
||||||
|
g.DrawPath(pen, path);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 텍스트 깜박임 효과 (배경은 유지하고 텍스트만 깜박임)
|
||||||
|
|
||||||
|
using (var font = new Font("Malgun Gothic", 12, FontStyle.Bold))
|
||||||
|
using (var brush = new SolidBrush(Color.Black))
|
||||||
|
{
|
||||||
|
var textSize = g.MeasureString(_infomessage, font);
|
||||||
|
g.DrawString(_infomessage, font, brush,
|
||||||
|
barX + (barWidth - textSize.Width) / 2,
|
||||||
|
barY + (barHeight - textSize.Height) / 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 경고 아이콘 그리기 (왼쪽)
|
||||||
|
// 간단한 느낌표 아이콘
|
||||||
|
int iconX = barX + 15;
|
||||||
|
int iconY = barY + barHeight / 2;
|
||||||
|
using (var brush = new SolidBrush(Color.Black))
|
||||||
|
{
|
||||||
|
g.FillEllipse(brush, iconX - 2, iconY - 8, 4, 16); // body
|
||||||
|
g.FillEllipse(brush, iconX - 2, iconY + 10, 4, 4); // dot
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
private void DrawSyncScreen(Graphics g)
|
private void DrawSyncScreen(Graphics g)
|
||||||
{
|
{
|
||||||
// 반투명 검은색 배경
|
// 반투명 검은색 배경
|
||||||
|
|||||||
@@ -138,47 +138,22 @@ namespace AGVNavigationCore.Controls
|
|||||||
private float _syncProgress = 0.0f;
|
private float _syncProgress = 0.0f;
|
||||||
private string _syncDetail = "";
|
private string _syncDetail = "";
|
||||||
|
|
||||||
string _alertmesage = "";
|
string _systemmesage = "";
|
||||||
bool showalert = false;
|
string _infomessage = "";
|
||||||
|
bool showalertsystem = false;
|
||||||
|
bool showinfo = false;
|
||||||
|
|
||||||
// 깜박임 효과를 위한 타이머 및 상태
|
public void SetInfoMessage(string m)
|
||||||
private Timer _alertBlinkTimer;
|
|
||||||
private bool _isAlertBlinkOn = true;
|
|
||||||
|
|
||||||
public void SetAlertMessage(string m)
|
|
||||||
{
|
{
|
||||||
_alertmesage = m;
|
_infomessage = m;
|
||||||
showalert = !string.IsNullOrEmpty(m);
|
showinfo = !string.IsNullOrEmpty(m);
|
||||||
|
|
||||||
//if (showalert)
|
|
||||||
//{
|
|
||||||
// if (_alertBlinkTimer == null)
|
|
||||||
// {
|
|
||||||
// _alertBlinkTimer = new Timer();
|
|
||||||
// _alertBlinkTimer.Interval = 500; // 0.5초 간격
|
|
||||||
// _alertBlinkTimer.Tick += _alertBlinkTimer_Tick;
|
|
||||||
// }
|
|
||||||
// _alertBlinkTimer.Start();
|
|
||||||
// _isAlertBlinkOn = true;
|
|
||||||
//}
|
|
||||||
//else
|
|
||||||
//{
|
|
||||||
// if (_alertBlinkTimer != null)
|
|
||||||
// {
|
|
||||||
// _alertBlinkTimer.Stop();
|
|
||||||
// }
|
|
||||||
// _isAlertBlinkOn = false;
|
|
||||||
//}
|
|
||||||
//Invalidate(); // 즉시 갱신
|
|
||||||
}
|
}
|
||||||
|
public void SetSystemMessage(string m)
|
||||||
private void _alertBlinkTimer_Tick(object sender, EventArgs e)
|
|
||||||
{
|
{
|
||||||
//_isAlertBlinkOn = !_isAlertBlinkOn;
|
_systemmesage = m;
|
||||||
//Invalidate();
|
showalertsystem = !string.IsNullOrEmpty(m);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// 브러쉬 및 펜
|
// 브러쉬 및 펜
|
||||||
private Brush _normalNodeBrush;
|
private Brush _normalNodeBrush;
|
||||||
private Brush _rotationNodeBrush;
|
private Brush _rotationNodeBrush;
|
||||||
@@ -963,13 +938,6 @@ namespace AGVNavigationCore.Controls
|
|||||||
// 이미지 정리
|
// 이미지 정리
|
||||||
_companyLogo?.Dispose();
|
_companyLogo?.Dispose();
|
||||||
|
|
||||||
// 타이머 정리
|
|
||||||
if (_alertBlinkTimer != null)
|
|
||||||
{
|
|
||||||
_alertBlinkTimer.Stop();
|
|
||||||
_alertBlinkTimer.Dispose();
|
|
||||||
_alertBlinkTimer = null;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
base.Dispose(disposing);
|
base.Dispose(disposing);
|
||||||
|
|||||||
@@ -75,6 +75,8 @@ namespace ENIGProtocol
|
|||||||
LIDAR_STOP,
|
LIDAR_STOP,
|
||||||
NOT_BUFFERPOINT,
|
NOT_BUFFERPOINT,
|
||||||
NOT_EQUIPMENTPOINT,
|
NOT_EQUIPMENTPOINT,
|
||||||
|
PATH_COMPLETE_INTEGRITY_FAIL,
|
||||||
|
UPDATEMOTION_TIMEOUT
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class AGVUtility
|
public static class AGVUtility
|
||||||
@@ -113,7 +115,9 @@ namespace ENIGProtocol
|
|||||||
case AGVErrorCode.CHARGE_RETRY_OVER: return $"충전명령 재전송 횟수 초과";
|
case AGVErrorCode.CHARGE_RETRY_OVER: return $"충전명령 재전송 횟수 초과";
|
||||||
case AGVErrorCode.NOT_BUFFERPOINT: return "현재 위치가 버퍼가 아닙니다";
|
case AGVErrorCode.NOT_BUFFERPOINT: return "현재 위치가 버퍼가 아닙니다";
|
||||||
case AGVErrorCode.NOT_EQUIPMENTPOINT: return "현재 위치가 장비 노드가 아닙니다";
|
case AGVErrorCode.NOT_EQUIPMENTPOINT: return "현재 위치가 장비 노드가 아닙니다";
|
||||||
|
case AGVErrorCode.PATH_COMPLETE_INTEGRITY_FAIL: return "목적지 도착 완료 했으나 노드 혹은 방향이 일치지하지 않습니다";
|
||||||
default: return ecode.ToString();
|
default: return ecode.ToString();
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -135,7 +135,7 @@ namespace Project
|
|||||||
//마지막위치가 아닌 다른 위치에 있으니 버퍼 작업을 할 수없다
|
//마지막위치가 아닌 다른 위치에 있으니 버퍼 작업을 할 수없다
|
||||||
PUB.XBE.StepMC = Device.eDocStep.NotSet;
|
PUB.XBE.StepMC = Device.eDocStep.NotSet;
|
||||||
PUB.log.AddE($"목적지가 버퍼이나 노드가 불일치 한다 오류사항");
|
PUB.log.AddE($"목적지가 버퍼이나 노드가 불일치 한다 오류사항");
|
||||||
PUB._mapCanvas.SetAlertMessage("목적지가 버퍼이나 노드 불일치 오류");
|
PUB._mapCanvas.SetInfoMessage("목적지가 버퍼이나 노드 불일치 오류");
|
||||||
PUB.sm.SetNewRunStep(ERunStep.ERROR);
|
PUB.sm.SetNewRunStep(ERunStep.ERROR);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -138,7 +138,7 @@ namespace Project
|
|||||||
PUB.AGV.AGVMoveLeft180Turn();
|
PUB.AGV.AGVMoveLeft180Turn();
|
||||||
PUB.log.Add($"[{funcname}-{PUB.sm.RunStepSeq}] AGV Left Turn");
|
PUB.log.Add($"[{funcname}-{PUB.sm.RunStepSeq}] AGV Left Turn");
|
||||||
VAR.TIME.Update(eVarTime.LastTurnCommandTime);
|
VAR.TIME.Update(eVarTime.LastTurnCommandTime);
|
||||||
PUB._mapCanvas.SetAlertMessage($"턴 실행");
|
PUB._mapCanvas.SetInfoMessage($"턴 실행");
|
||||||
}
|
}
|
||||||
PUB.sm.UpdateRunStepSeq();
|
PUB.sm.UpdateRunStepSeq();
|
||||||
return false;
|
return false;
|
||||||
@@ -166,7 +166,7 @@ namespace Project
|
|||||||
SetRunStepError(ENIGProtocol.AGVErrorCode.TURN_FAIL, $"[{funcname}] {overtime}초이내 턴 감지 안됨");
|
SetRunStepError(ENIGProtocol.AGVErrorCode.TURN_FAIL, $"[{funcname}] {overtime}초이내 턴 감지 안됨");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
else PUB._mapCanvas.SetAlertMessage($"턴 진행 중({PUB.AGV.TurnInformation.Runtime.TotalSeconds:N0}/{overtime})");
|
else PUB._mapCanvas.SetInfoMessage($"턴 진행 중({PUB.AGV.TurnInformation.Runtime.TotalSeconds:N0}/{overtime})");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
PUB._virtualAGV.Turn = AGVNavigationCore.Models.AGVTurn.L90; //턴완료
|
PUB._virtualAGV.Turn = AGVNavigationCore.Models.AGVTurn.L90; //턴완료
|
||||||
@@ -215,7 +215,7 @@ namespace Project
|
|||||||
VAR.I32[eVarInt32.RetryLift] = 0;
|
VAR.I32[eVarInt32.RetryLift] = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else PUB._mapCanvas.SetAlertMessage($"리프트 하강 확인 중({seqtime.TotalSeconds:N0}/20)");
|
else PUB._mapCanvas.SetInfoMessage($"리프트 하강 확인 중({seqtime.TotalSeconds:N0}/20)");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
VAR.I32[eVarInt32.RetryManget] = 0;
|
VAR.I32[eVarInt32.RetryManget] = 0;
|
||||||
@@ -294,7 +294,7 @@ namespace Project
|
|||||||
}
|
}
|
||||||
|
|
||||||
PUB.log.Add($"[{funcname}-{PUB.sm.RunStepSeq}] 도킹을 위해 후진 이동 시작 (Dir:Backward, Spd:Low)");
|
PUB.log.Add($"[{funcname}-{PUB.sm.RunStepSeq}] 도킹을 위해 후진 이동 시작 (Dir:Backward, Spd:Low)");
|
||||||
PUB._mapCanvas.SetAlertMessage($"도킹을 위해 후진 이동 시작");
|
PUB._mapCanvas.SetInfoMessage($"도킹을 위해 후진 이동 시작");
|
||||||
VAR.I32[eVarInt32.RetryMove] = 0;
|
VAR.I32[eVarInt32.RetryMove] = 0;
|
||||||
PUB.sm.UpdateRunStepSeq();
|
PUB.sm.UpdateRunStepSeq();
|
||||||
return false;
|
return false;
|
||||||
@@ -325,7 +325,7 @@ namespace Project
|
|||||||
VAR.I32[eVarInt32.RetryMove] = 0;
|
VAR.I32[eVarInt32.RetryMove] = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else PUB._mapCanvas.SetAlertMessage($"AGV이동 확인 중");
|
else PUB._mapCanvas.SetInfoMessage($"AGV이동 확인 중");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -342,7 +342,7 @@ namespace Project
|
|||||||
}
|
}
|
||||||
PUB.AGV.AGVMoveStop(funcname, arDev.Narumi.eStopOpt.MarkStop);
|
PUB.AGV.AGVMoveStop(funcname, arDev.Narumi.eStopOpt.MarkStop);
|
||||||
PUB.log.Add($"[{funcname}-{PUB.sm.RunStepSeq}] MarkStop 명령 전송 (도킹 위치 정렬)");
|
PUB.log.Add($"[{funcname}-{PUB.sm.RunStepSeq}] MarkStop 명령 전송 (도킹 위치 정렬)");
|
||||||
PUB._mapCanvas.SetAlertMessage($"도킹을 위해 후진 이동 시작");
|
PUB._mapCanvas.SetInfoMessage($"도킹을 위해 후진 이동 시작");
|
||||||
PUB.sm.UpdateRunStepSeq();
|
PUB.sm.UpdateRunStepSeq();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -288,7 +288,7 @@ namespace Project
|
|||||||
PUB.AGV.AGVMoveRight180Turn();
|
PUB.AGV.AGVMoveRight180Turn();
|
||||||
PUB.log.Add($"[{funcname}-{PUB.sm.RunStepSeq}] AGV Right Turn");
|
PUB.log.Add($"[{funcname}-{PUB.sm.RunStepSeq}] AGV Right Turn");
|
||||||
VAR.TIME.Update(eVarTime.LastTurnCommandTime);
|
VAR.TIME.Update(eVarTime.LastTurnCommandTime);
|
||||||
PUB._mapCanvas.SetAlertMessage($"턴 실행");
|
PUB._mapCanvas.SetInfoMessage($"턴 실행");
|
||||||
}
|
}
|
||||||
PUB.sm.UpdateRunStepSeq();
|
PUB.sm.UpdateRunStepSeq();
|
||||||
return false;
|
return false;
|
||||||
@@ -316,7 +316,7 @@ namespace Project
|
|||||||
SetRunStepError(ENIGProtocol.AGVErrorCode.TURN_FAIL, $"[{funcname}] {overtime}초이내 턴 감지 안됨");
|
SetRunStepError(ENIGProtocol.AGVErrorCode.TURN_FAIL, $"[{funcname}] {overtime}초이내 턴 감지 안됨");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
else PUB._mapCanvas.SetAlertMessage($"턴 진행 중({PUB.AGV.TurnInformation.Runtime.TotalSeconds:N0}/{overtime})");
|
else PUB._mapCanvas.SetInfoMessage($"턴 진행 중({PUB.AGV.TurnInformation.Runtime.TotalSeconds:N0}/{overtime})");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
PUB._virtualAGV.Turn = AGVNavigationCore.Models.AGVTurn.None; //턴완료
|
PUB._virtualAGV.Turn = AGVNavigationCore.Models.AGVTurn.None; //턴완료
|
||||||
|
|||||||
@@ -92,7 +92,7 @@ namespace Project
|
|||||||
VAR.I32[eVarInt32.RetryLift] = 0;
|
VAR.I32[eVarInt32.RetryLift] = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else PUB._mapCanvas.SetAlertMessage($"리프트 하강 확인 중({seqtime.TotalSeconds:N0}/20)");
|
else PUB._mapCanvas.SetInfoMessage($"리프트 하강 확인 중({seqtime.TotalSeconds:N0}/20)");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
VAR.I32[eVarInt32.RetryMoveset] = 0;
|
VAR.I32[eVarInt32.RetryMoveset] = 0;
|
||||||
@@ -138,7 +138,7 @@ namespace Project
|
|||||||
VAR.I32[eVarInt32.RetryMoveset] = 0;
|
VAR.I32[eVarInt32.RetryMoveset] = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else PUB._mapCanvas.SetAlertMessage($"이동설정 확인 중({seqtime.TotalSeconds:N0}/20)");
|
else PUB._mapCanvas.SetInfoMessage($"이동설정 확인 중({seqtime.TotalSeconds:N0}/20)");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
VAR.I32[eVarInt32.RetryMove] = 0;
|
VAR.I32[eVarInt32.RetryMove] = 0;
|
||||||
@@ -173,7 +173,7 @@ namespace Project
|
|||||||
VAR.I32[eVarInt32.RetryMove] = 0;
|
VAR.I32[eVarInt32.RetryMove] = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else PUB._mapCanvas.SetAlertMessage($"AGV RUN 확인 중({seqtime.TotalSeconds:N0}/20)");
|
else PUB._mapCanvas.SetInfoMessage($"AGV RUN 확인 중({seqtime.TotalSeconds:N0}/20)");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -209,7 +209,7 @@ namespace Project
|
|||||||
VAR.I32[eVarInt32.RetryMarkStop] = 0;
|
VAR.I32[eVarInt32.RetryMarkStop] = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else PUB._mapCanvas.SetAlertMessage($"리프트 하강 확인 중({seqtime.TotalSeconds:N0}/20)");
|
else PUB._mapCanvas.SetInfoMessage($"리프트 하강 확인 중({seqtime.TotalSeconds:N0}/20)");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
PUB.sm.UpdateRunStepSeq();
|
PUB.sm.UpdateRunStepSeq();
|
||||||
|
|||||||
@@ -103,11 +103,18 @@ namespace Project
|
|||||||
PUB.AGV.AGVMoveStop(funcname);
|
PUB.AGV.AGVMoveStop(funcname);
|
||||||
PUB.sm.UpdateRunStepSeq();
|
PUB.sm.UpdateRunStepSeq();
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (seqtime.TotalMinutes > 10)
|
||||||
|
{
|
||||||
|
//ACS에 이동 관련 타임아웃 오류를 보낸다
|
||||||
|
SetRunStepError(ENIGProtocol.AGVErrorCode.UPDATEMOTION_TIMEOUT, $"[{funcname}-{PUB.sm.RunStepSeq}] (UpdateMotionPositionForMark)이 완료되지 않습니다");
|
||||||
|
}
|
||||||
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
else if (PUB.sm.RunStepSeq == idx++)
|
else if (PUB.sm.RunStepSeq == idx++)
|
||||||
{
|
{
|
||||||
//QC까지 모두 완료되었다.(완전히 정차할때까지 기다린다)
|
|
||||||
PUB.log.Add($"[GOTO] Step {idx - 1}: Movement Finished. Waiting for full stop.");
|
PUB.log.Add($"[GOTO] Step {idx - 1}: Movement Finished. Waiting for full stop.");
|
||||||
PUB.Speak(Lang.이동완료, true);
|
PUB.Speak(Lang.이동완료, true);
|
||||||
PUB.AddEEDB($"이동완료({PUB._virtualAGV.TargetNode.ID2})");
|
PUB.AddEEDB($"이동완료({PUB._virtualAGV.TargetNode.ID2})");
|
||||||
|
|||||||
@@ -85,7 +85,7 @@ namespace Project
|
|||||||
|
|
||||||
PUB.AGV.AGVMoveStop(errmsg);
|
PUB.AGV.AGVMoveStop(errmsg);
|
||||||
PUB.log.AddE(errmsg);
|
PUB.log.AddE(errmsg);
|
||||||
PUB._mapCanvas.SetAlertMessage(errmsg);
|
PUB._mapCanvas.SetInfoMessage(errmsg);
|
||||||
PUB.Result.RunStepErrorCode = ecode;
|
PUB.Result.RunStepErrorCode = ecode;
|
||||||
PUB.sm.SetNewRunStep(ERunStep.ERROR);
|
PUB.sm.SetNewRunStep(ERunStep.ERROR);
|
||||||
}
|
}
|
||||||
@@ -195,6 +195,8 @@ namespace Project
|
|||||||
else VAR.I32[eVarInt32.PathValidationError] = 0;
|
else VAR.I32[eVarInt32.PathValidationError] = 0;
|
||||||
|
|
||||||
//현재위치 기준으로 재 계산하여. 더 최적화된 루트가 있다면 처리를 해준다.
|
//현재위치 기준으로 재 계산하여. 더 최적화된 루트가 있다면 처리를 해준다.
|
||||||
|
/*
|
||||||
|
//TODO: 이제 경로가 하드코딩되어있으니 자동 갱신은 사용하지 않는다.
|
||||||
if (PUB._virtualAGV.CurrentPath.DetailedPath.Count > 5)
|
if (PUB._virtualAGV.CurrentPath.DetailedPath.Count > 5)
|
||||||
{
|
{
|
||||||
var PathResult2 = CalcPath(PUB._virtualAGV.CurrentNode, PUB._virtualAGV.TargetNode);
|
var PathResult2 = CalcPath(PUB._virtualAGV.CurrentNode, PUB._virtualAGV.TargetNode);
|
||||||
@@ -213,6 +215,7 @@ namespace Project
|
|||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
//predict 를 이용하여 다음 이동을 모두 확인한다.
|
//predict 를 이용하여 다음 이동을 모두 확인한다.
|
||||||
var nextAction = PUB._virtualAGV.Predict();
|
var nextAction = PUB._virtualAGV.Predict();
|
||||||
@@ -234,20 +237,21 @@ namespace Project
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Moveforce = false;
|
//마크스탑을 해야하는데 움직이지 않는다면 움직이도록 해야한다
|
||||||
if (nextAction.Motor == MotorCommand.Stop && nextAction.Reason == eAGVCommandReason.MarkStop)
|
if (nextAction.Motor == MotorCommand.Stop && nextAction.Reason == eAGVCommandReason.MarkStop)
|
||||||
{
|
{
|
||||||
//마크스탑을 해야하는데 움직이지 않는다면 움직이도록 해야한다
|
|
||||||
if (PUB.AGV.system1.agv_run == false)
|
if (PUB.AGV.system1.agv_run == false)
|
||||||
{
|
{
|
||||||
PUB.log.Add("마크스탑을 해야하는데 중지상태라서 강제 이동하도록 합니다");
|
PUB.log.Add("마크스탑을 해야하는데 중지상태라서 강제 이동하도록 합니다");
|
||||||
Moveforce = true;
|
PUB.AGV.AGVMoveRun();
|
||||||
|
VAR.TIME[eVarTime.LastMarkStopCommandTime] = DateTime.Now.AddDays(-1);
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//모터에서 정지를 요청했다
|
//모터에서 정지를 요청했다
|
||||||
if (Moveforce == false && nextAction.Motor == AGVNavigationCore.Models.MotorCommand.Stop)
|
if (nextAction.Motor == AGVNavigationCore.Models.MotorCommand.Stop)
|
||||||
{
|
{
|
||||||
if (PUB.AGV.system1.agv_run)
|
if (PUB.AGV.system1.agv_run)
|
||||||
{
|
{
|
||||||
@@ -256,34 +260,26 @@ namespace Project
|
|||||||
{
|
{
|
||||||
if (PUB.AGV.data.Speed != 'S')
|
if (PUB.AGV.data.Speed != 'S')
|
||||||
{
|
{
|
||||||
// [쿨타임 적용] 정지 명령은 별도의 타이머(LastStopCommandTime)를 사용하여
|
//2초간격으로 명령을 전송한다
|
||||||
// 이동 직후라도 즉시 반응할 수 있도록 한다. (이미 정지신호를 보냈다면 2초 대기)
|
var tsCmd = VAR.TIME.RUN(eVarTime.LastMarkStopCommandTime);
|
||||||
var tsCmd = VAR.TIME.RUN(eVarTime.LastStopCommandTime);
|
|
||||||
if (tsCmd.TotalSeconds >= 2.0)
|
if (tsCmd.TotalSeconds >= 2.0)
|
||||||
{
|
{
|
||||||
PUB.log.Add("다음행동예측에서 MARK STOP이 확인되었습니다 (자동정지시퀀스)");
|
PUB.log.Add("다음행동예측에서 MARK-STOP이 확인되었습니다 (자동정지시퀀스)");
|
||||||
PUB.AGV.AGVMoveStop(nextAction.Message, arDev.Narumi.eStopOpt.MarkStop);
|
PUB.AGV.AGVMoveStop(nextAction.Message, arDev.Narumi.eStopOpt.MarkStop);
|
||||||
|
VAR.TIME.Update(eVarTime.LastMarkStopCommandTime);
|
||||||
// 정지 타이머 갱신 (연속 정지 방지)
|
|
||||||
VAR.TIME.Update(eVarTime.LastStopCommandTime);
|
|
||||||
// 일반 타이머도 갱신 (정지 직후 불필요한 이동 방지)
|
|
||||||
LastCommandTime = DateTime.Now;
|
LastCommandTime = DateTime.Now;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// [쿨타임 적용] 정지 명령은 별도의 타이머(LastStopCommandTime)를 사용하여
|
//마크스탑이 아니므로 바로 멈춰야한다
|
||||||
// 이동 직후라도 즉시 반응할 수 있도록 한다. (이미 정지신호를 보냈다면 2초 대기)
|
|
||||||
var tsCmd = VAR.TIME.RUN(eVarTime.LastStopCommandTime);
|
var tsCmd = VAR.TIME.RUN(eVarTime.LastStopCommandTime);
|
||||||
if (tsCmd.TotalSeconds >= 2.0)
|
if (tsCmd.TotalSeconds >= 2.0)
|
||||||
{
|
{
|
||||||
PUB.log.Add($"다음행동예측에서 장비 멈춤이 확인되었습니다({nextAction.Reason})");
|
PUB.log.Add($"다음행동예측에서 멈춤이 확인되었습니다({nextAction.Reason})");
|
||||||
PUB.AGV.AGVMoveStop(nextAction.Message);
|
PUB.AGV.AGVMoveStop(nextAction.Message);
|
||||||
// 정지 타이머 갱신 (연속 정지 방지)
|
|
||||||
VAR.TIME.Update(eVarTime.LastStopCommandTime);
|
VAR.TIME.Update(eVarTime.LastStopCommandTime);
|
||||||
|
|
||||||
// 일반 타이머도 갱신 (정지 직후 불필요한 이동 방지)
|
|
||||||
LastCommandTime = DateTime.Now;
|
LastCommandTime = DateTime.Now;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -292,6 +288,7 @@ namespace Project
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//여기시점에서는 장비는 멈춘 상태이다
|
||||||
if (nextAction.Reason == eAGVCommandReason.Complete)
|
if (nextAction.Reason == eAGVCommandReason.Complete)
|
||||||
{
|
{
|
||||||
// 목적지 도착 여부 확인
|
// 목적지 도착 여부 확인
|
||||||
@@ -299,20 +296,17 @@ namespace Project
|
|||||||
{
|
{
|
||||||
if (PUB._virtualAGV.TargetNode.StationType != StationType.Normal)
|
if (PUB._virtualAGV.TargetNode.StationType != StationType.Normal)
|
||||||
{
|
{
|
||||||
PUB.log.AddAT($"목표도착되었으나 마크센서가 감지되지 않아 완료처리 하지않습니다");
|
PUB.log.AddAT($"목표({PUB._virtualAGV.TargetNode.RfidId})도착되었으나 마크센서가 감지되지 않아 완료처리 하지않습니다");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
//일반노드가목표인경우에는 완료처리한다.
|
PUB.log.AddI($"일반노드({PUB._virtualAGV.TargetNode.RfidId})는 마크센서가 감지되지 않아도 완료처리 합니다");
|
||||||
PUB.log.AddI($"일반노드는 마크센서가 감지되지 않아도 완료처리 합니다");
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 경로가 존재한다면...
|
//완료되었고 마크센서가 확인된 상태이다
|
||||||
if (PUB._virtualAGV.CurrentPath != null && PUB._virtualAGV.CurrentPath.DetailedPath.Any())
|
|
||||||
{
|
|
||||||
var lastInfo = PUB._virtualAGV.CurrentPath.DetailedPath.Last();
|
var lastInfo = PUB._virtualAGV.CurrentPath.DetailedPath.Last();
|
||||||
|
|
||||||
// 위치와 방향이 모두 일치해야 완료된 것으로 본다.
|
// 위치와 방향이 모두 일치해야 완료된 것으로 본다.
|
||||||
@@ -326,29 +320,17 @@ namespace Project
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// [DEBUG] 도착했으나 조건 불일치, 그러면.. predict 가 stop을 반환하면 안된다.
|
var errmsg = $"[도착오류] 목적지 정보 불일치. CurNode:{PUB._virtualAGV.CurrentNode.Id}, Target:{lastInfo.NodeId}, CurDir:{PUB._virtualAGV.CurrentDirection}, TargetDir:{lastInfo.MotorDirection}";
|
||||||
PUB.log.Add($"[DEBUG] Arrived but condition mismatch. CurNode:{PUB._virtualAGV.CurrentNode.Id}, Target:{lastInfo.NodeId}, CurDir:{PUB._virtualAGV.CurrentDirection}, TargetDir:{lastInfo.MotorDirection}");
|
SetRunStepError(ENIGProtocol.AGVErrorCode.PATH_COMPLETE_INTEGRITY_FAIL, errmsg);
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
// ...
|
|
||||||
if (PUB._virtualAGV.CurrentNode.Id == PUB._virtualAGV.TargetNode.Id)
|
|
||||||
{
|
|
||||||
// ...
|
|
||||||
PUB.log.AddI($"목표 도착 및 정지 확인됨(MarkStop 완료, No Path Info) Node:...");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// 이동 명령 변환 (AGVNavigationCore -> arDev.Narumi)
|
//PREDICT에서 이동을 명령했따
|
||||||
var bunki = arDev.Narumi.eBunki.Strate;
|
var bunki = arDev.Narumi.eBunki.Strate;
|
||||||
if (nextAction.Magnet == AGVNavigationCore.Models.MagnetPosition.L) bunki = arDev.Narumi.eBunki.Left;
|
if (nextAction.Magnet == AGVNavigationCore.Models.MagnetPosition.L) bunki = arDev.Narumi.eBunki.Left;
|
||||||
else if (nextAction.Magnet == AGVNavigationCore.Models.MagnetPosition.R) bunki = arDev.Narumi.eBunki.Right;
|
else if (nextAction.Magnet == AGVNavigationCore.Models.MagnetPosition.R) bunki = arDev.Narumi.eBunki.Right;
|
||||||
@@ -360,19 +342,24 @@ namespace Project
|
|||||||
if (nextAction.Speed == AGVNavigationCore.Models.SpeedLevel.M) spd = arDev.Narumi.eMoveSpd.Mid;
|
if (nextAction.Speed == AGVNavigationCore.Models.SpeedLevel.M) spd = arDev.Narumi.eMoveSpd.Mid;
|
||||||
else if (nextAction.Speed == AGVNavigationCore.Models.SpeedLevel.H) spd = arDev.Narumi.eMoveSpd.High;
|
else if (nextAction.Speed == AGVNavigationCore.Models.SpeedLevel.H) spd = arDev.Narumi.eMoveSpd.High;
|
||||||
|
|
||||||
// 방향 전환 시 정지 로직 추가
|
var char_bunki = bunki.ToString()[0];
|
||||||
// 이동 중인데 방향이 다르면 먼저 정지시킨다.
|
var char_speed = spd.ToString()[0];
|
||||||
|
var char_dir = dir.ToString()[0];
|
||||||
|
|
||||||
|
|
||||||
|
// 방향 전환 시 정지 로직 추가 ( 이동 중인데 방향이 다르면 먼저 정지시킨다.)
|
||||||
if (PUB.AGV.system1.agv_run)
|
if (PUB.AGV.system1.agv_run)
|
||||||
{
|
{
|
||||||
if (PUB.AGV.data.Direction != dir.ToString()[0])
|
if ((PUB.AGV.data.Direction == 'F' && dir == arDev.Narumi.eMoveDir.Backward) ||
|
||||||
|
(PUB.AGV.data.Direction == 'B' && dir == arDev.Narumi.eMoveDir.Forward))
|
||||||
{
|
{
|
||||||
// 2초 쿨타임 (정지 명령도 빈번한 전송 방지)
|
var tsCmd = VAR.TIME.RUN(eVarTime.LastStopCommandTime);
|
||||||
var tsCmd = DateTime.Now - LastCommandTime;
|
|
||||||
if (tsCmd.TotalSeconds >= 2.0)
|
if (tsCmd.TotalSeconds >= 2.0)
|
||||||
{
|
{
|
||||||
PUB.log.Add($"방향 전환을 위해 정지 명령을 전송합니다 Current:{PUB.AGV.data.Direction} Target:{dir}");
|
var msg = "$[predict] Direction Change({ PUB.AGV.data.Direction} → { dir})";
|
||||||
PUB.AGV.AGVMoveStop("Direction Change");
|
PUB.log.Add(msg);
|
||||||
LastCommandTime = DateTime.Now;
|
PUB.AGV.AGVMoveStop(msg);
|
||||||
|
VAR.TIME[eVarTime.LastStopCommandTime] = DateTime.Now;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -380,44 +367,59 @@ namespace Project
|
|||||||
|
|
||||||
// 명령 설정
|
// 명령 설정
|
||||||
// 현재 상태와 다를 때만 전송 (불필요한 통신 부하 방지)
|
// 현재 상태와 다를 때만 전송 (불필요한 통신 부하 방지)
|
||||||
if (PUB.AGV.data.Sts != bunki.ToString()[0] ||
|
if (PUB.AGV.data.Sts != char_bunki ||
|
||||||
PUB.AGV.data.Direction != dir.ToString()[0] ||
|
PUB.AGV.data.Direction != char_dir ||
|
||||||
PUB.AGV.data.Speed != spd.ToString()[0] ||
|
PUB.AGV.data.Speed != char_speed ||
|
||||||
PUB.AGV.PBSSensor != arDev.eNarmiPBSSensor.on)
|
PUB.AGV.PBSSensor != arDev.eNarmiPBSSensor.on)
|
||||||
{
|
{
|
||||||
// 2초 쿨타임 적용
|
// 2초 쿨타임 적용
|
||||||
var tsCmd = DateTime.Now - LastCommandTime;
|
var tsCmd = VAR.TIME.RUN(eVarTime.LastMoveSetCommandTime);// DateTime.Now - VAR.TIME;
|
||||||
if (tsCmd.TotalSeconds >= 2.0)
|
if (tsCmd.TotalSeconds >= 2.0)
|
||||||
{
|
{
|
||||||
var ret = PUB.AGV.AGVMoveSet(new arDev.Narumi.BunkiData
|
var mp = new arDev.Narumi.BunkiData
|
||||||
{
|
{
|
||||||
Bunki = bunki,
|
Bunki = bunki,
|
||||||
Direction = dir,
|
Direction = dir,
|
||||||
PBSSensor = 2,
|
PBSSensor = 2,
|
||||||
Speed = spd,
|
Speed = spd,
|
||||||
});
|
};
|
||||||
|
var ret = PUB.AGV.AGVMoveSet(mp);
|
||||||
|
|
||||||
|
var msg = $"Predict Move Setting = bunki:{mp.Bunki},dir:{mp.Direction},pbs:1,spd:{mp.Speed}";
|
||||||
if (ret == arDev.eNarumiCommandResult.Success)
|
if (ret == arDev.eNarumiCommandResult.Success)
|
||||||
PUB.log.Add($"Predict Run Setting = bunki:{bunki},dir:{dir},pbs:1,spd:{spd}");
|
PUB.log.Add(msg);
|
||||||
else
|
else
|
||||||
PUB.log.AddE($"Predict Run Setting = bunki:{bunki},dir:{dir},pbs:1,spd:{spd}");
|
PUB.log.AddE(msg);
|
||||||
|
|
||||||
LastCommandTime = DateTime.Now;
|
VAR.TIME[eVarTime.LastMoveSetCommandTime] = DateTime.Now;
|
||||||
}
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// AGV가 정지 상태라면 구동 시작 (라이다가켜져있을때에만 사용한다)
|
// AGV가 정지 상태라면 구동 시작 (라이다가켜져있을때에만 사용한다)
|
||||||
if (PUB.AGV.system1.agv_run == false && PUB.AGV.PBSSensor == arDev.eNarmiPBSSensor.on)
|
if (PUB.AGV.system1.agv_run == false )
|
||||||
|
{
|
||||||
|
if(PUB.AGV.PBSSensor == arDev.eNarmiPBSSensor.on)
|
||||||
{
|
{
|
||||||
// 2초 쿨타임 적용 (AGVMoveSet과 동일한 타이머 사용)
|
// 2초 쿨타임 적용 (AGVMoveSet과 동일한 타이머 사용)
|
||||||
var tsCmd = DateTime.Now - LastCommandTime;
|
var tsCmd = VAR.TIME.RUN(eVarTime.LastRunCommandTime);// DateTime.Now - LastCommandTime;
|
||||||
if (tsCmd.TotalSeconds >= 2.0)
|
if (tsCmd.TotalSeconds >= 2.0)
|
||||||
{
|
{
|
||||||
|
var msg = $"[PREDICT] Run AGV Dir:{dir}";
|
||||||
|
PUB.log.Add(msg);
|
||||||
var runOpt = (dir == arDev.Narumi.eMoveDir.Forward) ? arDev.Narumi.eRunOpt.Forward : arDev.Narumi.eRunOpt.Backward;
|
var runOpt = (dir == arDev.Narumi.eMoveDir.Forward) ? arDev.Narumi.eRunOpt.Forward : arDev.Narumi.eRunOpt.Backward;
|
||||||
PUB.AGV.AGVMoveRun(runOpt);
|
PUB.AGV.AGVMoveRun(runOpt);
|
||||||
LastCommandTime = DateTime.Now;
|
VAR.TIME[eVarTime.LastRunCommandTime] = DateTime.Now;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
PUB._mapCanvas.SetInfoMessage("AGV가동이 필요하나 PBS가 OFF되어있습니다");
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -281,9 +281,7 @@ namespace Project.ViewForm
|
|||||||
errmsg = "자동모드가 아닙니다";
|
errmsg = "자동모드가 아닙니다";
|
||||||
}
|
}
|
||||||
|
|
||||||
PUB._mapCanvas.SetAlertMessage(errmsg);
|
PUB._mapCanvas.SetSystemMessage(errmsg);
|
||||||
|
|
||||||
|
|
||||||
tmrun = false;
|
tmrun = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -519,7 +519,7 @@ namespace Project
|
|||||||
PUB.Speak(Lang.자동전환, addlog: false);
|
PUB.Speak(Lang.자동전환, addlog: false);
|
||||||
|
|
||||||
PUB.log.Add($"자동전환 이전스텝:{PUB.sm.RunStep},IDX:{PUB.sm.RunStepSeq}]");
|
PUB.log.Add($"자동전환 이전스텝:{PUB.sm.RunStep},IDX:{PUB.sm.RunStepSeq}]");
|
||||||
PUB._mapCanvas.SetAlertMessage("START");
|
PUB._mapCanvas.SetInfoMessage($"START ({DateTime.Now.ToShortTimeString()})");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -230,5 +230,10 @@ namespace COMM
|
|||||||
/// 마지막을 실행 명령을 전송한 시간
|
/// 마지막을 실행 명령을 전송한 시간
|
||||||
/// </summary>
|
/// </summary>
|
||||||
LastRunCommandTime,
|
LastRunCommandTime,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 이동명령 설정 시간
|
||||||
|
/// </summary>
|
||||||
|
LastMoveSetCommandTime,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user