..
This commit is contained in:
@@ -52,6 +52,7 @@ namespace Project
|
||||
VAR.TIME.Update(eVarTime.ReadyStart);
|
||||
else
|
||||
VAR.TIME.Update(eVarTime.RunStart);
|
||||
VAR.I32[eVarInt32.PathValidationError] = 0;
|
||||
}
|
||||
|
||||
//자동모드에서 대기상태 (추가동작없음)
|
||||
@@ -90,7 +91,12 @@ namespace Project
|
||||
}
|
||||
|
||||
//현재위치를 모르는 상태라면 이동하여 현재 위치를 찾는다
|
||||
if (_SM_RUN_POSCHK(isFirst, stepTime) == false) return;
|
||||
if (_SM_RUN_POSCHK(isFirst, stepTime) == false)
|
||||
{
|
||||
PUB.Result.result_message = "현재 위치 확인 중";
|
||||
PUB.Result.result_progressmax = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
//나머지 상황체크
|
||||
switch (PUB.sm.RunStep)
|
||||
@@ -109,33 +115,46 @@ namespace Project
|
||||
var target = PUB._virtualAGV.TargetNode;
|
||||
PUB.log.Add($"목적지({target.RfidId}) 도착완료 타입:{target.Type}, 출발지:{PUB._virtualAGV.StartNode.RfidId}");
|
||||
|
||||
PUB.XBE.StepLoader = Device.eDocStep.NotSet;
|
||||
PUB.XBE.StepCleaner = Device.eDocStep.NotSet;
|
||||
PUB.XBE.StepUnloader = Device.eDocStep.NotSet;
|
||||
PUB.XBE.StepBuffer = Device.eDocStep.NotSet;
|
||||
|
||||
switch (target.StationType)
|
||||
{
|
||||
case AGVNavigationCore.Models.StationType.Buffer:
|
||||
//현재위치가 마지막경로의 NODEID와 일치해야한다
|
||||
if (PUB._virtualAGV.CurrentPath == null)
|
||||
{
|
||||
PUB.log.AddAT("목적지 버퍼이동완료 했지만 상세경로가 없습니다");
|
||||
PUB.XBE.BufferInComplete = false;
|
||||
PUB.XBE.BufferOutComplete = false;
|
||||
break;
|
||||
}
|
||||
var lastPath = PUB._virtualAGV.CurrentPath.DetailedPath.LastOrDefault();
|
||||
if (lastPath.NodeId.Equals(PUB._virtualAGV.CurrentNode.Id))
|
||||
{
|
||||
//버퍼진입전 노드에 도착완료했따
|
||||
PUB.XBE.BufferInReady = true;
|
||||
PUB.XBE.BufferReadyError = false;
|
||||
PUB.XBE.StepBuffer = Device.eDocStep.InReady;
|
||||
}
|
||||
else
|
||||
{
|
||||
//마지막위치가 아닌 다른 위치에 있으니 버퍼 작업을 할 수없다
|
||||
PUB.log.AddAT("목적지 버퍼이동완료 했지만 마지막 노드가 아닙니다");
|
||||
PUB.XBE.BufferInReady = false;
|
||||
PUB.XBE.BufferReadyError = true;
|
||||
PUB.XBE.StepBuffer = Device.eDocStep.NotSet;
|
||||
PUB.log.AddE($"목적지가 버퍼이나 노드가 불일치 한다 오류사항");
|
||||
PUB.sm.SetNewRunStep(ERunStep.ERROR);
|
||||
}
|
||||
PUB.XBE.BufferInComplete = false;
|
||||
PUB.XBE.BufferOutComplete = false;
|
||||
break;
|
||||
case AGVNavigationCore.Models.StationType.Charger:
|
||||
|
||||
break;
|
||||
|
||||
case AGVNavigationCore.Models.StationType.Loader:
|
||||
PUB.XBE.StepLoader = Device.eDocStep.InReady;
|
||||
break;
|
||||
|
||||
case AGVNavigationCore.Models.StationType.Clearner:
|
||||
PUB.XBE.StepCleaner = Device.eDocStep.InReady;
|
||||
break;
|
||||
|
||||
case AGVNavigationCore.Models.StationType.UnLoader:
|
||||
PUB.XBE.StepUnloader = Device.eDocStep.InReady;
|
||||
break;
|
||||
|
||||
default:
|
||||
PUB.log.Add($"정의되지 않은 스테이션 입니다({target.StationType}) ");
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -144,7 +163,7 @@ namespace Project
|
||||
}
|
||||
break;
|
||||
|
||||
case ERunStep.MARKSTOPB: //후진방향으로 마크스탑
|
||||
case ERunStep.MARKSTOPB: //후진방향으로 마크스탑
|
||||
case ERunStep.MARKSTOPF: //전진방향으로 마크스탑
|
||||
|
||||
//이동중이지 않다면 먼저 이동을 진행한다
|
||||
@@ -169,10 +188,6 @@ namespace Project
|
||||
}
|
||||
else if (_SM_RUN_GOCHARGE(runStepisFirst, PUB.sm.GetRunSteptime))
|
||||
{
|
||||
//230601
|
||||
//if (PUB.Result != null && PUB.sm != null)
|
||||
// EEMStatus.AddEEDBSQL(PUB.sm.Step, PUB.sm.RunStep.ToString(), PUB.Result.TargetPos.ToString());
|
||||
|
||||
PUB.Speak(Lang.충전을시작합니다);
|
||||
PUB.sm.SetNewRunStep(ERunStep.CHARGECHECK);
|
||||
return;
|
||||
@@ -207,16 +222,7 @@ namespace Project
|
||||
//충전상태가 활성화되었으므로 대기상태로 전환한다
|
||||
PUB.sm.ClearRunStep();
|
||||
|
||||
//충전기위치에서 OFF를 한 경우이다
|
||||
if (PUB.Result.CurrentPos != ePosition.CHARGE || PUB.Result.TargetPos != ePosition.CHARGE)
|
||||
{
|
||||
PUB.Result.CurrentPos = ePosition.NONE;
|
||||
}
|
||||
else
|
||||
{
|
||||
PUB.Result.TargetPos = ePosition.QC;
|
||||
}
|
||||
PUB.Result.CurrentPosCW = "1";
|
||||
//대기상태로 전환
|
||||
PUB.sm.SetNewRunStep(ERunStep.READY);
|
||||
PUB.log.AddAT("충전 해제로 대기상태로 전환 합니다");
|
||||
}
|
||||
@@ -228,8 +234,7 @@ namespace Project
|
||||
PUB.Speak(Lang.버퍼도킹해제완료);
|
||||
|
||||
//도킹완료상태를 업데이트한다.
|
||||
PUB.XBE.LoaderInComplete = false;
|
||||
PUB.XBE.LoaderOutComplete = true;
|
||||
PUB.XBE.StepLoader = Device.eDocStep.OutComplete;
|
||||
|
||||
//대기상태로 전환
|
||||
PUB.sm.SetNewRunStep(ERunStep.READY);
|
||||
@@ -243,23 +248,10 @@ namespace Project
|
||||
PUB.Speak(Lang.버퍼도킹이완료되었습니다);
|
||||
|
||||
//도킹완료상태를 업데이트한다.
|
||||
PUB.XBE.LoaderInComplete = true;
|
||||
PUB.XBE.StepLoader = Device.eDocStep.InComplete;
|
||||
|
||||
//로더아웃으로 자동 진행하지 않음 (ACS 명령 대기)
|
||||
if (PUB.NextWorkCmd == ENIGProtocol.AGVCommandHE.PickOn || PUB.NextWorkCmd == ENIGProtocol.AGVCommandHE.PickOff)
|
||||
{
|
||||
PUB.sm.SetNewRunStep(ERunStep.READY);
|
||||
PUB.NextWorkCmd = ENIGProtocol.AGVCommandHE.Stop; // Command consumed
|
||||
}
|
||||
else
|
||||
{
|
||||
// Legacy behavior or Goto command: Auto-exit?
|
||||
// User said separation is key. Let's Stop here too or keep legacy for GOTO?
|
||||
// Assuming GOTO might rely on this, but safer to STOP if we want strict separation.
|
||||
// However, let's keep legacy behavior for GOTO if possible, but for PickOn/Off we STOP.
|
||||
PUB.sm.ClearRunStep();
|
||||
PUB.sm.SetNewRunStep(ERunStep.LOADER_OUT);
|
||||
}
|
||||
//대기상태로 전환
|
||||
PUB.sm.SetNewRunStep(ERunStep.READY);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
@@ -270,8 +262,7 @@ namespace Project
|
||||
PUB.Speak(Lang.버퍼도킹해제완료);
|
||||
|
||||
//도킹완료상태를 업데이트한다.
|
||||
PUB.XBE.UnloaderInComplete = false;
|
||||
PUB.XBE.UnloaderOutComplete = true;
|
||||
PUB.XBE.StepUnloader = Device.eDocStep.OutComplete;
|
||||
|
||||
//대기상태로 전환
|
||||
PUB.sm.SetNewRunStep(ERunStep.READY);
|
||||
@@ -285,19 +276,10 @@ namespace Project
|
||||
PUB.Speak(Lang.버퍼도킹이완료되었습니다);
|
||||
|
||||
//도킹완료상태를 업데이트한다.
|
||||
PUB.XBE.UnloaderInComplete = true;
|
||||
PUB.XBE.StepUnloader = Device.eDocStep.InComplete;
|
||||
|
||||
//언로더아웃으로 자동 진행하지 않음
|
||||
if (PUB.NextWorkCmd == ENIGProtocol.AGVCommandHE.PickOn || PUB.NextWorkCmd == ENIGProtocol.AGVCommandHE.PickOff)
|
||||
{
|
||||
PUB.sm.SetNewRunStep(ERunStep.READY);
|
||||
PUB.NextWorkCmd = ENIGProtocol.AGVCommandHE.Stop;
|
||||
}
|
||||
else
|
||||
{
|
||||
PUB.sm.ClearRunStep();
|
||||
PUB.sm.SetNewRunStep(ERunStep.UNLOADER_OUT);
|
||||
}
|
||||
//대기상태로 전환
|
||||
PUB.sm.SetNewRunStep(ERunStep.READY);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
@@ -308,8 +290,7 @@ namespace Project
|
||||
PUB.Speak(Lang.버퍼도킹해제완료);
|
||||
|
||||
//도킹완료상태를 업데이트한다.
|
||||
PUB.XBE.CleanerInComplete = false;
|
||||
PUB.XBE.CleanerOutComplete = true;
|
||||
PUB.XBE.StepCleaner = Device.eDocStep.OutComplete;
|
||||
|
||||
//대기상태로 전환
|
||||
PUB.sm.SetNewRunStep(ERunStep.READY);
|
||||
@@ -323,19 +304,10 @@ namespace Project
|
||||
PUB.Speak(Lang.버퍼도킹이완료되었습니다);
|
||||
|
||||
//도킹완료상태를 업데이트한다.
|
||||
PUB.XBE.CleanerInComplete = true;
|
||||
PUB.XBE.StepCleaner = Device.eDocStep.InComplete;
|
||||
|
||||
//클리너아웃으로 자동 진행하지 않음
|
||||
if (PUB.NextWorkCmd == ENIGProtocol.AGVCommandHE.PickOn || PUB.NextWorkCmd == ENIGProtocol.AGVCommandHE.PickOff)
|
||||
{
|
||||
PUB.sm.SetNewRunStep(ERunStep.READY);
|
||||
PUB.NextWorkCmd = ENIGProtocol.AGVCommandHE.Stop;
|
||||
}
|
||||
else
|
||||
{
|
||||
PUB.sm.ClearRunStep();
|
||||
PUB.sm.SetNewRunStep(ERunStep.CLEANER_OUT);
|
||||
}
|
||||
PUB.sm.SetNewRunStep(ERunStep.READY);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
@@ -346,13 +318,13 @@ namespace Project
|
||||
PUB.Speak(Lang.버퍼도킹해제완료);
|
||||
|
||||
//도킹완료상태를 업데이트한다.
|
||||
PUB.XBE.BufferInComplete = false;
|
||||
PUB.XBE.BufferOutComplete = true;
|
||||
PUB.XBE.StepBuffer = Device.eDocStep.OutComplete;
|
||||
|
||||
//대기상태로 전환
|
||||
PUB.sm.SetNewRunStep(ERunStep.READY);
|
||||
return;
|
||||
}
|
||||
else PUB.XBE.StepBuffer = Device.eDocStep.OutIng;
|
||||
break;
|
||||
|
||||
case ERunStep.BUFFER_IN: //버퍼도킹
|
||||
@@ -361,28 +333,16 @@ namespace Project
|
||||
PUB.Speak(Lang.버퍼도킹이완료되었습니다);
|
||||
|
||||
//도킹완료상태를 업데이트한다.
|
||||
PUB.XBE.BufferInComplete = true;
|
||||
PUB.XBE.StepBuffer = Device.eDocStep.InComplete;
|
||||
|
||||
//버퍼아웃으로 자동 진행하지 않음
|
||||
if (PUB.NextWorkCmd == ENIGProtocol.AGVCommandHE.PickOn || PUB.NextWorkCmd == ENIGProtocol.AGVCommandHE.PickOff)
|
||||
{
|
||||
PUB.sm.SetNewRunStep(ERunStep.READY);
|
||||
PUB.NextWorkCmd = ENIGProtocol.AGVCommandHE.Stop;
|
||||
}
|
||||
else
|
||||
{
|
||||
PUB.sm.ClearRunStep();
|
||||
PUB.sm.SetNewRunStep(ERunStep.BUFFER_OUT);
|
||||
}
|
||||
//대기상태로 전환
|
||||
PUB.sm.SetNewRunStep(ERunStep.READY);
|
||||
return;
|
||||
}
|
||||
else PUB.XBE.StepBuffer = Device.eDocStep.InIng;
|
||||
break;
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
}//cvass
|
||||
|
||||
@@ -11,26 +11,17 @@ namespace Project
|
||||
{
|
||||
public partial class fMain
|
||||
{
|
||||
/// <summary>
|
||||
/// 버퍼도킹
|
||||
/// </summary>
|
||||
/// <param name="isFirst"></param>
|
||||
/// <param name="stepTime"></param>
|
||||
/// <returns></returns>
|
||||
public Boolean _SM_RUN_BUFFER_IN(bool isFirst, TimeSpan stepTime)
|
||||
public Boolean _SM_RUN_BUFFER_IN(bool isFirst, TimeSpan seqtime)
|
||||
{
|
||||
var funcname = "_SM_RUN_BUFFER_IN";
|
||||
var idx = 1;
|
||||
|
||||
//충전 상태가 OFF되어야 동작하게한다
|
||||
if (_SM_RUN_CHGOFF(isFirst, stepTime) == false) return false;
|
||||
if (_SM_RUN_CHGOFF(isFirst, seqtime) == false) return false;
|
||||
|
||||
//라이더멈춤이 설정되어있다면 음성으로 알려준다
|
||||
if (CheckLiderStop() == false) return false;
|
||||
|
||||
//현재 위치가 결정되어있는지 체크한다
|
||||
if (_SM_RUN_POSCHK(isFirst, stepTime) == false) return false;
|
||||
|
||||
/*
|
||||
* 버퍼IN시퀀스
|
||||
* 1. 회전이 진행되지 않았다면 회전을 진행한다.
|
||||
@@ -41,8 +32,8 @@ namespace Project
|
||||
|
||||
if (PUB.sm.RunStepSeq == idx++)
|
||||
{
|
||||
PUB.log.Add("버퍼도킹시작");
|
||||
PUB.Speak(Lang.하차작업을시작합니다);
|
||||
PUB.log.Add($"[{funcname}] 버퍼진입시작({PUB.NextWorkCmd}) Turn:{PUB._virtualAGV.Turn}");
|
||||
PUB.Speak(Lang.진입을작합니다);
|
||||
PUB.sm.UpdateRunStepSeq();
|
||||
return false;
|
||||
}
|
||||
@@ -70,9 +61,9 @@ namespace Project
|
||||
{
|
||||
if (PUB._virtualAGV.Turn != AGVNavigationCore.Models.AGVTurn.L90)
|
||||
{
|
||||
VAR.TIME.Update(eVarTime.LastTurnCommandTime);
|
||||
PUB.AGV.AGVMoveLeft180Turn();
|
||||
PUB.log.Add("AGV Left Turn");
|
||||
VAR.TIME.Update(eVarTime.LastTurnCommandTime);
|
||||
PUB.sm.UpdateRunStepSeq();
|
||||
}
|
||||
else PUB.sm.UpdateRunStepSeq(); //이미완료된상태이므로 다음으로 진행한다.
|
||||
@@ -80,59 +71,35 @@ namespace Project
|
||||
}
|
||||
else if (PUB.sm.RunStepSeq == idx++)
|
||||
{
|
||||
if (PUB._virtualAGV.Turn != AGVNavigationCore.Models.AGVTurn.L90)
|
||||
//왼쪽턴이 완료되지 않은경우
|
||||
if (PUB.AGV.TurnInformation.State != arDev.eNarumiTurn.Left)
|
||||
{
|
||||
//5초이내에 턴이동 상태가 확인되어야 한다.
|
||||
if (PUB.AGV.system1.agv_run == false)
|
||||
//움직임 확인을 위해 3초간은 검증을 유예한다
|
||||
if (PUB.AGV.TurnInformation.Runtime.TotalSeconds < 3) return false;
|
||||
|
||||
//턴 이동 상태가 확인되어야 한다.
|
||||
var overtime = 10;
|
||||
if (PUB.AGV.TurnInformation.Runtime.TotalSeconds > overtime)
|
||||
{
|
||||
var ts = VAR.TIME.RUN(eVarTime.LastTurnCommandTime);
|
||||
if (ts.TotalSeconds > 5)
|
||||
{
|
||||
//5초동안 AGV까 움직이지 않았다면 오류 처리한다.
|
||||
PUB.AGV.AGVMoveStop("5초이내 턴 감지 안됨");
|
||||
PUB.log.AddE("5초이내 턴 감지 안됨");
|
||||
PUB.sm.SetNewRunStep(ERunStep.ERROR);
|
||||
return false;
|
||||
}
|
||||
//5초동안 AGV까 움직이지 않았다면 오류 처리한다.
|
||||
PUB.AGV.AGVMoveStop($"[bufferin] {overtime}초이내 턴 감지 안됨");
|
||||
PUB.log.AddE($"[{funcname}] {overtime}초이내 턴 감지 안됨");
|
||||
PUB.sm.SetNewRunStep(ERunStep.ERROR);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
PUB.sm.UpdateRunStepSeq(); //이미완료된상태이므로 다음으로 진행한다.
|
||||
return false;
|
||||
}
|
||||
else if (PUB.sm.RunStepSeq == idx++)
|
||||
{
|
||||
//턴이완료되었느닞 확인한다.
|
||||
if (PUB._virtualAGV.Turn != AGVNavigationCore.Models.AGVTurn.L90)
|
||||
{
|
||||
//10초 이상 가동하고 있다면 문제이다
|
||||
if (PUB.AGV.system1.agv_run == true)
|
||||
{
|
||||
var ts = VAR.TIME.RUN(eVarTime.LastTurnCommandTime);
|
||||
if (ts.TotalSeconds > 15)
|
||||
{
|
||||
PUB.AGV.AGVMoveStop("15초이내 턴 이 완료되지 않음");
|
||||
PUB.log.AddE("5초이내 턴 완료 확인 안됨");
|
||||
PUB.sm.SetNewRunStep(ERunStep.ERROR);
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
else PUB._virtualAGV.Turn = AGVNavigationCore.Models.AGVTurn.L90;
|
||||
}
|
||||
PUB.sm.UpdateRunStepSeq(); //이미완료된상태이므로 다음으로 진행한다.
|
||||
return false;
|
||||
}
|
||||
else if (PUB.sm.RunStepSeq == idx++)
|
||||
{
|
||||
// [PickOn/PickOff] 초기 리프트 동작
|
||||
var liftCmd = arDev.Narumi.LiftCommand.DN;
|
||||
if (PUB.NextWorkCmd == ENIGProtocol.AGVCommandHE.PickOff)
|
||||
{
|
||||
liftCmd = arDev.Narumi.LiftCommand.UP;
|
||||
return false;
|
||||
}
|
||||
|
||||
PUB.log.Add($"[{funcname}] Turn(left) 완료");
|
||||
PUB.sm.UpdateRunStepSeq(); //이미완료된상태이므로 다음으로 진행한다.
|
||||
return false;
|
||||
}
|
||||
else if (PUB.sm.RunStepSeq == idx++)
|
||||
{
|
||||
//버퍼에들어갈때에는 가져다 놓을때도 가지러 갈때에도 리프트는 내려서 들어간다
|
||||
var liftCmd = arDev.Narumi.LiftCommand.DN;
|
||||
PUB.AGV.LiftControl(liftCmd);
|
||||
PUB.log.Add($"[{funcname}] 리프트를 내립니다");
|
||||
VAR.TIME.Update(eVarTime.LastTurnCommandTime);
|
||||
PUB.sm.UpdateRunStepSeq();
|
||||
return false;
|
||||
@@ -140,12 +107,32 @@ namespace Project
|
||||
else if (PUB.sm.RunStepSeq == idx++)
|
||||
{
|
||||
//리프트 센서 확인
|
||||
var ts = VAR.TIME.RUN(eVarTime.LastTurnCommandTime);
|
||||
if (ts.TotalSeconds > 10)
|
||||
{
|
||||
// Timebound check
|
||||
}
|
||||
PUB.log.Add("리프트 동작 확인 완료");
|
||||
if (PUB.AGV.signal1.lift_down == false)
|
||||
{
|
||||
if (seqtime.TotalSeconds > 20)
|
||||
{
|
||||
PUB.log.AddAT($"[{funcname}] 리프트가 내려가지 않아 1회 재시도 합니다");
|
||||
PUB.AGV.LiftControl(arDev.Narumi.LiftCommand.DN);
|
||||
//재시도를 했으니 다음으로 진행하게한다
|
||||
}
|
||||
else return false;
|
||||
}
|
||||
PUB.sm.UpdateRunStepSeq();
|
||||
return false;
|
||||
}
|
||||
else if (PUB.sm.RunStepSeq == idx++)
|
||||
{
|
||||
//리프트 센서 확인
|
||||
if (PUB.AGV.signal1.lift_down == false)
|
||||
{
|
||||
if (seqtime.TotalSeconds > 20)
|
||||
{
|
||||
PUB.log.AddE($"[{funcname}] 리프트가 내려가지 않습니다");
|
||||
PUB.AGV.LiftControl(arDev.Narumi.LiftCommand.STP);
|
||||
PUB.sm.SetNewRunStep(ERunStep.ERROR);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
PUB.sm.UpdateRunStepSeq();
|
||||
return false;
|
||||
}
|
||||
@@ -160,26 +147,32 @@ namespace Project
|
||||
else if (PUB.sm.RunStepSeq == idx++)
|
||||
{
|
||||
//저속이동 (후진 진입)
|
||||
var moveset = PUB.AGV.AGVMoveSet(new arDev.Narumi.BunkiData
|
||||
var ret = PUB.AGV.AGVMoveSet(new arDev.Narumi.BunkiData
|
||||
{
|
||||
Bunki = arDev.Narumi.eBunki.Strate,
|
||||
Direction = arDev.Narumi.eMoveDir.Backward,
|
||||
PBSSensor = 0,
|
||||
Speed = arDev.Narumi.eMoveSpd.Low,
|
||||
});
|
||||
if (moveset == false)
|
||||
|
||||
//명령이 실패되었다면 재시도를 한다
|
||||
if (ret != arDev.eNarumiCommandResult.Success)
|
||||
{
|
||||
var ts = VAR.TIME.RUN(eVarTime.LastTurnCommandTime);
|
||||
if (ts.TotalSeconds > 10)
|
||||
if (ret >= arDev.eNarumiCommandResult.Error)
|
||||
{
|
||||
PUB.AGV.AGVMoveStop(funcname);
|
||||
PUB.log.AddE("AGV속도설정이 완료되지 않았습니다");
|
||||
PUB.log.AddE($"[{funcname}] AGV속도설정이 완료되지 않았습니다");
|
||||
PUB.sm.SetNewRunStep(ERunStep.ERROR);
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
//후진이동을한다
|
||||
PUB.AGV.AGVMoveRun(arDev.Narumi.eRunOpt.Backward);
|
||||
|
||||
//마크스탑으로 이동
|
||||
PUB.AGV.AGVMoveStop(funcname, arDev.Narumi.eStopOpt.MarkStop);
|
||||
|
||||
VAR.TIME.Update(eVarTime.LastTurnCommandTime);
|
||||
PUB.sm.UpdateRunStepSeq();
|
||||
return false;
|
||||
@@ -193,7 +186,7 @@ namespace Project
|
||||
if (ts.TotalSeconds > 3)
|
||||
{
|
||||
PUB.AGV.AGVMoveStop(funcname);
|
||||
PUB.log.AddE("MARK STOP신호가 확인되지 않습니다");
|
||||
PUB.log.AddE($"[{funcname}] MARK STOP신호가 확인되지 않습니다");
|
||||
PUB.sm.SetNewRunStep(ERunStep.ERROR);
|
||||
return false;
|
||||
}
|
||||
@@ -211,7 +204,7 @@ namespace Project
|
||||
if (ts.TotalSeconds > 10)
|
||||
{
|
||||
PUB.AGV.AGVMoveStop(funcname);
|
||||
PUB.log.AddE("AGV가 멈추지 않아 강제종료 합니다");
|
||||
PUB.log.AddE($"[{funcname}] AGV가 멈추지 않아 강제종료 합니다");
|
||||
PUB.sm.SetNewRunStep(ERunStep.ERROR);
|
||||
return false;
|
||||
}
|
||||
@@ -223,45 +216,22 @@ namespace Project
|
||||
}
|
||||
else if (PUB.sm.RunStepSeq == idx++)
|
||||
{
|
||||
// [Action] 진입 완료 후 리프트 동작 (Pick/Drop)
|
||||
PUB.log.Add("버퍼 진입 완료. 작업 수행(Lift Pick/Drop)");
|
||||
|
||||
var liftCmd = arDev.Narumi.LiftCommand.UP;
|
||||
if (PUB.NextWorkCmd == ENIGProtocol.AGVCommandHE.PickOff)
|
||||
{
|
||||
liftCmd = arDev.Narumi.LiftCommand.DN;
|
||||
}
|
||||
|
||||
PUB.AGV.LiftControl(liftCmd);
|
||||
VAR.TIME.Update(eVarTime.LastTurnCommandTime);
|
||||
if (seqtime.TotalSeconds < 2) return false;
|
||||
PUB.log.Add($"[{funcname}] 작업({PUB.NextWorkCmd}) 완료. 대기 상태로 전환 (퇴출 명령 대기)");
|
||||
PUB.sm.UpdateRunStepSeq();
|
||||
return false;
|
||||
}
|
||||
else if (PUB.sm.RunStepSeq == idx++)
|
||||
{
|
||||
// 리프트 동작 대기
|
||||
// TODO: 실제 센서 확인 로직 추가 필요
|
||||
var ts = VAR.TIME.RUN(eVarTime.LastTurnCommandTime);
|
||||
if (ts.TotalSeconds < 2) return false;
|
||||
|
||||
PUB.log.Add("작업(Pick/Drop) 완료. 대기 상태로 전환 (퇴출 명령 대기)");
|
||||
PUB.sm.UpdateRunStepSeq();
|
||||
return false;
|
||||
}
|
||||
else if (PUB.sm.RunStepSeq == idx++)
|
||||
{
|
||||
//완료되었다. (ACS에 보내야함)
|
||||
PUB.log.Add("버퍼 진입 및 작업 완료");
|
||||
//완료되었다.
|
||||
PUB.log.Add($"[{funcname}] 버퍼 진입 및 작업 완료");
|
||||
PUB.sm.UpdateRunStepSeq();
|
||||
return false;
|
||||
}
|
||||
|
||||
// 작업을 마치고 설비 안에 멈춰있는 상태.
|
||||
// ACS가 이 상태를 확인하고 NextWorkCmd로 퇴출(Out) 명령을 보내야 함.
|
||||
PUB.AddEEDB($"버퍼작업완료({PUB.Result.TargetPos})");
|
||||
return true;
|
||||
|
||||
PUB.AddEEDB($"버퍼투입완료({PUB.Result.TargetPos})");
|
||||
PUB.AddEEDB($"[{funcname}] 버퍼작업완료({PUB.Result.TargetPos})");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,30 +11,97 @@ namespace Project
|
||||
{
|
||||
public partial class fMain
|
||||
{
|
||||
|
||||
public Boolean _SM_RUN_BUFFER_OUT(bool isFirst, TimeSpan stepTime)
|
||||
public Boolean _SM_RUN_BUFFER_OUT(bool isFirst, TimeSpan seqtime)
|
||||
{
|
||||
var funcname = "_SM_RUN_BUFFER_IN";
|
||||
var idx = 1;
|
||||
|
||||
//충전 상태가 OFF되어야 동작하게한다
|
||||
if (_SM_RUN_CHGOFF(isFirst, stepTime) == false) return false;
|
||||
if (_SM_RUN_CHGOFF(isFirst, seqtime) == false) return false;
|
||||
|
||||
//라이더멈춤이 설정되어있다면 음성으로 알려준다
|
||||
if (CheckLiderStop() == false) return false;
|
||||
|
||||
//현재 위치가 결정되어있는지 체크한다
|
||||
if (_SM_RUN_POSCHK(isFirst, stepTime) == false) return false;
|
||||
/*
|
||||
* 버퍼 OUT 시퀀스
|
||||
* 1-1. PickOn 라면 리프트를 Up 한다
|
||||
* 1-2. PickOff 라면 리프트를 Down 한다
|
||||
* 2.전진-저속-마크다운
|
||||
* 3.Turn-Right-180
|
||||
*/
|
||||
|
||||
var idx = 1;
|
||||
if (PUB.sm.RunStepSeq == idx++)
|
||||
{
|
||||
PUB.log.Add($"[{funcname}] 버퍼진출시작({PUB.NextWorkCmd}) Turn:{PUB._virtualAGV.Turn}");
|
||||
PUB.Speak(Lang.진출을시작합니다);
|
||||
PUB.sm.UpdateRunStepSeq();
|
||||
return false;
|
||||
}
|
||||
else if (PUB.sm.RunStepSeq == idx++)
|
||||
{
|
||||
arDev.Narumi.LiftCommand lift = PUB.NextWorkCmd == ENIGProtocol.AGVCommandHE.PickOn ? arDev.Narumi.LiftCommand.UP : arDev.Narumi.LiftCommand.DN;
|
||||
PUB.log.Add($"[{funcname}] 리프트제어 {lift}");
|
||||
PUB.AGV.LiftControl(lift);
|
||||
PUB.sm.UpdateRunStepSeq();
|
||||
return false;
|
||||
}
|
||||
else if (PUB.sm.RunStepSeq == idx++)
|
||||
{
|
||||
//리프트 센서 확인
|
||||
var checksensor = PUB.NextWorkCmd == ENIGProtocol.AGVCommandHE.PickOn ? PUB.AGV.signal1.lift_up : PUB.AGV.signal1.lift_down;
|
||||
if (checksensor == false)
|
||||
{
|
||||
if (seqtime.TotalSeconds > 20)
|
||||
{
|
||||
PUB.log.AddAT($"[{funcname}] 리프트가 완료되지 않아 1회 재시도 합니다");
|
||||
arDev.Narumi.LiftCommand lift = PUB.NextWorkCmd == ENIGProtocol.AGVCommandHE.PickOn ? arDev.Narumi.LiftCommand.UP : arDev.Narumi.LiftCommand.DN;
|
||||
PUB.AGV.LiftControl(lift);
|
||||
}
|
||||
else return false;
|
||||
}
|
||||
PUB.sm.UpdateRunStepSeq();
|
||||
return false;
|
||||
}
|
||||
else if (PUB.sm.RunStepSeq == idx++)
|
||||
{
|
||||
//리프트 센서 확인
|
||||
var checksensor = PUB.NextWorkCmd == ENIGProtocol.AGVCommandHE.PickOn ? PUB.AGV.signal1.lift_up : PUB.AGV.signal1.lift_down;
|
||||
if (checksensor == false)
|
||||
{
|
||||
if (seqtime.TotalSeconds > 20)
|
||||
{
|
||||
PUB.log.AddE($"[{funcname}] 리프트가 동작하지 않습니다");
|
||||
PUB.AGV.LiftControl(arDev.Narumi.LiftCommand.STP);
|
||||
PUB.sm.SetNewRunStep(ERunStep.ERROR);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
PUB.sm.UpdateRunStepSeq();
|
||||
return false;
|
||||
}
|
||||
else if (PUB.sm.RunStepSeq == idx++)
|
||||
{
|
||||
//빈 상태로 아웃해야한다.
|
||||
PUB.AGV.AGVMoveSet(new arDev.Narumi.BunkiData
|
||||
var ret = PUB.AGV.AGVMoveSet(new arDev.Narumi.BunkiData
|
||||
{
|
||||
Bunki = arDev.Narumi.eBunki.Strate,
|
||||
Direction = arDev.Narumi.eMoveDir.Forward,
|
||||
PBSSensor = 0,
|
||||
Speed = arDev.Narumi.eMoveSpd.Low,
|
||||
});
|
||||
//명령이 실패되었다면 재시도를 한다
|
||||
if (ret != arDev.eNarumiCommandResult.Success)
|
||||
{
|
||||
if (ret >= arDev.eNarumiCommandResult.Error)
|
||||
{
|
||||
PUB.AGV.AGVMoveStop(funcname);
|
||||
PUB.log.AddE($"[{funcname}] AGV속도설정이 완료되지 않았습니다");
|
||||
PUB.sm.SetNewRunStep(ERunStep.ERROR);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
PUB.sm.UpdateRunStepSeq();
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -25,9 +25,6 @@ namespace Project
|
||||
//라이더멈춤이 설정되어있다면 음성으로 알려준다
|
||||
if (CheckLiderStop() == false) return false;
|
||||
|
||||
//현재 위치가 결정되어있는지 체크한다
|
||||
if (_SM_RUN_POSCHK(isFirst, stepTime) == false) return false;
|
||||
|
||||
/*
|
||||
* 클리너 IN 시퀀스 (버퍼 복사 - 턴 제거)
|
||||
* 1. LIFT DOWN
|
||||
@@ -78,24 +75,25 @@ namespace Project
|
||||
else if (PUB.sm.RunStepSeq == idx++)
|
||||
{
|
||||
//저속이동 (후진 진입)
|
||||
var moveset = PUB.AGV.AGVMoveSet(new arDev.Narumi.BunkiData
|
||||
var ret = PUB.AGV.AGVMoveSet(new arDev.Narumi.BunkiData
|
||||
{
|
||||
Bunki = arDev.Narumi.eBunki.Strate,
|
||||
Direction = arDev.Narumi.eMoveDir.Backward,
|
||||
PBSSensor = 0,
|
||||
Speed = arDev.Narumi.eMoveSpd.Low,
|
||||
});
|
||||
if (moveset == false)
|
||||
//명령이 실패되었다면 재시도를 한다
|
||||
if (ret != arDev.eNarumiCommandResult.Success)
|
||||
{
|
||||
var ts = VAR.TIME.RUN(eVarTime.LastTurnCommandTime);
|
||||
if (ts.TotalSeconds > 10)
|
||||
if (ret >= arDev.eNarumiCommandResult.Error)
|
||||
{
|
||||
PUB.AGV.AGVMoveStop(funcname);
|
||||
PUB.log.AddE("AGV속도설정이 완료되지 않았습니다");
|
||||
PUB.log.AddE($"[{funcname}] AGV속도설정이 완료되지 않았습니다");
|
||||
PUB.sm.SetNewRunStep(ERunStep.ERROR);
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
PUB.AGV.AGVMoveRun(arDev.Narumi.eRunOpt.Backward);
|
||||
PUB.AGV.AGVMoveStop(funcname, arDev.Narumi.eStopOpt.MarkStop);
|
||||
VAR.TIME.Update(eVarTime.LastTurnCommandTime);
|
||||
|
||||
@@ -16,26 +16,37 @@ namespace Project
|
||||
/// </summary>
|
||||
public Boolean _SM_RUN_CLEANER_OUT(bool isFirst, TimeSpan stepTime)
|
||||
{
|
||||
var funcname = "CLEANEROUT";
|
||||
|
||||
//충전 상태가 OFF되어야 동작하게한다
|
||||
if (_SM_RUN_CHGOFF(isFirst, stepTime) == false) return false;
|
||||
|
||||
//라이더멈춤이 설정되어있다면 음성으로 알려준다
|
||||
if (CheckLiderStop() == false) return false;
|
||||
|
||||
//현재 위치가 결정되어있는지 체크한다
|
||||
if (_SM_RUN_POSCHK(isFirst, stepTime) == false) return false;
|
||||
|
||||
var idx = 1;
|
||||
if (PUB.sm.RunStepSeq == idx++)
|
||||
{
|
||||
//빈 상태로 아웃해야한다.
|
||||
PUB.AGV.AGVMoveSet(new arDev.Narumi.BunkiData
|
||||
var ret = PUB.AGV.AGVMoveSet(new arDev.Narumi.BunkiData
|
||||
{
|
||||
Bunki = arDev.Narumi.eBunki.Strate,
|
||||
Direction = arDev.Narumi.eMoveDir.Forward,
|
||||
PBSSensor = 0,
|
||||
Speed = arDev.Narumi.eMoveSpd.Low,
|
||||
});
|
||||
//명령이 실패되었다면 재시도를 한다
|
||||
if (ret != arDev.eNarumiCommandResult.Success)
|
||||
{
|
||||
if (ret >= arDev.eNarumiCommandResult.Error)
|
||||
{
|
||||
PUB.AGV.AGVMoveStop(funcname);
|
||||
PUB.log.AddE($"[{funcname}] AGV속도설정이 완료되지 않았습니다");
|
||||
PUB.sm.SetNewRunStep(ERunStep.ERROR);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
PUB.sm.UpdateRunStepSeq();
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -14,11 +14,11 @@ namespace Project
|
||||
DateTime tm_gocharge_command = DateTime.Now;
|
||||
public Boolean _SM_RUN_GOCHARGE(bool isFirst, TimeSpan stepTime)
|
||||
{
|
||||
var funcname = "GOCHARGE";
|
||||
if (runStepisFirst)
|
||||
{
|
||||
//홈을 찾도록 항상 위치를 지워버리자
|
||||
PUB.Result.CurrentPos = ePosition.NONE;
|
||||
PUB.Result.CurrentPos = ePosition.NONE;
|
||||
}
|
||||
|
||||
//HW 연결오류
|
||||
@@ -57,13 +57,7 @@ namespace Project
|
||||
return false;
|
||||
}
|
||||
|
||||
//현재 위치가 결정되어있는지 체크한다
|
||||
if (_SM_RUN_POSCHK(isFirst, stepTime) == false)
|
||||
{
|
||||
PUB.Result.result_message = "충전기 검색 전 현재 위치 검색";
|
||||
PUB.Result.result_progressmax = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
//충전작업진행상태 //220629
|
||||
//if (PUB.flag.get(EFlag.FLAG_GO_CHAGER_TEMP) == false)
|
||||
@@ -119,17 +113,26 @@ namespace Project
|
||||
{
|
||||
PUB.log.Add($"충전:충전기 검색을 위한 전진시작");
|
||||
PUB.Speak(Lang.충전기를검색합니다);
|
||||
PUB.AGV.AGVMoveSet(new arDev.Narumi.BunkiData
|
||||
var ret = PUB.AGV.AGVMoveSet(new arDev.Narumi.BunkiData
|
||||
{
|
||||
Speed = arDev.Narumi.eMoveSpd.Low,
|
||||
Bunki = arDev.Narumi.eBunki.Strate,
|
||||
Direction = arDev.Narumi.eMoveDir.Forward,
|
||||
PBSSensor = 1,
|
||||
});
|
||||
PUB.AGV.AGVMoveRun(arDev.Narumi.eRunOpt.Forward);
|
||||
//PUB.Result.TargetPos = ePosition.CHARGE;
|
||||
VAR.TIME.Update(eVarTime.ChargeSearch);
|
||||
if(ret != arDev.eNarumiCommandResult.Success)
|
||||
{
|
||||
if(ret >= arDev.eNarumiCommandResult.Error)
|
||||
{
|
||||
PUB.log.AddE($"[{funcname}] AGV속도설정 실패");
|
||||
PUB.AGV.AGVMoveStop("err");
|
||||
PUB.sm.SetNewRunStep(ERunStep.ERROR);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
PUB.AGV.AGVMoveRun(arDev.Narumi.eRunOpt.Forward);
|
||||
VAR.TIME.Update(eVarTime.ChargeSearch);
|
||||
PUB.sm.UpdateRunStepSeq();
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -72,8 +72,8 @@ namespace Project
|
||||
else if (PUB.sm.RunStepSeq == idx++)
|
||||
{
|
||||
//QC까지 모두 완료되었다.(완전히 정차할때까지 기다린다)
|
||||
PUB.Speak(Lang.홈검색완료, true);
|
||||
PUB.AddEEDB($"홈검색완료({PUB.Result.TargetPos})");
|
||||
PUB.Speak(Lang.이동완료, true);
|
||||
PUB.AddEEDB($"이동완료({PUB.Result.TargetPos})");
|
||||
PUB.sm.UpdateRunStepSeq();
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -67,8 +67,8 @@ namespace Project
|
||||
else if (PUB.sm.RunStepSeq == idx++)
|
||||
{
|
||||
//QC까지 모두 완료되었다.(완전히 정차할때까지 기다린다)
|
||||
PUB.Speak(Lang.홈검색완료, true);
|
||||
PUB.AddEEDB($"홈검색완료({PUB.Result.TargetPos})");
|
||||
PUB.Speak(Lang.이동완료, true);
|
||||
PUB.AddEEDB($"이동완료({PUB._virtualAGV.TargetNode.ID2})");
|
||||
PUB.sm.UpdateRunStepSeq();
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -25,9 +25,7 @@ namespace Project
|
||||
//라이더멈춤이 설정되어있다면 음성으로 알려준다
|
||||
if (CheckLiderStop() == false) return false;
|
||||
|
||||
//현재 위치가 결정되어있는지 체크한다
|
||||
if (_SM_RUN_POSCHK(isFirst, stepTime) == false) return false;
|
||||
|
||||
|
||||
/*
|
||||
* 로더 IN 시퀀스 (버퍼 복사 - 턴 제거)
|
||||
* 1. LIFT DOWN
|
||||
@@ -84,23 +82,22 @@ namespace Project
|
||||
else if (PUB.sm.RunStepSeq == idx++)
|
||||
{
|
||||
//저속이동 (후진 진입)
|
||||
var moveset = PUB.AGV.AGVMoveSet(new arDev.Narumi.BunkiData
|
||||
var ret = PUB.AGV.AGVMoveSet(new arDev.Narumi.BunkiData
|
||||
{
|
||||
Bunki = arDev.Narumi.eBunki.Strate,
|
||||
Direction = arDev.Narumi.eMoveDir.Backward,
|
||||
PBSSensor = 0,
|
||||
Speed = arDev.Narumi.eMoveSpd.Low,
|
||||
});
|
||||
if (moveset == false)
|
||||
if (ret != arDev.eNarumiCommandResult.Success)
|
||||
{
|
||||
var ts = VAR.TIME.RUN(eVarTime.LastTurnCommandTime);
|
||||
if (ts.TotalSeconds > 10)
|
||||
if (ret >= arDev.eNarumiCommandResult.Error)
|
||||
{
|
||||
PUB.AGV.AGVMoveStop(funcname);
|
||||
PUB.log.AddE("AGV속도설정이 완료되지 않았습니다");
|
||||
PUB.sm.SetNewRunStep(ERunStep.ERROR);
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
PUB.AGV.AGVMoveRun(arDev.Narumi.eRunOpt.Backward);
|
||||
PUB.AGV.AGVMoveStop(funcname, arDev.Narumi.eStopOpt.MarkStop);
|
||||
|
||||
@@ -16,27 +16,37 @@ namespace Project
|
||||
/// </summary>
|
||||
public Boolean _SM_RUN_LOADER_OUT(bool isFirst, TimeSpan stepTime)
|
||||
{
|
||||
|
||||
var funcname = "LOADEROUT";
|
||||
//충전 상태가 OFF되어야 동작하게한다
|
||||
if (_SM_RUN_CHGOFF(isFirst, stepTime) == false) return false;
|
||||
|
||||
//라이더멈춤이 설정되어있다면 음성으로 알려준다
|
||||
if (CheckLiderStop() == false) return false;
|
||||
|
||||
//현재 위치가 결정되어있는지 체크한다
|
||||
if (_SM_RUN_POSCHK(isFirst, stepTime) == false) return false;
|
||||
|
||||
var idx = 1;
|
||||
if (PUB.sm.RunStepSeq == idx++)
|
||||
{
|
||||
//빈 상태로 아웃해야한다.
|
||||
PUB.AGV.AGVMoveSet(new arDev.Narumi.BunkiData
|
||||
var ret = PUB.AGV.AGVMoveSet(new arDev.Narumi.BunkiData
|
||||
{
|
||||
Bunki = arDev.Narumi.eBunki.Strate,
|
||||
Direction = arDev.Narumi.eMoveDir.Forward,
|
||||
PBSSensor = 0,
|
||||
Speed = arDev.Narumi.eMoveSpd.Low,
|
||||
});
|
||||
//명령이 실패되었다면 재시도를 한다
|
||||
if (ret != arDev.eNarumiCommandResult.Success)
|
||||
{
|
||||
if (ret >= arDev.eNarumiCommandResult.Error)
|
||||
{
|
||||
PUB.AGV.AGVMoveStop(funcname);
|
||||
PUB.log.AddE($"[{funcname}] AGV속도설정이 완료되지 않았습니다");
|
||||
PUB.sm.SetNewRunStep(ERunStep.ERROR);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
PUB.sm.UpdateRunStepSeq();
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -16,9 +16,6 @@ namespace Project
|
||||
if (PUB._virtualAGV.CurrentNode != null && PUB._virtualAGV.PrevNode != null)
|
||||
return true;
|
||||
|
||||
//최소2개의 노드정보가 있어야 진행가능하므로 prevNode 값이 있는지 확인한다.
|
||||
|
||||
|
||||
//이동을 하지 않고있다면 전진을 진행한다
|
||||
if (PUB.AGV.system1.agv_run == false)
|
||||
{
|
||||
@@ -26,14 +23,17 @@ namespace Project
|
||||
if (ts.TotalSeconds > 5)
|
||||
{
|
||||
PUB.log.Add($"현재위치를 몰라 전진 이동 합니다");
|
||||
PUB.AGV.AGVMoveSet(new arDev.Narumi.BunkiData
|
||||
var ret = PUB.AGV.AGVMoveSet(new arDev.Narumi.BunkiData
|
||||
{
|
||||
Bunki = arDev.Narumi.eBunki.Strate,
|
||||
Direction = arDev.Narumi.eMoveDir.Forward,
|
||||
PBSSensor = 1,
|
||||
Speed = arDev.Narumi.eMoveSpd.Low,
|
||||
});
|
||||
PUB.AGV.AGVMoveRun(arDev.Narumi.eRunOpt.Forward);
|
||||
if(ret == arDev.eNarumiCommandResult.Success)
|
||||
{
|
||||
PUB.AGV.AGVMoveRun(arDev.Narumi.eRunOpt.Forward);
|
||||
}
|
||||
VAR.TIME.Update(eVarTime.LastRunCommandTime);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,9 +25,6 @@ namespace Project
|
||||
//라이더멈춤이 설정되어있다면 음성으로 알려준다
|
||||
if (CheckLiderStop() == false) return false;
|
||||
|
||||
//현재 위치가 결정되어있는지 체크한다
|
||||
if (_SM_RUN_POSCHK(isFirst, stepTime) == false) return false;
|
||||
|
||||
/*
|
||||
* 언로더 IN 시퀀스 (버퍼 복사 - 턴 제거)
|
||||
* 1. LIFT DOWN
|
||||
@@ -78,24 +75,27 @@ namespace Project
|
||||
else if (PUB.sm.RunStepSeq == idx++)
|
||||
{
|
||||
//저속이동 (후진 진입)
|
||||
var moveset = PUB.AGV.AGVMoveSet(new arDev.Narumi.BunkiData
|
||||
var ret = PUB.AGV.AGVMoveSet(new arDev.Narumi.BunkiData
|
||||
{
|
||||
Bunki = arDev.Narumi.eBunki.Strate,
|
||||
Direction = arDev.Narumi.eMoveDir.Backward,
|
||||
PBSSensor = 0,
|
||||
Speed = arDev.Narumi.eMoveSpd.Low,
|
||||
});
|
||||
if (moveset == false)
|
||||
|
||||
//명령이 실패되었다면 재시도를 한다
|
||||
if (ret != arDev.eNarumiCommandResult.Success)
|
||||
{
|
||||
var ts = VAR.TIME.RUN(eVarTime.LastTurnCommandTime);
|
||||
if (ts.TotalSeconds > 10)
|
||||
if (ret >= arDev.eNarumiCommandResult.Error)
|
||||
{
|
||||
PUB.AGV.AGVMoveStop(funcname);
|
||||
PUB.log.AddE("AGV속도설정이 완료되지 않았습니다");
|
||||
PUB.log.AddE($"[{funcname}] AGV속도설정이 완료되지 않았습니다");
|
||||
PUB.sm.SetNewRunStep(ERunStep.ERROR);
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
PUB.AGV.AGVMoveRun(arDev.Narumi.eRunOpt.Backward);
|
||||
PUB.AGV.AGVMoveStop(funcname, arDev.Narumi.eStopOpt.MarkStop);
|
||||
VAR.TIME.Update(eVarTime.LastTurnCommandTime);
|
||||
|
||||
@@ -16,27 +16,37 @@ namespace Project
|
||||
/// </summary>
|
||||
public Boolean _SM_RUN_UNLOADER_OUT(bool isFirst, TimeSpan stepTime)
|
||||
{
|
||||
|
||||
var funcname = "UNLOADEROUT";
|
||||
//충전 상태가 OFF되어야 동작하게한다
|
||||
if (_SM_RUN_CHGOFF(isFirst, stepTime) == false) return false;
|
||||
|
||||
//라이더멈춤이 설정되어있다면 음성으로 알려준다
|
||||
if (CheckLiderStop() == false) return false;
|
||||
|
||||
//현재 위치가 결정되어있는지 체크한다
|
||||
if (_SM_RUN_POSCHK(isFirst, stepTime) == false) return false;
|
||||
|
||||
var idx = 1;
|
||||
if (PUB.sm.RunStepSeq == idx++)
|
||||
{
|
||||
//빈 상태로 아웃해야한다.
|
||||
PUB.AGV.AGVMoveSet(new arDev.Narumi.BunkiData
|
||||
var ret = PUB.AGV.AGVMoveSet(new arDev.Narumi.BunkiData
|
||||
{
|
||||
Bunki = arDev.Narumi.eBunki.Strate,
|
||||
Direction = arDev.Narumi.eMoveDir.Forward,
|
||||
PBSSensor = 0,
|
||||
Speed = arDev.Narumi.eMoveSpd.Low,
|
||||
});
|
||||
//명령이 실패되었다면 재시도를 한다
|
||||
if (ret != arDev.eNarumiCommandResult.Success)
|
||||
{
|
||||
if (ret >= arDev.eNarumiCommandResult.Error)
|
||||
{
|
||||
PUB.AGV.AGVMoveStop(funcname);
|
||||
PUB.log.AddE($"[{funcname}] AGV속도설정이 완료되지 않았습니다");
|
||||
PUB.sm.SetNewRunStep(ERunStep.ERROR);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
PUB.sm.UpdateRunStepSeq();
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -34,7 +34,7 @@ namespace Project
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -44,7 +44,7 @@ namespace Project
|
||||
/// <returns></returns>
|
||||
public bool CheckLiderStop()
|
||||
{
|
||||
|
||||
|
||||
if (PUB.AGV.system1.stop_by_front_detect == true)
|
||||
{
|
||||
var tsSpeak = DateTime.Now - LastSpeakTime;
|
||||
@@ -67,8 +67,9 @@ namespace Project
|
||||
/// <returns></returns>
|
||||
Boolean UpdateMotionPositionForMark(string sender)
|
||||
{
|
||||
//현재위치를 모르는 상태라면 이동하여 현재 위치를 찾는다
|
||||
if (_SM_RUN_POSCHK(false, new TimeSpan()) == false) return false;
|
||||
////현재위치를 모르는 상태라면 처리하지 않는다
|
||||
if (PUB._virtualAGV.CurrentNode == null || PUB._virtualAGV.PrevNode == null)
|
||||
return false;
|
||||
|
||||
//현재위치노드 오류
|
||||
var currentNode = PUB.FindByNodeID(PUB._virtualAGV.CurrentNode.Id);
|
||||
@@ -119,6 +120,7 @@ namespace Project
|
||||
}
|
||||
else
|
||||
{
|
||||
//계산은 되었으나 현재위치가 전체 경로 없다면 시작노드를 현재로 변경해야한다.
|
||||
PUB._mapCanvas.CurrentPath = PathResult.result;
|
||||
PUB._virtualAGV.SetPath(PathResult.result);
|
||||
}
|
||||
@@ -133,19 +135,50 @@ namespace Project
|
||||
{
|
||||
PUB.AGV.AGVMoveStop("Path Integrity Fail");
|
||||
}
|
||||
PUB.log.AddE($"경로 무결성 오류");
|
||||
PUB.sm.SetNewRunStep(ERunStep.READY);
|
||||
PUB.log.AddE($"경로 무결성 오류로 인해 경로를 삭제 합니다");
|
||||
Console.WriteLine($"경로 무결성 오류로 인해 경로를 삭제 합니다");
|
||||
PUB._virtualAGV.SetPath(null);
|
||||
VAR.I32[eVarInt32.PathValidationError] += 1;
|
||||
if (VAR.I32[eVarInt32.PathValidationError] > 50)
|
||||
{
|
||||
PUB.log.AddE($"연속 경로 무결성 오류로 인해 중지 합니다");
|
||||
PUB.sm.SetNewRunStep(ERunStep.ERROR);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
else VAR.I32[eVarInt32.PathValidationError] = 0;
|
||||
|
||||
//현재위치 기준으로 재 계산하여. 더 최적화된 루트가 있다면 처리를 해준다.
|
||||
if (PUB._virtualAGV.CurrentPath.DetailedPath.Count > 5)
|
||||
{
|
||||
var PathResult2 = CalcPath(PUB._virtualAGV.CurrentNode, PUB._virtualAGV.TargetNode);
|
||||
if (PathResult2.result != null && PathResult2.result.Success)
|
||||
{
|
||||
//절반이상 경로가 짧을때에는 재계산을 하게한다
|
||||
var halfcnt = (int)(PUB._virtualAGV.CurrentPath.DetailedPath.Count / 2.0);
|
||||
if (PathResult2.result.DetailedPath.Count < halfcnt)
|
||||
{
|
||||
var msg = $"단축경로가 확인되었습니다. 경로를 삭제 합니다";
|
||||
PUB.log.AddE(msg);
|
||||
Console.WriteLine(msg);
|
||||
PUB._virtualAGV.SetPath(null);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
//predict 를 이용하여 다음 이동을 모두 확인한다.
|
||||
var nextAction = PUB._virtualAGV.Predict();
|
||||
if(nextAction.Reason == AGVNavigationCore.Models.eAGVCommandReason.PathOut)
|
||||
if (nextAction.Reason == AGVNavigationCore.Models.eAGVCommandReason.PathOut)
|
||||
{
|
||||
//경로이탈
|
||||
PUB._virtualAGV.CurrentPath.DetailedPath.Clear();
|
||||
var logmessage = $"경로이탈감지 시작노드를 현재위치로 설정합니다 START:{PUB._virtualAGV.StartNode},CURRENT:{PUB._virtualAGV.CurrentNode}";
|
||||
PUB.log.AddE(logmessage);
|
||||
Console.WriteLine(logmessage);
|
||||
PUB._virtualAGV.ClearPath();//.DetailedPath.Clear();
|
||||
PUB._virtualAGV.StartNode = PUB._virtualAGV.CurrentNode;
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -158,7 +191,7 @@ namespace Project
|
||||
$"현재 상태: {PUB._virtualAGV.CurrentState}\n" +
|
||||
$"현재 방향: {PUB._virtualAGV.CurrentDirection}\n" +
|
||||
$"위치 확정: {PUB._virtualAGV.IsPositionConfirmed} (RFID {PUB._virtualAGV.DetectedRfidCount}개)\n" +
|
||||
$"현재 노드: {PUB._virtualAGV.CurrentNode.Id ?? "없음"}";
|
||||
$"현재 노드: {PUB._virtualAGV.CurrentNodeID2}";
|
||||
|
||||
//모터에서 정지를 요청했다
|
||||
if (nextAction.Motor == AGVNavigationCore.Models.MotorCommand.Stop)
|
||||
@@ -181,13 +214,33 @@ namespace Project
|
||||
// 목적지 도착 여부 확인
|
||||
// 현재 노드가 타겟 노드와 같고, 위치가 확정된 상태라면 도착으로 간주
|
||||
// 단, AGV가 실제로 멈췄는지 확인 (agv_run == false)
|
||||
if (PUB._virtualAGV.IsPositionConfirmed &&
|
||||
PUB._virtualAGV.CurrentNode.Id == PUB._virtualAGV.TargetNode.Id)
|
||||
if (PUB._virtualAGV.IsPositionConfirmed)
|
||||
{
|
||||
if (PUB.AGV.system1.agv_run == false)
|
||||
{
|
||||
PUB.log.AddI($"목표 도착 및 정지 확인됨(MarkStop 완료). Node:{PUB._virtualAGV.CurrentNode.Id}");
|
||||
return true;
|
||||
//목적지도착완료시
|
||||
if (PUB._virtualAGV.CurrentNode.Id == PUB._virtualAGV.TargetNode.Id)
|
||||
{
|
||||
var node = PUB._mapCanvas.Nodes.Where(t => t.Id == PUB._virtualAGV.CurrentNodeId).FirstOrDefault();
|
||||
var rfid = node?.ID2 ?? "(X)";
|
||||
PUB.log.AddI($"목표 도착 및 정지 확인됨(MarkStop 완료) Node:{rfid}");
|
||||
return true;
|
||||
}
|
||||
|
||||
//목적지가 버퍼라면 그 앞에 멈춘다
|
||||
if (PUB._virtualAGV.TargetNode.StationType == AGVNavigationCore.Models.StationType.Buffer &&
|
||||
PUB._virtualAGV.CurrentPath != null && PUB._virtualAGV.CurrentPath.DetailedPath.Any())
|
||||
{
|
||||
if (PUB._virtualAGV.CurrentNode.Id == PUB._virtualAGV.CurrentPath.DetailedPath.Last().NodeId)
|
||||
{
|
||||
PUB.log.AddI($"목표(버퍼) 도착 및 정지 확인됨(MarkStop 완료). Node:{PUB._virtualAGV.CurrentNodeID2}");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
//아직 멈추지 않았다면 기다린다.
|
||||
}
|
||||
}
|
||||
|
||||
@@ -213,14 +266,17 @@ namespace Project
|
||||
PUB.AGV.data.Direction != dir.ToString()[0] ||
|
||||
PUB.AGV.data.Speed != spd.ToString()[0])
|
||||
{
|
||||
PUB.AGV.AGVMoveSet(new arDev.Narumi.BunkiData
|
||||
var ret = PUB.AGV.AGVMoveSet(new arDev.Narumi.BunkiData
|
||||
{
|
||||
Bunki = bunki,
|
||||
Direction = dir,
|
||||
PBSSensor = 1,
|
||||
Speed = spd,
|
||||
});
|
||||
PUB.log.Add($"Predict Run Setting = bunki:{bunki},dir:{dir},pbs:1,spd:{spd}");
|
||||
if (ret == arDev.eNarumiCommandResult.Success)
|
||||
PUB.log.Add($"Predict Run Setting = bunki:{bunki},dir:{dir},pbs:1,spd:{spd}");
|
||||
else
|
||||
PUB.log.AddE($"Predict Run Setting = bunki:{bunki},dir:{dir},pbs:1,spd:{spd}");
|
||||
}
|
||||
|
||||
// AGV가 정지 상태라면 구동 시작
|
||||
@@ -250,14 +306,18 @@ namespace Project
|
||||
PUB.AGV.error.Emergency == false &&
|
||||
PUB.AGV.system1.agv_run == false)
|
||||
{
|
||||
PUB.AGV.AGVMoveSet(new arDev.Narumi.BunkiData
|
||||
var ret = PUB.AGV.AGVMoveSet(new arDev.Narumi.BunkiData
|
||||
{
|
||||
Bunki = arDev.Narumi.eBunki.Strate,
|
||||
Direction = arDev.Narumi.eMoveDir.Forward,
|
||||
PBSSensor = 1,
|
||||
Speed = arDev.Narumi.eMoveSpd.Low,
|
||||
});
|
||||
PUB.AGV.AGVMoveRun( arDev.Narumi.eRunOpt.Forward);//
|
||||
if (ret == arDev.eNarumiCommandResult.Success)
|
||||
{
|
||||
PUB.AGV.AGVMoveRun(arDev.Narumi.eRunOpt.Forward);//
|
||||
}
|
||||
|
||||
tm_gocharge_command = DateTime.Now;
|
||||
}
|
||||
}
|
||||
@@ -278,14 +338,15 @@ namespace Project
|
||||
PUB.AGV.error.Emergency == false &&
|
||||
PUB.AGV.system1.agv_run == false)
|
||||
{
|
||||
PUB.AGV.AGVMoveSet(new arDev.Narumi.BunkiData
|
||||
var ret = PUB.AGV.AGVMoveSet(new arDev.Narumi.BunkiData
|
||||
{
|
||||
Bunki = arDev.Narumi.eBunki.Strate,
|
||||
Direction = arDev.Narumi.eMoveDir.Backward,
|
||||
PBSSensor = 1,
|
||||
Speed = arDev.Narumi.eMoveSpd.Low,
|
||||
});
|
||||
PUB.AGV.AGVMoveRun(arDev.Narumi.eRunOpt.Backward);//
|
||||
if (ret == arDev.eNarumiCommandResult.Success)
|
||||
PUB.AGV.AGVMoveRun(arDev.Narumi.eRunOpt.Backward);//
|
||||
LastCommandTime = DateTime.Now;
|
||||
}
|
||||
}
|
||||
@@ -311,7 +372,7 @@ namespace Project
|
||||
// 만약 수행되지 않았다면 여기서 수행.
|
||||
if (pathResult.DockingValidation == null)
|
||||
{
|
||||
pathResult.DockingValidation = AGVNavigationCore.Utils.DockingValidator.ValidateDockingDirection(pathResult, PUB._mapCanvas.Nodes);
|
||||
pathResult.DockingValidation = AGVNavigationCore.Utils.DockingValidator.ValidateDockingDirection(pathResult, PUB._mapCanvas.Nodes);
|
||||
}
|
||||
|
||||
// 검증 결과 확인
|
||||
|
||||
Reference in New Issue
Block a user