This commit is contained in:
backuppc
2025-12-12 17:27:50 +09:00
parent 07ddc0425f
commit 4e9d29d22f
44 changed files with 7173 additions and 61 deletions

View File

@@ -1775,6 +1775,11 @@ namespace AGVNavigationCore.Controls
/// </summary>
private Color GetAGVCenterColor(AGVState state)
{
// Stop-Mark 상태 (Error 상태와 유사하게 처리하거나 별도 처리)
// 여기서는 AGVState에 StopMark가 없으므로, 외부에서 상태를 Error로 설정하거나
// 별도의 플래그를 확인해야 함. 하지만 IAGV 인터페이스에는 플래그가 없음.
// 따라서 fMain에서 상태를 Error로 설정하는 것을 권장.
switch (state)
{
case AGVState.Moving: return Color.White;
@@ -1794,7 +1799,7 @@ namespace AGVNavigationCore.Controls
{
case AGVState.Moving: return Color.DarkGreen;
case AGVState.Charging: return Color.DarkBlue;
case AGVState.Error: return Color.DarkRed;
case AGVState.Error: return Color.DarkRed; // Stop-Mark 시 Error 상태 사용
case AGVState.Docking: return Color.DarkOrange;
default: return Color.DarkGray;
}

View File

@@ -17,6 +17,16 @@ namespace AGVNavigationCore.Controls
var worldPoint = ScreenToWorld(e.Location);
var hitNode = GetNodeAt(worldPoint);
// 에뮬레이터 모드 처리
if (_canvasMode == CanvasMode.Emulator)
{
if (e.Button == MouseButtons.Right && hitNode != null)
{
NodeRightClicked?.Invoke(this, hitNode);
}
return;
}
// 🔥 어떤 모드에서든 노드/빈 공간 클릭 시 선택 이벤트 발생 (속성창 업데이트)
bool ctrlPressed = (ModifierKeys & Keys.Control) == Keys.Control;

View File

@@ -36,7 +36,8 @@ namespace AGVNavigationCore.Controls
public enum CanvasMode
{
Edit, // 편집 가능 (맵 에디터)
Sync // 동기화 모드 (장비 설정 동기화)
Sync, // 동기화 모드 (장비 설정 동기화)
Emulator // 에뮬레이터 모드
}
/// <summary>
@@ -146,6 +147,9 @@ namespace AGVNavigationCore.Controls
// 컨텍스트 메뉴
private ContextMenuStrip _contextMenu;
// 이벤트
public event EventHandler<MapNode> NodeRightClicked;
#endregion
#region Events

View File

@@ -81,6 +81,13 @@ namespace AGVNavigationCore.Models
private List<string> _detectedRfids = new List<string>(); // 감지된 RFID 목록
private bool _isPositionConfirmed = false; // 위치 확정 여부 (RFID 2개 이상 감지)
// 에뮬레이터용 추가 속성
public double Angle { get; set; } = 0; // 0 = Right, 90 = Down, 180 = Left, 270 = Up (Standard Math)
// But AGV Direction: Forward usually means "Front of AGV".
// Let's assume Angle is the orientation of the AGV in degrees.
public bool IsStopMarkOn { get; set; } = false;
#endregion
#region Properties
@@ -433,6 +440,27 @@ namespace AGVNavigationCore.Models
OnError("긴급 정지가 실행되었습니다.");
}
/// <summary>
/// 일시 정지 (경로 유지)
/// </summary>
public void Pause()
{
_isMoving = false;
_currentSpeed = 0;
}
/// <summary>
/// 이동 재개
/// </summary>
public void Resume()
{
if (_currentPath != null && _remainingNodes != null && _remainingNodes.Count > 0)
{
_isMoving = true;
SetState(AGVState.Moving);
}
}
#endregion
#region Public Methods - ( )

View File

@@ -15,6 +15,8 @@ using Newtonsoft.Json;
using AGVNavigationCore.PathFinding.Planning;
using AGVNavigationCore.PathFinding.Core;
using AGVSimulator.Models;
using System.IO.Ports;
using System.Text;
namespace AGVSimulator.Forms
{
@@ -25,6 +27,86 @@ namespace AGVSimulator.Forms
{
#region Fields
// Emulator Fields
private SerialPort _emulatorPort;
private ComboBox _portCombo;
private Button _connectButton;
private bool _isEmulatorConnected = false;
// Emulator State Fields
private UInt16 _emu_system0 = 0;
private UInt16 _emu_system1 = 0;
private UInt16 _emu_error = 0;
private byte _emu_signal = 0;
private char _emu_sts_bunki = 'S';
private char _emu_sts_speed = 'L';
private char _emu_sts_dir = 'F';
private char _emu_sts_sensor = '1';
private string _lastSentNodeId = null;
public enum esystemflag0
{
Memory_RW_State = 5,
EXT_IO_Conn_State,
RFID_Conn_State,
M5E_Module_Run_State = 8,
Front_Ultrasonic_Conn_State,
Front_Untrasonic_Sensor_State,
Side_Ultrasonic_Conn_State,
Side_Ultrasonic_Sensor_State = 12,
Front_Guide_Sensor_State,
Rear_Guide_Sensor_State,
Battery_Level_Check
}
public enum esystemflag1
{
Side_Detect_Ignore = 3,
Melody_check,
Mark2_check,
Mark1_check,
gateout_check,
Battery_charging = 8,
re_Start,
front_detect_ignore,
front_detect_check,
stop_by_front_detect = 12,
stop_by_cross_in,
agv_stop,
agv_run
}
public enum eerror
{
Emergency = 0,
Overcurrent,
Charger_run_error,
Charger_pos_error,
line_out_error = 4,
runerror_by_no_magent_line,
controller_comm_error = 11,
arrive_ctl_comm_error,
door_ctl_comm_error,
charger_comm_error,
cross_ctrl_comm_error,
}
public enum esignal
{
front_gate_out = 0,
rear_sensor_out,
mark_sensor_1,
mark_sensor_2,
front_left_sensor,
front_right_sensor,
front_center_sensor,
charger_align_sensor,
}
public enum estsvaluetype
{
bunki,
speed,
direction,
sensor
}
private UnifiedAGVCanvas _simulatorCanvas;
private List<MapNode> _mapNodes;
private AGVPathfinder _advancedPathfinder;
@@ -92,6 +174,9 @@ namespace AGVSimulator.Forms
// 방향 콤보박스 초기화
InitializeDirectionCombo();
// 에뮬레이터 UI 초기화
InitializeEmulatorUI();
// 초기 상태 설정
UpdateUI();
@@ -716,12 +801,32 @@ namespace AGVSimulator.Forms
foreach (var agv in _agvList)
{
agv.Update(100); // 100ms 간격으로 업데이트
// Emulator Tag Logic
if (_isEmulatorConnected && agv == _agvList.FirstOrDefault())
{
if (agv.CurrentNodeId != null && agv.CurrentNodeId != _lastSentNodeId)
{
var rfid = GetRfidByNodeId(agv.CurrentNodeId);
if (!string.IsNullOrEmpty(rfid))
{
SendTag(rfid);
_lastSentNodeId = agv.CurrentNodeId;
}
}
}
}
}
// UI 업데이트
UpdateUI();
_simulatorCanvas.Invalidate(); // 화면 다시 그리기
// 에뮬레이터 상태 전송
if (_isEmulatorConnected)
{
SendEmulatorStatus();
}
}
#endregion
@@ -2005,6 +2110,412 @@ namespace AGVSimulator.Forms
MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
#region Emulator Logic
private void InitializeEmulatorUI()
{
// 에뮬레이터 제어 패널 생성
var emulatorPanel = new GroupBox();
emulatorPanel.Text = "AGV Emulator (RS232)";
emulatorPanel.Height = 60;
emulatorPanel.Dock = DockStyle.Top;
var layout = new FlowLayoutPanel();
layout.Dock = DockStyle.Fill;
layout.Padding = new Padding(5);
layout.AutoSize = true;
// 포트 선택 콤보박스
_portCombo = new ComboBox();
_portCombo.Width = 100;
_portCombo.DropDownStyle = ComboBoxStyle.DropDownList;
_portCombo.DropDown += (s, e) => {
_portCombo.Items.Clear();
_portCombo.Items.AddRange(SerialPort.GetPortNames());
};
_portCombo.Items.AddRange(SerialPort.GetPortNames());
if (_portCombo.Items.Count > 0) _portCombo.SelectedIndex = 0;
// 연결 버튼
_connectButton = new Button();
_connectButton.Text = "Connect";
_connectButton.Click += OnConnectEmulator_Click;
layout.Controls.Add(new Label { Text = "Port:", AutoSize = true, Margin = new Padding(3, 8, 3, 3) });
layout.Controls.Add(_portCombo);
layout.Controls.Add(_connectButton);
emulatorPanel.Controls.Add(layout);
// 폼의 최상단에 추가
this.Controls.Add(emulatorPanel);
emulatorPanel.BringToFront();
}
private void OnConnectEmulator_Click(object sender, EventArgs e)
{
if (_isEmulatorConnected)
{
DisconnectEmulator();
}
else
{
if (_portCombo.SelectedItem == null)
{
MessageBox.Show("포트를 선택해주세요.");
return;
}
ConnectEmulator(_portCombo.SelectedItem.ToString());
}
}
private void ConnectEmulator(string portName)
{
try
{
_emulatorPort = new SerialPort(portName, 115200, Parity.None, 8, StopBits.One);
_emulatorPort.DataReceived += OnEmulatorDataReceived;
_emulatorPort.Open();
_isEmulatorConnected = true;
_connectButton.Text = "Disconnect";
_portCombo.Enabled = false;
MessageBox.Show($"에뮬레이터 시작: {portName}");
}
catch (Exception ex)
{
MessageBox.Show($"연결 실패: {ex.Message}");
}
}
private void DisconnectEmulator()
{
try
{
if (_emulatorPort != null && _emulatorPort.IsOpen)
{
_emulatorPort.Close();
}
_isEmulatorConnected = false;
_connectButton.Text = "Connect";
_portCombo.Enabled = true;
}
catch (Exception ex)
{
MessageBox.Show($"해제 실패: {ex.Message}");
}
}
private StringBuilder _recvBuffer = new StringBuilder();
private void OnEmulatorDataReceived(object sender, SerialDataReceivedEventArgs e)
{
try
{
string data = _emulatorPort.ReadExisting();
_recvBuffer.Append(data);
string buffer = _recvBuffer.ToString();
int stxIndex = buffer.IndexOf((char)0x02);
while (stxIndex >= 0)
{
int etxIndex = buffer.IndexOf((char)0x03, stxIndex);
if (etxIndex > stxIndex)
{
string packet = buffer.Substring(stxIndex + 1, etxIndex - stxIndex - 1);
ProcessEmulatorPacket(packet);
// 처리된 패킷 제거
buffer = buffer.Substring(etxIndex + 1);
stxIndex = buffer.IndexOf((char)0x02);
}
else
{
break; // ETX 아직 안옴
}
}
_recvBuffer.Clear();
_recvBuffer.Append(buffer);
}
catch (Exception ex)
{
Console.WriteLine($"Emulator Recv Error: {ex.Message}");
}
}
#region Emulator Helpers
private bool GetBit(ref UInt16 _value, int idx)
{
var offset = (UInt16)(1 << idx);
return (_value & offset) != 0;
}
private bool SetBit(ref UInt16 _value, int idx, bool value)
{
var oldvalue = GetBit(ref _value, idx);
if (value)
{
var offset = (UInt16)(1 << idx);
_value = (UInt16)(_value | offset);
}
else
{
var offset = (UInt16)(~(1 << idx));
_value = (UInt16)(_value & offset);
}
return oldvalue != value;
}
private bool SetBit(ref byte _value, int idx, bool value)
{
var offset = (byte)(1 << idx);
if (value) _value |= offset;
else _value &= (byte)~offset;
return true;
}
private void SetAGV(esystemflag0 flag, bool value)
{
SetBit(ref _emu_system0, (int)flag, value);
}
private void SetAGV(esystemflag1 flag, bool value)
{
SetBit(ref _emu_system1, (int)flag, value);
}
private void SetAGV(eerror flag, bool value)
{
SetBit(ref _emu_error, (int)flag, value);
}
private void SetAGV(esignal flag, bool value)
{
SetBit(ref _emu_signal, (int)flag, value);
}
private void SetSTS(estsvaluetype target, char value)
{
switch (target)
{
case estsvaluetype.sensor: _emu_sts_sensor = value; break;
case estsvaluetype.direction: _emu_sts_dir = value; break;
case estsvaluetype.speed: _emu_sts_speed = value; break;
case estsvaluetype.bunki: _emu_sts_bunki = value; break;
}
}
#endregion
private void ProcessEmulatorPacket(string packet)
{
// Packet: CMD(3) + DATA(...) + Checksum(2)
// But here packet is substring between STX and ETX.
// Example: STS...Checksum
if (packet.Length < 3) return;
string cmd = packet.Substring(0, 3);
string data = "";
if (packet.Length > 5) // CMD + Checksum(2)
{
data = packet.Substring(3, packet.Length - 5);
}
// AGV 제어 (첫 번째 AGV 대상)
var agv = _agvList.FirstOrDefault();
this.Invoke(new Action(() => {
switch (cmd)
{
case "CRN": // 기동명령
if (data.Length > 0) SetSTS(estsvaluetype.direction, data[0]);
SetAGV(esystemflag1.agv_stop, false);
SetAGV(esystemflag1.agv_run, true);
if (agv != null) agv.Resume();
break;
case "CST": // 중지명령
if (data.StartsWith("M"))
{
// Mark Stop
// TODO: Implement Mark Stop logic in VirtualAGV if needed
// For now, just log it
Console.WriteLine("Mark Stop Command Received");
}
else
{
SetAGV(esystemflag1.agv_run, false);
SetAGV(esystemflag1.agv_stop, true);
if (agv != null) agv.Pause();
}
break;
case "CBR": // 분기명령
// FSL1
if (data.Length >= 4)
{
SetSTS(estsvaluetype.direction, data[0]);
SetSTS(estsvaluetype.bunki, data[1]);
SetSTS(estsvaluetype.speed, data[2]);
SetSTS(estsvaluetype.sensor, data[3]);
}
break;
case "CRT": // 수동제어
if (data.Length >= 4)
{
_emu_sts_dir = data[0];
_emu_sts_bunki = data[1];
_emu_sts_speed = data[2];
_emu_sts_sensor = data[3];
SetAGV(esystemflag1.agv_stop, false);
SetAGV(esystemflag1.agv_run, true);
if (agv != null) agv.Resume();
}
break;
case "SFR": // Reset
SetAGV(eerror.Emergency, false);
SetAGV(eerror.line_out_error, false);
SetAGV(eerror.Overcurrent, false);
SetAGV(esystemflag1.agv_run, false);
SetAGV(esystemflag1.agv_stop, true);
if (agv != null) agv.Pause();
break;
case "CBT": // 충전
SetAGV(esystemflag1.Battery_charging, true);
if (data.Length >= 5)
{
var cmdChar = data[4];
if (cmdChar == 'I') SetAGV(esystemflag1.Battery_charging, true);
else SetAGV(esystemflag1.Battery_charging, false);
}
break;
case "ACK":
// Log ACK
break;
default:
// Send ACK for other commands
SendCmd("ACK", cmd);
break;
}
}));
}
private void SendCmd(string cmd, string value)
{
if (_emulatorPort == null || !_emulatorPort.IsOpen) return;
var barr = new List<byte>();
barr.Add(0x02);
barr.AddRange(System.Text.Encoding.Default.GetBytes(cmd));
barr.AddRange(System.Text.Encoding.Default.GetBytes(value));
barr.Add((byte)'*');
barr.Add((byte)'*');
barr.Add(0x03);
try
{
_emulatorPort.Write(barr.ToArray(), 0, barr.Count);
}
catch { }
}
public void SendTag(string tagno)
{
if (_emulatorPort == null || !_emulatorPort.IsOpen) return;
tagno = tagno.PadLeft(6, '0');
if (tagno.Length > 6) tagno = tagno.Substring(0, 6);
var barr = new List<byte>();
barr.Add(0x02);
barr.Add((byte)'T');
barr.Add((byte)'A');
barr.Add((byte)'G');
barr.AddRange(System.Text.Encoding.Default.GetBytes(tagno));
barr.Add((byte)'*');
barr.Add((byte)'*');
barr.Add(0x03);
try
{
_emulatorPort.Write(barr.ToArray(), 0, barr.Count);
}
catch { }
}
private void SendEmulatorStatus()
{
if (_emulatorPort == null || !_emulatorPort.IsOpen) return;
var agv = _agvList.FirstOrDefault();
// Sync state from VirtualAGV
if (agv != null)
{
// Update Battery
// Update Position/Tag?
}
// STS Packet Construction
// STS(3) + Volt(3) + Sys0(4) + Sys1(4) + Err(4) + Spd(1) + Bunki(1) + Dir(1) + Sensor(1) + Signal(2) + Checksum(2)
// Default buffer
var sample = "02 53 54 53 32 35 38 46 46 46 46 34 30 30 30 30 30 30 30 4C 53 46 30 30 30 30 30 30 33 41 03";
var barr = sample.Split(' ').Select(t => Convert.ToByte(t, 16)).ToArray();
// Volt (255 for now)
var voltstr = "255";
var bufarr = System.Text.Encoding.Default.GetBytes(voltstr);
Array.Copy(bufarr, 0, barr, 4, bufarr.Length);
// System0
bufarr = System.Text.Encoding.Default.GetBytes(_emu_system0.ToString("X2").PadLeft(4, '0'));
Array.Copy(bufarr, 0, barr, 7, bufarr.Length);
// System1
bufarr = System.Text.Encoding.Default.GetBytes(_emu_system1.ToString("X2").PadLeft(4, '0'));
Array.Copy(bufarr, 0, barr, 11, bufarr.Length);
// Error
bufarr = System.Text.Encoding.Default.GetBytes(_emu_error.ToString("X2").PadLeft(4, '0'));
Array.Copy(bufarr, 0, barr, 15, bufarr.Length);
// Status Chars
barr[19] = (byte)_emu_sts_speed;
barr[20] = (byte)_emu_sts_bunki;
barr[21] = (byte)_emu_sts_dir;
barr[22] = (byte)_emu_sts_sensor;
// Signal
bufarr = System.Text.Encoding.Default.GetBytes(_emu_signal.ToString("X2").PadLeft(2, '0'));
Array.Copy(bufarr, 0, barr, 23, bufarr.Length);
// Checksum (**)
barr[barr.Length - 3] = (byte)'*';
barr[barr.Length - 2] = (byte)'*';
try
{
_emulatorPort.Write(barr, 0, barr.Length);
}
catch { }
}
private string CalculateChecksum(string data)
{
int sum = 0;
foreach (char c in data) sum += c;
// 16진수 변환 후 뒤 2자리
string hex = sum.ToString("X");
if (hex.Length >= 2) return hex.Substring(hex.Length - 2);
return hex.PadLeft(2, '0');
}
#endregion
}
/// <summary>

View File

@@ -284,6 +284,24 @@
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="PUB.cs" />
<Compile Include="CSetting.cs" />
<Compile Include="StateMachine\Step\_SM_RUN_CLEANER_IN.cs">
<SubType>Form</SubType>
</Compile>
<Compile Include="StateMachine\Step\_SM_RUN_CLEANER_OUT.cs">
<SubType>Form</SubType>
</Compile>
<Compile Include="StateMachine\Step\_SM_RUN_LOADER_IN.cs">
<SubType>Form</SubType>
</Compile>
<Compile Include="StateMachine\Step\_SM_RUN_LOADER_OUT.cs">
<SubType>Form</SubType>
</Compile>
<Compile Include="StateMachine\Step\_SM_RUN_UNLOADER_IN.cs">
<SubType>Form</SubType>
</Compile>
<Compile Include="StateMachine\Step\_SM_RUN_UNLOADER_OUT.cs">
<SubType>Form</SubType>
</Compile>
<Compile Include="StateMachine\Step\_Util.cs">
<SubType>Form</SubType>
</Compile>

View File

@@ -159,6 +159,13 @@ namespace Project.Device
public bool BufferOutComplete { get; set; }
public bool BufferReadyError { get; set; }
public bool LoaderInComplete { get; set; }
public bool LoaderOutComplete { get; set; }
public bool UnloaderInComplete { get; set; }
public bool UnloaderOutComplete { get; set; }
public bool CleanerInComplete { get; set; }
public bool CleanerOutComplete { get; set; }
/// <summary>
/// AGV상태를 Xbee 로 전송한다

View File

@@ -171,7 +171,7 @@ namespace Project
}
break;
case ERunStep.MARKSTROPB: //후진방향으로 마크스탑
case ERunStep.MARKSTOPB: //후진방향으로 마크스탑
case ERunStep.MARKSTOPF: //전진방향으로 마크스탑
//이동중이지 않다면 먼저 이동을 진행한다
@@ -249,6 +249,96 @@ namespace Project
}
}
break;
case ERunStep.LOADER_OUT: //로더아웃
if (_SM_RUN_LOADER_OUT(runStepisFirst, PUB.sm.GetRunSteptime))
{
PUB.Speak(Lang.);
//도킹완료상태를 업데이트한다.
PUB.XBE.LoaderInComplete = false;
PUB.XBE.LoaderOutComplete = true;
//대기상태로 전환
PUB.sm.SetNewRunStep(ERunStep.READY);
return;
}
break;
case ERunStep.LOADER_IN: //로더도킹
if (_SM_RUN_LOADER_IN(runStepisFirst, PUB.sm.GetRunSteptime))
{
PUB.Speak(Lang.);
//도킹완료상태를 업데이트한다.
PUB.XBE.LoaderInComplete = true;
//로더아웃으로 자동 진행 합니다
PUB.sm.ClearRunStep();
PUB.sm.SetNewRunStep(ERunStep.LOADER_OUT);
return;
}
break;
case ERunStep.UNLOADER_OUT: //언로더아웃
if (_SM_RUN_UNLOADER_OUT(runStepisFirst, PUB.sm.GetRunSteptime))
{
PUB.Speak(Lang.);
//도킹완료상태를 업데이트한다.
PUB.XBE.UnloaderInComplete = false;
PUB.XBE.UnloaderOutComplete = true;
//대기상태로 전환
PUB.sm.SetNewRunStep(ERunStep.READY);
return;
}
break;
case ERunStep.UNLOADER_IN: //언로더도킹
if (_SM_RUN_UNLOADER_IN(runStepisFirst, PUB.sm.GetRunSteptime))
{
PUB.Speak(Lang.);
//도킹완료상태를 업데이트한다.
PUB.XBE.UnloaderInComplete = true;
//언로더아웃으로 자동 진행 합니다
PUB.sm.ClearRunStep();
PUB.sm.SetNewRunStep(ERunStep.UNLOADER_OUT);
return;
}
break;
case ERunStep.CLEANER_OUT: //클리너아웃
if (_SM_RUN_CLEANER_OUT(runStepisFirst, PUB.sm.GetRunSteptime))
{
PUB.Speak(Lang.);
//도킹완료상태를 업데이트한다.
PUB.XBE.CleanerInComplete = false;
PUB.XBE.CleanerOutComplete = true;
//대기상태로 전환
PUB.sm.SetNewRunStep(ERunStep.READY);
return;
}
break;
case ERunStep.CLEANER_IN: //클리너도킹
if (_SM_RUN_CLEANER_IN(runStepisFirst, PUB.sm.GetRunSteptime))
{
PUB.Speak(Lang.);
//도킹완료상태를 업데이트한다.
PUB.XBE.CleanerInComplete = true;
//클리너아웃으로 자동 진행 합니다
PUB.sm.ClearRunStep();
PUB.sm.SetNewRunStep(ERunStep.CLEANER_OUT);
return;
}
break;
case ERunStep.BUFFER_OUT: //버퍼아웃
if (_SM_RUN_BUFFER_OUT(runStepisFirst, PUB.sm.GetRunSteptime))
{

View File

@@ -22,40 +22,14 @@ namespace Project
var funcname = "_SM_RUN_BUFFER_IN";
var idx = 1;
if (runStepisFirst)
{
//PUB.flag.set(EFlag.FLAG_NEXTSTOP_ALIGN, false);
VAR.BOOL[eVarBool.FLAG_NEXTSTOP_ALIGN] = false;//
//VAR.BOOL[eVarBool.FLAG_NEXTSTOP_MARK] = false;//);
}
//HW 연결오류
if (PUB.AGV.IsOpen == false)
{
PUB.Result.SetResultMessage(eResult.Hardware, eECode.AGVCONN, eNextStep.ERROR);
return false;
}
//충전 상태가 OFF되어야 동작하게한다
if (_SM_RUN_CHGOFF(isFirst, stepTime) == false)
return false;
if (_SM_RUN_CHGOFF(isFirst, stepTime) == false) return false;
//라이더멈춤이 설정되어있다면 음성으로 알려준다 200409
if (PUB.AGV.system1.stop_by_front_detect == true)
{
var tsSpeak = DateTime.Now - LastSpeakTime;
if (tsSpeak.TotalSeconds >= PUB.setting.alarmSoundTerm)
{
PUB.Speak(Lang.);
LastSpeakTime = DateTime.Now;
}
return false;
}
//라이더멈춤이 설정되어있다면 음성으로 알려준다
if (CheckLiderStop() == false) return false;
//현재 위치가 결정되어있는지 체크한다
if (_SM_RUN_POSCHK(isFirst, stepTime) == false)
return false;
if (_SM_RUN_POSCHK(isFirst, stepTime) == false) return false;
/*
* 버퍼IN시퀀스

View File

@@ -14,37 +14,15 @@ namespace Project
public Boolean _SM_RUN_BUFFER_OUT(bool isFirst, TimeSpan stepTime)
{
if (runStepisFirst)
{
}
//HW 연결오류
if (PUB.AGV.IsOpen == false)
{
PUB.Result.SetResultMessage(eResult.Hardware, eECode.AGVCONN, eNextStep.ERROR);
return false;
}
//충전 상태가 OFF되어야 동작하게한다
if (_SM_RUN_CHGOFF(isFirst, stepTime) == false)
return false;
if (_SM_RUN_CHGOFF(isFirst, stepTime) == false) return false;
//라이더멈춤이 설정되어있다면 음성으로 알려준다 200409
if (PUB.AGV.system1.stop_by_front_detect == true)
{
var tsSpeak = DateTime.Now - LastSpeakTime;
if (tsSpeak.TotalSeconds >= PUB.setting.alarmSoundTerm)
{
PUB.Speak(Lang.);
LastSpeakTime = DateTime.Now;
}
return false;
}
//라이더멈춤이 설정되어있다면 음성으로 알려준다
if (CheckLiderStop() == false) return false;
//현재 위치가 결정되어있는지 체크한다
if (_SM_RUN_POSCHK(isFirst, stepTime) == false)
return false;
if (_SM_RUN_POSCHK(isFirst, stepTime) == false) return false;
var idx = 1;
if (PUB.sm.RunStepSeq == idx++)

View File

@@ -0,0 +1,155 @@
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Text;
using Project.StateMachine;
using COMM;
using AR;
namespace Project
{
public partial class fMain
{
/// <summary>
/// 클리너 진입
/// </summary>
public Boolean _SM_RUN_CLEANER_IN(bool isFirst, TimeSpan stepTime)
{
var funcname = "_SM_RUN_CLEANER_IN";
var idx = 1;
//충전 상태가 OFF되어야 동작하게한다
if (_SM_RUN_CHGOFF(isFirst, stepTime) == false) return false;
//라이더멈춤이 설정되어있다면 음성으로 알려준다
if (CheckLiderStop() == false) return false;
//현재 위치가 결정되어있는지 체크한다
if (_SM_RUN_POSCHK(isFirst, stepTime) == false) return false;
/*
* 클리너 IN 시퀀스 (버퍼 복사 - 턴 제거)
* 1. LIFT DOWN
* 2. 후진-저속-마크다운 실행
*/
if (PUB.sm.RunStepSeq == idx++)
{
PUB.log.Add("클리너진입시작");
PUB.Speak("클리너 작업을 시작합니다");
PUB.sm.UpdateRunStepSeq();
return false;
}
else if (PUB.sm.RunStepSeq == idx++)
{
//리프트를 내린다.
PUB.AGV.LiftControl(arDev.Narumi.LiftCommand.DN);
VAR.TIME.Update(eVarTime.LastTurnCommandTime);
PUB.sm.UpdateRunStepSeq();
return false;
}
else if (PUB.sm.RunStepSeq == idx++)
{
//리프트다운센서를 확인한다.
var liftdown = true;
if (liftdown == false)
{
var ts = VAR.TIME.RUN(eVarTime.LastTurnCommandTime);
if (ts.TotalSeconds > 10)
{
PUB.AGV.LiftControl(arDev.Narumi.LiftCommand.STP);
PUB.log.AddE("리프트 하강이 확인되지 않습니다(10초)");
PUB.sm.SetNewRunStep(ERunStep.ERROR);
return false;
}
}
PUB.log.Add("리프트 하강 완료");
PUB.sm.UpdateRunStepSeq();
return false;
}
else if (PUB.sm.RunStepSeq == idx++)
{
//마크스탑셋팅
PUB.AGV.AGVMoveStop(funcname, arDev.Narumi.eStopOpt.MarkStop);
VAR.TIME.Update(eVarTime.LastTurnCommandTime);
PUB.sm.UpdateRunStepSeq();
return false;
}
else if (PUB.sm.RunStepSeq == idx++)
{
//저속이동
var moveset = 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)
{
var ts = VAR.TIME.RUN(eVarTime.LastTurnCommandTime);
if (ts.TotalSeconds > 10)
{
PUB.AGV.AGVMoveStop(funcname);
PUB.log.AddE("AGV속도설정이 완료되지 않았습니다");
PUB.sm.SetNewRunStep(ERunStep.ERROR);
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;
}
else if (PUB.sm.RunStepSeq == idx++)
{
//마크스탑신호가 3초이내로 들어와야 한다
if (VAR.BOOL[eVarBool.NEXTSTOP_MARK] == false)
{
var ts = VAR.TIME.RUN(eVarTime.LastTurnCommandTime);
if (ts.TotalSeconds > 3)
{
PUB.AGV.AGVMoveStop(funcname);
PUB.log.AddE("MARK STOP신호가 확인되지 않습니다");
PUB.sm.SetNewRunStep(ERunStep.ERROR);
return false;
}
}
VAR.TIME.Update(eVarTime.LastTurnCommandTime);
PUB.sm.UpdateRunStepSeq();
return false;
}
else if (PUB.sm.RunStepSeq == idx++)
{
//AGV가 멈출때까지 기다린다.
if (PUB.AGV.system1.agv_run == true)
{
var ts = VAR.TIME.RUN(eVarTime.LastTurnCommandTime);
if (ts.TotalSeconds > 10)
{
PUB.AGV.AGVMoveStop(funcname);
PUB.log.AddE("AGV가 멈추지 않아 강제종료 합니다");
PUB.sm.SetNewRunStep(ERunStep.ERROR);
return false;
}
return false;
}
VAR.TIME.Update(eVarTime.LastTurnCommandTime);
PUB.sm.UpdateRunStepSeq();
return false;
}
else if (PUB.sm.RunStepSeq == idx++)
{
//완료되었다.
PUB.log.Add("클리너진입완료");
PUB.sm.UpdateRunStepSeq();
return false;
}
PUB.AddEEDB($"클리너진입완료({PUB.Result.TargetPos})");
return true;
}
}
}

View File

@@ -0,0 +1,80 @@
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Text;
using Project.StateMachine;
using COMM;
using AR;
namespace Project
{
public partial class fMain
{
/// <summary>
/// 클리너 배출
/// </summary>
public Boolean _SM_RUN_CLEANER_OUT(bool isFirst, TimeSpan stepTime)
{
//충전 상태가 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
{
Bunki = arDev.Narumi.eBunki.Strate,
Direction = arDev.Narumi.eMoveDir.Forward,
PBSSensor = 0,
Speed = arDev.Narumi.eMoveSpd.Low,
});
PUB.sm.UpdateRunStepSeq();
return false;
}
else if (PUB.sm.RunStepSeq == idx++)
{
//전진이동
PUB.AGV.AGVMoveRun(arDev.Narumi.eRunOpt.Forward);
PUB.sm.UpdateRunStepSeq();
return false;
}
else if (PUB.sm.RunStepSeq == idx++)
{
//마크스탑
PUB.AGV.AGVMoveStop("cleaner out", arDev.Narumi.eStopOpt.MarkStop);
PUB.sm.UpdateRunStepSeq();
return false;
}
else if (PUB.sm.RunStepSeq == idx++)
{
//이동확인
if (PUB.AGV.system1.agv_run == false)
{
return false;
}
PUB.sm.UpdateRunStepSeq();
return false;
}
else if (PUB.sm.RunStepSeq == idx++)
{
//멈춤확인
if (PUB.AGV.system1.agv_run == true)
{
return false;
}
PUB.sm.UpdateRunStepSeq();
return false;
}
return true;
}
}
}

View File

@@ -0,0 +1,155 @@
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Text;
using Project.StateMachine;
using COMM;
using AR;
namespace Project
{
public partial class fMain
{
/// <summary>
/// 로더 진입
/// </summary>
public Boolean _SM_RUN_LOADER_IN(bool isFirst, TimeSpan stepTime)
{
var funcname = "_SM_RUN_LOADER_IN";
var idx = 1;
//충전 상태가 OFF되어야 동작하게한다
if (_SM_RUN_CHGOFF(isFirst, stepTime) == false) return false;
//라이더멈춤이 설정되어있다면 음성으로 알려준다
if (CheckLiderStop() == false) return false;
//현재 위치가 결정되어있는지 체크한다
if (_SM_RUN_POSCHK(isFirst, stepTime) == false) return false;
/*
* 로더 IN 시퀀스 (버퍼 복사 - 턴 제거)
* 1. LIFT DOWN
* 2. 후진-저속-마크다운 실행
*/
if (PUB.sm.RunStepSeq == idx++)
{
PUB.log.Add("로더진입시작");
PUB.Speak("로더 작업을 시작합니다"); // Lang resource might not exist, using string
PUB.sm.UpdateRunStepSeq();
return false;
}
else if (PUB.sm.RunStepSeq == idx++)
{
//리프트를 내린다.
PUB.AGV.LiftControl(arDev.Narumi.LiftCommand.DN);
VAR.TIME.Update(eVarTime.LastTurnCommandTime);
PUB.sm.UpdateRunStepSeq();
return false;
}
else if (PUB.sm.RunStepSeq == idx++)
{
//리프트다운센서를 확인한다.
var liftdown = true; // 센서 확인 로직이 주석처리되어 있거나 하드코딩되어 있었음 (버퍼 코드 참조)
if (liftdown == false)
{
var ts = VAR.TIME.RUN(eVarTime.LastTurnCommandTime);
if (ts.TotalSeconds > 10)
{
PUB.AGV.LiftControl(arDev.Narumi.LiftCommand.STP);
PUB.log.AddE("리프트 하강이 확인되지 않습니다(10초)");
PUB.sm.SetNewRunStep(ERunStep.ERROR);
return false;
}
}
PUB.log.Add("리프트 하강 완료");
PUB.sm.UpdateRunStepSeq();
return false;
}
else if (PUB.sm.RunStepSeq == idx++)
{
//마크스탑셋팅
PUB.AGV.AGVMoveStop(funcname, arDev.Narumi.eStopOpt.MarkStop);
VAR.TIME.Update(eVarTime.LastTurnCommandTime);
PUB.sm.UpdateRunStepSeq();
return false;
}
else if (PUB.sm.RunStepSeq == idx++)
{
//저속이동
var moveset = 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)
{
var ts = VAR.TIME.RUN(eVarTime.LastTurnCommandTime);
if (ts.TotalSeconds > 10)
{
PUB.AGV.AGVMoveStop(funcname);
PUB.log.AddE("AGV속도설정이 완료되지 않았습니다");
PUB.sm.SetNewRunStep(ERunStep.ERROR);
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;
}
else if (PUB.sm.RunStepSeq == idx++)
{
//마크스탑신호가 3초이내로 들어와야 한다
if (VAR.BOOL[eVarBool.NEXTSTOP_MARK] == false)
{
var ts = VAR.TIME.RUN(eVarTime.LastTurnCommandTime);
if (ts.TotalSeconds > 3)
{
PUB.AGV.AGVMoveStop(funcname);
PUB.log.AddE("MARK STOP신호가 확인되지 않습니다");
PUB.sm.SetNewRunStep(ERunStep.ERROR);
return false;
}
}
VAR.TIME.Update(eVarTime.LastTurnCommandTime);
PUB.sm.UpdateRunStepSeq();
return false;
}
else if (PUB.sm.RunStepSeq == idx++)
{
//AGV가 멈출때까지 기다린다.
if (PUB.AGV.system1.agv_run == true)
{
var ts = VAR.TIME.RUN(eVarTime.LastTurnCommandTime);
if (ts.TotalSeconds > 10)
{
PUB.AGV.AGVMoveStop(funcname);
PUB.log.AddE("AGV가 멈추지 않아 강제종료 합니다");
PUB.sm.SetNewRunStep(ERunStep.ERROR);
return false;
}
return false;
}
VAR.TIME.Update(eVarTime.LastTurnCommandTime);
PUB.sm.UpdateRunStepSeq();
return false;
}
else if (PUB.sm.RunStepSeq == idx++)
{
//완료되었다.
PUB.log.Add("로더진입완료");
PUB.sm.UpdateRunStepSeq();
return false;
}
PUB.AddEEDB($"로더진입완료({PUB.Result.TargetPos})");
return true;
}
}
}

View File

@@ -0,0 +1,82 @@
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Text;
using Project.StateMachine;
using COMM;
using AR;
namespace Project
{
public partial class fMain
{
/// <summary>
/// 로더 배출
/// </summary>
public Boolean _SM_RUN_LOADER_OUT(bool isFirst, TimeSpan stepTime)
{
//충전 상태가 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
{
Bunki = arDev.Narumi.eBunki.Strate,
Direction = arDev.Narumi.eMoveDir.Forward,
PBSSensor = 0,
Speed = arDev.Narumi.eMoveSpd.Low,
});
PUB.sm.UpdateRunStepSeq();
return false;
}
else if (PUB.sm.RunStepSeq == idx++)
{
//전진이동
PUB.AGV.AGVMoveRun(arDev.Narumi.eRunOpt.Forward);
PUB.sm.UpdateRunStepSeq();
return false;
}
else if (PUB.sm.RunStepSeq == idx++)
{
//마크스탑
PUB.AGV.AGVMoveStop("loader out", arDev.Narumi.eStopOpt.MarkStop);
PUB.sm.UpdateRunStepSeq();
return false;
}
else if (PUB.sm.RunStepSeq == idx++)
{
//이동확인
if (PUB.AGV.system1.agv_run == false)
{
return false;
}
PUB.sm.UpdateRunStepSeq();
return false;
}
else if (PUB.sm.RunStepSeq == idx++)
{
//멈춤확인
if (PUB.AGV.system1.agv_run == true)
{
return false;
}
PUB.sm.UpdateRunStepSeq();
return false;
}
// 턴 제거됨
return true;
}
}
}

View File

@@ -0,0 +1,155 @@
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Text;
using Project.StateMachine;
using COMM;
using AR;
namespace Project
{
public partial class fMain
{
/// <summary>
/// 언로더 진입
/// </summary>
public Boolean _SM_RUN_UNLOADER_IN(bool isFirst, TimeSpan stepTime)
{
var funcname = "_SM_RUN_UNLOADER_IN";
var idx = 1;
//충전 상태가 OFF되어야 동작하게한다
if (_SM_RUN_CHGOFF(isFirst, stepTime) == false) return false;
//라이더멈춤이 설정되어있다면 음성으로 알려준다
if (CheckLiderStop() == false) return false;
//현재 위치가 결정되어있는지 체크한다
if (_SM_RUN_POSCHK(isFirst, stepTime) == false) return false;
/*
* 언로더 IN 시퀀스 (버퍼 복사 - 턴 제거)
* 1. LIFT DOWN
* 2. 후진-저속-마크다운 실행
*/
if (PUB.sm.RunStepSeq == idx++)
{
PUB.log.Add("언로더진입시작");
PUB.Speak("언로더 작업을 시작합니다");
PUB.sm.UpdateRunStepSeq();
return false;
}
else if (PUB.sm.RunStepSeq == idx++)
{
//리프트를 내린다.
PUB.AGV.LiftControl(arDev.Narumi.LiftCommand.DN);
VAR.TIME.Update(eVarTime.LastTurnCommandTime);
PUB.sm.UpdateRunStepSeq();
return false;
}
else if (PUB.sm.RunStepSeq == idx++)
{
//리프트다운센서를 확인한다.
var liftdown = true;
if (liftdown == false)
{
var ts = VAR.TIME.RUN(eVarTime.LastTurnCommandTime);
if (ts.TotalSeconds > 10)
{
PUB.AGV.LiftControl(arDev.Narumi.LiftCommand.STP);
PUB.log.AddE("리프트 하강이 확인되지 않습니다(10초)");
PUB.sm.SetNewRunStep(ERunStep.ERROR);
return false;
}
}
PUB.log.Add("리프트 하강 완료");
PUB.sm.UpdateRunStepSeq();
return false;
}
else if (PUB.sm.RunStepSeq == idx++)
{
//마크스탑셋팅
PUB.AGV.AGVMoveStop(funcname, arDev.Narumi.eStopOpt.MarkStop);
VAR.TIME.Update(eVarTime.LastTurnCommandTime);
PUB.sm.UpdateRunStepSeq();
return false;
}
else if (PUB.sm.RunStepSeq == idx++)
{
//저속이동
var moveset = 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)
{
var ts = VAR.TIME.RUN(eVarTime.LastTurnCommandTime);
if (ts.TotalSeconds > 10)
{
PUB.AGV.AGVMoveStop(funcname);
PUB.log.AddE("AGV속도설정이 완료되지 않았습니다");
PUB.sm.SetNewRunStep(ERunStep.ERROR);
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;
}
else if (PUB.sm.RunStepSeq == idx++)
{
//마크스탑신호가 3초이내로 들어와야 한다
if (VAR.BOOL[eVarBool.NEXTSTOP_MARK] == false)
{
var ts = VAR.TIME.RUN(eVarTime.LastTurnCommandTime);
if (ts.TotalSeconds > 3)
{
PUB.AGV.AGVMoveStop(funcname);
PUB.log.AddE("MARK STOP신호가 확인되지 않습니다");
PUB.sm.SetNewRunStep(ERunStep.ERROR);
return false;
}
}
VAR.TIME.Update(eVarTime.LastTurnCommandTime);
PUB.sm.UpdateRunStepSeq();
return false;
}
else if (PUB.sm.RunStepSeq == idx++)
{
//AGV가 멈출때까지 기다린다.
if (PUB.AGV.system1.agv_run == true)
{
var ts = VAR.TIME.RUN(eVarTime.LastTurnCommandTime);
if (ts.TotalSeconds > 10)
{
PUB.AGV.AGVMoveStop(funcname);
PUB.log.AddE("AGV가 멈추지 않아 강제종료 합니다");
PUB.sm.SetNewRunStep(ERunStep.ERROR);
return false;
}
return false;
}
VAR.TIME.Update(eVarTime.LastTurnCommandTime);
PUB.sm.UpdateRunStepSeq();
return false;
}
else if (PUB.sm.RunStepSeq == idx++)
{
//완료되었다.
PUB.log.Add("언로더진입완료");
PUB.sm.UpdateRunStepSeq();
return false;
}
PUB.AddEEDB($"언로더진입완료({PUB.Result.TargetPos})");
return true;
}
}
}

View File

@@ -0,0 +1,81 @@
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Text;
using Project.StateMachine;
using COMM;
using AR;
namespace Project
{
public partial class fMain
{
/// <summary>
/// 언로더 배출
/// </summary>
public Boolean _SM_RUN_UNLOADER_OUT(bool isFirst, TimeSpan stepTime)
{
//충전 상태가 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
{
Bunki = arDev.Narumi.eBunki.Strate,
Direction = arDev.Narumi.eMoveDir.Forward,
PBSSensor = 0,
Speed = arDev.Narumi.eMoveSpd.Low,
});
PUB.sm.UpdateRunStepSeq();
return false;
}
else if (PUB.sm.RunStepSeq == idx++)
{
//전진이동
PUB.AGV.AGVMoveRun(arDev.Narumi.eRunOpt.Forward);
PUB.sm.UpdateRunStepSeq();
return false;
}
else if (PUB.sm.RunStepSeq == idx++)
{
//마크스탑
PUB.AGV.AGVMoveStop("unloader out", arDev.Narumi.eStopOpt.MarkStop);
PUB.sm.UpdateRunStepSeq();
return false;
}
else if (PUB.sm.RunStepSeq == idx++)
{
//이동확인
if (PUB.AGV.system1.agv_run == false)
{
return false;
}
PUB.sm.UpdateRunStepSeq();
return false;
}
else if (PUB.sm.RunStepSeq == idx++)
{
//멈춤확인
if (PUB.AGV.system1.agv_run == true)
{
return false;
}
PUB.sm.UpdateRunStepSeq();
return false;
}
return true;
}
}
}

View File

@@ -17,6 +17,26 @@ namespace Project
return true;
}
/// <summary>
/// 라이더멈춤이 설정되어있다면 음성으로 알려준다
/// </summary>
/// <returns></returns>
public bool CheckLiderStop()
{
if (PUB.AGV.system1.stop_by_front_detect == true)
{
var tsSpeak = DateTime.Now - LastSpeakTime;
if (tsSpeak.TotalSeconds >= PUB.setting.alarmSoundTerm)
{
PUB.Speak(Lang.);
LastSpeakTime = DateTime.Now;
}
return false;
}
return true;
}
/// <summary>
/// 설정된 목적지까지 이동을 완료 한 후 True를 반환합니다.
/// 목적지 : PUB._virtualAGV.TargetNode

View File

@@ -714,6 +714,30 @@ namespace Project
}
else UpdateStatusMessage(String.Format("상차 이동 중 ({0})", PUB.Result.TargetPos), Color.Lime, Color.Black);
}
else if (PUB.sm.RunStep == ERunStep.LOADER_IN)
{
UpdateStatusMessage(String.Format("로더 진입 중 ({0})", PUB.Result.TargetPos), Color.Lime, Color.Black);
}
else if (PUB.sm.RunStep == ERunStep.LOADER_OUT)
{
UpdateStatusMessage(String.Format("로더 배출 중 ({0})", PUB.Result.TargetPos), Color.Lime, Color.Black);
}
else if (PUB.sm.RunStep == ERunStep.UNLOADER_IN)
{
UpdateStatusMessage(String.Format("언로더 진입 중 ({0})", PUB.Result.TargetPos), Color.Lime, Color.Black);
}
else if (PUB.sm.RunStep == ERunStep.UNLOADER_OUT)
{
UpdateStatusMessage(String.Format("언로더 배출 중 ({0})", PUB.Result.TargetPos), Color.Lime, Color.Black);
}
else if (PUB.sm.RunStep == ERunStep.CLEANER_IN)
{
UpdateStatusMessage(String.Format("클리너 진입 중 ({0})", PUB.Result.TargetPos), Color.Lime, Color.Black);
}
else if (PUB.sm.RunStep == ERunStep.CLEANER_OUT)
{
UpdateStatusMessage(String.Format("클리너 배출 중 ({0})", PUB.Result.TargetPos), Color.Lime, Color.Black);
}
else if (PUB.sm.RunStep == ERunStep.GOCHARGE)
{
if (PUB.Result.result_message.isEmpty() == true)

View File

@@ -78,7 +78,12 @@ namespace Project.StateMachine
/// </summary>
BUFFER_IN,
LOADER_IN,
LOADER_OUT,
UNLOADER_IN,
UNLOADER_OUT,
CLEANER_IN,
CLEANER_OUT,
/// <summary>
/// 목적지로 이동합니다
@@ -93,7 +98,7 @@ namespace Project.StateMachine
/// <summary>
/// 후진방향으로 마크스탑진행
/// </summary>
MARKSTROPB,
MARKSTOPB,
/// <summary>
/// 에러발생