diff --git a/AGVEmulator/AGVEmulator.csproj b/AGVEmulator/AGVEmulator.csproj
index 5a22417..b8e128e 100644
--- a/AGVEmulator/AGVEmulator.csproj
+++ b/AGVEmulator/AGVEmulator.csproj
@@ -34,6 +34,9 @@
4
false
+
+ icons8-robot-80.ico
+
..\Cs_HMI\DLL\arControl.Net4.dll
@@ -136,5 +139,8 @@
ENIGProtocol
+
+
+
\ No newline at end of file
diff --git a/AGVEmulator/DevXBE.cs b/AGVEmulator/DevXBE.cs
index 2bdfd5f..efd096f 100644
--- a/AGVEmulator/DevXBE.cs
+++ b/AGVEmulator/DevXBE.cs
@@ -61,29 +61,52 @@ namespace AGVEmulator
///
public void SendGotoTag(byte id, uint tag)
{
- var idSTR = id.ToString("X2");
- var tagSTR = tag.ToString("0000");
- var dataStr = $"{idSTR}{tagSTR}";
- Send(ENIGProtocol.AGVCommandHE.Goto, dataStr);
+ //var idSTR = id.ToString("X2");
+ //var tagSTR = tag.ToString("0000");
+ //var dataStr = $"{idSTR}{tagSTR}";
+ var data = new List();
+ data.Add(id);
+ data.AddRange(System.Text.Encoding.Default.GetBytes(tag.ToString("0000")));
+ Send(ENIGProtocol.AGVCommandHE.Goto, data.ToArray());
}
+
+ ///
+ /// 카트를 가지러 들어간다
+ ///
+ ///
+ public void SendPickOn(byte id)
+ {
+ var data = new List();
+ data.Add(id);
+ Send(ENIGProtocol.AGVCommandHE.PickOn, data.ToArray());
+ }
+
+ ///
+ /// 카트를 내려놓는다
+ ///
+ ///
+ public void SendPickOff(byte id)
+ {
+ var data = new List();
+ data.Add(id);
+ Send(ENIGProtocol.AGVCommandHE.PickOff, data.ToArray());
+ }
+
public void SendCurrentPos(byte id, uint tag)
{
- var idSTR = id.ToString("X2");
- var tagSTR = tag.ToString("0000");
- var dataStr = $"{idSTR}{tagSTR}";
- Send(ENIGProtocol.AGVCommandHE.SetCurrent, dataStr);
+ var data = new List();
+ data.Add(id);
+ data.AddRange(System.Text.Encoding.Default.GetBytes(tag.ToString("0000")));
+ Send(ENIGProtocol.AGVCommandHE.SetCurrent, data.ToArray());
}
- private void Send(ENIGProtocol.AGVCommandHE Command, string datastr)
+ private void Send(ENIGProtocol.AGVCommandHE Command, byte[] data)
{
byte id = 0;
byte cmd = (byte)Command; //move to target
- byte[] data = null;
- if (datastr != null && string.IsNullOrEmpty(datastr) == false)
- data = System.Text.Encoding.Default.GetBytes(datastr);
var packet = proto.CreatePacket(id, cmd, data);
if (WriteData(packet, false))
{
- var hexstr = System.Text.Encoding.Default.GetString(data);
+ var hexstr =(data == null || data.Any()==false) ? string.Empty : System.Text.Encoding.Default.GetString(data);
RaiseMessage(MessageType.Send, $"ID:{id},CMD:{cmd},DATA:{hexstr}");
}
}
diff --git a/AGVEmulator/fMain.Designer.cs b/AGVEmulator/fMain.Designer.cs
index 1757da5..c06e5f9 100644
--- a/AGVEmulator/fMain.Designer.cs
+++ b/AGVEmulator/fMain.Designer.cs
@@ -32,7 +32,6 @@ namespace AGVEmulator
private void InitializeComponent()
{
this.components = new System.ComponentModel.Container();
- System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(fMain));
AGVEmulator.UC.AgvViewer.ptdata ptdata57 = new AGVEmulator.UC.AgvViewer.ptdata();
AGVEmulator.UC.AgvViewer.ptdata ptdata58 = new AGVEmulator.UC.AgvViewer.ptdata();
AGVEmulator.UC.AgvViewer.ptdata ptdata59 = new AGVEmulator.UC.AgvViewer.ptdata();
@@ -61,6 +60,7 @@ namespace AGVEmulator
AGVEmulator.UC.AgvViewer.ptdata ptdata82 = new AGVEmulator.UC.AgvViewer.ptdata();
AGVEmulator.UC.AgvViewer.ptdata ptdata83 = new AGVEmulator.UC.AgvViewer.ptdata();
AGVEmulator.UC.AgvViewer.ptdata ptdata84 = new AGVEmulator.UC.AgvViewer.ptdata();
+ System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(fMain));
this.groupBox1 = new System.Windows.Forms.GroupBox();
this.rtBMS = new arCtl.LogTextBox();
this.panel1 = new System.Windows.Forms.Panel();
@@ -86,6 +86,7 @@ namespace AGVEmulator
this.label2 = new System.Windows.Forms.Label();
this.label1 = new System.Windows.Forms.Label();
this.trackBar1 = new System.Windows.Forms.TrackBar();
+ this.serBMS = new AGVEmulator.SerialConn();
this.rtAGV = new arCtl.LogTextBox();
this.panel4 = new System.Windows.Forms.Panel();
this.groupBox9 = new System.Windows.Forms.GroupBox();
@@ -127,6 +128,7 @@ namespace AGVEmulator
this.button4 = new System.Windows.Forms.Button();
this.groupBox3 = new System.Windows.Forms.GroupBox();
this.rtCAL = new arCtl.LogTextBox();
+ this.serCAL = new AGVEmulator.SerialConn();
this.timer1 = new System.Windows.Forms.Timer(this.components);
this.tabControl1 = new System.Windows.Forms.TabControl();
this.tabPage4 = new System.Windows.Forms.TabPage();
@@ -134,6 +136,8 @@ namespace AGVEmulator
this.tableLayoutPanel3 = new System.Windows.Forms.TableLayoutPanel();
this.rtAGVPro = new arCtl.LogTextBox();
this.panel12 = new System.Windows.Forms.Panel();
+ this.agvViewer1 = new AGVEmulator.UC.AgvViewer();
+ this.serAGV = new AGVEmulator.SerialConn();
this.tabPage2 = new System.Windows.Forms.TabPage();
this.tabPage3 = new System.Windows.Forms.TabPage();
this.panel3 = new System.Windows.Forms.Panel();
@@ -152,6 +156,10 @@ namespace AGVEmulator
this.toolStrip1 = new System.Windows.Forms.ToolStrip();
this.toolStripButton1 = new System.Windows.Forms.ToolStripButton();
this.toolStripButton2 = new System.Windows.Forms.ToolStripButton();
+ this.toolStripSeparator1 = new System.Windows.Forms.ToolStripSeparator();
+ this.toolStripButton3 = new System.Windows.Forms.ToolStripButton();
+ this.toolStripButton4 = new System.Windows.Forms.ToolStripButton();
+ this.toolStripButton5 = new System.Windows.Forms.ToolStripButton();
this.statusStrip1 = new System.Windows.Forms.StatusStrip();
this.toolStripStatusLabel8 = new System.Windows.Forms.ToolStripStatusLabel();
this.sbAGV = new System.Windows.Forms.ToolStripStatusLabel();
@@ -159,14 +167,8 @@ namespace AGVEmulator
this.sbBMS = new System.Windows.Forms.ToolStripStatusLabel();
this.toolStripStatusLabel2 = new System.Windows.Forms.ToolStripStatusLabel();
this.sbCAL = new System.Windows.Forms.ToolStripStatusLabel();
- this.toolStripSeparator1 = new System.Windows.Forms.ToolStripSeparator();
- this.toolStripButton3 = new System.Windows.Forms.ToolStripButton();
- this.agvViewer1 = new AGVEmulator.UC.AgvViewer();
- this.serAGV = new AGVEmulator.SerialConn();
- this.serBMS = new AGVEmulator.SerialConn();
- this.serCAL = new AGVEmulator.SerialConn();
- this.toolStripButton4 = new System.Windows.Forms.ToolStripButton();
- this.toolStripButton5 = new System.Windows.Forms.ToolStripButton();
+ this.button2 = new System.Windows.Forms.Button();
+ this.button3 = new System.Windows.Forms.Button();
this.groupBox1.SuspendLayout();
this.panel1.SuspendLayout();
((System.ComponentModel.ISupportInitialize)(this.trbT2)).BeginInit();
@@ -501,6 +503,18 @@ namespace AGVEmulator
this.trackBar1.Value = 7000;
this.trackBar1.Scroll += new System.EventHandler(this.trackBar1_Scroll);
//
+ // serBMS
+ //
+ this.serBMS.BaudRate = 9600;
+ this.serBMS.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
+ this.serBMS.dev = null;
+ this.serBMS.Dock = System.Windows.Forms.DockStyle.Top;
+ this.serBMS.Location = new System.Drawing.Point(3, 17);
+ this.serBMS.Name = "serBMS";
+ this.serBMS.PortName = "COM31";
+ this.serBMS.Size = new System.Drawing.Size(1134, 84);
+ this.serBMS.TabIndex = 1;
+ //
// rtAGV
//
this.rtAGV.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(24)))), ((int)(((byte)(24)))), ((int)(((byte)(24)))));
@@ -984,6 +998,18 @@ namespace AGVEmulator
this.rtCAL.TabIndex = 2;
this.rtCAL.Text = "";
//
+ // serCAL
+ //
+ this.serCAL.BaudRate = 9600;
+ this.serCAL.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
+ this.serCAL.dev = null;
+ this.serCAL.Dock = System.Windows.Forms.DockStyle.Top;
+ this.serCAL.Location = new System.Drawing.Point(3, 17);
+ this.serCAL.Name = "serCAL";
+ this.serCAL.PortName = "COM41";
+ this.serCAL.Size = new System.Drawing.Size(776, 84);
+ this.serCAL.TabIndex = 1;
+ //
// timer1
//
this.timer1.Interval = 200;
@@ -1069,6 +1095,149 @@ namespace AGVEmulator
this.panel12.Size = new System.Drawing.Size(1140, 120);
this.panel12.TabIndex = 5;
//
+ // agvViewer1
+ //
+ this.agvViewer1.Dock = System.Windows.Forms.DockStyle.Fill;
+ this.agvViewer1.FontMrk = new System.Drawing.Font("Microsoft Sans Serif", 7F);
+ this.agvViewer1.FontTag = new System.Drawing.Font("Microsoft Sans Serif", 6.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+ this.agvViewer1.lastmark = "";
+ this.agvViewer1.lastmarkdir = "";
+ this.agvViewer1.lasttag = "";
+ this.agvViewer1.lasttagdir = "";
+ ptdata57.active = false;
+ ptdata57.data = "NOT";
+ ptdata57.pos = 30F;
+ ptdata58.active = false;
+ ptdata58.data = "QA";
+ ptdata58.pos = 200F;
+ ptdata59.active = false;
+ ptdata59.data = "CHG";
+ ptdata59.pos = 300F;
+ ptdata60.active = false;
+ ptdata60.data = "QC";
+ ptdata60.pos = 400F;
+ ptdata61.active = false;
+ ptdata61.data = "#FVI-1";
+ ptdata61.pos = 500F;
+ ptdata62.active = false;
+ ptdata62.data = "#FVI-2";
+ ptdata62.pos = 600F;
+ ptdata63.active = false;
+ ptdata63.data = "#FVI-3";
+ ptdata63.pos = 700F;
+ ptdata64.active = false;
+ ptdata64.data = "#FVI-4";
+ ptdata64.pos = 800F;
+ ptdata65.active = false;
+ ptdata65.data = "#FVI-5";
+ ptdata65.pos = 900F;
+ ptdata66.active = false;
+ ptdata66.data = "POT";
+ ptdata66.pos = 970F;
+ this.agvViewer1.listMRK = new AGVEmulator.UC.AgvViewer.ptdata[] {
+ ptdata57,
+ ptdata58,
+ ptdata59,
+ ptdata60,
+ ptdata61,
+ ptdata62,
+ ptdata63,
+ ptdata64,
+ ptdata65,
+ ptdata66};
+ ptdata67.active = false;
+ ptdata67.data = "9000";
+ ptdata67.pos = 80F;
+ ptdata68.active = false;
+ ptdata68.data = "9001";
+ ptdata68.pos = 120F;
+ ptdata69.active = false;
+ ptdata69.data = "9010";
+ ptdata69.pos = 180F;
+ ptdata70.active = false;
+ ptdata70.data = "9011";
+ ptdata70.pos = 220F;
+ ptdata71.active = false;
+ ptdata71.data = "9020";
+ ptdata71.pos = 280F;
+ ptdata72.active = false;
+ ptdata72.data = "9021";
+ ptdata72.pos = 320F;
+ ptdata73.active = false;
+ ptdata73.data = "9030";
+ ptdata73.pos = 380F;
+ ptdata74.active = false;
+ ptdata74.data = "9031";
+ ptdata74.pos = 420F;
+ ptdata75.active = false;
+ ptdata75.data = "9040";
+ ptdata75.pos = 480F;
+ ptdata76.active = false;
+ ptdata76.data = "9041";
+ ptdata76.pos = 520F;
+ ptdata77.active = false;
+ ptdata77.data = "9050";
+ ptdata77.pos = 580F;
+ ptdata78.active = false;
+ ptdata78.data = "9051";
+ ptdata78.pos = 620F;
+ ptdata79.active = false;
+ ptdata79.data = "9060";
+ ptdata79.pos = 680F;
+ ptdata80.active = false;
+ ptdata80.data = "9061";
+ ptdata80.pos = 720F;
+ ptdata81.active = false;
+ ptdata81.data = "9070";
+ ptdata81.pos = 780F;
+ ptdata82.active = false;
+ ptdata82.data = "9071";
+ ptdata82.pos = 820F;
+ ptdata83.active = false;
+ ptdata83.data = "9000";
+ ptdata83.pos = 10F;
+ ptdata84.active = false;
+ ptdata84.data = "9001";
+ ptdata84.pos = 50F;
+ this.agvViewer1.listTAG = new AGVEmulator.UC.AgvViewer.ptdata[] {
+ ptdata67,
+ ptdata68,
+ ptdata69,
+ ptdata70,
+ ptdata71,
+ ptdata72,
+ ptdata73,
+ ptdata74,
+ ptdata75,
+ ptdata76,
+ ptdata77,
+ ptdata78,
+ ptdata79,
+ ptdata80,
+ ptdata81,
+ ptdata82,
+ ptdata83,
+ ptdata84};
+ this.agvViewer1.Location = new System.Drawing.Point(241, 0);
+ this.agvViewer1.Name = "agvViewer1";
+ this.agvViewer1.Size = new System.Drawing.Size(899, 120);
+ this.agvViewer1.StopbyMark = false;
+ this.agvViewer1.TabIndex = 0;
+ this.agvViewer1.Text = "agvViewer1";
+ this.agvViewer1.MouseDown += new System.Windows.Forms.MouseEventHandler(this.agvViewer1_MouseDown);
+ //
+ // serAGV
+ //
+ this.serAGV.BaudRate = 9600;
+ this.serAGV.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
+ this.serAGV.dev = null;
+ this.serAGV.Dock = System.Windows.Forms.DockStyle.Left;
+ this.serAGV.Location = new System.Drawing.Point(0, 0);
+ this.serAGV.Name = "serAGV";
+ this.serAGV.PortName = "COM21";
+ this.serAGV.Size = new System.Drawing.Size(241, 120);
+ this.serAGV.TabIndex = 0;
+ //
// tabPage2
//
this.tabPage2.Controls.Add(this.groupBox1);
@@ -1093,6 +1262,8 @@ namespace AGVEmulator
//
// panel3
//
+ this.panel3.Controls.Add(this.button3);
+ this.panel3.Controls.Add(this.button2);
this.panel3.Controls.Add(this.nudIDAgv);
this.panel3.Controls.Add(this.label7);
this.panel3.Controls.Add(this.numericUpDown2);
@@ -1288,6 +1459,38 @@ namespace AGVEmulator
this.toolStripButton2.Text = "All Close";
this.toolStripButton2.Click += new System.EventHandler(this.toolStripButton2_Click);
//
+ // toolStripSeparator1
+ //
+ this.toolStripSeparator1.Name = "toolStripSeparator1";
+ this.toolStripSeparator1.Size = new System.Drawing.Size(6, 25);
+ //
+ // toolStripButton3
+ //
+ this.toolStripButton3.Image = ((System.Drawing.Image)(resources.GetObject("toolStripButton3.Image")));
+ this.toolStripButton3.ImageTransparentColor = System.Drawing.Color.Magenta;
+ this.toolStripButton3.Name = "toolStripButton3";
+ this.toolStripButton3.Size = new System.Drawing.Size(84, 22);
+ this.toolStripButton3.Text = "Open Map";
+ this.toolStripButton3.Click += new System.EventHandler(this.toolStripButton3_Click);
+ //
+ // toolStripButton4
+ //
+ this.toolStripButton4.Image = ((System.Drawing.Image)(resources.GetObject("toolStripButton4.Image")));
+ this.toolStripButton4.ImageTransparentColor = System.Drawing.Color.Magenta;
+ this.toolStripButton4.Name = "toolStripButton4";
+ this.toolStripButton4.Size = new System.Drawing.Size(117, 22);
+ this.toolStripButton4.Text = "Change Rotation";
+ this.toolStripButton4.Click += new System.EventHandler(this.toolStripButton4_Click);
+ //
+ // toolStripButton5
+ //
+ this.toolStripButton5.Image = ((System.Drawing.Image)(resources.GetObject("toolStripButton5.Image")));
+ this.toolStripButton5.ImageTransparentColor = System.Drawing.Color.Magenta;
+ this.toolStripButton5.Name = "toolStripButton5";
+ this.toolStripButton5.Size = new System.Drawing.Size(87, 22);
+ this.toolStripButton5.Text = "SetPosition";
+ this.toolStripButton5.Click += new System.EventHandler(this.toolStripButton5_Click);
+ //
// statusStrip1
//
this.statusStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
@@ -1339,204 +1542,27 @@ namespace AGVEmulator
this.sbCAL.Size = new System.Drawing.Size(19, 17);
this.sbCAL.Text = "●";
//
- // toolStripSeparator1
+ // button2
//
- this.toolStripSeparator1.Name = "toolStripSeparator1";
- this.toolStripSeparator1.Size = new System.Drawing.Size(6, 25);
+ this.button2.Location = new System.Drawing.Point(246, 295);
+ this.button2.Name = "button2";
+ this.button2.Size = new System.Drawing.Size(86, 38);
+ this.button2.TabIndex = 14;
+ this.button2.Tag = "--";
+ this.button2.Text = "Pick On";
+ this.button2.UseVisualStyleBackColor = true;
+ this.button2.Click += new System.EventHandler(this.button2_Click);
//
- // toolStripButton3
+ // button3
//
- this.toolStripButton3.Image = ((System.Drawing.Image)(resources.GetObject("toolStripButton3.Image")));
- this.toolStripButton3.ImageTransparentColor = System.Drawing.Color.Magenta;
- this.toolStripButton3.Name = "toolStripButton3";
- this.toolStripButton3.Size = new System.Drawing.Size(84, 22);
- this.toolStripButton3.Text = "Open Map";
- this.toolStripButton3.Click += new System.EventHandler(this.toolStripButton3_Click);
- //
- // agvViewer1
- //
- this.agvViewer1.Dock = System.Windows.Forms.DockStyle.Fill;
- this.agvViewer1.FontMrk = new System.Drawing.Font("Microsoft Sans Serif", 7F);
- this.agvViewer1.FontTag = new System.Drawing.Font("Microsoft Sans Serif", 6.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
- this.agvViewer1.lastmark = "";
- this.agvViewer1.lastmarkdir = "";
- this.agvViewer1.lasttag = "";
- this.agvViewer1.lasttagdir = "";
- ptdata57.active = false;
- ptdata57.data = "NOT";
- ptdata57.pos = 30F;
- ptdata58.active = false;
- ptdata58.data = "QA";
- ptdata58.pos = 200F;
- ptdata59.active = false;
- ptdata59.data = "CHG";
- ptdata59.pos = 300F;
- ptdata60.active = false;
- ptdata60.data = "QC";
- ptdata60.pos = 400F;
- ptdata61.active = false;
- ptdata61.data = "#FVI-1";
- ptdata61.pos = 500F;
- ptdata62.active = false;
- ptdata62.data = "#FVI-2";
- ptdata62.pos = 600F;
- ptdata63.active = false;
- ptdata63.data = "#FVI-3";
- ptdata63.pos = 700F;
- ptdata64.active = false;
- ptdata64.data = "#FVI-4";
- ptdata64.pos = 800F;
- ptdata65.active = false;
- ptdata65.data = "#FVI-5";
- ptdata65.pos = 900F;
- ptdata66.active = false;
- ptdata66.data = "POT";
- ptdata66.pos = 970F;
- this.agvViewer1.listMRK = new AGVEmulator.UC.AgvViewer.ptdata[] {
- ptdata57,
- ptdata58,
- ptdata59,
- ptdata60,
- ptdata61,
- ptdata62,
- ptdata63,
- ptdata64,
- ptdata65,
- ptdata66};
- ptdata67.active = false;
- ptdata67.data = "9000";
- ptdata67.pos = 80F;
- ptdata68.active = false;
- ptdata68.data = "9001";
- ptdata68.pos = 120F;
- ptdata69.active = false;
- ptdata69.data = "9010";
- ptdata69.pos = 180F;
- ptdata70.active = false;
- ptdata70.data = "9011";
- ptdata70.pos = 220F;
- ptdata71.active = false;
- ptdata71.data = "9020";
- ptdata71.pos = 280F;
- ptdata72.active = false;
- ptdata72.data = "9021";
- ptdata72.pos = 320F;
- ptdata73.active = false;
- ptdata73.data = "9030";
- ptdata73.pos = 380F;
- ptdata74.active = false;
- ptdata74.data = "9031";
- ptdata74.pos = 420F;
- ptdata75.active = false;
- ptdata75.data = "9040";
- ptdata75.pos = 480F;
- ptdata76.active = false;
- ptdata76.data = "9041";
- ptdata76.pos = 520F;
- ptdata77.active = false;
- ptdata77.data = "9050";
- ptdata77.pos = 580F;
- ptdata78.active = false;
- ptdata78.data = "9051";
- ptdata78.pos = 620F;
- ptdata79.active = false;
- ptdata79.data = "9060";
- ptdata79.pos = 680F;
- ptdata80.active = false;
- ptdata80.data = "9061";
- ptdata80.pos = 720F;
- ptdata81.active = false;
- ptdata81.data = "9070";
- ptdata81.pos = 780F;
- ptdata82.active = false;
- ptdata82.data = "9071";
- ptdata82.pos = 820F;
- ptdata83.active = false;
- ptdata83.data = "9000";
- ptdata83.pos = 10F;
- ptdata84.active = false;
- ptdata84.data = "9001";
- ptdata84.pos = 50F;
- this.agvViewer1.listTAG = new AGVEmulator.UC.AgvViewer.ptdata[] {
- ptdata67,
- ptdata68,
- ptdata69,
- ptdata70,
- ptdata71,
- ptdata72,
- ptdata73,
- ptdata74,
- ptdata75,
- ptdata76,
- ptdata77,
- ptdata78,
- ptdata79,
- ptdata80,
- ptdata81,
- ptdata82,
- ptdata83,
- ptdata84};
- this.agvViewer1.Location = new System.Drawing.Point(241, 0);
- this.agvViewer1.Name = "agvViewer1";
- this.agvViewer1.Size = new System.Drawing.Size(899, 120);
- this.agvViewer1.StopbyMark = false;
- this.agvViewer1.TabIndex = 0;
- this.agvViewer1.Text = "agvViewer1";
- this.agvViewer1.MouseDown += new System.Windows.Forms.MouseEventHandler(this.agvViewer1_MouseDown);
- //
- // serAGV
- //
- this.serAGV.BaudRate = 9600;
- this.serAGV.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
- this.serAGV.dev = null;
- this.serAGV.Dock = System.Windows.Forms.DockStyle.Left;
- this.serAGV.Location = new System.Drawing.Point(0, 0);
- this.serAGV.Name = "serAGV";
- this.serAGV.PortName = "COM20";
- this.serAGV.Size = new System.Drawing.Size(241, 120);
- this.serAGV.TabIndex = 0;
- //
- // serBMS
- //
- this.serBMS.BaudRate = 9600;
- this.serBMS.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
- this.serBMS.dev = null;
- this.serBMS.Dock = System.Windows.Forms.DockStyle.Top;
- this.serBMS.Location = new System.Drawing.Point(3, 17);
- this.serBMS.Name = "serBMS";
- this.serBMS.PortName = "COM40";
- this.serBMS.Size = new System.Drawing.Size(1134, 84);
- this.serBMS.TabIndex = 1;
- //
- // serCAL
- //
- this.serCAL.BaudRate = 9600;
- this.serCAL.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
- this.serCAL.dev = null;
- this.serCAL.Dock = System.Windows.Forms.DockStyle.Top;
- this.serCAL.Location = new System.Drawing.Point(3, 17);
- this.serCAL.Name = "serCAL";
- this.serCAL.PortName = "COM50";
- this.serCAL.Size = new System.Drawing.Size(776, 84);
- this.serCAL.TabIndex = 1;
- //
- // toolStripButton4
- //
- this.toolStripButton4.Image = ((System.Drawing.Image)(resources.GetObject("toolStripButton4.Image")));
- this.toolStripButton4.ImageTransparentColor = System.Drawing.Color.Magenta;
- this.toolStripButton4.Name = "toolStripButton4";
- this.toolStripButton4.Size = new System.Drawing.Size(117, 22);
- this.toolStripButton4.Text = "Change Rotation";
- this.toolStripButton4.Click += new System.EventHandler(this.toolStripButton4_Click);
- //
- // toolStripButton5
- //
- this.toolStripButton5.Image = ((System.Drawing.Image)(resources.GetObject("toolStripButton5.Image")));
- this.toolStripButton5.ImageTransparentColor = System.Drawing.Color.Magenta;
- this.toolStripButton5.Name = "toolStripButton5";
- this.toolStripButton5.Size = new System.Drawing.Size(87, 22);
- this.toolStripButton5.Text = "SetPosition";
- this.toolStripButton5.Click += new System.EventHandler(this.toolStripButton5_Click);
+ this.button3.Location = new System.Drawing.Point(246, 339);
+ this.button3.Name = "button3";
+ this.button3.Size = new System.Drawing.Size(86, 38);
+ this.button3.TabIndex = 15;
+ this.button3.Tag = "--";
+ this.button3.Text = "Pick Off";
+ this.button3.UseVisualStyleBackColor = true;
+ this.button3.Click += new System.EventHandler(this.button3_Click);
//
// fMain
//
@@ -1706,6 +1732,8 @@ namespace AGVEmulator
private ToolStripButton toolStripButton3;
private ToolStripButton toolStripButton4;
private ToolStripButton toolStripButton5;
+ private Button button3;
+ private Button button2;
}
}
diff --git a/AGVEmulator/fMain.cs b/AGVEmulator/fMain.cs
index b5cf7e8..352e443 100644
--- a/AGVEmulator/fMain.cs
+++ b/AGVEmulator/fMain.cs
@@ -351,8 +351,8 @@ namespace AGVEmulator
private void AgvViewer1_TagTouched(object sender, UC.AgvViewer.TagArgs e)
{
logAGV.Add($"tag touch:{e.Data}");
- numericUpDown1.Text = e.Data;// decimal.Parse(e.Data);
- button18.PerformClick();
+ //numericUpDown1.Text = e.Data;// decimal.Parse(e.Data);
+ //button18.PerformClick();
UpdateVisualAgvPosition(e.Data);
}
@@ -559,7 +559,7 @@ namespace AGVEmulator
-private void UpdateVisualAGV()
+ private void UpdateVisualAGV()
{
if (_visualAgv != null)
{
@@ -619,18 +619,18 @@ private void UpdateVisualAGV()
// Send Tag
if (node.Id != numericUpDown1.Text)
{
- if (int.TryParse(node.Id, out int tag))
- {
- AGV.SendTag(node.Id);
- numericUpDown1.Text = node.Id;
+ if (int.TryParse(node.Id, out int tag))
+ {
+ //AGV.SendTag(node.Id);
+ numericUpDown1.Text = node.Id;
- // Snap to node
- _currentPosF = node.Position;
- _visualAgv.CurrentPosition = node.Position;
+ // Snap to node
+ _currentPosF = node.Position;
+ _visualAgv.CurrentPosition = node.Position;
- // Decide Next Move (Turn/Straight)
- DecideNextMove(node);
- }
+ // Decide Next Move (Turn/Straight)
+ DecideNextMove(node);
+ }
}
}
}
@@ -793,7 +793,7 @@ private void UpdateVisualAGV()
private void toolStripButton3_Click(object sender, EventArgs e)
{
var file = @"C:\Data\Amkor\AGV4\route\NewMap.agvmap";
- if(System.IO.File.Exists(file)==false)
+ if (System.IO.File.Exists(file) == false)
{
var od = new OpenFileDialog();
od.Filter = "json|*.json";
@@ -916,6 +916,19 @@ private void UpdateVisualAGV()
}
}
}
+
+ private void button2_Click(object sender, EventArgs e)
+ {
+ var target = (byte)nudIDAgv.Value;
+ this.XBE.SendPickOn(target);
+ }
+
+ private void button3_Click(object sender, EventArgs e)
+ {
+ var target = (byte)nudIDAgv.Value;
+ this.XBE.SendPickOff(target);
+ }
+
private void trbT2_Scroll(object sender, EventArgs e)
{
Temp2 = (UInt16)trbT2.Value;
diff --git a/AGVEmulator/icons8-robot-80.ico b/AGVEmulator/icons8-robot-80.ico
new file mode 100644
index 0000000..a84bc77
Binary files /dev/null and b/AGVEmulator/icons8-robot-80.ico differ
diff --git a/Cs_HMI/AGVLogic/AGVNavigationCore/Controls/UnifiedAGVCanvas.Events.cs b/Cs_HMI/AGVLogic/AGVNavigationCore/Controls/UnifiedAGVCanvas.Events.cs
index da3bcf1..fe97a93 100644
--- a/Cs_HMI/AGVLogic/AGVNavigationCore/Controls/UnifiedAGVCanvas.Events.cs
+++ b/Cs_HMI/AGVLogic/AGVNavigationCore/Controls/UnifiedAGVCanvas.Events.cs
@@ -78,6 +78,8 @@ namespace AGVNavigationCore.Controls
// 노드 라벨 그리기 (가장 나중 - 선이 텍스트를 가리지 않게)
DrawNodeLabels(g);
DrawLabels(g); // 추가: 텍스트 라벨
+
+
}
finally
{
@@ -93,6 +95,12 @@ namespace AGVNavigationCore.Controls
{
DrawSyncScreen(g);
}
+
+ //예측문자는 디버깅시에만 표시한다.
+ if (string.IsNullOrEmpty(PredictMessage) == false && System.Diagnostics.Debugger.IsAttached)
+ {
+ g.DrawString(this.PredictMessage, this.Font, Brushes.White, 10, 10);
+ }
}
private void DrawSyncScreen(Graphics g)
diff --git a/Cs_HMI/AGVLogic/AGVNavigationCore/Controls/UnifiedAGVCanvas.cs b/Cs_HMI/AGVLogic/AGVNavigationCore/Controls/UnifiedAGVCanvas.cs
index 798e760..305c3ea 100644
--- a/Cs_HMI/AGVLogic/AGVNavigationCore/Controls/UnifiedAGVCanvas.cs
+++ b/Cs_HMI/AGVLogic/AGVNavigationCore/Controls/UnifiedAGVCanvas.cs
@@ -478,6 +478,17 @@ namespace AGVNavigationCore.Controls
}
}
+ ///
+ /// 상세경로가 설정되어있는가?
+ ///
+ ///
+ public bool HasPath()
+ {
+ if (_currentPath == null) return false;
+ if (_currentPath.DetailedPath == null) return false;
+ return _currentPath.DetailedPath.Any();
+ }
+
///
/// 모든 경로 목록 (다중 AGV 경로 표시용)
///
diff --git a/Cs_HMI/AGVLogic/AGVNavigationCore/Models/MapNode.cs b/Cs_HMI/AGVLogic/AGVNavigationCore/Models/MapNode.cs
index 1d84d99..35583af 100644
--- a/Cs_HMI/AGVLogic/AGVNavigationCore/Models/MapNode.cs
+++ b/Cs_HMI/AGVLogic/AGVNavigationCore/Models/MapNode.cs
@@ -19,7 +19,7 @@ namespace AGVNavigationCore.Models
[Description("표시할 텍스트입니다.")]
public string Text { get; set; } = "";
- public StationType StationType { get; set; }
+ public StationType StationType { get; set; }
[Browsable(false)]
public bool CanDocking
@@ -103,7 +103,7 @@ namespace AGVNavigationCore.Models
{
Type = NodeType.Normal;
}
-
+
public MapNode(string nodeId, Point position, StationType type) : base(nodeId, position)
{
Type = NodeType.Normal;
@@ -152,6 +152,18 @@ namespace AGVNavigationCore.Models
return $"RFID:{RfidId}(NODE:{Id}): AS:{AliasName} ({Type}) at ({Position.X}, {Position.Y})";
}
+ ///
+ /// RFID(*ID)
+ ///
+ public string ID2
+ {
+ get
+ {
+ if (HasRfid()) return $"{this.RfidId:0000}(*{this.Id})";
+ else return $"(*{this.Id})";
+ }
+ }
+
public bool IsNavigationNode()
{
// 이제 MapNode는 항상 내비게이션 노드임 (Label, Image 분리됨)
diff --git a/Cs_HMI/AGVLogic/AGVNavigationCore/Models/NodeBase.cs b/Cs_HMI/AGVLogic/AGVNavigationCore/Models/NodeBase.cs
index 86fac5b..f1928ad 100644
--- a/Cs_HMI/AGVLogic/AGVNavigationCore/Models/NodeBase.cs
+++ b/Cs_HMI/AGVLogic/AGVNavigationCore/Models/NodeBase.cs
@@ -40,13 +40,12 @@ namespace AGVNavigationCore.Models
[JsonIgnore]
public bool IsSelected { get; set; } = false;
-
[Browsable(false)]
[JsonIgnore]
public bool IsHovered { get; set; } = false;
-
+
public NodeBase()
{
diff --git a/Cs_HMI/AGVLogic/AGVNavigationCore/Models/VirtualAGV.cs b/Cs_HMI/AGVLogic/AGVNavigationCore/Models/VirtualAGV.cs
index 0cb21db..49f8208 100644
--- a/Cs_HMI/AGVLogic/AGVNavigationCore/Models/VirtualAGV.cs
+++ b/Cs_HMI/AGVLogic/AGVNavigationCore/Models/VirtualAGV.cs
@@ -83,9 +83,9 @@ namespace AGVNavigationCore.Models
// 에뮬레이터용 추가 속성
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.
-
+ // 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
@@ -143,6 +143,11 @@ namespace AGVNavigationCore.Models
///
public AGVPathResult CurrentPath => _currentPath;
+ public void ClearPath()
+ {
+ _currentPath = null;
+ }
+
///
/// 현재 노드 ID
///
@@ -153,6 +158,18 @@ namespace AGVNavigationCore.Models
///
public string CurrentNodeId => _currentNode?.Id;
+ ///
+ /// 현재노드의 RFID(id)값을 표시합니다 없는경우 (X)가 표시됩니다
+ ///
+ public string CurrentNodeID2
+ {
+ get
+ {
+ if (_currentNode == null) return "(X)";
+ return _currentNode.ID2;
+ }
+ }
+
///
/// 이전 위치
///
@@ -282,7 +299,7 @@ namespace AGVNavigationCore.Models
if (_currentNode == null) return false;
if (_currentPath == null) return false;
var 미완료된처음노드 = _currentPath.DetailedPath.Where(t => t.IsPass == false).OrderBy(t => t.seq).FirstOrDefault();
- if (미완료된처음노드 == null) return false;
+ if (미완료된처음노드 == null) return false;
미완료된처음노드.IsPass = true;
Console.WriteLine($"미완료된처음노드를 true러치합니다");
return true;
@@ -295,6 +312,7 @@ namespace AGVNavigationCore.Models
/// 다음에 수행할 모터/마그넷/속도 명령
public AGVCommand Predict()
{
+
// 1. 위치 미확정 상태 (RFID 2개 미만 감지)
if (!_isPositionConfirmed)
{
@@ -311,12 +329,17 @@ namespace AGVNavigationCore.Models
// 2. 위치 확정됨 + 경로 없음 → 정지 (목적지 미설정 상태)
if (_currentPath == null || (_currentPath.DetailedPath?.Count ?? 0) < 1)
{
+ var curpos = "알수없음";
+ if (_currentNode != null)
+ {
+ curpos = _currentNode.HasRfid() ? $"RFID #{_currentNode.RfidId} (*{_currentNode.Id})" : $"(*{_currentNode.Id})";
+ }
return new AGVCommand(
MotorCommand.Stop,
MagnetPosition.S,
SpeedLevel.L,
eAGVCommandReason.NoPath,
- $"위치 확정 완료 (목적지 미설정) - 현재:{_currentNode?.Id ?? "알수없음"}"
+ $"(목적지 미설정) - 현재={curpos}"
);
}
@@ -325,6 +348,9 @@ namespace AGVNavigationCore.Models
if (_currentPath.DetailedPath.Where(t => t.seq < lastNode.seq && t.IsPass == false).Any() == false)
{
// 마지막 노드에 도착했는지 확인 (현재 노드가 마지막 노드와 같은지)
+
+
+
if (_currentNode != null && _currentNode.Id == lastNode.NodeId)
{
if (lastNode.IsPass) //이미완료되었다.
@@ -334,7 +360,7 @@ namespace AGVNavigationCore.Models
MagnetPosition.S,
SpeedLevel.L,
eAGVCommandReason.Complete,
- $"목적지 도착 - 최종:{_currentNode?.Id ?? "알수없음"}"
+ $"목적지 도착 - 최종:{CurrentNodeID2}"
);
}
else
@@ -345,7 +371,7 @@ namespace AGVNavigationCore.Models
MagnetPosition.S,
SpeedLevel.L,
eAGVCommandReason.MarkStop,
- $"목적지 도착 전(MarkStop) - 최종:{_currentNode?.Id ?? "알수없음"}"
+ $"목적지 도착 전(MarkStop) - 최종:{CurrentNodeID2}"
);
}
@@ -361,7 +387,7 @@ namespace AGVNavigationCore.Models
MagnetPosition.S,
SpeedLevel.L,
eAGVCommandReason.PathOut,
- $"(재탐색요청)경로이탈 현재위치:{_currentNode.Id}"
+ $"(재탐색요청)경로이탈 현재위치:{CurrentNodeID2}"
);
}
@@ -403,6 +429,18 @@ namespace AGVNavigationCore.Models
#region Public Methods - 경로 실행
+ ///
+ /// 경로가 설정되어있는지?
+ ///
+ ///
+ public bool HasPath()
+ {
+ if (_currentPath == null) return false;
+ if (_currentPath.DetailedPath == null) return false;
+ return _currentPath.DetailedPath.Any();
+
+ }
+
///
/// 경로 설정 (실제 AGV 및 시뮬레이터에서 사용)
///
@@ -411,6 +449,9 @@ namespace AGVNavigationCore.Models
{
if (path == null)
{
+ _currentPath = null;
+ _remainingNodes.Clear();// = null;
+ _currentNodeIndex = 0;
OnError("경로가 null입니다.");
return;
}
@@ -612,7 +653,7 @@ namespace AGVNavigationCore.Models
PositionChanged?.Invoke(this, (_currentPosition, _currentDirection, _currentNode));
}
-
+
#endregion
diff --git a/Cs_HMI/AGVLogic/AGVNavigationCore/PathFinding/Core/AGVPathResult.cs b/Cs_HMI/AGVLogic/AGVNavigationCore/PathFinding/Core/AGVPathResult.cs
index 4578313..6f146e5 100644
--- a/Cs_HMI/AGVLogic/AGVNavigationCore/PathFinding/Core/AGVPathResult.cs
+++ b/Cs_HMI/AGVLogic/AGVNavigationCore/PathFinding/Core/AGVPathResult.cs
@@ -322,7 +322,7 @@ namespace AGVNavigationCore.PathFinding.Core
}
return Path?.Select(n => n.Id).ToList() ?? new List();
}
-
+
///
/// 문자열 표현
///
diff --git a/Cs_HMI/AGVLogic/AGVNavigationCore/PathFinding/Planning/NodeMotorInfo.cs b/Cs_HMI/AGVLogic/AGVNavigationCore/PathFinding/Planning/NodeMotorInfo.cs
index 5c5cb71..cda4182 100644
--- a/Cs_HMI/AGVLogic/AGVNavigationCore/PathFinding/Planning/NodeMotorInfo.cs
+++ b/Cs_HMI/AGVLogic/AGVNavigationCore/PathFinding/Planning/NodeMotorInfo.cs
@@ -123,6 +123,8 @@ namespace AGVNavigationCore.PathFinding.Planning
if (RequiresSpecialAction)
result += $" [특수동작:{SpecialActionDescription}]";
+ if (IsPass) result += "(O)";
+
return result;
}
}
diff --git a/Cs_HMI/Project/Class/Lang.cs b/Cs_HMI/Project/Class/Lang.cs
index addf803..f619b08 100644
--- a/Cs_HMI/Project/Class/Lang.cs
+++ b/Cs_HMI/Project/Class/Lang.cs
@@ -55,10 +55,10 @@ namespace Project
public static string 상차 = "상차";
public static string 하차 = "하차";
- public static string 홈검색완료 = "홈 검색 완료";
+ public static string 이동완료 = "이동 완료";
public static string 오버로드감지 = "오버로드 감지";
- public static string 상차작업을시작합니다 { get { return string.Format("{0} 작업을 시작 합니다",상차); } }
- public static string 하차작업을시작합니다 { get { return string.Format("{0} 작업을 시작 합니다", 하차); } }
+ public static string 진출을시작합니다 { get { return "진출 시작"; } }
+ public static string 진입을작합니다 { get { return "진입 시작"; } }
public static string 안전커버를내려주세요 = "안전 커버를 내려 주세요";
public static string 안전커버를올려주세요 = "안전 커버를 올려 주세요";
public static string 안전커버를올리면상차가완료됩니다 = "안전 커버를 올리면 상차가 완료 됩니다";
diff --git a/Cs_HMI/Project/Device/Xbee.cs b/Cs_HMI/Project/Device/Xbee.cs
index bcd5993..06760a7 100644
--- a/Cs_HMI/Project/Device/Xbee.cs
+++ b/Cs_HMI/Project/Device/Xbee.cs
@@ -14,6 +14,36 @@ using System.Windows.Forms;
namespace Project.Device
{
+ public enum eDocStep : byte
+ {
+ NotSet = 0,
+
+ ///
+ /// 투입준비됨
+ ///
+ InReady = 10,
+
+ ///
+ /// 투입완료
+ ///
+ InComplete = 11,
+
+ ///
+ /// 투입(진행중)
+ ///
+ InIng = 12,
+
+ ///
+ /// 진출완료
+ ///
+ OutComplete = 21,
+
+ ///
+ /// 진출중
+ ///
+ OutIng = 22,
+ }
+
public class Xbee : SerialPort, arDev.ISerialComm
{
public string buffer = string.Empty;
@@ -166,17 +196,10 @@ namespace Project.Device
Send(packet);
}
- public bool BufferInReady { get; set; }
- public bool BufferInComplete { get; set; }
- 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; }
+ public eDocStep StepBuffer { get; set; } = eDocStep.NotSet;
+ public eDocStep StepUnloader { get; set; } = eDocStep.NotSet;
+ public eDocStep StepLoader { get; set; } = eDocStep.NotSet;
+ public eDocStep StepCleaner { get; set; } = eDocStep.NotSet;
ManualResetEvent sendlock = new ManualResetEvent(true);
diff --git a/Cs_HMI/Project/StateMachine/Step/_SM_RUN.cs b/Cs_HMI/Project/StateMachine/Step/_SM_RUN.cs
index e7c0fe9..5100d7e 100644
--- a/Cs_HMI/Project/StateMachine/Step/_SM_RUN.cs
+++ b/Cs_HMI/Project/StateMachine/Step/_SM_RUN.cs
@@ -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
diff --git a/Cs_HMI/Project/StateMachine/Step/_SM_RUN_BUFFER_IN.cs b/Cs_HMI/Project/StateMachine/Step/_SM_RUN_BUFFER_IN.cs
index 3df0ffa..e1a947f 100644
--- a/Cs_HMI/Project/StateMachine/Step/_SM_RUN_BUFFER_IN.cs
+++ b/Cs_HMI/Project/StateMachine/Step/_SM_RUN_BUFFER_IN.cs
@@ -11,26 +11,17 @@ namespace Project
{
public partial class fMain
{
- ///
- /// 버퍼도킹
- ///
- ///
- ///
- ///
- 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;
}
}
diff --git a/Cs_HMI/Project/StateMachine/Step/_SM_RUN_BUFFER_OUT.cs b/Cs_HMI/Project/StateMachine/Step/_SM_RUN_BUFFER_OUT.cs
index 6de2b83..6e7bf8f 100644
--- a/Cs_HMI/Project/StateMachine/Step/_SM_RUN_BUFFER_OUT.cs
+++ b/Cs_HMI/Project/StateMachine/Step/_SM_RUN_BUFFER_OUT.cs
@@ -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;
}
diff --git a/Cs_HMI/Project/StateMachine/Step/_SM_RUN_CLEANER_IN.cs b/Cs_HMI/Project/StateMachine/Step/_SM_RUN_CLEANER_IN.cs
index 2981a69..38e4e01 100644
--- a/Cs_HMI/Project/StateMachine/Step/_SM_RUN_CLEANER_IN.cs
+++ b/Cs_HMI/Project/StateMachine/Step/_SM_RUN_CLEANER_IN.cs
@@ -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);
diff --git a/Cs_HMI/Project/StateMachine/Step/_SM_RUN_CLEANER_OUT.cs b/Cs_HMI/Project/StateMachine/Step/_SM_RUN_CLEANER_OUT.cs
index 2a743ff..a92c947 100644
--- a/Cs_HMI/Project/StateMachine/Step/_SM_RUN_CLEANER_OUT.cs
+++ b/Cs_HMI/Project/StateMachine/Step/_SM_RUN_CLEANER_OUT.cs
@@ -16,26 +16,37 @@ namespace Project
///
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;
}
diff --git a/Cs_HMI/Project/StateMachine/Step/_SM_RUN_GOCHARGE.cs b/Cs_HMI/Project/StateMachine/Step/_SM_RUN_GOCHARGE.cs
index cd1e4a9..4fdee1d 100644
--- a/Cs_HMI/Project/StateMachine/Step/_SM_RUN_GOCHARGE.cs
+++ b/Cs_HMI/Project/StateMachine/Step/_SM_RUN_GOCHARGE.cs
@@ -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;
}
diff --git a/Cs_HMI/Project/StateMachine/Step/_SM_RUN_GOHOME.cs b/Cs_HMI/Project/StateMachine/Step/_SM_RUN_GOHOME.cs
index 5a86d6c..0120e07 100644
--- a/Cs_HMI/Project/StateMachine/Step/_SM_RUN_GOHOME.cs
+++ b/Cs_HMI/Project/StateMachine/Step/_SM_RUN_GOHOME.cs
@@ -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;
}
diff --git a/Cs_HMI/Project/StateMachine/Step/_SM_RUN_GOTO.cs b/Cs_HMI/Project/StateMachine/Step/_SM_RUN_GOTO.cs
index 6f39bed..21fc0a7 100644
--- a/Cs_HMI/Project/StateMachine/Step/_SM_RUN_GOTO.cs
+++ b/Cs_HMI/Project/StateMachine/Step/_SM_RUN_GOTO.cs
@@ -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;
}
diff --git a/Cs_HMI/Project/StateMachine/Step/_SM_RUN_LOADER_IN.cs b/Cs_HMI/Project/StateMachine/Step/_SM_RUN_LOADER_IN.cs
index 6200f41..cc5fd0d 100644
--- a/Cs_HMI/Project/StateMachine/Step/_SM_RUN_LOADER_IN.cs
+++ b/Cs_HMI/Project/StateMachine/Step/_SM_RUN_LOADER_IN.cs
@@ -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);
diff --git a/Cs_HMI/Project/StateMachine/Step/_SM_RUN_LOADER_OUT.cs b/Cs_HMI/Project/StateMachine/Step/_SM_RUN_LOADER_OUT.cs
index 2487ec0..1b39129 100644
--- a/Cs_HMI/Project/StateMachine/Step/_SM_RUN_LOADER_OUT.cs
+++ b/Cs_HMI/Project/StateMachine/Step/_SM_RUN_LOADER_OUT.cs
@@ -16,27 +16,37 @@ namespace Project
///
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;
}
diff --git a/Cs_HMI/Project/StateMachine/Step/_SM_RUN_POSCHK.cs b/Cs_HMI/Project/StateMachine/Step/_SM_RUN_POSCHK.cs
index e7ae26e..e8468e8 100644
--- a/Cs_HMI/Project/StateMachine/Step/_SM_RUN_POSCHK.cs
+++ b/Cs_HMI/Project/StateMachine/Step/_SM_RUN_POSCHK.cs
@@ -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);
}
}
diff --git a/Cs_HMI/Project/StateMachine/Step/_SM_RUN_UNLOADER_IN.cs b/Cs_HMI/Project/StateMachine/Step/_SM_RUN_UNLOADER_IN.cs
index 352f4f5..5ccd751 100644
--- a/Cs_HMI/Project/StateMachine/Step/_SM_RUN_UNLOADER_IN.cs
+++ b/Cs_HMI/Project/StateMachine/Step/_SM_RUN_UNLOADER_IN.cs
@@ -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);
diff --git a/Cs_HMI/Project/StateMachine/Step/_SM_RUN_UNLOADER_OUT.cs b/Cs_HMI/Project/StateMachine/Step/_SM_RUN_UNLOADER_OUT.cs
index eedea06..e57ab00 100644
--- a/Cs_HMI/Project/StateMachine/Step/_SM_RUN_UNLOADER_OUT.cs
+++ b/Cs_HMI/Project/StateMachine/Step/_SM_RUN_UNLOADER_OUT.cs
@@ -16,27 +16,37 @@ namespace Project
///
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;
}
diff --git a/Cs_HMI/Project/StateMachine/Step/_Util.cs b/Cs_HMI/Project/StateMachine/Step/_Util.cs
index 64e7d53..9ff11f7 100644
--- a/Cs_HMI/Project/StateMachine/Step/_Util.cs
+++ b/Cs_HMI/Project/StateMachine/Step/_Util.cs
@@ -34,7 +34,7 @@ namespace Project
return false;
}
-
+
return true;
}
@@ -44,7 +44,7 @@ namespace Project
///
public bool CheckLiderStop()
{
-
+
if (PUB.AGV.system1.stop_by_front_detect == true)
{
var tsSpeak = DateTime.Now - LastSpeakTime;
@@ -67,8 +67,9 @@ namespace Project
///
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);
}
// 검증 결과 확인
diff --git a/Cs_HMI/Project/StateMachine/_AGV.cs b/Cs_HMI/Project/StateMachine/_AGV.cs
index f8912fa..8c4a593 100644
--- a/Cs_HMI/Project/StateMachine/_AGV.cs
+++ b/Cs_HMI/Project/StateMachine/_AGV.cs
@@ -66,7 +66,7 @@ namespace Project
if (PUB._virtualAGV.CurrentDirection != syncDir)
PUB.UpdateAGVDirection(syncDir);
}
-
+
// [Sync] Update VirtualAGV State
AGVState syncState = AGVState.Idle;
@@ -106,7 +106,7 @@ namespace Project
PUB.log.Add($"충전상태전환 {agv_chg}");
VAR.BOOL[eVarBool.FLAG_CHARGEONA] = agv_chg;
}
-
+
if (PUB.AGV.error.Charger_pos_error != VAR.BOOL[eVarBool.CHG_POSERR])
{
@@ -199,9 +199,11 @@ namespace Project
else
{
//모터방향 확인해서 UI와 AGV클래스에 적용한다
- var MotDireciton = PUB.AGV.data.Direction == 'B' ? AGVNavigationCore.Models.AgvDirection.Backward : AGVNavigationCore.Models.AgvDirection.Forward;
+ var MotDireciton = PUB.AGV.data.Direction == 'B' ? AgvDirection.Backward : AgvDirection.Forward;
PUB._mapCanvas.SetAGVPosition(PUB.setting.MCID, CurrentNode, MotDireciton);
PUB._virtualAGV.SetPosition(CurrentNode, MotDireciton);
+
+ //방향을 다시 확인하여. 기존 경로의 무결성을 검증한다, 필요한 경우 다시 계산할 필요가 있다.
}
//태그를 읽었다면 상태를 바로 전송한다
@@ -221,16 +223,42 @@ namespace Project
if (PUB._mapCanvas != null && PUB._virtualAGV != null)
{
var nextAction = PUB._virtualAGV.Predict();
- var message = $"[다음 행동 예측]\n\n" +
- $"모터: {nextAction.Motor}\n" +
+ var message = $"[다음 행동 예측]\n\n";
+
+ if (VAR.BOOL[eVarBool.FLAG_AUTORUN] == false)
+ message += "[수동모드]\n\n";
+
+ var node = PUB._virtualAGV.CurrentNode;
+ var curpos = PUB._virtualAGV.CurrentNodeID2;
+ var targetpos = PUB._virtualAGV.TargetNode?.ID2 ?? "(X)";
+
+ var pathdetail = "";
+ if (PUB._virtualAGV.CurrentPath != null && PUB._virtualAGV.CurrentPath.DetailedPath.Any())
+ {
+ var idx = 0;
+ foreach (var item in PUB._virtualAGV.CurrentPath.DetailedPath)
+ {
+ idx += 1;
+ if (pathdetail.isEmpty() == false) pathdetail += "->";
+ if (idx % 6 == 0) pathdetail += "\n";
+ pathdetail += $"{item.RfidId:0000}({item.MotorDirection.ToString().Substring(0, 1)}{item.MagnetDirection.ToString().Substring(0, 1)}{item.Speed.ToString().Substring(0, 1)})";
+ if (item.IsPass) pathdetail += "(O)";
+ }
+ }
+
+ message += $"모터: {nextAction.Motor}\n" +
$"마그넷: {nextAction.Magnet}\n" +
$"속도: {nextAction.Speed}\n" +
- $"이유: {nextAction.Message}\n\n" +
+ $"이유: {nextAction.Message}\n" +
+ $"상태머신:{PUB.sm.Step}:{PUB.sm.RunStep}:{PUB.sm.RunStepSeq}\n"+
$"---\n" +
$"현재 상태: {PUB._virtualAGV.CurrentState}\n" +
$"현재 방향: {PUB._virtualAGV.CurrentDirection}\n" +
+ $"턴: {PUB._virtualAGV.Turn}\n" +
$"위치 확정: {PUB._virtualAGV.IsPositionConfirmed} (RFID {PUB._virtualAGV.DetectedRfidCount}개)\n" +
- $"현재 노드: {PUB._virtualAGV.CurrentNode.Id ?? "없음"}";
+ $"현재 노드: {curpos}\n" +
+ $"대상 노드: {targetpos}\n" +
+ $"상세 경로: {pathdetail}";
PUB._mapCanvas.PredictMessage = message;
}
diff --git a/Cs_HMI/Project/StateMachine/_Loop.cs b/Cs_HMI/Project/StateMachine/_Loop.cs
index ac9de15..2038fde 100644
--- a/Cs_HMI/Project/StateMachine/_Loop.cs
+++ b/Cs_HMI/Project/StateMachine/_Loop.cs
@@ -49,8 +49,15 @@ namespace Project
else if (PUB.DriveSpeed)
{
var rlt = PUB.AGV.AGVCommand("SSH", PUB.setting.SPD_H.ToString("0000"));
- if (rlt) PUB.DriveSpeed = false;
- PUB.log.Add($"Screen Change and DriveSpeed Off:{rlt}");
+ if (rlt == arDev.eNarumiCommandResult.Success)
+ {
+ PUB.DriveSpeed = false;
+ PUB.log.Add($"Screen Change and DriveSpeed Off:{rlt}");
+ } else
+ {
+ PUB.log.AddE($"Screen Change and DriveSpeed Off:{rlt}");
+ }
+
}
MenuAuto.ForeColor = Color.FromArgb(180, 180, 180);
diff --git a/Cs_HMI/Project/StateMachine/_Xbee.cs b/Cs_HMI/Project/StateMachine/_Xbee.cs
index 9a0b813..c3bb679 100644
--- a/Cs_HMI/Project/StateMachine/_Xbee.cs
+++ b/Cs_HMI/Project/StateMachine/_Xbee.cs
@@ -79,25 +79,37 @@ namespace Project
var currNode = PUB._virtualAGV.CurrentNode;
if (currNode == null)
{
- PUB.log.AddE($"[{logPrefix}-{cmd}] 현재 노드를 알 수 없습니다 NodeID:{PUB._virtualAGV.CurrentNode.Id}");
- PUB.XBE.SendError(ENIGProtocol.AGVErrorCode.EmptyNode, "Unknown Node");
+ PUB.log.AddE($"[{logPrefix}-{cmd}] 현재 노드를 알 수 없습니다");
+ PUB.XBE.SendError(ENIGProtocol.AGVErrorCode.EmptyNode, "Unknown Current Node");
return;
}
- PUB.NextWorkCmd = cmd;
- ERunStep nextStep = ERunStep.READY;
+ var targetNode = PUB._virtualAGV.TargetNode;
+ if (targetNode == null)
+ {
+ PUB.log.AddE($"[{logPrefix}-{cmd}] 목표 노드를 알 수 없습니다");
+ PUB.XBE.SendError(ENIGProtocol.AGVErrorCode.EmptyNode, "Unknown Target Node");
+ return;
+ }
- switch (currNode.StationType)
+ //버퍼의 경우 직전에 멈추기 때문에 스테이션종류를 보정해준다
+ var StationType = currNode.StationType;
+ if (StationType == StationType.Normal && targetNode.StationType == StationType.Buffer)
+ StationType = StationType.Buffer;
+
+ ERunStep nextStep = ERunStep.READY;
+ switch (StationType)
{
case StationType.Loader: nextStep = ERunStep.LOADER_IN; break;
case StationType.UnLoader: nextStep = ERunStep.UNLOADER_IN; break;
case StationType.Buffer: nextStep = ERunStep.BUFFER_IN; break;
case StationType.Clearner: nextStep = ERunStep.CLEANER_IN; break;
default:
- PUB.log.AddE($"[{logPrefix}-{cmd}] 해당 노드타입({currNode.Type})은 작업을 지원하지 않습니다.");
+ PUB.log.AddE($"[{logPrefix}-{cmd}] 해당 노드타입({StationType})은 작업을 지원하지 않습니다.");
return;
}
+ PUB.NextWorkCmd = cmd;
PUB.log.AddI($"작업 시작: {nextStep} (Type: {cmd})");
PUB.sm.SetNewRunStep(nextStep);
}
@@ -118,10 +130,10 @@ namespace Project
{
var currTag = System.Text.Encoding.Default.GetString(data, 1, data.Length - 1).Trim();
MapNode targetNode = null;
- if(cmd == ENIGProtocol.AGVCommandHE.GotoAlias)
+ if (cmd == ENIGProtocol.AGVCommandHE.GotoAlias)
{
targetNode = PUB._mapCanvas.Nodes.FirstOrDefault(t => t.AliasName == currTag);
- }
+ }
else
{
if (ushort.TryParse(currTag, out ushort currtagvalue))
@@ -155,14 +167,14 @@ namespace Project
{
PUB.log.AddE($"[{logPrefix}-Goto] 시작노드가 없습니다(현재위치 없음) NodeID:{PUB._virtualAGV.CurrentNode.Id}");
}
-
+
//대상이동으로 처리한다.
- if(PUB.sm.RunStep != ERunStep.GOTO)
- {
+ if (PUB.sm.RunStep != ERunStep.GOTO)
+ {
PUB.sm.SetNewRunStep(StateMachine.ERunStep.GOTO);
PUB.sm.ResetRunStepSeq();
}
-
+
//Move to
PUB.log.Add($"[{logPrefix}-{cmd}] {startNode.RfidId} -> {targetNode.RfidId}");
@@ -242,9 +254,15 @@ namespace Project
if (Lidar == 0) bunkidata.PBSSensor = 0;
else bunkidata.PBSSensor = 2;
- PUB.log.Add($"[{logPrefix}-AutoMove] DIR:{bunkidata.Direction}-{bunkidata.Bunki},SPD:{bunkidata.Speed}");
- PUB.AGV.AGVMoveSet(bunkidata);
- PUB.AGV.AGVMoveRun((MotDirection == 0 ? arDev.Narumi.eRunOpt.Backward : arDev.Narumi.eRunOpt.Forward));
+ PUB.log.Add($"[{logPrefix}-AutoMove] DIR:{bunkidata.Direction}-{bunkidata.Bunki},SPD:{bunkidata.Speed}");
+
+ if (PUB.AGV.AGVMoveSet(bunkidata) != eNarumiCommandResult.Success)
+ PUB.log.AddE($"AGV속도설정실패로 인해 자동전환이 실패되었습니다");
+ else
+ {
+ PUB.log.Add($"XBE 에서 자동모드로 전환합니다");
+ PUB.AGV.AGVMoveRun((MotDirection == 0 ? arDev.Narumi.eRunOpt.Backward : arDev.Narumi.eRunOpt.Forward));
+ }
break;
case ENIGProtocol.AGVCommandHE.MarkStop: //Set MarkStop
@@ -274,7 +292,7 @@ namespace Project
PUB.log.AddI($"충전을 시작합니다");
}
break;
-
+
default:
PUB.logagv.AddE($"Unknown Command : {cmd} Sender:{e.ReceivedPacket.ID}, Target:{data[0]}");
PUB.XBE.SendError(ENIGProtocol.AGVErrorCode.UnknownCommand, $"{cmd}");
@@ -323,7 +341,7 @@ namespace Project
advancedResult.DockingValidation = DockingValidator.ValidateDockingDirection(advancedResult, _mapNodes);
//마지막대상이 버퍼라면 시퀀스처리를 해야한다
- if (targetNode.StationType == StationType.Buffer&& advancedResult.DetailedPath.Any())
+ if (targetNode.StationType == StationType.Buffer && advancedResult.DetailedPath.Any())
{
var lastDetailPath = advancedResult.DetailedPath.Last();
if (lastDetailPath.NodeId == targetNode.Id) //마지막노드 재확인
@@ -349,7 +367,7 @@ namespace Project
//UpdateAdvancedPathDebugInfo(advancedResult);
}
- else if(advancedResult != null)
+ else if (advancedResult != null)
{
// 경로 실패시 디버깅 정보 초기화
//_pathDebugLabel.Text = $"경로: 실패 - {advancedResult.ErrorMessage}";
diff --git a/Cs_HMI/Project/ViewForm/fManual.cs b/Cs_HMI/Project/ViewForm/fManual.cs
index 46c08f7..cb35c52 100644
--- a/Cs_HMI/Project/ViewForm/fManual.cs
+++ b/Cs_HMI/Project/ViewForm/fManual.cs
@@ -200,8 +200,8 @@ namespace Project.ViewForm
var dlg = UTIL.MsgQ("자동 진행을 시작할까요?\n우측 옵션을 확인 하세요");
if (dlg != DialogResult.Yes) return;
var opt = makeopt();
- PUB.AGV.AGVMoveSet(opt);
- PUB.AGV.AGVMoveRun(opt.Direction == arDev.Narumi.eMoveDir.Forward ? arDev.Narumi.eRunOpt.Forward : arDev.Narumi.eRunOpt.Backward);
+ if (PUB.AGV.AGVMoveSet(opt) == eNarumiCommandResult.Success)
+ PUB.AGV.AGVMoveRun(opt.Direction == arDev.Narumi.eMoveDir.Forward ? arDev.Narumi.eRunOpt.Forward : arDev.Narumi.eRunOpt.Backward);
}
else
{
@@ -350,7 +350,7 @@ namespace Project.ViewForm
PUB.log.Add($"사용자 설정 : {bunkiopt}");
if (PUB.DriveSpeed)
{
- if (PUB.AGV.AGVCommand("SSH", PUB.setting.SPD_H.ToString("0000")) == true)
+ if (PUB.AGV.AGVCommand("SSH", PUB.setting.SPD_H.ToString("0000")) == eNarumiCommandResult.Success)
PUB.DriveSpeed = false;
}
@@ -361,7 +361,7 @@ namespace Project.ViewForm
private void arLabel1_Click_1(object sender, EventArgs e)
{
- if (PUB.AGV.AGVCommand("SSH", PUB.setting.SPD_DRIVE.ToString("0000")) == false)
+ if (PUB.AGV.AGVCommand("SSH", PUB.setting.SPD_DRIVE.ToString("0000")) != eNarumiCommandResult.Success)
{
AR.UTIL.MsgE("고속속도에 주행속도 연결 실패\n잠시 후 다시 시도하세요");
return;
@@ -369,12 +369,18 @@ namespace Project.ViewForm
if (this.bunkiopt == null) bunkiopt = makeopt();
bunkiopt.Speed = arDev.Narumi.eMoveSpd.High;
- PUB.AGV.AGVMoveSet(bunkiopt);
- PUB.log.Add($"고속주행설정 : {bunkiopt}");
- PUB.DriveSpeed = true;
+ if (PUB.AGV.AGVMoveSet(bunkiopt) == eNarumiCommandResult.Success)
+ {
+ PUB.log.Add($"고속주행설정 : {bunkiopt}");
+ PUB.DriveSpeed = true;
- AR.UTIL.MsgI($"주행속도({PUB.setting.SPD_DRIVE})가 '고속' 속도에 연결되었습니다.\n" +
- $"창을 이동하거나 '설정적용'을 누르면 원래속도({PUB.setting.SPD_H})로 변경 됩니다");
+ AR.UTIL.MsgI($"주행속도({PUB.setting.SPD_DRIVE})가 '고속' 속도에 연결되었습니다.\n" +
+ $"창을 이동하거나 '설정적용'을 누르면 원래속도({PUB.setting.SPD_H})로 변경 됩니다");
+ }
+ else
+ {
+ UTIL.MsgE($"고속 속도 설정이 실패되었습니다");
+ }
}
private void btLeft180_Click(object sender, EventArgs e)
@@ -398,7 +404,7 @@ namespace Project.ViewForm
private void button2_Click(object sender, EventArgs e)
{
- PUB.AGV.LiftControl(arDev.Narumi.LiftCommand.OFF);
+ PUB.AGV.LiftControl(arDev.Narumi.LiftCommand.OFF);
}
}
}
diff --git a/Cs_HMI/Project/fMain.cs b/Cs_HMI/Project/fMain.cs
index 0144139..77ee9ef 100644
--- a/Cs_HMI/Project/fMain.cs
+++ b/Cs_HMI/Project/fMain.cs
@@ -432,10 +432,7 @@ namespace Project
//충전상태확인
if (PUB.CheckManualChargeMode() == false) return;
- PUB.popup.needClose = true;
- //PUB.sm.bPause = false;
- //PUB.sm.ClearRunStep();
- //PUB.sm.SetNewRunStep(ERunStep.READY);
+ PUB.popup.needClose = true;
PUB.sm.SetNewStep(eSMStep.RUN);
PUB.Speak(Lang.자동전환, addlog: false);
diff --git a/Cs_HMI/Project/fSetup.cs b/Cs_HMI/Project/fSetup.cs
index 5f4471e..a3cf266 100644
--- a/Cs_HMI/Project/fSetup.cs
+++ b/Cs_HMI/Project/fSetup.cs
@@ -471,7 +471,7 @@ namespace Project
if (tagStr == "XBE") tbPortXBE.Text = newPort;
else if (tagStr == "AGV") tbPortAGV.Text = newPort;
- // else if (tagStr == "PLC") tbPortPLC.Text = newPort;
+ // else if (tagStr == "PLC") tbPortPLC.Text = newPort;
else if (tagStr == "BAT") tbportBMS.Text = newPort;
}
@@ -511,7 +511,7 @@ namespace Project
}
try
{
- if (PUB.mplayer.SoundLocation.isEmpty()==false) PUB.mplayer.Stop();
+ if (PUB.mplayer.SoundLocation.isEmpty() == false) PUB.mplayer.Stop();
PUB.mplayer.SoundLocation = tbMusic.Text;// (new Uri(tbMusic.Text));
PUB.mplayer.Play();
PUB.bPlayMusic = true;
@@ -535,14 +535,14 @@ namespace Project
if (this.tbPortAGV.Text == "COM21")
{
this.tbPortAGV.Text = "COM11";
- // this.tbPortPLC.Text = "COM6";
+ // this.tbPortPLC.Text = "COM6";
this.tbportBMS.Text = "COM15";
this.tbPortXBE.Text = "COM18";
}
else
{
this.tbPortAGV.Text = "COM21";
- // this.tbPortPLC.Text = "COM31";
+ // this.tbPortPLC.Text = "COM31";
this.tbportBMS.Text = "COM41";
this.tbPortXBE.Text = "COM51";
}
@@ -615,35 +615,35 @@ namespace Project
private void button7_Click(object sender, EventArgs e)
{
var value = tbagvaddr.Text.PadLeft(4, '0');
- if (PUB.AGV.AGVCommand("SAD", value))
+ if (PUB.AGV.AGVCommand("SAD", value) == arDev.eNarumiCommandResult.Success)
{
PUB.setting.AGV_ADDRESS = value;
PUB.setting.Save();
}
-
+
}
private void button5_Click(object sender, EventArgs e)
{
var value = tbagvpanid.Text.PadLeft(4, '0');
- if (PUB.AGV.AGVCommand("SPN", value))
+ if (PUB.AGV.AGVCommand("SPN", value) == arDev.eNarumiCommandResult.Success)
{
PUB.setting.AGV_PANID = value;
PUB.setting.Save();
}
-
+
}
private void button6_Click(object sender, EventArgs e)
{
var value = tbagvchannel.Text.PadLeft(4, '0');
- if (PUB.AGV.AGVCommand("SCH", value))
+ if (PUB.AGV.AGVCommand("SCH", value) == arDev.eNarumiCommandResult.Success)
{
PUB.setting.AGV_CHANNEL = value;
PUB.setting.Save();
}
-
+
}
private void tbagvaddr_Click(object sender, EventArgs e)
@@ -659,7 +659,7 @@ namespace Project
{
var value = (ushort)vcGDS.Value;
var rlt = PUB.AGV.TurnGDSCenterScope(value);
- if (rlt == false) UTIL.MsgE("Error");
+ if (rlt != arDev.eNarumiCommandResult.Success) UTIL.MsgE($"Error\n{rlt}");
else UTIL.MsgI("OK");
}
}
diff --git a/Cs_HMI/SubProject/AGV/Command.cs b/Cs_HMI/SubProject/AGV/Command.cs
index 8f06845..2aeb027 100644
--- a/Cs_HMI/SubProject/AGV/Command.cs
+++ b/Cs_HMI/SubProject/AGV/Command.cs
@@ -12,20 +12,75 @@ using AR;
namespace arDev
{
+ public enum eNarumiTurn
+ {
+ None = 0,
+ LeftIng,
+ Left,
+ RightIng,
+ Right,
+ }
+ public class NarumiTurnInfo
+ {
+ public DateTime Start { get; set; }
+ public DateTime End { get; set; }
+ public TimeSpan Runtime
+ {
+ get
+ {
+ if (End.Year < 2000) return DateTime.Now - Start;
+ if (End < Start) return DateTime.Now - Start;
+ else return End - Start;
+ }
+ }
+ public eNarumiTurn State { get; set; }
+ public NarumiTurnInfo()
+ {
+ Start = new DateTime(1982, 11, 23);
+ End = new DateTime(1982, 11, 23);
+ State = eNarumiTurn.None;
+ }
+ }
+ public class NarumiCommandTime
+ {
+ public DateTime Time { get; set; }
+ public ushort count { get; set; }
+ public NarumiCommandTime(ushort cnt)
+ {
+ Time = DateTime.Now;
+ this.count = cnt;
+ }
+ }
+
+ ///
+ /// error 이상은모두 처리불가한 오류 조건을 의미한다
+ ///
+ public enum eNarumiCommandResult : byte
+ {
+ Fail = 0,
+ Success = 1,
+ Wait = 2,
+ Error = 100,
+ Timeout,
+
+ }
public partial class Narumi
{
+ public NarumiTurnInfo TurnInformation { get; set; } = null;
+ Dictionary SendCommandFailList { get; set; } = new Dictionary();
- public bool AGVMoveSet(BunkiData opt)
+ public eNarumiCommandResult AGVMoveSet(BunkiData opt)
{
- return AddCommand(eAgvCmd.MoveSet, opt.ToString());
+ var param = opt.ToString();
+ return AddCommand(eAgvCmd.MoveSet, param);
}
- public bool AGVMoveManual(ManulOpt opt, Speed spd, Sensor ss)
+ public eNarumiCommandResult AGVMoveManual(ManulOpt opt, Speed spd, Sensor ss)
{
var param = opt.ToString() + spd.ToString()[0] + ((int)ss).ToString();
return AddCommand(eAgvCmd.ManualMove, param);
}
- public bool AGVMoveRun(eRunOpt opt = eRunOpt.NotSet)
+ public eNarumiCommandResult AGVMoveRun(eRunOpt opt = eRunOpt.NotSet)
{
System.Text.StringBuilder sb = new StringBuilder();
if (opt == eRunOpt.Backward) sb.Append("B");
@@ -35,7 +90,7 @@ namespace arDev
return AddCommand(eAgvCmd.MoveStart, sb.ToString());
}
- public bool AGVSetSpeed(eSetSpeed item, int speed)
+ public eNarumiCommandResult AGVSetSpeed(eSetSpeed item, int speed)
{
string cmd = "SS";
if (item == eSetSpeed.Rotation) cmd = "SRS";
@@ -43,7 +98,7 @@ namespace arDev
cmd += speed.ToString("0000");
return AddCommand(cmd);
}
- public bool AGVMoveStop(string Reason, eStopOpt opt = eStopOpt.Stop)
+ public eNarumiCommandResult AGVMoveStop(string Reason, eStopOpt opt = eStopOpt.Stop)
{
System.Text.StringBuilder sb = new StringBuilder();
if (opt == eStopOpt.MarkStop) sb.Append("MS");
@@ -53,147 +108,187 @@ namespace arDev
else sb.Append("0S");
sb.Append("00");
sb.Append("0000"); //재기동시간
- //if (opt == eStopOpt.MarkStop)
- // VAR.BOOL[eVarBool.NEXTSTOP_MARK] = true;
//동작중이면 이 멈춤 명령을 기록으로 남긴다 230116
if (this.system1.agv_run)
RaiseMessage(MessageType.Normal, $"stop command from {Reason}");
- return AddCommand(eAgvCmd.MoveStop, sb.ToString());
+ var retval = AddCommand(eAgvCmd.MoveStop, sb.ToString());
+ if (retval == eNarumiCommandResult.Success && opt == eStopOpt.MarkStop)
+ VAR.BOOL[eVarBool.NEXTSTOP_MARK] = true;
+
+ return retval;
}
- public bool AGVCommand(string cmd, string data)
+ public eNarumiCommandResult AGVCommand(string cmd, string data)
{
return AddCommand(cmd + data);
}
- public bool LiftControl(LiftCommand cmd)
+ public eNarumiCommandResult LiftControl(LiftCommand cmd)
{
return AddCommand(eAgvCmd.LiftControl, cmd.ToString());
}
- public bool AGVCharge(int chargetID, bool on, int waittime = 3)
+ public eNarumiCommandResult AGVCharge(int chargetID, bool on, int waittime = 3)
{
if (on)
return AddCommand(eAgvCmd.ChargeOn, chargetID.ToString("0000"));
else
return AddCommand(eAgvCmd.ChargeOf, chargetID.ToString("0000"));
}
- public bool SetBackturnTime(int time)
+ public eNarumiCommandResult SetBackturnTime(int time)
{
return AddCommand(eAgvCmd.BackTrunResumeTime, time.ToString("0000"));
}
- public bool SetGateOutOffTime(int time)
+ public eNarumiCommandResult SetGateOutOffTime(int time)
{
return AddCommand(eAgvCmd.GateoutTime, time.ToString("0000"));
}
- public bool TurnGDSCenterScope(UInt16 time)
+ public eNarumiCommandResult TurnGDSCenterScope(UInt16 time)
{
if (time > 2000) time = 2000;
return AddCommand(eAgvCmd.TurnGDSCenterScope, time.ToString("0000"));
}
- public bool AGVMoveLeft180Turn()
+ public eNarumiCommandResult AGVMoveLeft180Turn()
{
return AddCommand(eAgvCmd.TurnLeft);
}
- public bool AGVMoveRight180Turn()
+ public eNarumiCommandResult AGVMoveRight180Turn()
{
return AddCommand(eAgvCmd.TurnRight);
}
- public bool AGVMoveBack180Turn(bool leftTurn)
+ public eNarumiCommandResult AGVMoveBack180Turn(bool leftTurn)
{
var dir = leftTurn ? "L" : "R";
return AddCommand(eAgvCmd.BackAndTurn, dir);
}
-
-
- public bool AGVErrorReset()
+ public eNarumiCommandResult AGVErrorReset()
{
return AddCommand(eAgvCmd.ErrorReset, "FFFF");
}
- public bool AGVTowerLamp(bool on)
+ public eNarumiCommandResult AGVTowerLamp(bool on)
{
return AddCommand(eAgvCmd.TowerLamp, (on ? "I" : "O"));
}
- public bool AGVSetAddress(int value)
+ public eNarumiCommandResult AGVSetAddress(int value)
{
return AddCommand($"SAD{value:0000}");
}
- public bool AGVSetPanID(string value)
+ public eNarumiCommandResult AGVSetPanID(string value)
{
value = value.PadLeft(4, '0');
return AddCommand($"SPN{value}");
}
- public bool AGVSetChannel(string value)
+ public eNarumiCommandResult AGVSetChannel(string value)
{
value = value.PadLeft(4, '0');
return AddCommand($"SCH{value}");
}
- //public bool AGVGateOutTimer(int value)
- //{
- // return AddCommand($"SGT{value:0000}");
- //}
- ///
- /// 정지감속주기 및 상수
- ///
- ///
- public bool AGVSetStopAcc(int interval, int value)
- {
- var cmds = new string[] {
- $"SSK{interval:0000}",
- $"SCK{value:0000}"
- };
- return AddCommand( cmds);
- }
- public bool AGVSetTagReinputTime(int value)
+ public eNarumiCommandResult AGVSetTagReinputTime(int value)
{
return AddCommand($"STT{value:0000}");
}
- public bool AGVSetPID(eSetPIDSpeed speed, int P, int I, int D)
- {
- var cmd = "S";
- var cmd2 = "";
- if (speed == eSetPIDSpeed.High) cmd2 = "K";
- else if (speed == eSetPIDSpeed.Middle) cmd2 = "M";
- else if (speed == eSetPIDSpeed.Low) cmd2 = "L";
- else if (speed == eSetPIDSpeed.Stop) cmd2 = "S";
- var cmds = new string[] {
- $"{cmd}P{cmd2}{P:0000}",
- $"{cmd}I{cmd2}{I:0000}",
- $"{cmd}D{cmd2}{D:0000}",
- };
- return AddCommand( cmds);
- }
-
- ///
- /// 전송을시도한 시간
- ///
- //public Dictionary LastCommandTime { get; set; }
-
- ///
- /// 전송에 성공한 명령시간
- ///
- //public Dictionary LastCommandOKTime { get; set; }
- protected bool AddCommand(params string[] cmds)
+ /////
+ ///// 전송에 성공한 명령시간
+ /////
+ ////public Dictionary LastCommandOKTime { get; set; }
+ protected bool SendCommand(string cmdline)
{
bool ret = true;
- ACKData = string.Empty; //회신값 제거
- //LastCommandTime.Add(cmd, DateTime.Now);
- foreach (var cmdline in cmds)
- {
- var fullcmd = MakeCheckSum(cmdline);
- //commandQueue.Enqueue(fullcmd);
- if (WriteData(fullcmd) == false) ret = false;
- //else LastCommandOKTime.Add(cmd, DateTime.Now);
- System.Threading.Thread.Sleep(1);
- }
+ ACKData = string.Empty;
+ var fullcmd = MakeCheckSum(cmdline);
+ if (WriteData(fullcmd) == false) ret = false;
+ System.Threading.Thread.Sleep(1);
return ret;
}
+ ManualResetEvent mrecmd = new ManualResetEvent(true);
+ public eNarumiCommandResult AddCommand(string cmd, int waitms = 1)
+ {
+ if (mrecmd.WaitOne(waitms) == false)
+ {
+ //다른명령을 처리하는 중이므로 대기상태로 반환한다
+ return eNarumiCommandResult.Wait;
+ }
- protected bool AddCommand(eAgvCmd command, BunkiData param)
+ //다른신호를 처리하지 못하게한다.
+ mrecmd.Reset();
+
+ try
+ {
+ if (SendCommandFailList.ContainsKey(cmd) == false)
+ {
+ //실패기록이 없다
+ var ret = SendCommand(cmd);
+ if (ret == false)
+ {
+ SendCommandFailList.Add(cmd, new NarumiCommandTime(1));
+ return eNarumiCommandResult.Fail;
+ }
+ else return eNarumiCommandResult.Success;
+ }
+ else
+ {
+ //실패기록이 존재한다.
+ //1.동일 명령이 아니면 바로 전송한다
+ var precmd = SendCommandFailList[cmd];
+
+ //동일명령의 실패기록이 존재한다.
+ //2초간의 간격을 둔다
+ var ts = DateTime.Now - precmd.Time;
+ if (ts.TotalSeconds < 2)
+ {
+ precmd.Time = DateTime.Now;
+ SendCommandFailList[cmd] = precmd;
+ return eNarumiCommandResult.Wait; //대기한다
+ }
+ else
+ {
+ //오류가 누적되었다.
+ var ret = SendCommand(cmd);
+ if (ret == false)
+ {
+ precmd.Time = DateTime.Now;
+ precmd.count += 1;
+ SendCommandFailList[cmd] = precmd;
+
+ //5회연속 실패했다면 타임아웃처리한다
+ if (precmd.count > 5)
+ {
+ //타임아웃
+ return eNarumiCommandResult.Timeout;
+ }
+ else
+ {
+ //실패
+ return eNarumiCommandResult.Fail;
+ }
+ }
+ else
+ {
+ //전송이성공했으니 키를 제거한다.
+ SendCommandFailList.Remove(cmd);
+ return eNarumiCommandResult.Success;
+ }
+ }
+
+ }
+ }
+ catch (Exception ex)
+ {
+ Console.WriteLine($"narumi addCommand error : {ex.Message}");
+ return eNarumiCommandResult.Error;
+ }
+ finally
+ {
+ mrecmd.Set();
+ }
+ }
+
+
+ protected eNarumiCommandResult AddCommand(eAgvCmd command, BunkiData param)
{
return AddCommand(command, param.ToString());
}
@@ -204,15 +299,15 @@ namespace arDev
///
///
///
- protected bool AddCommand(BunkiData param)
+ protected eNarumiCommandResult AddCommand(BunkiData param)
{
return AddCommand(eAgvCmd.MoveSet, param.ToString());
}
- protected bool AddCommand(eAgvCmd command, string param = "")
+ protected eNarumiCommandResult AddCommand(eAgvCmd command, string param = "")
{
string cmdString;
- bool retval = false;
+ eNarumiCommandResult retval = eNarumiCommandResult.Error;
switch (command)
{
case eAgvCmd.ErrorReset:
@@ -247,10 +342,24 @@ namespace arDev
case eAgvCmd.TurnLeft:
cmdString = $"CTL0000";
retval = AddCommand(cmdString);
+ if (retval == eNarumiCommandResult.Success)
+ {
+ if (TurnInformation == null) TurnInformation = new NarumiTurnInfo();
+ TurnInformation.Start = DateTime.Now;
+ TurnInformation.End = new DateTime(1982, 11, 23);
+ TurnInformation.State = eNarumiTurn.LeftIng;
+ }
break;
case eAgvCmd.TurnRight:
cmdString = $"CTR0000";
retval = AddCommand(cmdString);
+ if (retval == eNarumiCommandResult.Success)
+ {
+ if (TurnInformation == null) TurnInformation = new NarumiTurnInfo();
+ TurnInformation.Start = DateTime.Now;
+ TurnInformation.End = new DateTime(1982, 11, 23);
+ TurnInformation.State = eNarumiTurn.RightIng;
+ }
break;
case eAgvCmd.BackAndTurn:
if (param.isEmpty()) param = "L";
diff --git a/Cs_HMI/SubProject/AGV/Narumi.cs b/Cs_HMI/SubProject/AGV/Narumi.cs
index 48d588f..97684da 100644
--- a/Cs_HMI/SubProject/AGV/Narumi.cs
+++ b/Cs_HMI/SubProject/AGV/Narumi.cs
@@ -229,7 +229,7 @@ namespace arDev
private void RevSTS(Dataframe frame)
{
LastSTS = frame.DataString;
- string rcvdNow = frame.DataString.Replace("\0","");
+ string rcvdNow = frame.DataString.Replace("\0", "");
byte[] bRcvData = frame.Buffer;
var encoding = System.Text.Encoding.Default;
try
@@ -258,21 +258,39 @@ namespace arDev
error.SetValue(nDataTemp);
idx += 4;
-
data.Speed = rcvdNow.Substring(idx, 1)[0]; idx += 1; //L,M.H
data.Sts = rcvdNow.Substring(idx, 1)[0]; idx += 1; //S(직진),L(좌분기),R(우분기)
data.Direction = rcvdNow.Substring(idx, 1)[0]; idx += 1; //F,B,L,R
data.guidesensor = int.Parse(rcvdNow.Substring(idx, 1)); idx += 1; //가이드 좌측부터 1~9
nDataTemp = Convert.ToByte(rcvdNow.Substring(idx, 2), 16);
- signal1.SetValue(nDataTemp); idx += 2;
+ signal1.SetValue(nDataTemp); idx += 2;
- if(idx <= rcvdNow.Length-2)
+ //agv가 멈춰있고 마크센서가 들어온경우, 턴 작업이었다면 턴 셋팅을 한다
+ if (system1.agv_run == false && system1.agv_stop == true &&
+ TurnInformation != null && signal1.mark_sensor)
+ {
+ if (TurnInformation.Start.Year > 2000)
+ {
+ if (TurnInformation.State == eNarumiTurn.LeftIng || TurnInformation.State == eNarumiTurn.RightIng)
+ {
+ TurnInformation.End = DateTime.Now;
+ if (TurnInformation.State == eNarumiTurn.LeftIng) TurnInformation.State = eNarumiTurn.Left;
+ if (TurnInformation.State == eNarumiTurn.RightIng) TurnInformation.State = eNarumiTurn.Right;
+ }
+ }
+ else
+ {
+ //시작시간이 설정되지 않았다면 처리하지 않는다.
+ }
+ }
+
+ if (idx <= rcvdNow.Length - 2)
{
nDataTemp = Convert.ToByte(rcvdNow.Substring(idx, 2), 16);
signal2.SetValue(nDataTemp);
}
-
+
DataReceive?.Invoke(this, new DataEventArgs(DataType.STS));
@@ -462,7 +480,7 @@ namespace arDev
OFF
}
-
+
private bool CheckSum(byte[] bData)
{
if (bData.Length < 2) // 데이터 길이가 2이하일 경우 비정상 처리
diff --git a/Cs_HMI/SubProject/CommData/Enum.cs b/Cs_HMI/SubProject/CommData/Enum.cs
index 41181ef..e62aa47 100644
--- a/Cs_HMI/SubProject/CommData/Enum.cs
+++ b/Cs_HMI/SubProject/CommData/Enum.cs
@@ -13,6 +13,7 @@ namespace COMM
SumQty,
ChargeWaitSec,
SyncItemCount,
+ PathValidationError,
}
public enum eVarUInt32
{
diff --git a/Cs_HMI/SubProject/EnigProtocol b/Cs_HMI/SubProject/EnigProtocol
index 14ff055..bca75dd 160000
--- a/Cs_HMI/SubProject/EnigProtocol
+++ b/Cs_HMI/SubProject/EnigProtocol
@@ -1 +1 @@
-Subproject commit 14ff055fa98a3e692c796d961133635e21e9ff69
+Subproject commit bca75ddd6a85bb8bf7c196e8ac8bb2eea52ba522
diff --git a/Document/NewMap.json b/Document/NewMap.json
new file mode 100644
index 0000000..5799617
--- /dev/null
+++ b/Document/NewMap.json
@@ -0,0 +1,1005 @@
+{
+ "Nodes": [
+ {
+ "Id": "N001",
+ "Text": "Unloader",
+ "Position": "298, 270",
+ "Type": 0,
+ "StationType": 3,
+ "ConnectedNodes": [
+ "12",
+ "14"
+ ],
+ "RfidId": 1,
+ "NodeTextForeColor": "White",
+ "NodeTextFontSize": 30,
+ "AliasName": "",
+ "SpeedLimit": 0,
+ "CanDocking": true,
+ "DockDirection": 0,
+ "CanTurnLeft": true,
+ "CanTurnRight": true,
+ "DisableCross": false,
+ "IsActive": true
+ },
+ {
+ "Id": "N010",
+ "Text": "Cleaner",
+ "Position": "298, 446",
+ "Type": 0,
+ "StationType": 2,
+ "ConnectedNodes": [
+ "5",
+ "15"
+ ],
+ "RfidId": 11,
+ "NodeTextForeColor": "",
+ "NodeTextFontSize": 7,
+ "AliasName": "",
+ "SpeedLimit": 0,
+ "CanDocking": true,
+ "DockDirection": 1,
+ "CanTurnLeft": true,
+ "CanTurnRight": true,
+ "DisableCross": false,
+ "IsActive": true
+ },
+ {
+ "Id": "N014",
+ "Text": "Loader",
+ "Position": "520, 653",
+ "Type": 0,
+ "StationType": 1,
+ "ConnectedNodes": [
+ "6",
+ "16"
+ ],
+ "RfidId": 8,
+ "NodeTextForeColor": "",
+ "NodeTextFontSize": 7,
+ "AliasName": "",
+ "SpeedLimit": 0,
+ "CanDocking": true,
+ "DockDirection": 0,
+ "CanTurnLeft": true,
+ "CanTurnRight": true,
+ "DisableCross": false,
+ "IsActive": true
+ },
+ {
+ "Id": "N019",
+ "Text": "Chg #1",
+ "Position": "402, 375",
+ "Type": 0,
+ "StationType": 5,
+ "ConnectedNodes": [],
+ "RfidId": 15,
+ "NodeTextForeColor": "",
+ "NodeTextFontSize": 7,
+ "AliasName": "",
+ "SpeedLimit": 0,
+ "CanDocking": true,
+ "DockDirection": 1,
+ "CanTurnLeft": true,
+ "CanTurnRight": true,
+ "DisableCross": false,
+ "IsActive": true
+ },
+ {
+ "Id": "N026",
+ "Text": "Chg #2",
+ "Position": "541, 570",
+ "Type": 0,
+ "StationType": 5,
+ "ConnectedNodes": [],
+ "RfidId": 19,
+ "NodeTextForeColor": "",
+ "NodeTextFontSize": 7,
+ "AliasName": "",
+ "SpeedLimit": 0,
+ "CanDocking": true,
+ "DockDirection": 1,
+ "CanTurnLeft": true,
+ "CanTurnRight": true,
+ "DisableCross": false,
+ "IsActive": true
+ },
+ {
+ "Id": "N018",
+ "Text": "",
+ "Position": "213, 630",
+ "Type": 0,
+ "StationType": 0,
+ "ConnectedNodes": [
+ "N030",
+ "N005",
+ "1"
+ ],
+ "RfidId": 34,
+ "NodeTextForeColor": "",
+ "NodeTextFontSize": 7,
+ "AliasName": "",
+ "SpeedLimit": 0,
+ "CanDocking": false,
+ "DockDirection": 0,
+ "CanTurnLeft": true,
+ "CanTurnRight": true,
+ "DisableCross": false,
+ "IsActive": true
+ },
+ {
+ "Id": "N005",
+ "Text": "",
+ "Position": "113, 629",
+ "Type": 0,
+ "StationType": 0,
+ "ConnectedNodes": [
+ "N018",
+ "N020",
+ "N029"
+ ],
+ "RfidId": 33,
+ "NodeTextForeColor": "",
+ "NodeTextFontSize": 7,
+ "AliasName": "",
+ "SpeedLimit": 0,
+ "CanDocking": false,
+ "DockDirection": 0,
+ "CanTurnLeft": true,
+ "CanTurnRight": true,
+ "DisableCross": false,
+ "IsActive": true
+ },
+ {
+ "Id": "N020",
+ "Text": "",
+ "Position": "38, 626",
+ "Type": 0,
+ "StationType": 0,
+ "ConnectedNodes": [
+ "N005",
+ "N021",
+ "N028"
+ ],
+ "RfidId": 32,
+ "NodeTextForeColor": "",
+ "NodeTextFontSize": 7,
+ "AliasName": "",
+ "SpeedLimit": 0,
+ "CanDocking": false,
+ "DockDirection": 0,
+ "CanTurnLeft": true,
+ "CanTurnRight": true,
+ "DisableCross": false,
+ "IsActive": true
+ },
+ {
+ "Id": "N021",
+ "Text": "",
+ "Position": "-54, 626",
+ "Type": 0,
+ "StationType": 0,
+ "ConnectedNodes": [
+ "N020",
+ "N027",
+ "11"
+ ],
+ "RfidId": 31,
+ "NodeTextForeColor": "",
+ "NodeTextFontSize": 7,
+ "AliasName": "",
+ "SpeedLimit": 0,
+ "CanDocking": false,
+ "DockDirection": 0,
+ "CanTurnLeft": true,
+ "CanTurnRight": true,
+ "DisableCross": false,
+ "IsActive": true
+ },
+ {
+ "Id": "N027",
+ "Text": "Buf #1",
+ "Position": "-76, 676",
+ "Type": 0,
+ "StationType": 4,
+ "ConnectedNodes": [
+ "N021"
+ ],
+ "RfidId": 41,
+ "NodeTextForeColor": "",
+ "NodeTextFontSize": 7,
+ "AliasName": "",
+ "SpeedLimit": 0,
+ "CanDocking": true,
+ "DockDirection": 0,
+ "CanTurnLeft": true,
+ "CanTurnRight": true,
+ "DisableCross": false,
+ "IsActive": true
+ },
+ {
+ "Id": "N028",
+ "Text": "Buf #2",
+ "Position": "12, 676",
+ "Type": 0,
+ "StationType": 4,
+ "ConnectedNodes": [
+ "N020"
+ ],
+ "RfidId": 40,
+ "NodeTextForeColor": "",
+ "NodeTextFontSize": 7,
+ "AliasName": "",
+ "SpeedLimit": 0,
+ "CanDocking": true,
+ "DockDirection": 0,
+ "CanTurnLeft": true,
+ "CanTurnRight": true,
+ "DisableCross": false,
+ "IsActive": true
+ },
+ {
+ "Id": "N029",
+ "Text": "Buf #3",
+ "Position": "89, 674",
+ "Type": 0,
+ "StationType": 4,
+ "ConnectedNodes": [
+ "N005"
+ ],
+ "RfidId": 39,
+ "NodeTextForeColor": "",
+ "NodeTextFontSize": 7,
+ "AliasName": "",
+ "SpeedLimit": 0,
+ "CanDocking": true,
+ "DockDirection": 0,
+ "CanTurnLeft": true,
+ "CanTurnRight": true,
+ "DisableCross": false,
+ "IsActive": true
+ },
+ {
+ "Id": "N030",
+ "Text": "Buf #4",
+ "Position": "183, 675",
+ "Type": 0,
+ "StationType": 4,
+ "ConnectedNodes": [
+ "N018"
+ ],
+ "RfidId": 38,
+ "NodeTextForeColor": "",
+ "NodeTextFontSize": 7,
+ "AliasName": "",
+ "SpeedLimit": 0,
+ "CanDocking": true,
+ "DockDirection": 0,
+ "CanTurnLeft": true,
+ "CanTurnRight": true,
+ "DisableCross": false,
+ "IsActive": true
+ },
+ {
+ "Id": "1",
+ "Text": "",
+ "Position": "285, 628",
+ "Type": 0,
+ "StationType": 0,
+ "ConnectedNodes": [
+ "N018",
+ "2"
+ ],
+ "RfidId": 2,
+ "NodeTextForeColor": "",
+ "NodeTextFontSize": 7,
+ "AliasName": "",
+ "SpeedLimit": 0,
+ "CanDocking": false,
+ "DockDirection": 0,
+ "CanTurnLeft": true,
+ "CanTurnRight": true,
+ "DisableCross": false,
+ "IsActive": true
+ },
+ {
+ "Id": "2",
+ "Text": "",
+ "Position": "354, 628",
+ "Type": 0,
+ "StationType": 0,
+ "ConnectedNodes": [
+ "1",
+ "3"
+ ],
+ "RfidId": 4,
+ "NodeTextForeColor": "",
+ "NodeTextFontSize": 7,
+ "AliasName": "",
+ "SpeedLimit": 0,
+ "CanDocking": false,
+ "DockDirection": 0,
+ "CanTurnLeft": true,
+ "CanTurnRight": true,
+ "DisableCross": false,
+ "IsActive": true
+ },
+ {
+ "Id": "3",
+ "Text": "",
+ "Position": "400, 578",
+ "Type": 0,
+ "StationType": 0,
+ "ConnectedNodes": [
+ "2",
+ "4"
+ ],
+ "RfidId": 3,
+ "NodeTextForeColor": "",
+ "NodeTextFontSize": 7,
+ "AliasName": "",
+ "SpeedLimit": 0,
+ "CanDocking": false,
+ "DockDirection": 0,
+ "CanTurnLeft": true,
+ "CanTurnRight": true,
+ "DisableCross": false,
+ "IsActive": true
+ },
+ {
+ "Id": "4",
+ "Text": "",
+ "Position": "400, 499",
+ "Type": 0,
+ "StationType": 0,
+ "ConnectedNodes": [
+ "3",
+ "5"
+ ],
+ "RfidId": 5,
+ "NodeTextForeColor": "",
+ "NodeTextFontSize": 7,
+ "AliasName": "",
+ "SpeedLimit": 0,
+ "CanDocking": false,
+ "DockDirection": 0,
+ "CanTurnLeft": true,
+ "CanTurnRight": true,
+ "DisableCross": false,
+ "IsActive": true
+ },
+ {
+ "Id": "5",
+ "Text": "",
+ "Position": "462, 451",
+ "Type": 0,
+ "StationType": 0,
+ "ConnectedNodes": [
+ "N010",
+ "4",
+ "6",
+ "7"
+ ],
+ "RfidId": 6,
+ "NodeTextForeColor": "",
+ "NodeTextFontSize": 7,
+ "AliasName": "",
+ "SpeedLimit": 0,
+ "CanDocking": false,
+ "DockDirection": 0,
+ "CanTurnLeft": true,
+ "CanTurnRight": true,
+ "DisableCross": false,
+ "IsActive": true
+ },
+ {
+ "Id": "6",
+ "Text": "",
+ "Position": "518, 519",
+ "Type": 0,
+ "StationType": 0,
+ "ConnectedNodes": [
+ "N014",
+ "5"
+ ],
+ "RfidId": 13,
+ "NodeTextForeColor": "",
+ "NodeTextFontSize": 7,
+ "AliasName": "",
+ "SpeedLimit": 0,
+ "CanDocking": false,
+ "DockDirection": 0,
+ "CanTurnLeft": true,
+ "CanTurnRight": true,
+ "DisableCross": false,
+ "IsActive": true
+ },
+ {
+ "Id": "7",
+ "Text": "",
+ "Position": "517, 400",
+ "Type": 0,
+ "StationType": 0,
+ "ConnectedNodes": [
+ "5",
+ "8"
+ ],
+ "RfidId": 7,
+ "NodeTextForeColor": "",
+ "NodeTextFontSize": 7,
+ "AliasName": "",
+ "SpeedLimit": 0,
+ "CanDocking": false,
+ "DockDirection": 0,
+ "CanTurnLeft": true,
+ "CanTurnRight": true,
+ "DisableCross": false,
+ "IsActive": true
+ },
+ {
+ "Id": "8",
+ "Text": "",
+ "Position": "474, 353",
+ "Type": 0,
+ "StationType": 0,
+ "ConnectedNodes": [
+ "7",
+ "9",
+ "13"
+ ],
+ "RfidId": 9,
+ "NodeTextForeColor": "",
+ "NodeTextFontSize": 7,
+ "AliasName": "",
+ "SpeedLimit": 0,
+ "CanDocking": false,
+ "DockDirection": 0,
+ "CanTurnLeft": true,
+ "CanTurnRight": true,
+ "DisableCross": false,
+ "IsActive": true
+ },
+ {
+ "Id": "9",
+ "Text": "",
+ "Position": "517, 311",
+ "Type": 0,
+ "StationType": 0,
+ "ConnectedNodes": [
+ "8",
+ "10"
+ ],
+ "RfidId": 10,
+ "NodeTextForeColor": "",
+ "NodeTextFontSize": 7,
+ "AliasName": "",
+ "SpeedLimit": 0,
+ "CanDocking": false,
+ "DockDirection": 0,
+ "CanTurnLeft": true,
+ "CanTurnRight": true,
+ "DisableCross": false,
+ "IsActive": true
+ },
+ {
+ "Id": "10",
+ "Text": "",
+ "Position": "458, 268",
+ "Type": 0,
+ "StationType": 0,
+ "ConnectedNodes": [
+ "9",
+ "12"
+ ],
+ "RfidId": 12,
+ "NodeTextForeColor": "",
+ "NodeTextFontSize": 7,
+ "AliasName": "",
+ "SpeedLimit": 0,
+ "CanDocking": false,
+ "DockDirection": 0,
+ "CanTurnLeft": true,
+ "CanTurnRight": true,
+ "DisableCross": false,
+ "IsActive": true
+ },
+ {
+ "Id": "12",
+ "Text": "",
+ "Position": "389, 270",
+ "Type": 0,
+ "StationType": 0,
+ "ConnectedNodes": [
+ "N001",
+ "10"
+ ],
+ "RfidId": 16,
+ "NodeTextForeColor": "",
+ "NodeTextFontSize": 7,
+ "AliasName": "",
+ "SpeedLimit": 0,
+ "CanDocking": false,
+ "DockDirection": 0,
+ "CanTurnLeft": true,
+ "CanTurnRight": true,
+ "DisableCross": false,
+ "IsActive": true
+ },
+ {
+ "Id": "13",
+ "Text": "",
+ "Position": "350, 353",
+ "Type": 0,
+ "StationType": 0,
+ "ConnectedNodes": [
+ "8"
+ ],
+ "RfidId": 17,
+ "NodeTextForeColor": "",
+ "NodeTextFontSize": 7,
+ "AliasName": "",
+ "SpeedLimit": 0,
+ "CanDocking": false,
+ "DockDirection": 0,
+ "CanTurnLeft": true,
+ "CanTurnRight": true,
+ "DisableCross": false,
+ "IsActive": true
+ }
+ ],
+ "Labels": [
+ {
+ "Id": "11",
+ "Type": 1,
+ "Text": "Label",
+ "Position": "-120, 625",
+ "ForeColor": "White",
+ "BackColor": "Transparent",
+ "FontFamily": "Arial",
+ "FontSize": 7,
+ "FontStyle": 0,
+ "Padding": 5
+ },
+ {
+ "Id": "14",
+ "Type": 1,
+ "Text": "Label",
+ "Position": "224, 272",
+ "ForeColor": "White",
+ "BackColor": "Transparent",
+ "FontFamily": "Arial",
+ "FontSize": 7,
+ "FontStyle": 0,
+ "Padding": 5
+ },
+ {
+ "Id": "15",
+ "Type": 1,
+ "Text": "Label",
+ "Position": "247, 449",
+ "ForeColor": "White",
+ "BackColor": "Transparent",
+ "FontFamily": "Arial",
+ "FontSize": 7,
+ "FontStyle": 0,
+ "Padding": 5
+ },
+ {
+ "Id": "16",
+ "Type": 1,
+ "Text": "Label",
+ "Position": "517, 721",
+ "ForeColor": "White",
+ "BackColor": "Transparent",
+ "FontFamily": "Arial",
+ "FontSize": 7,
+ "FontStyle": 0,
+ "Padding": 5
+ },
+ {
+ "Id": "LBL001",
+ "Type": 1,
+ "Text": "Amkor Technology Korea",
+ "Position": "180, 105",
+ "ForeColor": "White",
+ "BackColor": "MidnightBlue",
+ "FontFamily": "Arial",
+ "FontSize": 20,
+ "FontStyle": 0,
+ "Padding": 5
+ }
+ ],
+ "Images": [
+ {
+ "Id": "IMG001",
+ "Type": 2,
+ "Name": "Image",
+ "Position": "633, 310",
+ "ImagePath": "",
+ "ImageBase64": "",
+ "Scale": "1, 1",
+ "Opacity": 1,
+ "Rotation": 0
+ }
+ ],
+ "Magnets": [
+ {
+ "Id": "5a0edec2-7ac3-4c99-bbb4-8debde0c1d07",
+ "Type": 4,
+ "P1": {
+ "X": 358.5378151260505,
+ "Y": 628.438429217841
+ },
+ "P2": {
+ "X": -119.57759581805529,
+ "Y": 626.7844959888976
+ },
+ "ControlPoint": null
+ },
+ {
+ "Id": "def7c4b9-86db-42eb-aae6-0c6c9bedcc30",
+ "Type": 4,
+ "P1": {
+ "X": -75.0847526191485,
+ "Y": 716.1415561436951
+ },
+ "P2": {
+ "X": -73.1298113651053,
+ "Y": 561.6311923370746
+ },
+ "ControlPoint": null
+ },
+ {
+ "Id": "624327ee-be0f-4373-b60a-786a93c1eabf",
+ "Type": 4,
+ "P1": {
+ "X": 12.69302515862924,
+ "Y": 717.2526672548062
+ },
+ "P2": {
+ "X": 11.870188634894689,
+ "Y": 560.2502399561221
+ },
+ "ControlPoint": null
+ },
+ {
+ "Id": "f1e885ae-55f7-42e9-b3aa-648541e97da0",
+ "Type": 4,
+ "P1": {
+ "X": 90.47080293640698,
+ "Y": 716.1415561436951
+ },
+ "P2": {
+ "X": 89.72733149203751,
+ "Y": 560.9169066227888
+ },
+ "ControlPoint": null
+ },
+ {
+ "Id": "dc3e8061-2c99-4f24-ac9b-4020dd91fa8b",
+ "Type": 4,
+ "P1": {
+ "X": 185.470802936407,
+ "Y": 725.0304450325839
+ },
+ "P2": {
+ "X": 181.87018863489462,
+ "Y": 563.059763765646
+ },
+ "ControlPoint": null
+ },
+ {
+ "Id": "f4c97a5a-2c2c-4b5e-9dd5-332b1670b827",
+ "Type": 4,
+ "P1": {
+ "X": 343.98784548784573,
+ "Y": 353.9221611721613
+ },
+ "P2": {
+ "X": 472.59413991107186,
+ "Y": 353.73144759338567
+ },
+ "ControlPoint": null
+ },
+ {
+ "Id": "a5424add-e8c9-483c-a5db-733dca1b8f57",
+ "Type": 4,
+ "P1": {
+ "X": 519.3272283272282,
+ "Y": 720.2549019607841
+ },
+ "P2": {
+ "X": 516.1655684825004,
+ "Y": 309.44573330767145
+ },
+ "ControlPoint": null
+ },
+ {
+ "Id": "0bbb27a4-2355-4294-9f2d-a40e4d3d2930",
+ "Type": 4,
+ "P1": {
+ "X": 249.6240475640633,
+ "Y": 449.77059623383167
+ },
+ "P2": {
+ "X": 518.0855860256017,
+ "Y": 452.84751931075476
+ },
+ "ControlPoint": null
+ },
+ {
+ "Id": "92527d4a-8e63-404f-86e8-37568bd4790e",
+ "Type": 4,
+ "P1": {
+ "X": 225.77789371790945,
+ "Y": 271.3090577722932
+ },
+ "P2": {
+ "X": 463.6655684825004,
+ "Y": 269.44573330767145
+ },
+ "ControlPoint": null
+ },
+ {
+ "Id": "0db9553a-f203-478d-8c17-e07f00987828",
+ "Type": 4,
+ "P1": {
+ "X": 463.41452991452985,
+ "Y": 270.2549019607843
+ },
+ "P2": {
+ "X": 515.0811965811965,
+ "Y": 310.25490196078425
+ },
+ "ControlPoint": {
+ "X": 517.8589743589743,
+ "Y": 266.3660130718954
+ }
+ },
+ {
+ "Id": "0650b2cb-57f9-44ec-9787-fab878cf2b47",
+ "Type": 4,
+ "P1": {
+ "X": 473.41452991452985,
+ "Y": 353.032679738562
+ },
+ "P2": {
+ "X": 515.6367521367521,
+ "Y": 399.1437908496731
+ },
+ "ControlPoint": {
+ "X": 521.7478632478632,
+ "Y": 351.3660130718954
+ }
+ },
+ {
+ "Id": "7007db10-b61b-4726-9775-417951454ddf",
+ "Type": 4,
+ "P1": {
+ "X": 465.08119658119654,
+ "Y": 450.2549019607842
+ },
+ "P2": {
+ "X": 518.2491858425353,
+ "Y": 519.0597150914111
+ },
+ "ControlPoint": {
+ "X": 522.8589743589743,
+ "Y": 450.8104575163398
+ }
+ },
+ {
+ "Id": "4ef4bfd0-8fc4-48a5-a490-92b35c7fd1c3",
+ "Type": 4,
+ "P1": {
+ "X": 473.3084256253576,
+ "Y": 351.58859045052856
+ },
+ "P2": {
+ "X": 515.4512827682147,
+ "Y": 309.8028761648143
+ },
+ "ControlPoint": {
+ "X": 519.0227113396433,
+ "Y": 358.01716187909994
+ }
+ },
+ {
+ "Id": "7d18ae7e-7926-4cf4-8dd6-861462e31352",
+ "Type": 4,
+ "P1": {
+ "X": 464.73699705392903,
+ "Y": 450.5171618790999
+ },
+ "P2": {
+ "X": 516.5227113396433,
+ "Y": 402.6600190219571
+ },
+ "ControlPoint": {
+ "X": 516.1655684825004,
+ "Y": 454.44573330767133
+ }
+ },
+ {
+ "Id": "532be14d-170e-45c5-adcf-0d555b83b010",
+ "Type": 4,
+ "P1": {
+ "X": 399.76697627462613,
+ "Y": 521.7210880257198
+ },
+ "P2": {
+ "X": 462.6173982141941,
+ "Y": 449.66152357736206
+ },
+ "ControlPoint": {
+ "X": 391.9923982141941,
+ "Y": 447.16152357736206
+ }
+ },
+ {
+ "Id": "086955e0-0542-4ab5-9ccf-8880e749722a",
+ "Type": 4,
+ "P1": {
+ "X": 399.0526905603404,
+ "Y": 523.5068023114342
+ },
+ "P2": {
+ "X": 400.1113258122239,
+ "Y": 580.622765294022
+ },
+ "ControlPoint": null
+ },
+ {
+ "Id": "2ac7d720-a6df-4174-be74-15ddfe96459b",
+ "Type": 4,
+ "P1": {
+ "X": 353.8613258122239,
+ "Y": 629.3727652940219
+ },
+ "P2": {
+ "X": 400.1113258122239,
+ "Y": 576.872765294022
+ },
+ "ControlPoint": {
+ "X": 404.4863258122239,
+ "Y": 630.6227652940219
+ }
+ }
+ ],
+ "Marks": [
+ {
+ "Id": "2cb51787-c8cf-4ddb-97f0-b71f519d47dc",
+ "Type": 3,
+ "Position": "520, 690",
+ "X": 520,
+ "Y": 690,
+ "Rotation": -178.01940688369234
+ },
+ {
+ "Id": "f704ebe0-1653-4559-b06f-1eaecafbefba",
+ "Type": 3,
+ "Position": "-74, 624",
+ "X": -74,
+ "Y": 624,
+ "Rotation": 90
+ },
+ {
+ "Id": "d5b27365-79a2-4351-84c3-6767941ec0be",
+ "Type": 3,
+ "Position": "12, 625",
+ "X": 12,
+ "Y": 625,
+ "Rotation": 90
+ },
+ {
+ "Id": "0367cafb-9f85-4440-b6b4-c802a58e6181",
+ "Type": 3,
+ "Position": "91, 625",
+ "X": 91,
+ "Y": 625,
+ "Rotation": 89.2872271068898
+ },
+ {
+ "Id": "1f4ab2c9-07f8-4675-802d-9b4824b55198",
+ "Type": 3,
+ "Position": "183, 622",
+ "X": 183,
+ "Y": 622,
+ "Rotation": 88.40516772072262
+ },
+ {
+ "Id": "15fddfa4-ff74-48ff-b922-4aacdce1960b",
+ "Type": 3,
+ "Position": "275, 269",
+ "X": 275,
+ "Y": 269,
+ "Rotation": 91.71222012905176
+ },
+ {
+ "Id": "4b699847-36d4-471c-b990-4ad37967c2dc",
+ "Type": 3,
+ "Position": "89, 697",
+ "X": 89,
+ "Y": 697,
+ "Rotation": 0.3824344779617803
+ },
+ {
+ "Id": "a9f68317-f1c2-47d8-b029-348b5428be9f",
+ "Type": 3,
+ "Position": "183, 699",
+ "X": 183,
+ "Y": 699,
+ "Rotation": -1.3380194104322385
+ },
+ {
+ "Id": "fe227205-2a65-4ba9-bb4a-4efb4ed0a7b0",
+ "Type": 3,
+ "Position": "9, 699",
+ "X": 9,
+ "Y": 699,
+ "Rotation": 0.8431103833306963
+ },
+ {
+ "Id": "5dd29191-798c-480c-b066-7947bfcc4fb7",
+ "Type": 3,
+ "Position": "-74, 697",
+ "X": -74,
+ "Y": 697,
+ "Rotation": 1.659829660758831
+ },
+ {
+ "Id": "649729f0-ff04-4e11-8869-f6a39d815427",
+ "Type": 3,
+ "Position": "-71, 596",
+ "X": -71,
+ "Y": 596,
+ "Rotation": 0
+ },
+ {
+ "Id": "2bb9a821-f86b-4190-a182-64abe2c940ed",
+ "Type": 3,
+ "Position": "10, 601",
+ "X": 10,
+ "Y": 601,
+ "Rotation": 0
+ },
+ {
+ "Id": "821598e1-091a-4884-96fe-6ed5f43c4f62",
+ "Type": 3,
+ "Position": "91, 598",
+ "X": 91,
+ "Y": 598,
+ "Rotation": 0
+ },
+ {
+ "Id": "66c1bbee-89a8-45a9-b585-ddfd59768f6b",
+ "Type": 3,
+ "Position": "184, 596",
+ "X": 184,
+ "Y": 596,
+ "Rotation": 0
+ },
+ {
+ "Id": "06a10f46-bda8-4b0f-9e7a-63d66bd2f7e4",
+ "Type": 3,
+ "Position": "381, 355",
+ "X": 381,
+ "Y": 355,
+ "Rotation": 91.24536426676838
+ },
+ {
+ "Id": "835b8982-042b-4e2e-a83b-19b32e55cd5b",
+ "Type": 3,
+ "Position": "519, 550",
+ "X": 519,
+ "Y": 550,
+ "Rotation": 0
+ }
+ ],
+ "Settings": {
+ "BackgroundColorArgb": -14671840,
+ "ShowGrid": false
+ },
+ "CreatedDate": "2025-12-23T04:16:13.079Z",
+ "Version": "1.3"
+}
\ No newline at end of file