This commit is contained in:
backuppc
2026-01-06 17:35:34 +09:00
parent 649d87cae3
commit 90340f4a7d
39 changed files with 2127 additions and 685 deletions

View File

@@ -34,6 +34,9 @@
<WarningLevel>4</WarningLevel>
<Prefer32Bit>false</Prefer32Bit>
</PropertyGroup>
<PropertyGroup>
<ApplicationIcon>icons8-robot-80.ico</ApplicationIcon>
</PropertyGroup>
<ItemGroup>
<Reference Include="arControl.Net4">
<HintPath>..\Cs_HMI\DLL\arControl.Net4.dll</HintPath>
@@ -136,5 +139,8 @@
<Name>ENIGProtocol</Name>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<Content Include="icons8-robot-80.ico" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
</Project>

View File

@@ -61,29 +61,52 @@ namespace AGVEmulator
/// </summary>
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<byte>();
data.Add(id);
data.AddRange(System.Text.Encoding.Default.GetBytes(tag.ToString("0000")));
Send(ENIGProtocol.AGVCommandHE.Goto, data.ToArray());
}
/// <summary>
/// 카트를 가지러 들어간다
/// </summary>
/// <param name="id"></param>
public void SendPickOn(byte id)
{
var data = new List<byte>();
data.Add(id);
Send(ENIGProtocol.AGVCommandHE.PickOn, data.ToArray());
}
/// <summary>
/// 카트를 내려놓는다
/// </summary>
/// <param name="id"></param>
public void SendPickOff(byte id)
{
var data = new List<byte>();
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<byte>();
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}");
}
}

View File

@@ -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;
}
}

View File

@@ -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;

Binary file not shown.

After

Width:  |  Height:  |  Size: 110 KiB

View File

@@ -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)

View File

@@ -478,6 +478,17 @@ namespace AGVNavigationCore.Controls
}
}
/// <summary>
/// 상세경로가 설정되어있는가?
/// </summary>
/// <returns></returns>
public bool HasPath()
{
if (_currentPath == null) return false;
if (_currentPath.DetailedPath == null) return false;
return _currentPath.DetailedPath.Any();
}
/// <summary>
/// 모든 경로 목록 (다중 AGV 경로 표시용)
/// </summary>

View File

@@ -152,6 +152,18 @@ namespace AGVNavigationCore.Models
return $"RFID:{RfidId}(NODE:{Id}): AS:{AliasName} ({Type}) at ({Position.X}, {Position.Y})";
}
/// <summary>
/// RFID(*ID)
/// </summary>
public string ID2
{
get
{
if (HasRfid()) return $"{this.RfidId:0000}(*{this.Id})";
else return $"(*{this.Id})";
}
}
public bool IsNavigationNode()
{
// 이제 MapNode는 항상 내비게이션 노드임 (Label, Image 분리됨)

View File

@@ -41,7 +41,6 @@ namespace AGVNavigationCore.Models
public bool IsSelected { get; set; } = false;
[Browsable(false)]
[JsonIgnore]
public bool IsHovered { get; set; } = false;

View File

@@ -83,8 +83,8 @@ 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;
@@ -143,6 +143,11 @@ namespace AGVNavigationCore.Models
/// </summary>
public AGVPathResult CurrentPath => _currentPath;
public void ClearPath()
{
_currentPath = null;
}
/// <summary>
/// 현재 노드 ID
/// </summary>
@@ -153,6 +158,18 @@ namespace AGVNavigationCore.Models
/// </summary>
public string CurrentNodeId => _currentNode?.Id;
/// <summary>
/// 현재노드의 RFID(id)값을 표시합니다 없는경우 (X)가 표시됩니다
/// </summary>
public string CurrentNodeID2
{
get
{
if (_currentNode == null) return "(X)";
return _currentNode.ID2;
}
}
/// <summary>
/// 이전 위치
/// </summary>
@@ -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
/// <returns>다음에 수행할 모터/마그넷/속도 명령</returns>
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 -
/// <summary>
/// 경로가 설정되어있는지?
/// </summary>
/// <returns></returns>
public bool HasPath()
{
if (_currentPath == null) return false;
if (_currentPath.DetailedPath == null) return false;
return _currentPath.DetailedPath.Any();
}
/// <summary>
/// 경로 설정 (실제 AGV 및 시뮬레이터에서 사용)
/// </summary>
@@ -411,6 +449,9 @@ namespace AGVNavigationCore.Models
{
if (path == null)
{
_currentPath = null;
_remainingNodes.Clear();// = null;
_currentNodeIndex = 0;
OnError("경로가 null입니다.");
return;
}

View File

@@ -123,6 +123,8 @@ namespace AGVNavigationCore.PathFinding.Planning
if (RequiresSpecialAction)
result += $" [특수동작:{SpecialActionDescription}]";
if (IsPass) result += "(O)";
return result;
}
}

View File

@@ -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 = "안전 커버를 올리면 상차가 완료 됩니다";

View File

@@ -14,6 +14,36 @@ using System.Windows.Forms;
namespace Project.Device
{
public enum eDocStep : byte
{
NotSet = 0,
/// <summary>
/// 투입준비됨
/// </summary>
InReady = 10,
/// <summary>
/// 투입완료
/// </summary>
InComplete = 11,
/// <summary>
/// 투입(진행중)
/// </summary>
InIng = 12,
/// <summary>
/// 진출완료
/// </summary>
OutComplete = 21,
/// <summary>
/// 진출중
/// </summary>
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);

View File

@@ -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

View File

@@ -11,26 +11,17 @@ namespace Project
{
public partial class fMain
{
/// <summary>
/// 버퍼도킹
/// </summary>
/// <param name="isFirst"></param>
/// <param name="stepTime"></param>
/// <returns></returns>
public Boolean _SM_RUN_BUFFER_IN(bool isFirst, TimeSpan stepTime)
public Boolean _SM_RUN_BUFFER_IN(bool isFirst, TimeSpan seqtime)
{
var funcname = "_SM_RUN_BUFFER_IN";
var idx = 1;
//충전 상태가 OFF되어야 동작하게한다
if (_SM_RUN_CHGOFF(isFirst, stepTime) == false) return false;
if (_SM_RUN_CHGOFF(isFirst, seqtime) == false) return false;
//라이더멈춤이 설정되어있다면 음성으로 알려준다
if (CheckLiderStop() == false) return false;
//현재 위치가 결정되어있는지 체크한다
if (_SM_RUN_POSCHK(isFirst, stepTime) == false) return false;
/*
* 버퍼IN시퀀스
* 1. 회전이 진행되지 않았다면 회전을 진행한다.
@@ -41,8 +32,8 @@ namespace Project
if (PUB.sm.RunStepSeq == idx++)
{
PUB.log.Add("버퍼도킹시작");
PUB.Speak(Lang.);
PUB.log.Add($"[{funcname}] 버퍼진입시작({PUB.NextWorkCmd}) Turn:{PUB._virtualAGV.Turn}");
PUB.Speak(Lang.);
PUB.sm.UpdateRunStepSeq();
return false;
}
@@ -70,9 +61,9 @@ namespace Project
{
if (PUB._virtualAGV.Turn != AGVNavigationCore.Models.AGVTurn.L90)
{
VAR.TIME.Update(eVarTime.LastTurnCommandTime);
PUB.AGV.AGVMoveLeft180Turn();
PUB.log.Add("AGV Left Turn");
VAR.TIME.Update(eVarTime.LastTurnCommandTime);
PUB.sm.UpdateRunStepSeq();
}
else PUB.sm.UpdateRunStepSeq(); //이미완료된상태이므로 다음으로 진행한다.
@@ -80,59 +71,35 @@ namespace Project
}
else if (PUB.sm.RunStepSeq == idx++)
{
if (PUB._virtualAGV.Turn != AGVNavigationCore.Models.AGVTurn.L90)
//왼쪽턴이 완료되지 않은경우
if (PUB.AGV.TurnInformation.State != arDev.eNarumiTurn.Left)
{
//5초이내에 턴이동 상태가 확인되어야 한다.
if (PUB.AGV.system1.agv_run == false)
//움직임 확인을 위해 3초간은 검증을 유예한다
if (PUB.AGV.TurnInformation.Runtime.TotalSeconds < 3) return false;
//턴 이동 상태가 확인되어야 한다.
var overtime = 10;
if (PUB.AGV.TurnInformation.Runtime.TotalSeconds > overtime)
{
var ts = VAR.TIME.RUN(eVarTime.LastTurnCommandTime);
if (ts.TotalSeconds > 5)
{
//5초동안 AGV까 움직이지 않았다면 오류 처리한다.
PUB.AGV.AGVMoveStop("5초이내 턴 감지 안됨");
PUB.log.AddE("5초이내 턴 감지 안됨");
PUB.sm.SetNewRunStep(ERunStep.ERROR);
return false;
}
//5초동안 AGV까 움직이지 않았다면 오류 처리한다.
PUB.AGV.AGVMoveStop($"[bufferin] {overtime}초이내 턴 감지 안됨");
PUB.log.AddE($"[{funcname}] {overtime}초이내 턴 감지 안됨");
PUB.sm.SetNewRunStep(ERunStep.ERROR);
return false;
}
}
PUB.sm.UpdateRunStepSeq(); //이미완료된상태이므로 다음으로 진행한다.
return false;
}
else if (PUB.sm.RunStepSeq == idx++)
{
//턴이완료되었느닞 확인한다.
if (PUB._virtualAGV.Turn != AGVNavigationCore.Models.AGVTurn.L90)
{
//10초 이상 가동하고 있다면 문제이다
if (PUB.AGV.system1.agv_run == true)
{
var ts = VAR.TIME.RUN(eVarTime.LastTurnCommandTime);
if (ts.TotalSeconds > 15)
{
PUB.AGV.AGVMoveStop("15초이내 턴 이 완료되지 않음");
PUB.log.AddE("5초이내 턴 완료 확인 안됨");
PUB.sm.SetNewRunStep(ERunStep.ERROR);
return false;
}
return false;
}
else PUB._virtualAGV.Turn = AGVNavigationCore.Models.AGVTurn.L90;
}
PUB.sm.UpdateRunStepSeq(); //이미완료된상태이므로 다음으로 진행한다.
return false;
}
else if (PUB.sm.RunStepSeq == idx++)
{
// [PickOn/PickOff] 초기 리프트 동작
var liftCmd = arDev.Narumi.LiftCommand.DN;
if (PUB.NextWorkCmd == ENIGProtocol.AGVCommandHE.PickOff)
{
liftCmd = arDev.Narumi.LiftCommand.UP;
return false;
}
PUB.log.Add($"[{funcname}] Turn(left) 완료");
PUB.sm.UpdateRunStepSeq(); //이미완료된상태이므로 다음으로 진행한다.
return false;
}
else if (PUB.sm.RunStepSeq == idx++)
{
//버퍼에들어갈때에는 가져다 놓을때도 가지러 갈때에도 리프트는 내려서 들어간다
var liftCmd = arDev.Narumi.LiftCommand.DN;
PUB.AGV.LiftControl(liftCmd);
PUB.log.Add($"[{funcname}] 리프트를 내립니다");
VAR.TIME.Update(eVarTime.LastTurnCommandTime);
PUB.sm.UpdateRunStepSeq();
return false;
@@ -140,12 +107,32 @@ namespace Project
else if (PUB.sm.RunStepSeq == idx++)
{
//리프트 센서 확인
var ts = VAR.TIME.RUN(eVarTime.LastTurnCommandTime);
if (ts.TotalSeconds > 10)
{
// Timebound check
}
PUB.log.Add("리프트 동작 확인 완료");
if (PUB.AGV.signal1.lift_down == false)
{
if (seqtime.TotalSeconds > 20)
{
PUB.log.AddAT($"[{funcname}] 리프트가 내려가지 않아 1회 재시도 합니다");
PUB.AGV.LiftControl(arDev.Narumi.LiftCommand.DN);
//재시도를 했으니 다음으로 진행하게한다
}
else return false;
}
PUB.sm.UpdateRunStepSeq();
return false;
}
else if (PUB.sm.RunStepSeq == idx++)
{
//리프트 센서 확인
if (PUB.AGV.signal1.lift_down == false)
{
if (seqtime.TotalSeconds > 20)
{
PUB.log.AddE($"[{funcname}] 리프트가 내려가지 않습니다");
PUB.AGV.LiftControl(arDev.Narumi.LiftCommand.STP);
PUB.sm.SetNewRunStep(ERunStep.ERROR);
}
return false;
}
PUB.sm.UpdateRunStepSeq();
return false;
}
@@ -160,26 +147,32 @@ namespace Project
else if (PUB.sm.RunStepSeq == idx++)
{
//저속이동 (후진 진입)
var moveset = PUB.AGV.AGVMoveSet(new arDev.Narumi.BunkiData
var ret = PUB.AGV.AGVMoveSet(new arDev.Narumi.BunkiData
{
Bunki = arDev.Narumi.eBunki.Strate,
Direction = arDev.Narumi.eMoveDir.Backward,
PBSSensor = 0,
Speed = arDev.Narumi.eMoveSpd.Low,
});
if (moveset == false)
//명령이 실패되었다면 재시도를 한다
if (ret != arDev.eNarumiCommandResult.Success)
{
var ts = VAR.TIME.RUN(eVarTime.LastTurnCommandTime);
if (ts.TotalSeconds > 10)
if (ret >= arDev.eNarumiCommandResult.Error)
{
PUB.AGV.AGVMoveStop(funcname);
PUB.log.AddE("AGV속도설정이 완료되지 않았습니다");
PUB.log.AddE($"[{funcname}] AGV속도설정이 완료되지 않았습니다");
PUB.sm.SetNewRunStep(ERunStep.ERROR);
return false;
}
return false;
}
//후진이동을한다
PUB.AGV.AGVMoveRun(arDev.Narumi.eRunOpt.Backward);
//마크스탑으로 이동
PUB.AGV.AGVMoveStop(funcname, arDev.Narumi.eStopOpt.MarkStop);
VAR.TIME.Update(eVarTime.LastTurnCommandTime);
PUB.sm.UpdateRunStepSeq();
return false;
@@ -193,7 +186,7 @@ namespace Project
if (ts.TotalSeconds > 3)
{
PUB.AGV.AGVMoveStop(funcname);
PUB.log.AddE("MARK STOP신호가 확인되지 않습니다");
PUB.log.AddE($"[{funcname}] MARK STOP신호가 확인되지 않습니다");
PUB.sm.SetNewRunStep(ERunStep.ERROR);
return false;
}
@@ -211,7 +204,7 @@ namespace Project
if (ts.TotalSeconds > 10)
{
PUB.AGV.AGVMoveStop(funcname);
PUB.log.AddE("AGV가 멈추지 않아 강제종료 합니다");
PUB.log.AddE($"[{funcname}] AGV가 멈추지 않아 강제종료 합니다");
PUB.sm.SetNewRunStep(ERunStep.ERROR);
return false;
}
@@ -223,45 +216,22 @@ namespace Project
}
else if (PUB.sm.RunStepSeq == idx++)
{
// [Action] 진입 완료 후 리프트 동작 (Pick/Drop)
PUB.log.Add("버퍼 진입 완료. 작업 수행(Lift Pick/Drop)");
var liftCmd = arDev.Narumi.LiftCommand.UP;
if (PUB.NextWorkCmd == ENIGProtocol.AGVCommandHE.PickOff)
{
liftCmd = arDev.Narumi.LiftCommand.DN;
}
PUB.AGV.LiftControl(liftCmd);
VAR.TIME.Update(eVarTime.LastTurnCommandTime);
if (seqtime.TotalSeconds < 2) return false;
PUB.log.Add($"[{funcname}] 작업({PUB.NextWorkCmd}) 완료. 대기 상태로 전환 (퇴출 명령 대기)");
PUB.sm.UpdateRunStepSeq();
return false;
}
else if (PUB.sm.RunStepSeq == idx++)
{
// 리프트 동작 대기
// TODO: 실제 센서 확인 로직 추가 필요
var ts = VAR.TIME.RUN(eVarTime.LastTurnCommandTime);
if (ts.TotalSeconds < 2) return false;
PUB.log.Add("작업(Pick/Drop) 완료. 대기 상태로 전환 (퇴출 명령 대기)");
PUB.sm.UpdateRunStepSeq();
return false;
}
else if (PUB.sm.RunStepSeq == idx++)
{
//완료되었다. (ACS에 보내야함)
PUB.log.Add("버퍼 진입 및 작업 완료");
//완료되었다.
PUB.log.Add($"[{funcname}] 버퍼 진입 및 작업 완료");
PUB.sm.UpdateRunStepSeq();
return false;
}
// 작업을 마치고 설비 안에 멈춰있는 상태.
// ACS가 이 상태를 확인하고 NextWorkCmd로 퇴출(Out) 명령을 보내야 함.
PUB.AddEEDB($"버퍼작업완료({PUB.Result.TargetPos})");
return true;
PUB.AddEEDB($"버퍼투입완료({PUB.Result.TargetPos})");
PUB.AddEEDB($"[{funcname}] 버퍼작업완료({PUB.Result.TargetPos})");
return true;
}
}

View File

@@ -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;
}

View File

@@ -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);

View File

@@ -16,26 +16,37 @@ namespace Project
/// </summary>
public Boolean _SM_RUN_CLEANER_OUT(bool isFirst, TimeSpan stepTime)
{
var funcname = "CLEANEROUT";
//충전 상태가 OFF되어야 동작하게한다
if (_SM_RUN_CHGOFF(isFirst, stepTime) == false) return false;
//라이더멈춤이 설정되어있다면 음성으로 알려준다
if (CheckLiderStop() == false) return false;
//현재 위치가 결정되어있는지 체크한다
if (_SM_RUN_POSCHK(isFirst, stepTime) == false) return false;
var idx = 1;
if (PUB.sm.RunStepSeq == idx++)
{
//빈 상태로 아웃해야한다.
PUB.AGV.AGVMoveSet(new arDev.Narumi.BunkiData
var ret = PUB.AGV.AGVMoveSet(new arDev.Narumi.BunkiData
{
Bunki = arDev.Narumi.eBunki.Strate,
Direction = arDev.Narumi.eMoveDir.Forward,
PBSSensor = 0,
Speed = arDev.Narumi.eMoveSpd.Low,
});
//명령이 실패되었다면 재시도를 한다
if (ret != arDev.eNarumiCommandResult.Success)
{
if (ret >= arDev.eNarumiCommandResult.Error)
{
PUB.AGV.AGVMoveStop(funcname);
PUB.log.AddE($"[{funcname}] AGV속도설정이 완료되지 않았습니다");
PUB.sm.SetNewRunStep(ERunStep.ERROR);
}
return false;
}
PUB.sm.UpdateRunStepSeq();
return false;
}

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -25,8 +25,6 @@ namespace Project
//라이더멈춤이 설정되어있다면 음성으로 알려준다
if (CheckLiderStop() == false) return false;
//현재 위치가 결정되어있는지 체크한다
if (_SM_RUN_POSCHK(isFirst, stepTime) == false) return false;
/*
* 로더 IN 시퀀스 (버퍼 복사 - 턴 제거)
@@ -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);

View File

@@ -16,27 +16,37 @@ namespace Project
/// </summary>
public Boolean _SM_RUN_LOADER_OUT(bool isFirst, TimeSpan stepTime)
{
var funcname = "LOADEROUT";
//충전 상태가 OFF되어야 동작하게한다
if (_SM_RUN_CHGOFF(isFirst, stepTime) == false) return false;
//라이더멈춤이 설정되어있다면 음성으로 알려준다
if (CheckLiderStop() == false) return false;
//현재 위치가 결정되어있는지 체크한다
if (_SM_RUN_POSCHK(isFirst, stepTime) == false) return false;
var idx = 1;
if (PUB.sm.RunStepSeq == idx++)
{
//빈 상태로 아웃해야한다.
PUB.AGV.AGVMoveSet(new arDev.Narumi.BunkiData
var ret = PUB.AGV.AGVMoveSet(new arDev.Narumi.BunkiData
{
Bunki = arDev.Narumi.eBunki.Strate,
Direction = arDev.Narumi.eMoveDir.Forward,
PBSSensor = 0,
Speed = arDev.Narumi.eMoveSpd.Low,
});
//명령이 실패되었다면 재시도를 한다
if (ret != arDev.eNarumiCommandResult.Success)
{
if (ret >= arDev.eNarumiCommandResult.Error)
{
PUB.AGV.AGVMoveStop(funcname);
PUB.log.AddE($"[{funcname}] AGV속도설정이 완료되지 않았습니다");
PUB.sm.SetNewRunStep(ERunStep.ERROR);
}
return false;
}
PUB.sm.UpdateRunStepSeq();
return false;
}

View File

@@ -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);
}
}

View File

@@ -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);

View File

@@ -16,27 +16,37 @@ namespace Project
/// </summary>
public Boolean _SM_RUN_UNLOADER_OUT(bool isFirst, TimeSpan stepTime)
{
var funcname = "UNLOADEROUT";
//충전 상태가 OFF되어야 동작하게한다
if (_SM_RUN_CHGOFF(isFirst, stepTime) == false) return false;
//라이더멈춤이 설정되어있다면 음성으로 알려준다
if (CheckLiderStop() == false) return false;
//현재 위치가 결정되어있는지 체크한다
if (_SM_RUN_POSCHK(isFirst, stepTime) == false) return false;
var idx = 1;
if (PUB.sm.RunStepSeq == idx++)
{
//빈 상태로 아웃해야한다.
PUB.AGV.AGVMoveSet(new arDev.Narumi.BunkiData
var ret = PUB.AGV.AGVMoveSet(new arDev.Narumi.BunkiData
{
Bunki = arDev.Narumi.eBunki.Strate,
Direction = arDev.Narumi.eMoveDir.Forward,
PBSSensor = 0,
Speed = arDev.Narumi.eMoveSpd.Low,
});
//명령이 실패되었다면 재시도를 한다
if (ret != arDev.eNarumiCommandResult.Success)
{
if (ret >= arDev.eNarumiCommandResult.Error)
{
PUB.AGV.AGVMoveStop(funcname);
PUB.log.AddE($"[{funcname}] AGV속도설정이 완료되지 않았습니다");
PUB.sm.SetNewRunStep(ERunStep.ERROR);
}
return false;
}
PUB.sm.UpdateRunStepSeq();
return false;
}

View File

@@ -67,8 +67,9 @@ namespace Project
/// <returns></returns>
Boolean UpdateMotionPositionForMark(string sender)
{
//현재위치를 모르는 상태라면 이동하여 현재 위치를 찾는다
if (_SM_RUN_POSCHK(false, new TimeSpan()) == false) return false;
////현재위치를 모르는 상태라면 처리하지 않는다
if (PUB._virtualAGV.CurrentNode == null || PUB._virtualAGV.PrevNode == null)
return false;
//현재위치노드 오류
var currentNode = PUB.FindByNodeID(PUB._virtualAGV.CurrentNode.Id);
@@ -119,6 +120,7 @@ namespace Project
}
else
{
//계산은 되었으나 현재위치가 전체 경로 없다면 시작노드를 현재로 변경해야한다.
PUB._mapCanvas.CurrentPath = PathResult.result;
PUB._virtualAGV.SetPath(PathResult.result);
}
@@ -133,19 +135,50 @@ namespace Project
{
PUB.AGV.AGVMoveStop("Path Integrity Fail");
}
PUB.log.AddE($"경로 무결성 오류");
PUB.sm.SetNewRunStep(ERunStep.READY);
PUB.log.AddE($"경로 무결성 오류로 인해 경로를 삭제 합니다");
Console.WriteLine($"경로 무결성 오류로 인해 경로를 삭제 합니다");
PUB._virtualAGV.SetPath(null);
VAR.I32[eVarInt32.PathValidationError] += 1;
if (VAR.I32[eVarInt32.PathValidationError] > 50)
{
PUB.log.AddE($"연속 경로 무결성 오류로 인해 중지 합니다");
PUB.sm.SetNewRunStep(ERunStep.ERROR);
}
return false;
}
else VAR.I32[eVarInt32.PathValidationError] = 0;
//현재위치 기준으로 재 계산하여. 더 최적화된 루트가 있다면 처리를 해준다.
if (PUB._virtualAGV.CurrentPath.DetailedPath.Count > 5)
{
var PathResult2 = CalcPath(PUB._virtualAGV.CurrentNode, PUB._virtualAGV.TargetNode);
if (PathResult2.result != null && PathResult2.result.Success)
{
//절반이상 경로가 짧을때에는 재계산을 하게한다
var halfcnt = (int)(PUB._virtualAGV.CurrentPath.DetailedPath.Count / 2.0);
if (PathResult2.result.DetailedPath.Count < halfcnt)
{
var msg = $"단축경로가 확인되었습니다. 경로를 삭제 합니다";
PUB.log.AddE(msg);
Console.WriteLine(msg);
PUB._virtualAGV.SetPath(null);
}
return false;
}
}
//predict 를 이용하여 다음 이동을 모두 확인한다.
var nextAction = PUB._virtualAGV.Predict();
if(nextAction.Reason == AGVNavigationCore.Models.eAGVCommandReason.PathOut)
if (nextAction.Reason == AGVNavigationCore.Models.eAGVCommandReason.PathOut)
{
//경로이탈
PUB._virtualAGV.CurrentPath.DetailedPath.Clear();
var logmessage = $"경로이탈감지 시작노드를 현재위치로 설정합니다 START:{PUB._virtualAGV.StartNode},CURRENT:{PUB._virtualAGV.CurrentNode}";
PUB.log.AddE(logmessage);
Console.WriteLine(logmessage);
PUB._virtualAGV.ClearPath();//.DetailedPath.Clear();
PUB._virtualAGV.StartNode = PUB._virtualAGV.CurrentNode;
return false;
}
@@ -158,7 +191,7 @@ namespace Project
$"현재 상태: {PUB._virtualAGV.CurrentState}\n" +
$"현재 방향: {PUB._virtualAGV.CurrentDirection}\n" +
$"위치 확정: {PUB._virtualAGV.IsPositionConfirmed} (RFID {PUB._virtualAGV.DetectedRfidCount}개)\n" +
$"현재 노드: {PUB._virtualAGV.CurrentNode.Id ?? ""}";
$"현재 노드: {PUB._virtualAGV.CurrentNodeID2}";
//모터에서 정지를 요청했다
if (nextAction.Motor == AGVNavigationCore.Models.MotorCommand.Stop)
@@ -181,13 +214,33 @@ namespace Project
// 목적지 도착 여부 확인
// 현재 노드가 타겟 노드와 같고, 위치가 확정된 상태라면 도착으로 간주
// 단, AGV가 실제로 멈췄는지 확인 (agv_run == false)
if (PUB._virtualAGV.IsPositionConfirmed &&
PUB._virtualAGV.CurrentNode.Id == PUB._virtualAGV.TargetNode.Id)
if (PUB._virtualAGV.IsPositionConfirmed)
{
if (PUB.AGV.system1.agv_run == false)
{
PUB.log.AddI($"목표 도착 및 정지 확인됨(MarkStop 완료). Node:{PUB._virtualAGV.CurrentNode.Id}");
return true;
//목적지도착완료시
if (PUB._virtualAGV.CurrentNode.Id == PUB._virtualAGV.TargetNode.Id)
{
var node = PUB._mapCanvas.Nodes.Where(t => t.Id == PUB._virtualAGV.CurrentNodeId).FirstOrDefault();
var rfid = node?.ID2 ?? "(X)";
PUB.log.AddI($"목표 도착 및 정지 확인됨(MarkStop 완료) Node:{rfid}");
return true;
}
//목적지가 버퍼라면 그 앞에 멈춘다
if (PUB._virtualAGV.TargetNode.StationType == AGVNavigationCore.Models.StationType.Buffer &&
PUB._virtualAGV.CurrentPath != null && PUB._virtualAGV.CurrentPath.DetailedPath.Any())
{
if (PUB._virtualAGV.CurrentNode.Id == PUB._virtualAGV.CurrentPath.DetailedPath.Last().NodeId)
{
PUB.log.AddI($"목표(버퍼) 도착 및 정지 확인됨(MarkStop 완료). Node:{PUB._virtualAGV.CurrentNodeID2}");
return true;
}
}
}
else
{
//아직 멈추지 않았다면 기다린다.
}
}
@@ -213,14 +266,17 @@ namespace Project
PUB.AGV.data.Direction != dir.ToString()[0] ||
PUB.AGV.data.Speed != spd.ToString()[0])
{
PUB.AGV.AGVMoveSet(new arDev.Narumi.BunkiData
var ret = PUB.AGV.AGVMoveSet(new arDev.Narumi.BunkiData
{
Bunki = bunki,
Direction = dir,
PBSSensor = 1,
Speed = spd,
});
PUB.log.Add($"Predict Run Setting = bunki:{bunki},dir:{dir},pbs:1,spd:{spd}");
if (ret == arDev.eNarumiCommandResult.Success)
PUB.log.Add($"Predict Run Setting = bunki:{bunki},dir:{dir},pbs:1,spd:{spd}");
else
PUB.log.AddE($"Predict Run Setting = bunki:{bunki},dir:{dir},pbs:1,spd:{spd}");
}
// AGV가 정지 상태라면 구동 시작
@@ -250,14 +306,18 @@ namespace Project
PUB.AGV.error.Emergency == false &&
PUB.AGV.system1.agv_run == false)
{
PUB.AGV.AGVMoveSet(new arDev.Narumi.BunkiData
var ret = PUB.AGV.AGVMoveSet(new arDev.Narumi.BunkiData
{
Bunki = arDev.Narumi.eBunki.Strate,
Direction = arDev.Narumi.eMoveDir.Forward,
PBSSensor = 1,
Speed = arDev.Narumi.eMoveSpd.Low,
});
PUB.AGV.AGVMoveRun( arDev.Narumi.eRunOpt.Forward);//
if (ret == arDev.eNarumiCommandResult.Success)
{
PUB.AGV.AGVMoveRun(arDev.Narumi.eRunOpt.Forward);//
}
tm_gocharge_command = DateTime.Now;
}
}
@@ -278,14 +338,15 @@ namespace Project
PUB.AGV.error.Emergency == false &&
PUB.AGV.system1.agv_run == false)
{
PUB.AGV.AGVMoveSet(new arDev.Narumi.BunkiData
var ret = PUB.AGV.AGVMoveSet(new arDev.Narumi.BunkiData
{
Bunki = arDev.Narumi.eBunki.Strate,
Direction = arDev.Narumi.eMoveDir.Backward,
PBSSensor = 1,
Speed = arDev.Narumi.eMoveSpd.Low,
});
PUB.AGV.AGVMoveRun(arDev.Narumi.eRunOpt.Backward);//
if (ret == arDev.eNarumiCommandResult.Success)
PUB.AGV.AGVMoveRun(arDev.Narumi.eRunOpt.Backward);//
LastCommandTime = DateTime.Now;
}
}
@@ -311,7 +372,7 @@ namespace Project
// 만약 수행되지 않았다면 여기서 수행.
if (pathResult.DockingValidation == null)
{
pathResult.DockingValidation = AGVNavigationCore.Utils.DockingValidator.ValidateDockingDirection(pathResult, PUB._mapCanvas.Nodes);
pathResult.DockingValidation = AGVNavigationCore.Utils.DockingValidator.ValidateDockingDirection(pathResult, PUB._mapCanvas.Nodes);
}
// 검증 결과 확인

View File

@@ -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;
}

View File

@@ -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);

View File

@@ -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,7 +130,7 @@ 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);
}
@@ -157,7 +169,7 @@ namespace Project
}
//대상이동으로 처리한다.
if(PUB.sm.RunStep != ERunStep.GOTO)
if (PUB.sm.RunStep != ERunStep.GOTO)
{
PUB.sm.SetNewRunStep(StateMachine.ERunStep.GOTO);
PUB.sm.ResetRunStepSeq();
@@ -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
@@ -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}";

View File

@@ -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)

View File

@@ -433,9 +433,6 @@ namespace Project
//충전상태확인
if (PUB.CheckManualChargeMode() == false) return;
PUB.popup.needClose = true;
//PUB.sm.bPause = false;
//PUB.sm.ClearRunStep();
//PUB.sm.SetNewRunStep(ERunStep.READY);
PUB.sm.SetNewStep(eSMStep.RUN);
PUB.Speak(Lang., addlog: false);

View File

@@ -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,7 +615,7 @@ 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();
@@ -626,7 +626,7 @@ namespace Project
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();
@@ -637,7 +637,7 @@ namespace Project
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();
@@ -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");
}
}

View File

@@ -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;
}
}
/// <summary>
/// error 이상은모두 처리불가한 오류 조건을 의미한다
/// </summary>
public enum eNarumiCommandResult : byte
{
Fail = 0,
Success = 1,
Wait = 2,
Error = 100,
Timeout,
}
public partial class Narumi
{
public NarumiTurnInfo TurnInformation { get; set; } = null;
Dictionary<string, NarumiCommandTime> SendCommandFailList { get; set; } = new Dictionary<string, NarumiCommandTime>();
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}");
//}
/// <summary>
/// 정지감속주기 및 상수
/// </summary>
/// <returns></returns>
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);
}
/// <summary>
/// 전송을시도한 시간
/// </summary>
//public Dictionary<String,DateTime> LastCommandTime { get; set; }
/// <summary>
/// 전송에 성공한 명령시간
/// </summary>
//public Dictionary<String, DateTime> LastCommandOKTime { get; set; }
protected bool AddCommand(params string[] cmds)
///// <summary>
///// 전송에 성공한 명령시간
///// </summary>
////public Dictionary<String, DateTime> 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
/// </summary>
/// <param name="param"></param>
/// <param name="Repeat"></param>
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";

View File

@@ -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,16 +258,34 @@ 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);

View File

@@ -13,6 +13,7 @@ namespace COMM
SumQty,
ChargeWaitSec,
SyncItemCount,
PathValidationError,
}
public enum eVarUInt32
{

Submodule Cs_HMI/SubProject/EnigProtocol updated: 14ff055fa9...bca75ddd6a

1005
Document/NewMap.json Normal file

File diff suppressed because it is too large Load Diff