From 00dd50192b86123a757d73b88b004dd68da7542e Mon Sep 17 00:00:00 2001 From: chi Date: Mon, 30 Jun 2025 13:48:19 +0900 Subject: [PATCH] .. --- Cs_HMI/Project/Device/Xbee.cs | 2 +- Cs_HMI/Project/StateMachine/Step/_SM_RUN.cs | 34 +- .../StateMachine/Step/_SM_RUN_READY.cs | 116 +-- Cs_HMI/Project/StateMachine/_AGV.cs | 45 +- Cs_HMI/Project/StateMachine/_BMS.cs | 7 +- Cs_HMI/Project/StateMachine/_SPS.cs | 3 - Cs_HMI/Project/StateMachine/_Xbee.cs | 21 +- Cs_HMI/Project/fMain.Designer.cs | 19 +- Cs_HMI/Project/fMain.cs | 388 ++++----- Cs_HMI/Project/fMain.resx | 50 +- Cs_HMI/Project/sample.route | 249 +++--- .../AGVControl/Dialog/fMapDesign.Designer.cs | 103 +++ .../AGVControl/Dialog/fMapDesign.cs | 48 ++ .../AGVControl/Dialog/fMapDesign.resx | 142 ++++ .../Dialog/fPropertyRFIDPoint.Designer.cs | 158 ++++ .../AGVControl/Dialog/fPropertyRFIDPoint.cs | 55 ++ .../AGVControl/Dialog/fPropertyRFIDPoint.resx | 120 +++ Cs_HMI/SubProject/AGVControl/MapControl.cs | 759 ++++++++++++------ .../AGVControl/MapControlManager.cs | 332 +++++--- Cs_HMI/SubProject/AGVControl/Models/AGV.cs | 488 ++++++----- .../AGVControl/Models/AGVActionPrediction.cs | 45 +- .../AGVControl/Models/MagnetLine.cs | 68 +- .../AGVControl/Models/RFIDConnection.cs | 189 ++++- .../SubProject/AGVControl/Models/RFIDPoint.cs | 5 +- .../AGVControl/Models/enumStruct.cs | 20 + .../SubProject/AGVControl/agvControl.csproj | 18 + Cs_HMI/SubProject/BMS/BMS.cs | 20 +- Emulator/AGVEmulator/Form1.Designer.cs | 20 +- Emulator/AGVEmulator/Form1.cs | 9 +- 29 files changed, 2397 insertions(+), 1136 deletions(-) create mode 100644 Cs_HMI/SubProject/AGVControl/Dialog/fMapDesign.Designer.cs create mode 100644 Cs_HMI/SubProject/AGVControl/Dialog/fMapDesign.cs create mode 100644 Cs_HMI/SubProject/AGVControl/Dialog/fMapDesign.resx create mode 100644 Cs_HMI/SubProject/AGVControl/Dialog/fPropertyRFIDPoint.Designer.cs create mode 100644 Cs_HMI/SubProject/AGVControl/Dialog/fPropertyRFIDPoint.cs create mode 100644 Cs_HMI/SubProject/AGVControl/Dialog/fPropertyRFIDPoint.resx diff --git a/Cs_HMI/Project/Device/Xbee.cs b/Cs_HMI/Project/Device/Xbee.cs index 54513a7..04b846c 100644 --- a/Cs_HMI/Project/Device/Xbee.cs +++ b/Cs_HMI/Project/Device/Xbee.cs @@ -19,7 +19,7 @@ namespace Project.Device public string buffer = string.Empty; public System.Text.StringBuilder newbuffer = new StringBuilder(); public string errorMessage = string.Empty; - public DateTime LastStatusSendTime = DateTime.Now; + public DateTime LastStatusSendTime { get; set; } = DateTime.Now; private EEProtocol proto; public class MessageArgs : EventArgs diff --git a/Cs_HMI/Project/StateMachine/Step/_SM_RUN.cs b/Cs_HMI/Project/StateMachine/Step/_SM_RUN.cs index 6cc7a15..b454aca 100644 --- a/Cs_HMI/Project/StateMachine/Step/_SM_RUN.cs +++ b/Cs_HMI/Project/StateMachine/Step/_SM_RUN.cs @@ -26,16 +26,11 @@ namespace Project return; } - //사용자 스텝처리가 아닌경우에만 검사 - //if (Pub.flag.get(eFlag.UserStepCheck) == false) + //가동불가 조건 확인 + if (CheckStopCondition() == false) { - - //가동불가 조건 확인 - if (CheckStopCondition() == false) - { - PUB.sm.SetNewStep(eSMStep.PAUSE); - return; - } + PUB.sm.SetNewStep(eSMStep.PAUSE); + return; } //이머전시상태라면 stop 처리한다. @@ -46,13 +41,6 @@ namespace Project PUB.sm.SetNewStep(eSMStep.IDLE); } - //실행스텝보정 - //if (Pub.sm.runStep == eRunStep.NOTSET && Pub.sm.runStepNew == eRunStep.NOTSET) - //{ - // Pub.sm.setNewRunStep(eRunStep.IDLE); - // Pub.log.Add("RUnStep Initialize"); - //} - //스텝이 변경되었다면? if (PUB.sm.RunStep != PUB.sm.RunStepNew) { @@ -88,7 +76,7 @@ namespace Project //if (PUB.Result != null && PUB.sm != null) // EEMStatus.AddEEDBSQL(PUB.sm.Step, PUB.sm.RunStep.ToString(), PUB.Result.TargetPos.ToString()); - PUB.Speak(Lang.충전을시작합니다) ; + PUB.Speak(Lang.충전을시작합니다); PUB.sm.SetNewRunStep(ERunStep.CHARGECHECK); return; } @@ -143,8 +131,8 @@ namespace Project PUB.Speak(Lang.상차작업이완료되었습니다); //230601 - // if (PUB.Result != null && PUB.sm != null) - // EEMStatus.AddEEDBSQL(PUB.sm.Step, PUB.sm.RunStep.ToString(), PUB.Result.TargetPos.ToString()); + // if (PUB.Result != null && PUB.sm != null) + // EEMStatus.AddEEDBSQL(PUB.sm.Step, PUB.sm.RunStep.ToString(), PUB.Result.TargetPos.ToString()); //QA를 제외한 경우에는 기본 QC로 이동한다 if (PUB.Result.NextPos == ePosition.QA) @@ -184,7 +172,7 @@ namespace Project PUB.sm.ClearRunStep(); PUB.Result.TargetPos = ePosition.QC; PUB.sm.SetNewRunStep(ERunStep.GOHOME); - PUB.Speak( Lang.홈위치로이동합니다); + PUB.Speak(Lang.홈위치로이동합니다); } return; } @@ -198,7 +186,7 @@ namespace Project else if (_SM_RUN_GOHOME(runStepisFirst, PUB.sm.GetRunSteptime)) { //230601 - // if (PUB.Result != null && PUB.sm != null) + // if (PUB.Result != null && PUB.sm != null) // EEMStatus.AddEEDBSQL(PUB.sm.Step, PUB.sm.RunStep.ToString(), PUB.Result.TargetPos.ToString()); PUB.Speak(Lang.홈이동완료대기상태로전환합니다); @@ -215,7 +203,7 @@ namespace Project return true; } - + void CheckAGVMoveTo(eGoDir dir) { //계속내려간다 @@ -545,7 +533,7 @@ namespace Project return false; } - + }//cvass } diff --git a/Cs_HMI/Project/StateMachine/Step/_SM_RUN_READY.cs b/Cs_HMI/Project/StateMachine/Step/_SM_RUN_READY.cs index 53a46af..01719e4 100644 --- a/Cs_HMI/Project/StateMachine/Step/_SM_RUN_READY.cs +++ b/Cs_HMI/Project/StateMachine/Step/_SM_RUN_READY.cs @@ -13,12 +13,12 @@ namespace Project { public Boolean _SM_RUN_READY(bool isFirst, TimeSpan stepTime) { - //이동 불가 조건이 걸려있다면 충전을 하지 못하게 한다. - Boolean bAutoChageOn = true; - if (PUB.AGV.system1.stop_by_front_detect) bAutoChageOn = false; - else if (PUB.AGV.error.Emergency) bAutoChageOn = false; - else if (VAR.BOOL[eVarBool.FLAG_CHARGEONA]) bAutoChageOn = false; - else if (VAR.BOOL[eVarBool.FLAG_CHARGEONM]) bAutoChageOn = false; + ////이동 불가 조건이 걸려있다면 충전을 하지 못하게 한다. + //Boolean bAutoChageOn = true; + //if (PUB.AGV.system1.stop_by_front_detect) bAutoChageOn = false; + //else if (PUB.AGV.error.Emergency) bAutoChageOn = false; + //else if (VAR.BOOL[eVarBool.FLAG_CHARGEONA]) bAutoChageOn = false; + //else if (VAR.BOOL[eVarBool.FLAG_CHARGEONM]) bAutoChageOn = false; //자동 충전 중이라면 최대 충전시간과 레벨을 체크한다 @@ -73,58 +73,58 @@ namespace Project } VAR.STR[eVarString.ChargeCheckMsg] = "현재 위치 모름"; } - else if (PUB.setting.Enable_AutoCharge == true ) - { - if(bAutoChageOn) - { - VAR.BOOL[eVarBool.CHARGE_READY] = true; - if (PUB.BMS.Current_Level < PUB.setting.ChargeStartLevel) - { - //레벨에 의한 자동 충전간격은 - var ts = VAR.TIME.RUN(eVarTime.ChargeTry); - if (ts.TotalSeconds >= PUB.setting.ChargeRetryTerm) - { - VAR.I32[eVarInt32.ChargeWaitSec] = 0; - VAR.BOOL[eVarBool.CHARGE_WAIT] = false; - PUB.log.Add($"자동충전레벨시작 {PUB.BMS.Current_Level}/{PUB.setting.ChargeStartLevel}"); - PUB.sm.ClearRunStep(); - PUB.sm.SetNewRunStep(ERunStep.GOCHARGE); - PUB.sm.SetNewStep(eSMStep.RUN); - PUB.AddEEDB($"자동충전레벨시작 {PUB.BMS.Current_Level}/{PUB.setting.ChargeStartLevel}"); - } - else - { - VAR.I32[eVarInt32.ChargeWaitSec] = (int)(PUB.setting.ChargeRetryTerm - ts.TotalSeconds); - VAR.BOOL[eVarBool.CHARGE_WAIT] = true; - } - VAR.STR[eVarString.ChargeCheckMsg] = "배터리 충전 레벨 필요"; - } - else - { - //아직 레벨이 높다 - VAR.BOOL[eVarBool.CHARGE_READY] = false; - VAR.I32[eVarInt32.ChargeWaitSec] = 0; - VAR.BOOL[eVarBool.CHARGE_WAIT] = false; - VAR.STR[eVarString.ChargeCheckMsg] = "배터리 레벨상 충전 불필요"; - } - } - else - { - VAR.BOOL[eVarBool.CHARGE_READY] = false; - VAR.I32[eVarInt32.ChargeWaitSec] = 0; - VAR.BOOL[eVarBool.CHARGE_WAIT] = false; - VAR.STR[eVarString.ChargeCheckMsg] = "충전 불가 조건"; - //충전조건이 맞지 않는다 - } - } - else - { - VAR.BOOL[eVarBool.CHARGE_READY] = false; - VAR.I32[eVarInt32.ChargeWaitSec] = 0; - VAR.BOOL[eVarBool.CHARGE_WAIT] = false; - //자동충전이 해제된 상태이므로 처리하지 않는다 - VAR.STR[eVarString.ChargeCheckMsg] = "자동 충전 해제 됨"; - } + //else if (PUB.setting.Enable_AutoCharge == true ) + //{ + // if(bAutoChageOn) + // { + // VAR.BOOL[eVarBool.CHARGE_READY] = true; + // if (PUB.BMS.Current_Level < PUB.setting.ChargeStartLevel) + // { + // //레벨에 의한 자동 충전간격은 + // var ts = VAR.TIME.RUN(eVarTime.ChargeTry); + // if (ts.TotalSeconds >= PUB.setting.ChargeRetryTerm) + // { + // VAR.I32[eVarInt32.ChargeWaitSec] = 0; + // VAR.BOOL[eVarBool.CHARGE_WAIT] = false; + // PUB.log.Add($"자동충전레벨시작 {PUB.BMS.Current_Level}/{PUB.setting.ChargeStartLevel}"); + // PUB.sm.ClearRunStep(); + // PUB.sm.SetNewRunStep(ERunStep.GOCHARGE); + // PUB.sm.SetNewStep(eSMStep.RUN); + // PUB.AddEEDB($"자동충전레벨시작 {PUB.BMS.Current_Level}/{PUB.setting.ChargeStartLevel}"); + // } + // else + // { + // VAR.I32[eVarInt32.ChargeWaitSec] = (int)(PUB.setting.ChargeRetryTerm - ts.TotalSeconds); + // VAR.BOOL[eVarBool.CHARGE_WAIT] = true; + // } + // VAR.STR[eVarString.ChargeCheckMsg] = "배터리 충전 레벨 필요"; + // } + // else + // { + // //아직 레벨이 높다 + // VAR.BOOL[eVarBool.CHARGE_READY] = false; + // VAR.I32[eVarInt32.ChargeWaitSec] = 0; + // VAR.BOOL[eVarBool.CHARGE_WAIT] = false; + // VAR.STR[eVarString.ChargeCheckMsg] = "배터리 레벨상 충전 불필요"; + // } + // } + // else + // { + // VAR.BOOL[eVarBool.CHARGE_READY] = false; + // VAR.I32[eVarInt32.ChargeWaitSec] = 0; + // VAR.BOOL[eVarBool.CHARGE_WAIT] = false; + // VAR.STR[eVarString.ChargeCheckMsg] = "충전 불가 조건"; + // //충전조건이 맞지 않는다 + // } + //} + //else + //{ + // VAR.BOOL[eVarBool.CHARGE_READY] = false; + // VAR.I32[eVarInt32.ChargeWaitSec] = 0; + // VAR.BOOL[eVarBool.CHARGE_WAIT] = false; + // //자동충전이 해제된 상태이므로 처리하지 않는다 + // VAR.STR[eVarString.ChargeCheckMsg] = "자동 충전 해제 됨"; + //} //대기모드에서는 움직이지 않게 한다 if(PUB.AGV.system1.agv_run) diff --git a/Cs_HMI/Project/StateMachine/_AGV.cs b/Cs_HMI/Project/StateMachine/_AGV.cs index 2f1d394..5147d4c 100644 --- a/Cs_HMI/Project/StateMachine/_AGV.cs +++ b/Cs_HMI/Project/StateMachine/_AGV.cs @@ -41,31 +41,7 @@ namespace Project { try { - if (PUB.mapctl != null) - { - var rlt = AGVControl.MapControlManager.PredictNextAction(); - - if (rlt.ReasonCode == AGVControl.AGVActionReasonCode.busy) - { - //var premsg = $"이전 예측작업이 완료되지 않았습니다"; - //PUB.log.AddE(premsg); - //PUB.log.AddE(premsg); - //Console.WriteLine(premsg); - - //predicterr += 1; - //if (predicterr > 10) - //{ - // var premsg = $"행동예측 오류카운트 초과"; - // PUB.AGV.AGVMoveStop(premsg); - // PUB.log.AddE(premsg); - // PUB.logagv.AddE(premsg); - // Console.WriteLine(premsg); - //} - } - } - - - + //데이터 파싱 switch (e.DataType) { case arDev.Narumi.DataType.STS: @@ -83,12 +59,12 @@ namespace Project //모터방향 입력 if (PUB.AGV.data.Direction == 'B') - AGVControl.MapControlManager.agv.CurrentMOTDirection = AGVControl.Models.Direction.Backward; + PUB.mapctl.Manager.agv.CurrentMOTDirection = AGVControl.Direction.Backward; else - AGVControl.MapControlManager.agv.CurrentMOTDirection = AGVControl.Models.Direction.Forward; + PUB.mapctl.Manager.agv.CurrentMOTDirection = AGVControl.Direction.Forward; - AGVControl.MapControlManager.agv.IsMoving = PUB.AGV.system1.agv_run; - AGVControl.MapControlManager.agv.IsMarkCheck = PUB.AGV.system1.Mark1_check || PUB.AGV.system1.Mark2_check; + PUB.mapctl.Manager.agv.IsMoving = PUB.AGV.system1.agv_run; + PUB.mapctl.Manager.agv.IsMarkCheck = PUB.AGV.system1.Mark1_check || PUB.AGV.system1.Mark2_check; if (PUB.AGV.signal.mark_sensor == false) { @@ -201,10 +177,8 @@ namespace Project else { //위치는 찾았다 해당 위치가 내 목적지라면 mark stop기능으로 전환한다 - } - ////자동, 상하차 모드일때 RFID 가 타겟위치에 올때는 - 멈춤을 설정해준다 //if (VAR.BOOL[eVarBool.FLAG_AUTORUN] == true && // PUB.Result.CurrentPos == PUB.Result.TargetPos && @@ -237,12 +211,19 @@ namespace Project break; } + + //이 후 상황을 예측한다 + if (PUB.mapctl != null) + { + var rlt = PUB.mapctl.Manager.PredictNextAction(); + if (rlt.Changed) + Console.WriteLine($"[new] predict idx:{rlt.Idx}"); + } } catch (Exception ex) { Console.WriteLine($"[AGV_DataReceive] {ex.Message}"); } } - } } diff --git a/Cs_HMI/Project/StateMachine/_BMS.cs b/Cs_HMI/Project/StateMachine/_BMS.cs index 8a2f681..c11a53a 100644 --- a/Cs_HMI/Project/StateMachine/_BMS.cs +++ b/Cs_HMI/Project/StateMachine/_BMS.cs @@ -158,9 +158,10 @@ namespace Project private void Bms_BMSDataReceive(object sender, EventArgs e) { - AGVControl.MapControlManager.agv.BatteryLevel = PUB.BMS.Current_Level; - AGVControl.MapControlManager.agv.BatteryTemp1 = PUB.BMS.Current_temp1; - AGVControl.MapControlManager.agv.BatteryTemp2 = PUB.BMS.Current_temp2; + + PUB.mapctl.Manager.agv.BatteryLevel = PUB.BMS.Current_Level; + PUB.mapctl.Manager.agv.BatteryTemp1 = PUB.BMS.Current_temp1; + PUB.mapctl.Manager.agv.BatteryTemp2 = PUB.BMS.Current_temp2; if (PUB.BMS.Current_Level <= PUB.setting.ChargeStartLevel) { //배터리 레벨이 기준보다 낮다면 경고를 활성화 한다 diff --git a/Cs_HMI/Project/StateMachine/_SPS.cs b/Cs_HMI/Project/StateMachine/_SPS.cs index 20fba04..670c77e 100644 --- a/Cs_HMI/Project/StateMachine/_SPS.cs +++ b/Cs_HMI/Project/StateMachine/_SPS.cs @@ -163,10 +163,7 @@ namespace Project { PUB.BMS.SendQuery(); } - - Update_BatteryWarnSpeak(); - } } } diff --git a/Cs_HMI/Project/StateMachine/_Xbee.cs b/Cs_HMI/Project/StateMachine/_Xbee.cs index c3d7c43..c5f8597 100644 --- a/Cs_HMI/Project/StateMachine/_Xbee.cs +++ b/Cs_HMI/Project/StateMachine/_Xbee.cs @@ -25,6 +25,25 @@ namespace Project var data = e.ReceivedPacket.Data; var dataStr = System.Text.Encoding.Default.GetString(data); var cmd = (ENIGProtocol.AGVCommands)e.ReceivedPacket.Command; + var TargetID = 0; + if (dataStr.Length >= 2) + { + //대상디바이스 + TargetID = Convert.ToByte(dataStr.Substring(0, 2), 16); + + //데이터영역을 다시 설정 + if (dataStr.Length > 2) dataStr = dataStr.Substring(2); + else dataStr = string.Empty; + } + else + { + PUB.log.Add($"ACS 데이터에서 TARGET ID가 없습니다(data : first byte)"); + } + + + if (PUB.setting.XBE_ID != TargetID) + return; + switch (cmd) { @@ -60,7 +79,7 @@ namespace Project case ENIGProtocol.AGVCommands.Goto: //move to tag if (uint.TryParse(dataStr, out uint tagno2)) { - var currPos = AGVControl.MapControlManager.agv.CurrentRFID;///.AGVMoveToRFID(; + var currPos = PUB.mapctl.Manager.agv.CurrentRFID;///.AGVMoveToRFID(; if (PUB.mapctl.SetTargetPosition(tagno2)) PUB.log.AddI($"New Target {tagno2}"); else diff --git a/Cs_HMI/Project/fMain.Designer.cs b/Cs_HMI/Project/fMain.Designer.cs index 52b3266..6528a27 100644 --- a/Cs_HMI/Project/fMain.Designer.cs +++ b/Cs_HMI/Project/fMain.Designer.cs @@ -172,7 +172,7 @@ namespace Project MenuLift.Text = "LIFT"; toolTip1.SetToolTip(MenuLift, "I/O 및 FLAG를 확인 합니다"); MenuLift.UseVisualStyleBackColor = true; - MenuLift.Click += button3_Click; + MenuLift.Click += MenuLift_Click; // // MenuMAN // @@ -189,7 +189,7 @@ namespace Project MenuMAN.Text = "MANUAL"; toolTip1.SetToolTip(MenuMAN, "작업 내역을 확인 합니다"); MenuMAN.UseVisualStyleBackColor = true; - MenuMAN.Click += button4_Click; + MenuMAN.Click += ManualMan_Click; // // MenuFlag // @@ -206,7 +206,7 @@ namespace Project MenuFlag.Text = "FLAG"; toolTip1.SetToolTip(MenuFlag, "I/O 및 FLAG를 확인 합니다"); MenuFlag.UseVisualStyleBackColor = true; - MenuFlag.Click += button1_Click; + MenuFlag.Click += btMenuFlag_Click; // // MenuAuto // @@ -223,7 +223,7 @@ namespace Project MenuAuto.Text = "AUTO"; toolTip1.SetToolTip(MenuAuto, "작업 내역을 확인 합니다"); MenuAuto.UseVisualStyleBackColor = true; - MenuAuto.Click += button2_Click; + MenuAuto.Click += btMenuAuto_Click; // // MenuLog // @@ -258,7 +258,7 @@ namespace Project MenuAGV.Text = "AGV"; toolTip1.SetToolTip(MenuAGV, "I/O 및 FLAG를 확인 합니다"); MenuAGV.UseVisualStyleBackColor = false; - MenuAGV.Click += button1_Click_1; + MenuAGV.Click += btMenuAGV_Click_1; // // MenuBMS // @@ -275,7 +275,7 @@ namespace Project MenuBMS.Text = "BMS"; toolTip1.SetToolTip(MenuBMS, "I/O 및 FLAG를 확인 합니다"); MenuBMS.UseVisualStyleBackColor = true; - MenuBMS.Click += button2_Click_1; + MenuBMS.Click += btMenuBMS_Click_1; // // btAutoRun // @@ -323,7 +323,7 @@ namespace Project btAutoRun.TextShadow = true; btAutoRun.TextVisible = true; toolTip1.SetToolTip(btAutoRun, "작업상태(자동/수동)를 표시 합니다"); - btAutoRun.Click += btStart_Click; + btAutoRun.Click += btAutorun_Click; // // btChargeA // @@ -837,14 +837,12 @@ namespace Project gridviewTestToolStripMenuItem.Name = "gridviewTestToolStripMenuItem"; gridviewTestToolStripMenuItem.Size = new Size(228, 22); gridviewTestToolStripMenuItem.Text = "GridviewTest"; - gridviewTestToolStripMenuItem.Click += gridviewTestToolStripMenuItem_Click; // // 으ㅆㄷㄴㅅToolStripMenuItem // 으ㅆㄷㄴㅅToolStripMenuItem.Name = "으ㅆㄷㄴㅅToolStripMenuItem"; 으ㅆㄷㄴㅅToolStripMenuItem.Size = new Size(228, 22); 으ㅆㄷㄴㅅToolStripMenuItem.Text = "Test DataMatrix StripID"; - 으ㅆㄷㄴㅅToolStripMenuItem.Click += 으ㅆㄷㄴㅅToolStripMenuItem_Click; // // messageToolStripMenuItem // @@ -879,7 +877,6 @@ namespace Project reloadLotListToolStripMenuItem.Name = "reloadLotListToolStripMenuItem"; reloadLotListToolStripMenuItem.Size = new Size(228, 22); reloadLotListToolStripMenuItem.Text = "Reload Lot List"; - reloadLotListToolStripMenuItem.Click += reloadLotListToolStripMenuItem_Click; // // moveSourceListToDestListToolStripMenuItem // @@ -1044,7 +1041,7 @@ namespace Project btHome.TextAlign = ContentAlignment.MiddleCenter; btHome.TextShadow = true; btHome.TextVisible = true; - btHome.Click += arLabel1_Click; + btHome.Click += brHome_Click; // // btChargeM // diff --git a/Cs_HMI/Project/fMain.cs b/Cs_HMI/Project/fMain.cs index 4145aa1..24955eb 100644 --- a/Cs_HMI/Project/fMain.cs +++ b/Cs_HMI/Project/fMain.cs @@ -26,6 +26,7 @@ namespace Project ViewForm.fFlag form_flag = null; ViewForm.fAgv form_agv = null; ViewForm.fBms form_bms = null; + Dialog.fLog form_log = null; readonly usbdetect.DriveDetector usbdet; public fMain() @@ -59,6 +60,10 @@ namespace Project this.FormClosing += __Closing; if (PUB.setting.FullScreen) this.WindowState = FormWindowState.Maximized; + + lbTime.Click += (s1,e1) => { + PUB.mapctl.ShowDesign(); + }; } protected override void WndProc(ref Message m) @@ -240,10 +245,10 @@ namespace Project this.btDebug.Visible = PUB.setting.UseDebugMode; PUB.log.Add("Program Start"); - UpdateControlText(); + //수량표시 - PUB.counter.PropertyChanged += Counter_PropertyChanged; + PUB.counter.PropertyChanged += (s1, e1) => Update_Count(); Update_Count(); PUB.log.Add("프로그램 실행 기록 추가"); @@ -256,15 +261,6 @@ namespace Project } - - - private void Counter_PropertyChanged(object sender, PropertyChangedEventArgs e) - { - //수량에 변화가 잇다면 업데이트 한다 - Update_Count(); - } - - #region "Mouse Form Move" private Boolean fMove = false; @@ -296,6 +292,137 @@ namespace Project } #endregion + void socket_SendMessage(object sender, Device.Socket.SocketMessageEventArgs e) + { + //핑로그가 꺼져있는 상황일때 핑로그는 로그를 기록하지 않는다. 181205 + if (!PUB.setting.Log_Ping && e.Message.Type == Device.Socket.eType.REPLY && e.Message.SType == Device.Socket.eSType.STATUS) + { + return; + } + PUB.log.Add("WS << " + e.rawData); + } + + + + + void socket_RecvMessage(object sender, Device.Socket.SocketMessageEventArgs e) + { + if (e.Message.isError) + PUB.log.AddE("WS >> " + e.Message.ErrorMessage + ",RAW=" + e.rawData); + else + { + + switch (e.Message.Type) + { + case Device.Socket.eType.REQUEST: + if (e.Message.SType == Device.Socket.eSType.STATUS) + { + var packet = PUB.sock_debug.makeReplyStatus(Device.Socket.eStatus.IDLE); + var rlt = PUB.sock_debug.Send(PUB.setting.Asset, Device.Socket.eType.REPLY, Device.Socket.eSType.STATUS, packet); + if (!rlt) + { + PUB.log.AddE("Status Reply Error"); + } + else + { + if (PUB.setting.Log_Ping) PUB.log.AddI("Server Status Reply OK"); + } + } + else + { + PUB.log.Add("WS >> " + e.rawData); + } + break; + } + } + } + + void socket_GetMessage(object sender, Device.Socket.MesasgeEventArgs e) + { + if (e.isError) PUB.log.AddE("WS:" + e.Message); + else PUB.log.Add("WS:" + e.Message); + } + delegate void SelectModelHandler(string modelName); + void SelectModelM(string modelName) + { + if (this.InvokeRequired) + { + this.Invoke(new SelectModelHandler(SelectModelM), new object[] { modelName }); + return; + } + } + + void func_sw_start(bool Prompt = false) + { + if (VAR.BOOL[eVarBool.FLAG_AUTORUN] == false) //자동상태가 아니라면 + { + PUB.AGV.AGVErrorReset(); + if (Prompt) + { + if (UTIL.MsgQ("AGV상태를 자동으로 전환 할까요?") != DialogResult.Yes) return; + } + //충전상태확인 + if (PUB.CheckManualChargeMode() == false) return; + PUB.popup.needClose = true; + PUB.sm.bPause = false; + PUB.sm.SetNewStep(eSMStep.RUN); + + if (PUB.Result.CurrentPos == ePosition.NONE || PUB.Result.TargetPos == ePosition.NONE) + { + PUB.sm.SetNewRunStep(ERunStep.GOHOME); + } + PUB.Speak(Lang.자동전환); + } + else + { + PUB.AGV.AGVCharge(PUB.setting.ChargerID, false); //230425 수동전환하면 충전 해제한다 + PUB.sm.SetNewStep(eSMStep.IDLE); + PUB.Speak(Lang.작업종료); + } + } + + void Resultclear() + { + PUB.Result.Clear(); + PUB.log.AddI("Clear Resultclear"); + } + + + void CheckFreeSpace() + { + try + { + + if (PUB.path.FullName.StartsWith("\\")) + { + SSInfo.setTitle(0, 1, "UNC Path Detected"); + SSInfo.setValue(0, 1, 2); + } + else + { + double freeSpaceRate_ = PUB.GetFreeSpace(); + this.freeSpaceRate = freeSpaceRate_; + SSInfo.setTitle(0, 1, "FREE(" + PUB.path.FullName.Substring(0, 1) + ") : " + freeSpaceRate.ToString("N2") + "%"); + if (freeSpaceRate < PUB.setting.AutoDeleteThreshold) + { + VAR.BOOL[eVarBool.MINSPACE] = true; + SSInfo.setValue(0, 1, 2); //lbFreeSpace.ForeColor = Color.Tomato; + } + else + { + VAR.BOOL[eVarBool.MINSPACE] = false; + SSInfo.setValue(0, 1, 3);// lbFreeSpace.ForeColor = Color.White; + } + } + + //Pub.log.Add("남은디스크공간확인:" + freeSpaceRate.ToString("N2") + "%"); 190129 + } + catch (Exception ex) + { + SSInfo.setTitle(0, 1, "FREE SPACE : -ERROR-"); + PUB.log.AddE("check free space : " + ex.Message); + } + } private void CtlPos1_ItemClick(object sender, CtlPos.ItemClickEventArgs e) @@ -451,191 +578,16 @@ namespace Project if (dlg != null) dlg.Dispose(); } - void socket_SendMessage(object sender, Device.Socket.SocketMessageEventArgs e) - { - //핑로그가 꺼져있는 상황일때 핑로그는 로그를 기록하지 않는다. 181205 - if (!PUB.setting.Log_Ping && e.Message.Type == Device.Socket.eType.REPLY && e.Message.SType == Device.Socket.eSType.STATUS) - { - return; - } - PUB.log.Add("WS << " + e.rawData); - } - - void socket_RecvMessage(object sender, Device.Socket.SocketMessageEventArgs e) - { - if (e.Message.isError) - PUB.log.AddE("WS >> " + e.Message.ErrorMessage + ",RAW=" + e.rawData); - else - { - - switch (e.Message.Type) - { - case Device.Socket.eType.REQUEST: - if (e.Message.SType == Device.Socket.eSType.STATUS) - { - var packet = PUB.sock_debug.makeReplyStatus(Device.Socket.eStatus.IDLE); - var rlt = PUB.sock_debug.Send(PUB.setting.Asset, Device.Socket.eType.REPLY, Device.Socket.eSType.STATUS, packet); - if (!rlt) - { - PUB.log.AddE("Status Reply Error"); - } - else - { - if (PUB.setting.Log_Ping) PUB.log.AddI("Server Status Reply OK"); - } - } - else - { - PUB.log.Add("WS >> " + e.rawData); - } - break; - } - } - } - - void socket_GetMessage(object sender, Device.Socket.MesasgeEventArgs e) - { - if (e.isError) PUB.log.AddE("WS:" + e.Message); - else PUB.log.Add("WS:" + e.Message); - } - delegate void SelectModelHandler(string modelName); - void SelectModelM(string modelName) - { - if (this.InvokeRequired) - { - this.Invoke(new SelectModelHandler(SelectModelM), new object[] { modelName }); - return; - } - } - - void func_sw_start(bool Prompt = false) - { - if (VAR.BOOL[eVarBool.FLAG_AUTORUN] == false) //자동상태가 아니라면 - { - PUB.AGV.AGVErrorReset(); - if (Prompt) - { - if (UTIL.MsgQ("AGV상태를 자동으로 전환 할까요?") != DialogResult.Yes) return; - } - //충전상태확인 - if (PUB.CheckManualChargeMode() == false) return; - PUB.popup.needClose = true; - PUB.sm.bPause = false; - PUB.sm.SetNewStep(eSMStep.RUN); - - if (PUB.Result.CurrentPos == ePosition.NONE || PUB.Result.TargetPos == ePosition.NONE) - { - PUB.sm.SetNewRunStep(ERunStep.GOHOME); - } - PUB.Speak(Lang.자동전환); - } - else - { - PUB.AGV.AGVCharge(PUB.setting.ChargerID, false); //230425 수동전환하면 충전 해제한다 - PUB.sm.SetNewStep(eSMStep.IDLE); - PUB.Speak(Lang.작업종료); - } - } - - void Resultclear() - { - PUB.Result.Clear(); - PUB.log.AddI("Clear Resultclear"); - } - - - void CheckFreeSpace() - { - try - { - - if (PUB.path.FullName.StartsWith("\\")) - { - SSInfo.setTitle(0, 1, "UNC Path Detected"); - SSInfo.setValue(0, 1, 2); - } - else - { - double freeSpaceRate_ = PUB.GetFreeSpace(); - this.freeSpaceRate = freeSpaceRate_; - SSInfo.setTitle(0, 1, "FREE(" + PUB.path.FullName.Substring(0, 1) + ") : " + freeSpaceRate.ToString("N2") + "%"); - if (freeSpaceRate < PUB.setting.AutoDeleteThreshold) - { - VAR.BOOL[eVarBool.MINSPACE] = true; - SSInfo.setValue(0, 1, 2); //lbFreeSpace.ForeColor = Color.Tomato; - } - else - { - VAR.BOOL[eVarBool.MINSPACE] = false; - SSInfo.setValue(0, 1, 3);// lbFreeSpace.ForeColor = Color.White; - } - } - - //Pub.log.Add("남은디스크공간확인:" + freeSpaceRate.ToString("N2") + "%"); 190129 - } - catch (Exception ex) - { - SSInfo.setTitle(0, 1, "FREE SPACE : -ERROR-"); - PUB.log.AddE("check free space : " + ex.Message); - } - } - private void demoRunToolStripMenuItem_Click(object sender, EventArgs e) { PUB.Result.JobEndTime = DateTime.Now; - // Pub.flag.Toggle(eFlag.DemoRun); - // Pub.log.AddAT(string.Format("데모변경: {0}", Pub.flag.get(eFlag.DemoRun))); } - private void openMapFileToolStripMenuItem_Click(object sender, EventArgs e) - { - using (OpenFileDialog od = new OpenFileDialog()) - if (od.ShowDialog() != System.Windows.Forms.DialogResult.OK) return; - //if (orgImage != null) orgImage.Dispose(); - - } - - - private void setZValidToolStripMenuItem_Click(object sender, EventArgs e) { - PUB.log.Add("user set z-home set on"); } - private void gridviewTestToolStripMenuItem_Click(object sender, EventArgs e) - { - - - } - - private void 으ㅆㄷㄴㅅToolStripMenuItem_Click(object sender, EventArgs e) - { - /////HB9225-4280A 0901 - //var striplist = new string[]{ - // "HB9125-7560A 0704", - //"HB9125-7800A 0104", - //"HB9125-8480A 0701", - //"HB9130-8550A 5108", - //"HB9130-8620A 0701", - //"HB9131-9340A 0201", - //"HB9206-0810A 5301", - //"HB9206-0820A 0902", - //"HB9222-3020A 0208", - //"HB9222-3020A 0508", - //"HB9222-3720A 0205", - //"HB9222-3720A 0902", - //"HB9225-3790A 0604", - //"HB9225-4280A 0901", - //"HB9228-4840A 0104", - //"HB9228-4840A 5908", - //"HB9313-7600A 1006", - //"HB9319-9540A 6003", - //"ZGP490510700 1305" - //}; - - } - private void errorToolStripMenuItem_Click(object sender, EventArgs e) { PUB.popup.setMessage("error\berror message"); @@ -651,12 +603,6 @@ namespace Project PUB.popup.setMessage("attention\nattention message", MessageWindow.eWindowType.attention); } - private void reloadLotListToolStripMenuItem_Click(object sender, EventArgs e) - { - - } - - private void arLabel3_Click(object sender, EventArgs e) { @@ -676,11 +622,6 @@ namespace Project this.Close(); } - void UpdateControlText() - { - - } - private void arLabel5_Click(object sender, EventArgs e) { //SetScreen(form_setup); @@ -700,7 +641,7 @@ namespace Project } VAR.BOOL[eVarBool.FLAG_SETUP] = false;// VAR.BOOL[eVarBool.FLAG_SETUP] = false;//VAR.BOOL[eVarBool.FLAG_SETUP] = false; - UpdateControlText(); + if (popmsg) PUB.popup.Visible = true; } @@ -737,13 +678,13 @@ namespace Project UTIL.RunExplorer(UTIL.CurrentPath); } - private void button4_Click(object sender, EventArgs e) + private void ManualMan_Click(object sender, EventArgs e) { SetScreen(form_manu); MenuMAN.ForeColor = Color.Gold; } - private void button3_Click(object sender, EventArgs e) + private void MenuLift_Click(object sender, EventArgs e) { SetScreen(form_zlift); MenuLift.ForeColor = Color.Gold; @@ -755,7 +696,7 @@ namespace Project this.cmDebug.Show(ctl, new Point((int)(ctl.Width / 1.5), (int)(ctl.Height / 1.5))); } - private void btStart_Click(object sender, EventArgs e) + private void btAutorun_Click(object sender, EventArgs e) { var ctl = sender as arCtl.arLabel; if (ctl.Enabled == false) return; @@ -763,20 +704,18 @@ namespace Project func_sw_start(true); } - private void button2_Click(object sender, EventArgs e) + private void btMenuAuto_Click(object sender, EventArgs e) { SetScreen(form_auto); MenuAuto.ForeColor = Color.Gold; } - private void button1_Click(object sender, EventArgs e) + private void btMenuFlag_Click(object sender, EventArgs e) { SetScreen(form_flag); MenuFlag.ForeColor = Color.Gold; } - - - Dialog.fLog form_log = null; + private void btLog_Click(object sender, EventArgs e) { if (form_log == null || form_log.IsDisposed || form_log.Disposing) @@ -844,8 +783,7 @@ namespace Project PUB.Speak("고경석 수석님 밥은 드셨습니까?", true); UpdateProgressStatus(20, 100, "progre"); } - - private void arLabel1_Click(object sender, EventArgs e) + private void brHome_Click(object sender, EventArgs e) { var bCharge = PUB.sm.Step == eSMStep.RUN && (PUB.sm.RunStep == ERunStep.GOHOME); @@ -878,30 +816,6 @@ namespace Project } - //private void btChargeM_Click(object sender, EventArgs e) - //{ - // var bCharge = PUB.flag.get(EFlag.FLAG_CHARGEONM); - - // //충전을 시작해라ㅏ - // if (bCharge == true) - // { - // var dlg = Util.MsgQ("수동 충전 상태를 해제 할까요?"); - // if (dlg == DialogResult.Yes) - // { - // PUB.flag.set(EFlag.FLAG_CHARGEONM, false); - // Pub.log.Add("수동 충전 상태 해제"); - // } - // } - // else - // { - // var dlg = Util.MsgQ("수동 충전 상태를 설정 할까요?\n수동충전이 설정되면 AGV는 움직지 않습니다"); - // if (dlg == DialogResult.Yes) - // { - // PUB.flag.set(EFlag.FLAG_CHARGEONM, true); - // Pub.log.Add("수동 충전 상태 설정"); - // } - // } - //} private void arLabel2_Click_1(object sender, EventArgs e) { @@ -911,17 +825,18 @@ namespace Project private void lbCNtUp_Click(object sender, EventArgs e) { + //down,up둘다 연결해야함 using (var f = new Dialog.fCounter()) f.ShowDialog(); } - private void button1_Click_1(object sender, EventArgs e) + private void btMenuAGV_Click_1(object sender, EventArgs e) { SetScreen(form_agv); MenuAGV.ForeColor = Color.Gold; } - private void button2_Click_1(object sender, EventArgs e) + private void btMenuBMS_Click_1(object sender, EventArgs e) { SetScreen(form_bms); MenuBMS.ForeColor = Color.Gold; @@ -971,5 +886,10 @@ namespace Project PUB.log.Add("수동 충전 실행"); } } + + private void lbTime_Click(object sender, EventArgs e) + { + PUB.mapctl.ShowDesign(); + } } } diff --git a/Cs_HMI/Project/fMain.resx b/Cs_HMI/Project/fMain.resx index cd1bc76..a0d11b6 100644 --- a/Cs_HMI/Project/fMain.resx +++ b/Cs_HMI/Project/fMain.resx @@ -1,17 +1,17 @@  - diff --git a/Cs_HMI/Project/sample.route b/Cs_HMI/Project/sample.route index cea5fcc..4569868 100644 --- a/Cs_HMI/Project/sample.route +++ b/Cs_HMI/Project/sample.route @@ -1,105 +1,152 @@ [RFID_POINTS] -100,486,517 -173,488,516 -230,493,515 -309,489,514 -370,490,513 -437,487,512 -483,459,511 -511,421,510 -543,371,509 -569,329,508 -608,289,507 -661,279,506 -701,297,505 -698,349,504 -698,391,503 -699,449,502 -691,491,501 -570,275,400 -517,264,401 -454,264,402 -388,262,403 -315,258,404 -639,234,600 -621,182,601 -641,183,602 -657,101,603 -627,82,604 -560,73,605 -499,65,606 -432,65,607 -264,232,405 -363,60,608 -654,508,500 -96,542,100 -159,542,101 -226,542,102 -309,541,103 -369,542,104 -483,165,753 -735,163,700 -523,170,752 -565,175,751 -597,182,750 -665,181,703 -700,176,702 -722,170,701 +100,486,517,False,,False +162,487,516,False,,False +230,493,515,False,,False +309,489,514,False,,False +370,490,513,False,,False +429,487,512,False,Forward,False +488,476,511,False,,False +538,445,510,False,,False +576,393,509,False,,False +598,343,508,False,,False +621,287,507,True,,False +671,293,506,False,,False +702,314,505,False,,False +711,354,504,False,,False +711,396,503,False,,False +707,454,502,False,,False +685,499,501,False,Forward,False +566,281,400,False,,False +504,274,401,False,,False +439,271,402,False,,False +383,267,403,False,,False +311,260,404,False,Forward,False +633,237,600,False,,False +609,186,601,False,,False +639,184,602,False,,False +657,101,603,False,,False +627,82,604,False,,False +560,73,605,False,,False +499,65,606,False,,False +432,65,607,False,Forward,False +242,239,405,False,Forward,True +363,60,608,False,Forward,True +633,547,500,False,Forward,True +96,542,100,False,Forward,True +159,542,101,False,Forward,True +226,542,102,False,Forward,True +310,541,103,False,Forward,True +369,542,104,False,Forward,True +397,166,753,False,Backward,True +847,152,700,False,Backward,True +484,169,752,False,Backward,False +535,176,751,False,,False +573,184,750,False,,False +665,181,703,False,,False +714,174,702,False,,False +756,165,701,False,Backward,False [RFID_LINES] -100,486,173,488,517,516,False,73.02739 -173,488,230,493,516,515,False,57.21888 -230,493,309,489,515,514,False,79.1012 -309,489,370,490,514,513,False,61.0082 -370,490,437,487,513,512,False,67.06713 -437,487,483,459,512,511,False,53.85165 -483,459,511,421,511,510,False,47.20169 -511,421,543,371,510,509,False,59.36329 -543,371,569,329,509,508,False,49.39635 -569,329,608,289,508,507,False,55.86591 -608,289,639,234,507,600,False,63.13478 -639,234,665,181,600,703,False,59.03389 -665,181,657,101,703,603,False,80.399 -657,101,627,82,603,604,False,35.51056 -627,82,560,73,604,605,False,67.60178 -560,73,499,65,605,606,False,61.52235 -499,65,432,65,606,607,False,67 -432,65,363,60,607,608,False,69.18092 -641,183,665,181,602,703,False,24.08319 -665,181,700,176,703,702,False,35.35534 -700,176,722,170,702,701,False,22.80351 -722,170,735,163,701,700,False,14.76482 -641,183,621,182,602,601,False,20.02498 -621,182,597,182,601,750,False,24 -597,182,565,175,750,751,False,32.75668 -565,175,523,170,751,752,False,42.29657 -523,170,483,165,752,753,False,40.31129 -264,232,315,258,405,404,False,57.24509 -315,258,388,262,404,403,False,73.1095 -388,262,454,264,403,402,False,66.0303 -454,264,517,264,402,401,False,63 -517,264,570,275,401,400,False,54.12947 -570,275,608,289,400,507,False,40.49691 -608,289,661,279,507,506,False,53.93515 -661,279,701,297,506,505,False,43.86343 -701,297,698,349,505,504,False,52.08647 -698,349,698,391,504,503,False,42 -698,391,699,449,503,502,False,58.00862 -699,449,691,491,502,501,False,42.75512 -691,491,654,508,501,500,False,40.71855 -96,542,100,486,100,517,False,56.14267 -159,542,173,488,101,516,False,55.7853 -226,542,230,493,102,515,False,49.16299 -309,541,309,489,103,514,False,52 -369,542,370,490,104,513,False,52.00961 +100,486,162,487,[RFIDPoint] 517,P:100,486,[RFIDPoint] 516,P:162,487,false,false,0 +162,487,230,493,[RFIDPoint] 516,P:162,487,[RFIDPoint] 515,P:230,493,false,false,0 +230,493,309,489,[RFIDPoint] 515,P:230,493,[RFIDPoint] 514,P:309,489,false,false,0 +309,489,370,490,[RFIDPoint] 514,P:309,489,[RFIDPoint] 513,P:370,490,false,false,0 +370,490,429,487,[RFIDPoint] 513,P:370,490,[RFIDPoint] 512,P:429,487,false,false,0 +429,487,488,476,[RFIDPoint] 512,P:429,487,[RFIDPoint] 511,P:488,476,false,false,0 +488,476,538,445,[RFIDPoint] 511,P:488,476,[RFIDPoint] 510,P:538,445,false,false,0 +538,445,576,393,[RFIDPoint] 510,P:538,445,[RFIDPoint] 509,P:576,393,false,false,0 +576,393,598,343,[RFIDPoint] 509,P:576,393,[RFIDPoint] 508,P:598,343,false,false,0 +598,343,621,287,[RFIDPoint] 508,P:598,343,[RFIDPoint] 507,P:621,287,false,false,0 +621,287,633,237,[RFIDPoint] 507,P:621,287,[RFIDPoint] 600,P:633,237,false,false,0 +633,237,665,181,[RFIDPoint] 600,P:633,237,[RFIDPoint] 703,P:665,181,false,false,0 +665,181,657,101,[RFIDPoint] 703,P:665,181,[RFIDPoint] 603,P:657,101,false,false,0 +657,101,627,82,[RFIDPoint] 603,P:657,101,[RFIDPoint] 604,P:627,82,false,false,0 +627,82,560,73,[RFIDPoint] 604,P:627,82,[RFIDPoint] 605,P:560,73,false,false,0 +560,73,499,65,[RFIDPoint] 605,P:560,73,[RFIDPoint] 606,P:499,65,false,false,0 +499,65,432,65,[RFIDPoint] 606,P:499,65,[RFIDPoint] 607,P:432,65,false,false,0 +432,65,363,60,[RFIDPoint] 607,P:432,65,[RFIDPoint] 608,P:363,60,false,false,0 +639,184,665,181,[RFIDPoint] 602,P:639,184,[RFIDPoint] 703,P:665,181,false,false,0 +665,181,714,174,[RFIDPoint] 703,P:665,181,[RFIDPoint] 702,P:714,174,false,false,0 +714,174,756,165,[RFIDPoint] 702,P:714,174,[RFIDPoint] 701,P:756,165,false,false,0 +756,165,847,152,[RFIDPoint] 701,P:756,165,[RFIDPoint] 700,P:847,152,false,false,0 +639,184,609,186,[RFIDPoint] 602,P:639,184,[RFIDPoint] 601,P:609,186,false,false,0 +609,186,573,184,[RFIDPoint] 601,P:609,186,[RFIDPoint] 750,P:573,184,false,false,0 +573,184,535,176,[RFIDPoint] 750,P:573,184,[RFIDPoint] 751,P:535,176,false,false,0 +535,176,484,169,[RFIDPoint] 751,P:535,176,[RFIDPoint] 752,P:484,169,false,false,0 +484,169,397,166,[RFIDPoint] 752,P:484,169,[RFIDPoint] 753,P:397,166,false,false,0 +242,239,311,260,[RFIDPoint] 405,P:242,239,[RFIDPoint] 404,P:311,260,false,false,0 +311,260,383,267,[RFIDPoint] 404,P:311,260,[RFIDPoint] 403,P:383,267,false,false,0 +383,267,439,271,[RFIDPoint] 403,P:383,267,[RFIDPoint] 402,P:439,271,false,false,0 +439,271,504,274,[RFIDPoint] 402,P:439,271,[RFIDPoint] 401,P:504,274,false,false,0 +504,274,566,281,[RFIDPoint] 401,P:504,274,[RFIDPoint] 400,P:566,281,false,false,0 +566,281,621,287,[RFIDPoint] 400,P:566,281,[RFIDPoint] 507,P:621,287,false,false,0 +621,287,671,293,[RFIDPoint] 507,P:621,287,[RFIDPoint] 506,P:671,293,false,false,0 +671,293,702,314,[RFIDPoint] 506,P:671,293,[RFIDPoint] 505,P:702,314,false,false,0 +702,314,711,354,[RFIDPoint] 505,P:702,314,[RFIDPoint] 504,P:711,354,false,false,0 +711,354,711,396,[RFIDPoint] 504,P:711,354,[RFIDPoint] 503,P:711,396,false,false,0 +711,396,707,454,[RFIDPoint] 503,P:711,396,[RFIDPoint] 502,P:707,454,false,false,0 +707,454,685,499,[RFIDPoint] 502,P:707,454,[RFIDPoint] 501,P:685,499,false,false,0 +685,499,633,547,[RFIDPoint] 501,P:685,499,[RFIDPoint] 500,P:633,547,false,false,0 +96,542,100,486,[RFIDPoint] 100,P:96,542,[RFIDPoint] 517,P:100,486,false,false,0 +159,542,162,487,[RFIDPoint] 101,P:159,542,[RFIDPoint] 516,P:162,487,false,false,0 +226,542,230,493,[RFIDPoint] 102,P:226,542,[RFIDPoint] 515,P:230,493,false,false,0 +310,541,309,489,[RFIDPoint] 103,P:310,541,[RFIDPoint] 514,P:309,489,false,false,0 +369,542,370,490,[RFIDPoint] 104,P:369,542,[RFIDPoint] 513,P:370,490,false,false,0 +[RFID_CONNECTION] +100,486,162,487,517,516,1,,, +162,487,230,493,516,515,1,,, +230,493,309,489,515,514,1,,, +309,489,370,490,514,513,1,,, +370,490,429,487,513,512,1,,, +429,487,488,476,512,511,1,,, +488,476,538,445,511,510,1,,, +538,445,576,393,510,509,1,,, +576,393,598,343,509,508,1,,, +598,343,621,287,508,507,1,,, +621,287,633,237,507,600,1,,, +633,237,665,181,600,703,1,,, +665,181,657,101,703,603,1,,, +657,101,627,82,603,604,1,,, +627,82,560,73,604,605,1,,, +560,73,499,65,605,606,1,,, +499,65,432,65,606,607,1,,, +432,65,363,60,607,608,1,,, +639,184,665,181,602,703,1,,, +665,181,714,174,703,702,1,,, +714,174,756,165,702,701,1,,, +756,165,847,152,701,700,1,,, +639,184,609,186,602,601,1,,, +609,186,573,184,601,750,1,,, +573,184,535,176,750,751,1,,, +535,176,484,169,751,752,1,,, +484,169,397,166,752,753,1,,, +242,239,311,260,405,404,1,,, +311,260,383,267,404,403,1,,, +383,267,439,271,403,402,1,,, +439,271,504,274,402,401,1,,, +504,274,566,281,401,400,1,,, +566,281,621,287,400,507,1,,, +621,287,671,293,507,506,1,,, +671,293,702,314,506,505,1,,, +702,314,711,354,505,504,1,,, +711,354,711,396,504,503,1,,, +711,396,707,454,503,502,1,,, +707,454,685,499,502,501,1,,, +685,499,633,547,501,500,1,,, +96,542,100,486,100,517,1,,, +159,542,162,487,101,516,1,,, +226,542,230,493,102,515,1,,, +310,541,309,489,103,514,1,,, +369,542,370,490,104,513,1,,, [MAP_TEXTS] -179,251,-1,-16777216,Arial,12,OPS-2 -239,52,-256,-65408,Arial,12,SSOTRON-3 -617,527,-16711936,-16777216,Arial,12,SSOTRON-1 -87,551,-16777216,16777215,Arial,12,B1 -150,550,-16777216,16777215,Arial,12,B2 -227,553,-16777216,16777215,Arial,12,B3 -299,555,-16777216,16777215,Arial,12,B4 -367,554,-16777216,16777215,Arial,12,B5 -453,128,-16777216,-8323073,Arial,12,CHG1 -725,124,-16777216,-8323073,Arial,12,CHG2 +231,193,-16777216,-2448096,Arial,12,TOPS-2 +315,25,-256,-65408,Arial,12,SSOTRON-3 +586,577,-16711936,-16777216,Arial,12,SSOTRON-1 +81,564,-16777216,-1,Arial,12,B1 +144,563,-16777216,-1,Arial,12,B2 +214,561,-16777216,-1,Arial,12,B3 +301,562,-16777216,-1,Arial,12,B4 +359,562,-16777216,-1,Arial,12,B5 +371,115,-16777216,-8323073,Arial,12,CHG1 +822,110,-16777216,-8323073,Arial,12,CHG2 +[CUSTOM_LINES] [CUSTOM_LINES] diff --git a/Cs_HMI/SubProject/AGVControl/Dialog/fMapDesign.Designer.cs b/Cs_HMI/SubProject/AGVControl/Dialog/fMapDesign.Designer.cs new file mode 100644 index 0000000..60aedc6 --- /dev/null +++ b/Cs_HMI/SubProject/AGVControl/Dialog/fMapDesign.Designer.cs @@ -0,0 +1,103 @@ +namespace AGVControl.Dialog +{ + partial class fMapDesign + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(fMapDesign)); + this.panel1 = new System.Windows.Forms.Panel(); + this.toolStrip1 = new System.Windows.Forms.ToolStrip(); + this.statusStrip1 = new System.Windows.Forms.StatusStrip(); + this.btOK = new System.Windows.Forms.ToolStripButton(); + this.toolStrip1.SuspendLayout(); + this.SuspendLayout(); + // + // panel1 + // + this.panel1.Dock = System.Windows.Forms.DockStyle.Fill; + this.panel1.Font = new System.Drawing.Font("Tahoma", 8F, System.Drawing.FontStyle.Bold); + this.panel1.Location = new System.Drawing.Point(0, 47); + this.panel1.Name = "panel1"; + this.panel1.Size = new System.Drawing.Size(888, 547); + this.panel1.TabIndex = 22; + // + // toolStrip1 + // + this.toolStrip1.ImageScalingSize = new System.Drawing.Size(40, 40); + this.toolStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.btOK}); + this.toolStrip1.Location = new System.Drawing.Point(0, 0); + this.toolStrip1.Name = "toolStrip1"; + this.toolStrip1.Size = new System.Drawing.Size(888, 47); + this.toolStrip1.TabIndex = 23; + this.toolStrip1.Text = "toolStrip1"; + // + // statusStrip1 + // + this.statusStrip1.Location = new System.Drawing.Point(0, 594); + this.statusStrip1.Name = "statusStrip1"; + this.statusStrip1.Size = new System.Drawing.Size(888, 22); + this.statusStrip1.TabIndex = 24; + this.statusStrip1.Text = "statusStrip1"; + // + // btOK + // + this.btOK.Alignment = System.Windows.Forms.ToolStripItemAlignment.Right; + this.btOK.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; + this.btOK.Image = ((System.Drawing.Image)(resources.GetObject("btOK.Image"))); + this.btOK.ImageTransparentColor = System.Drawing.Color.Magenta; + this.btOK.Name = "btOK"; + this.btOK.Size = new System.Drawing.Size(44, 44); + this.btOK.Text = "toolStripButton1"; + this.btOK.Click += new System.EventHandler(this.btOK_Click); + // + // fMapDesign + // + this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 12F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(888, 616); + this.Controls.Add(this.panel1); + this.Controls.Add(this.statusStrip1); + this.Controls.Add(this.toolStrip1); + this.Name = "fMapDesign"; + this.Text = "fMapDesign"; + this.Load += new System.EventHandler(this.fMapDesign_Load); + this.toolStrip1.ResumeLayout(false); + this.toolStrip1.PerformLayout(); + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + + private System.Windows.Forms.Panel panel1; + private System.Windows.Forms.ToolStrip toolStrip1; + private System.Windows.Forms.ToolStripButton btOK; + private System.Windows.Forms.StatusStrip statusStrip1; + } +} \ No newline at end of file diff --git a/Cs_HMI/SubProject/AGVControl/Dialog/fMapDesign.cs b/Cs_HMI/SubProject/AGVControl/Dialog/fMapDesign.cs new file mode 100644 index 0000000..04f91b4 --- /dev/null +++ b/Cs_HMI/SubProject/AGVControl/Dialog/fMapDesign.cs @@ -0,0 +1,48 @@ +using AR; +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Linq; +using System.Security.Cryptography.X509Certificates; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Forms; + +namespace AGVControl.Dialog +{ + public partial class fMapDesign : Form + { + AGVControl.MapControl mapctl; + public fMapDesign(string fn) + { + InitializeComponent(); + + mapctl = new AGVControl.MapControl(); + mapctl.Dock = DockStyle.Fill; + mapctl.Visible = true; + mapctl.Font = this.panel1.Font; + mapctl.BackColor = Color.FromArgb(32, 32, 32); + this.panel1.Controls.Add(mapctl); + + if (System.IO.File.Exists(fn)) + { + //auto load + var rlt = mapctl.LoadFromFile(fn, out string errmsg); + if (rlt == false) AR.UTIL.MsgE(errmsg); + } + } + + private void fMapDesign_Load(object sender, EventArgs e) + { + + } + + private void btOK_Click(object sender, EventArgs e) + { + this.mapctl.SaveToFile(this.mapctl.Filename); + DialogResult = DialogResult.OK; + } + } +} diff --git a/Cs_HMI/SubProject/AGVControl/Dialog/fMapDesign.resx b/Cs_HMI/SubProject/AGVControl/Dialog/fMapDesign.resx new file mode 100644 index 0000000..3a6bdfb --- /dev/null +++ b/Cs_HMI/SubProject/AGVControl/Dialog/fMapDesign.resx @@ -0,0 +1,142 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 17, 17 + + + + + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 + YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAIDSURBVDhPpZLrS5NhGMb3j4SWh0oRQVExD4gonkDpg4hG + YKxG6WBogkMZKgPNCEVJFBGdGETEvgwyO9DJE5syZw3PIlPEE9pgBCLZ5XvdMB8Ew8gXbl54nuf63dd9 + 0OGSnwCahxbPRNPAPMw9Xpg6ZmF46kZZ0xSKzJPIrhpDWsVnpBhGkKx3nAX8Pv7z1zg8OoY/cITdn4fw + bf/C0kYAN3Ma/w3gWfZL5kzTKBxjWyK2DftwI9tyMYCZKXbNHaD91bLYJrDXsYbrWfUKwJrPE9M2M1Oc + VzOOpHI7Jr376Hi9ogHqFIANO0/MmmmbmSmm9a8ze+I4MrNWAdjtoJgWcx+PSzg166yZZ8xM8XvXDix9 + c4jIqFYAjoriBV9AhEPv1mH/sonogha0afbZMMZz+yreTGyhpusHwtNNCsA5U1zS4BLxzJIfg299qO32 + Ir7UJtZfftyATqeT+8o2D8JSjQrAJblrncYL7ZJ2+bfaFnC/1S1NjL3diRat7qrO7wLRP3HjWsojBeCo + mDEo5mNjuweFGvjWg2EBhCbpkW78htSHHwRyNdmgAFzPEee2iFkzayy2OLXzT4gr6UdUnlXrullsxxQ+ + kx0g8BTA3aZlButjSTyjODq/WcQcW/B/Je4OQhLvKQDnzN1mp0nnkvAhR8VuMzNrpm1mpjgkoVwB/v8D + TgDQASA1MVpwzwAAAABJRU5ErkJggg== + + + + 124, 17 + + \ No newline at end of file diff --git a/Cs_HMI/SubProject/AGVControl/Dialog/fPropertyRFIDPoint.Designer.cs b/Cs_HMI/SubProject/AGVControl/Dialog/fPropertyRFIDPoint.Designer.cs new file mode 100644 index 0000000..dac7dd1 --- /dev/null +++ b/Cs_HMI/SubProject/AGVControl/Dialog/fPropertyRFIDPoint.Designer.cs @@ -0,0 +1,158 @@ +namespace AGVControl.Dialog +{ + partial class fPropertyRFIDPoint + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.propertyGrid1 = new System.Windows.Forms.PropertyGrid(); + this.comboBox1 = new System.Windows.Forms.ComboBox(); + this.propertyGrid2 = new System.Windows.Forms.PropertyGrid(); + this.panel1 = new System.Windows.Forms.Panel(); + this.label2 = new System.Windows.Forms.Label(); + this.panel2 = new System.Windows.Forms.Panel(); + this.label1 = new System.Windows.Forms.Label(); + this.button1 = new System.Windows.Forms.Button(); + this.panel1.SuspendLayout(); + this.panel2.SuspendLayout(); + this.SuspendLayout(); + // + // propertyGrid1 + // + this.propertyGrid1.Dock = System.Windows.Forms.DockStyle.Fill; + this.propertyGrid1.Location = new System.Drawing.Point(0, 31); + this.propertyGrid1.Name = "propertyGrid1"; + this.propertyGrid1.Size = new System.Drawing.Size(346, 456); + this.propertyGrid1.TabIndex = 0; + // + // comboBox1 + // + this.comboBox1.Dock = System.Windows.Forms.DockStyle.Top; + this.comboBox1.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; + this.comboBox1.Font = new System.Drawing.Font("굴림", 18F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(129))); + this.comboBox1.FormattingEnabled = true; + this.comboBox1.Location = new System.Drawing.Point(1, 32); + this.comboBox1.Name = "comboBox1"; + this.comboBox1.Size = new System.Drawing.Size(519, 32); + this.comboBox1.TabIndex = 1; + this.comboBox1.SelectedIndexChanged += new System.EventHandler(this.comboBox1_SelectedIndexChanged); + // + // propertyGrid2 + // + this.propertyGrid2.Dock = System.Windows.Forms.DockStyle.Fill; + this.propertyGrid2.Location = new System.Drawing.Point(1, 64); + this.propertyGrid2.Name = "propertyGrid2"; + this.propertyGrid2.Size = new System.Drawing.Size(519, 362); + this.propertyGrid2.TabIndex = 2; + // + // panel1 + // + this.panel1.BackColor = System.Drawing.Color.Gray; + this.panel1.Controls.Add(this.propertyGrid2); + this.panel1.Controls.Add(this.button1); + this.panel1.Controls.Add(this.comboBox1); + this.panel1.Controls.Add(this.label2); + this.panel1.Dock = System.Windows.Forms.DockStyle.Fill; + this.panel1.Location = new System.Drawing.Point(346, 0); + this.panel1.Name = "panel1"; + this.panel1.Padding = new System.Windows.Forms.Padding(1); + this.panel1.Size = new System.Drawing.Size(521, 487); + this.panel1.TabIndex = 3; + // + // label2 + // + this.label2.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(224)))), ((int)(((byte)(224)))), ((int)(((byte)(224))))); + this.label2.Dock = System.Windows.Forms.DockStyle.Top; + this.label2.Font = new System.Drawing.Font("굴림", 9F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(129))); + this.label2.Location = new System.Drawing.Point(1, 1); + this.label2.Name = "label2"; + this.label2.Size = new System.Drawing.Size(519, 31); + this.label2.TabIndex = 3; + this.label2.Text = "Connection Information"; + this.label2.TextAlign = System.Drawing.ContentAlignment.MiddleCenter; + // + // panel2 + // + this.panel2.Controls.Add(this.propertyGrid1); + this.panel2.Controls.Add(this.label1); + this.panel2.Dock = System.Windows.Forms.DockStyle.Left; + this.panel2.Location = new System.Drawing.Point(0, 0); + this.panel2.Name = "panel2"; + this.panel2.Size = new System.Drawing.Size(346, 487); + this.panel2.TabIndex = 4; + // + // label1 + // + this.label1.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(224)))), ((int)(((byte)(224)))), ((int)(((byte)(224))))); + this.label1.Dock = System.Windows.Forms.DockStyle.Top; + this.label1.Font = new System.Drawing.Font("굴림", 9F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(129))); + this.label1.Location = new System.Drawing.Point(0, 0); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(346, 31); + this.label1.TabIndex = 0; + this.label1.Text = "Point Information"; + this.label1.TextAlign = System.Drawing.ContentAlignment.MiddleCenter; + // + // button1 + // + this.button1.Dock = System.Windows.Forms.DockStyle.Bottom; + this.button1.Font = new System.Drawing.Font("Arial Rounded MT Bold", 27.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.button1.Location = new System.Drawing.Point(1, 426); + this.button1.Name = "button1"; + this.button1.Size = new System.Drawing.Size(519, 60); + this.button1.TabIndex = 4; + this.button1.Text = "P1 ↔ P2"; + this.button1.UseVisualStyleBackColor = true; + this.button1.Click += new System.EventHandler(this.button1_Click); + // + // fPropertyRFIDPoint + // + this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 12F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(867, 487); + this.Controls.Add(this.panel1); + this.Controls.Add(this.panel2); + this.Name = "fPropertyRFIDPoint"; + this.Text = "fPropertyRFIDPoint"; + this.Load += new System.EventHandler(this.fPropertyRFIDPoint_Load); + this.panel1.ResumeLayout(false); + this.panel2.ResumeLayout(false); + this.ResumeLayout(false); + + } + + #endregion + + private System.Windows.Forms.PropertyGrid propertyGrid1; + private System.Windows.Forms.ComboBox comboBox1; + private System.Windows.Forms.PropertyGrid propertyGrid2; + private System.Windows.Forms.Panel panel1; + private System.Windows.Forms.Panel panel2; + private System.Windows.Forms.Label label1; + private System.Windows.Forms.Label label2; + private System.Windows.Forms.Button button1; + } +} \ No newline at end of file diff --git a/Cs_HMI/SubProject/AGVControl/Dialog/fPropertyRFIDPoint.cs b/Cs_HMI/SubProject/AGVControl/Dialog/fPropertyRFIDPoint.cs new file mode 100644 index 0000000..917f1b1 --- /dev/null +++ b/Cs_HMI/SubProject/AGVControl/Dialog/fPropertyRFIDPoint.cs @@ -0,0 +1,55 @@ +using AGVControl.Models; +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Forms; + +namespace AGVControl.Dialog +{ + public partial class fPropertyRFIDPoint : Form + { + RFIDPoint RFIDPt; + List Connections; + public fPropertyRFIDPoint(RFIDPoint point, List connection) + { + InitializeComponent(); + this.RFIDPt = point; + this.Connections = connection; + this.propertyGrid1.SelectedObject = point; + this.KeyPreview = true; + this.KeyDown += (s1, e1) => { + if (e1.KeyCode == Keys.Escape) this.Close(); + }; + } + + private void fPropertyRFIDPoint_Load(object sender, EventArgs e) + { + foreach (var item in Connections) + comboBox1.Items.Add($"{item.P1.Value} ↔ {item.P2.Value}"); + + if(comboBox1.Items.Count > 0) + comboBox1.SelectedIndex = 0; + } + + private void comboBox1_SelectedIndexChanged(object sender, EventArgs e) + { + this.propertyGrid2.SelectedObject = this.Connections[this.comboBox1.SelectedIndex]; + } + + private void button1_Click(object sender, EventArgs e) + { + var item = this.Connections[this.comboBox1.SelectedIndex]; + var p1 = item.P1; + var p2 = item.P2; + item.P2 = p1;// item.P1; + item.P1 = p2;// p1; + this.propertyGrid2.SelectedObject = item; + this.Validate(); + } + } +} diff --git a/Cs_HMI/SubProject/AGVControl/Dialog/fPropertyRFIDPoint.resx b/Cs_HMI/SubProject/AGVControl/Dialog/fPropertyRFIDPoint.resx new file mode 100644 index 0000000..29dcb1b --- /dev/null +++ b/Cs_HMI/SubProject/AGVControl/Dialog/fPropertyRFIDPoint.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/Cs_HMI/SubProject/AGVControl/MapControl.cs b/Cs_HMI/SubProject/AGVControl/MapControl.cs index 6f27ed3..76d0318 100644 --- a/Cs_HMI/SubProject/AGVControl/MapControl.cs +++ b/Cs_HMI/SubProject/AGVControl/MapControl.cs @@ -4,6 +4,7 @@ using System.Drawing; using System.Drawing.Drawing2D; using System.IO; using System.Linq; +using System.Management.Instrumentation; using System.Text.RegularExpressions; using System.Threading; using System.Windows.Forms; @@ -17,23 +18,23 @@ namespace AGVControl public partial class MapControl : Control { #region 상수 정의 - private const int SNAP_DISTANCE = 10; // 점 근접 거리 private const int LINE_WIDTH = 20; // 선 굵기 private const int TOOLBAR_WIDTH = 58; // 툴바 너비 private const int TOOLBAR_WIDTHR = 78; // 우측 툴바 너비 private const int TOOLBAR_BUTTON_HEIGHT = 40; // 툴바 버튼 높이 private const int TOOLBAR_MARGIN = 5; // 툴바 마진 - private const int SELECTION_DISTANCE = 15; // 선택 가능 거리 + private const int SELECTION_DISTANCE_POINT = 7; // 선택 가능 거리 + private const int SELECTION_DISTANCE_TEXT = 3; // 선택 가능 거리 #endregion #region 멤버 변수 // 맵 데이터 private List mapTexts; - private List customLines; + //private List customLines; private List rfidLines; - + public MapControlManager Manager = new MapControlManager(); // 화면 조작 관련 private float zoom = 1.0f; @@ -42,7 +43,6 @@ namespace AGVControl private Point currentMousePosition; private bool isDragging = false; private Point? previewStartPoint = null; - private Point? lineStartPoint = null; private Point? branchPoint = null; // 모드 관련 @@ -69,7 +69,7 @@ namespace AGVControl // RFID 관련 public string RFIDStartNo { get; set; } = string.Empty; public int RFIDLastNumber = 0; - private string filename = string.Empty; + public string Filename = string.Empty; #endregion #region 속성 @@ -84,7 +84,7 @@ namespace AGVControl { this.DoubleBuffered = true; mapTexts = new List(); - customLines = new List(); + // customLines = new List(); rfidLines = new List(); UpdateToolbarRects(); @@ -137,7 +137,7 @@ namespace AGVControl case "cline": MouseMode = (eMouseMode.addcustomline); break; case "point": MouseMode = (eMouseMode.addrfidpoint); break; case "clear": - MapControlManager.agv.MainPath.Clear(); + Manager.agv.MainPath.Clear(); break; case "path": @@ -158,7 +158,7 @@ namespace AGVControl return; } - var rlt = MapControlManager.CalculatePath(vstart, vend); + var rlt = Manager.CalculatePath(vstart, vend); if (rlt.Success == false) { MessageBox.Show(rlt.Message, "경로 계산", MessageBoxButtons.OK, MessageBoxIcon.Warning); @@ -188,16 +188,16 @@ namespace AGVControl od.Filter = "path data|*.route"; od.FilterIndex = 0; od.RestoreDirectory = true; - if (filename.isEmpty() == false) + if (Filename.isEmpty() == false) { - od.FileName = System.IO.Path.GetFileName(filename); - od.InitialDirectory = System.IO.Path.GetDirectoryName(filename); + od.FileName = System.IO.Path.GetFileName(Filename); + od.InitialDirectory = System.IO.Path.GetDirectoryName(Filename); } if (od.ShowDialog() == DialogResult.OK) { - filename = od.FileName; - this.SaveToFile(filename); + Filename = od.FileName; + this.SaveToFile(Filename); this.Invalidate(); } } @@ -209,10 +209,10 @@ namespace AGVControl od.FilterIndex = 0; - if (string.IsNullOrEmpty(this.filename) == false) + if (string.IsNullOrEmpty(this.Filename) == false) { - od.FileName = System.IO.Path.GetFileName(this.filename); - od.InitialDirectory = System.IO.Path.GetDirectoryName(this.filename); + od.FileName = System.IO.Path.GetFileName(this.Filename); + od.InitialDirectory = System.IO.Path.GetDirectoryName(this.Filename); } else { @@ -233,7 +233,7 @@ namespace AGVControl } // RFID 포인트 선택 - var clickedRFID = MapControlManager.RFIDPoints.FirstOrDefault(r => MapControlManager.GetDistance(mapPoint, r.Location) <= SNAP_DISTANCE); + var clickedRFID = Manager.RFIDPoints.FirstOrDefault(r => Manager.GetDistance(mapPoint, r.Location) <= SELECTION_DISTANCE_POINT); switch (mousemode) { case eMouseMode.rfidcut: @@ -279,28 +279,29 @@ namespace AGVControl }; mapTexts.Add(text); selectedText = text; + this.mousemode = eMouseMode.Default; this.Invalidate(); break; - case eMouseMode.addcustomline: - if (previewStartPoint == null) - { - previewStartPoint = mapPoint; - } - else - { - var line = new CustomLine - { - StartPoint = previewStartPoint.Value, - EndPoint = mapPoint, - LineColor = Color.Red, - LineWidth = 2 - }; - customLines.Add(line); - selectedLine = line; - previewStartPoint = null; - this.Invalidate(); - } - break; + //case eMouseMode.addcustomline: + // if (previewStartPoint == null) + // { + // previewStartPoint = mapPoint; + // } + // else + // { + // var line = new CustomLine + // { + // StartPoint = previewStartPoint.Value, + // EndPoint = mapPoint, + // LineColor = Color.Red, + // LineWidth = 2 + // }; + // customLines.Add(line); + // selectedLine = line; + // previewStartPoint = null; + // this.Invalidate(); + // } + // break; case eMouseMode.addrfidline: if (clickedRFID != null) { @@ -310,7 +311,7 @@ namespace AGVControl } else { - var startRFID = MapControlManager.RFIDPoints.FirstOrDefault(r => r.Location == previewStartPoint); + var startRFID = Manager.RFIDPoints.FirstOrDefault(r => r.Location == previewStartPoint); if (startRFID != null) { var line = new RFIDLine @@ -342,16 +343,26 @@ namespace AGVControl var mapPoint = ScreenToMap(e.Location); //RFID 포인트 찾기 - var selected_rfid = MapControlManager.RFIDPoints.Where(t => t.Bounds.Expand(SELECTION_DISTANCE, SELECTION_DISTANCE).Contains(mapPoint)).FirstOrDefault(); + var selected_rfid = Manager.RFIDPoints.Where(t => t.Bounds.Expand(SELECTION_DISTANCE_POINT, SELECTION_DISTANCE_POINT).Contains(mapPoint)).FirstOrDefault(); if (selected_rfid != null) { - UTIL.ShowPropertyDialog(selected_rfid); + //연결정보확인 + List connections = new List(); + var p1 = Manager.rfidConnections.Where(t => t.P1.Value == selected_rfid.Value); + var p2 = Manager.rfidConnections.Where(t => t.P2.Value == selected_rfid.Value); + if (p1.Any()) connections.AddRange(p1.ToArray()); + if (p2.Any()) connections.AddRange(p2.ToArray()); + + + using (var f = new Dialog.fPropertyRFIDPoint(selected_rfid, connections)) + f.ShowDialog(); + //UTIL.ShowPropertyDialog(selected_rfid); this.Invalidate(); return; } - // 텍스트 객체 찾기 - var selected_txt = mapTexts.Where(t => t.Bounds.Expand(SELECTION_DISTANCE, SELECTION_DISTANCE).Contains(mapPoint)).FirstOrDefault(); + // 텍스트 객체 찾기 + var selected_txt = mapTexts.Where(t => t.Bounds.Expand(SELECTION_DISTANCE_TEXT , SELECTION_DISTANCE_TEXT).Contains(mapPoint)).FirstOrDefault(); if (selected_txt != null) { UTIL.ShowPropertyDialog(selected_txt); @@ -404,10 +415,10 @@ namespace AGVControl { var textSize = CreateGraphics().MeasureString(text.Text, text.Font); var rect = new RectangleF( - text.Location.X - SELECTION_DISTANCE, - text.Location.Y - SELECTION_DISTANCE, - textSize.Width + SELECTION_DISTANCE * 2, - textSize.Height + SELECTION_DISTANCE * 2 + text.Location.X - SELECTION_DISTANCE_TEXT, + text.Location.Y - SELECTION_DISTANCE_TEXT, + textSize.Width + SELECTION_DISTANCE_TEXT * 2, + textSize.Height + SELECTION_DISTANCE_TEXT * 2 ); if (rect.Contains(mapPoint)) @@ -423,32 +434,32 @@ namespace AGVControl } } - // 커스텀 라인 선택 및 드래그 포인트 설정 - foreach (var line in customLines) - { - float startDistance = MapControlManager.GetDistance(mapPoint, line.StartPoint); - float endDistance = MapControlManager.GetDistance(mapPoint, line.EndPoint); + //// 커스텀 라인 선택 및 드래그 포인트 설정 + //foreach (var line in customLines) + //{ + // float startDistance = Manager.GetDistance(mapPoint, line.StartPoint); + // float endDistance = Manager.GetDistance(mapPoint, line.EndPoint); - if (startDistance < SELECTION_DISTANCE) - { - selectedLine = line; - draggingPoint = line.StartPoint; - isDraggingPoint = true; - return; - } - else if (endDistance < SELECTION_DISTANCE) - { - selectedLine = line; - draggingPoint = line.EndPoint; - isDraggingPoint = true; - return; - } - } + // if (startDistance < SELECTION_DISTANCE) + // { + // selectedLine = line; + // draggingPoint = line.StartPoint; + // isDraggingPoint = true; + // return; + // } + // else if (endDistance < SELECTION_DISTANCE) + // { + // selectedLine = line; + // draggingPoint = line.EndPoint; + // isDraggingPoint = true; + // return; + // } + //} // RFID 포인트 선택 - var clickedRFID = MapControlManager.RFIDPoints.FirstOrDefault(r => - MapControlManager.GetDistance(mapPoint, r.Location) <= SNAP_DISTANCE); + var clickedRFID = Manager.RFIDPoints.FirstOrDefault(r => + Manager.GetDistance(mapPoint, r.Location) <= SELECTION_DISTANCE_POINT); if (clickedRFID != null) { selectedRFID = clickedRFID; @@ -683,9 +694,9 @@ namespace AGVControl private Point SnapToPoint(Point point) { // RFID 포인트와 근접한지 확인 - foreach (var rfid in MapControlManager.RFIDPoints) + foreach (var rfid in Manager.RFIDPoints) { - if (MapControlManager.GetDistance(point, rfid.Location) <= SNAP_DISTANCE) + if (Manager.GetDistance(point, rfid.Location) <= SELECTION_DISTANCE_POINT) { return rfid.Location; } @@ -703,25 +714,25 @@ namespace AGVControl /// public bool SetCurrentPosition(UInt16 rfidTagNo) { - var rfidPoint = MapControlManager.FindRFIDPoint(rfidTagNo); + var rfidPoint = Manager.FindRFIDPoint(rfidTagNo); if (rfidPoint != null) { // 이동 경로에 추가 (위치 업데이트보다 먼저) - MapControlManager.agv.AddToMovementHistory(rfidTagNo, rfidPoint.Location, MapControlManager.agv.CurrentMOTDirection); + Manager.agv.AddToMovementHistory(rfidTagNo, rfidPoint.Location, Manager.agv.CurrentMOTDirection); // AGV 위치 업데이트 - MapControlManager.agv.CurrentRFID = rfidPoint; + Manager.agv.CurrentRFID = rfidPoint; // 목적지가 설정되어 있고 경로가 있는 경우 검증 - if (MapControlManager.agv.TargetRFID.IsEmpty == false && MapControlManager.agv.MainPath.Count > 0) + if (Manager.agv.TargetRFID.IsEmpty == false && Manager.agv.MainPath.Count > 0) { // 현재 위치가 경로에 있는지 확인 - bool isOnPath = MapControlManager.agv.MainPath.Contains(MapControlManager.agv.CurrentRFID); + bool isOnPath = Manager.agv.MainPath.Contains(Manager.agv.CurrentRFID); if (!isOnPath) { // 경로를 벗어났으므로 새로운 경로 계산 - var pathResult = MapControlManager.CalculatePath(MapControlManager.agv.CurrentRFID, MapControlManager.agv.TargetRFID, false); + var pathResult = Manager.CalculatePath(Manager.agv.CurrentRFID, Manager.agv.TargetRFID); if (pathResult.Success) { SetCurrentPath(pathResult.Path); @@ -730,12 +741,12 @@ namespace AGVControl } // 목적지 RFID에 도착했고, 해당 RFID에 고정방향이 있으면 TargetDirection을 강제 설정 - if (MapControlManager.agv.TargetRFID.Value == rfidTagNo) + if (Manager.agv.TargetRFID.Value == rfidTagNo) { - var destRFID = MapControlManager.FindRFIDPoint(rfidTagNo); + var destRFID = Manager.FindRFIDPoint(rfidTagNo); if (destRFID != null && destRFID.FixedDirection.HasValue) { - MapControlManager.agv.TargetDirection = destRFID.FixedDirection.Value; + Manager.agv.TargetDirection = destRFID.FixedDirection.Value; } } @@ -750,10 +761,10 @@ namespace AGVControl public bool SetTargetPosition(uint rfidValue) { - var rfidPoint = MapControlManager.FindRFIDPoint(rfidValue); + var rfidPoint = Manager.FindRFIDPoint(rfidValue); if (rfidPoint != null) { - MapControlManager.agv.TargetRFID = rfidPoint; + Manager.agv.TargetRFID = rfidPoint; this.Invalidate(); return true; } @@ -762,13 +773,13 @@ namespace AGVControl public void SetRFIDPoints(List points) { - MapControlManager.RFIDPoints = points; + Manager.RFIDPoints = points; this.Invalidate(); } public void SetAGV(AGV vehicle) { - MapControlManager.agv = vehicle; + Manager.agv = vehicle; this.Invalidate(); } @@ -779,12 +790,12 @@ namespace AGVControl this.Invalidate(); } - public void SetCustomLines(List lines) - { - customLines = lines; - if (customLines == null) customLines = new List(); - this.Invalidate(); - } + //public void SetCustomLines(List lines) + //{ + // customLines = lines; + // if (customLines == null) customLines = new List(); + // this.Invalidate(); + //} public void SetIsAddingText(bool value) { @@ -899,7 +910,7 @@ namespace AGVControl public void SetCurrentPath(List path) { - MapControlManager.agv.MainPath = path; + Manager.agv.MainPath = path; this.Invalidate(); } @@ -960,23 +971,26 @@ namespace AGVControl DrawToolbarButton(e.Graphics, item.Bounds, item.Title, item.isHovering); //예측값디스플레잉(임시) - var predictresult = MapControlManager.PredictResult; + var predictresult = Manager.PredictResult; if (predictresult != null) { var nextRFID = predictresult.NextRFID?.Value.ToString() ?? ""; - var str = $"{predictresult.ReasonCode}|{predictresult.MoveState}|{predictresult.Direction}|Next:{nextRFID}"; + var nextSPD = predictresult.MoveSpeed?.ToString() ?? string.Empty; + var nextDIV = predictresult.MoveDiv?.ToString() ?? string.Empty; + var str = $"{predictresult.ReasonCode}|{predictresult.MoveState}|{predictresult.Direction}|Next:{nextRFID}|SPD:{nextSPD}|DIV:{nextDIV}"; var strsize = e.Graphics.MeasureString(str, this.Font); var textcolor = Color.Red; if (predictresult.MoveState == AGVMoveState.Stop) textcolor = Color.Gold; + using (var sb = new SolidBrush(textcolor)) e.Graphics.DrawString(str, this.Font, sb, this.Right - strsize.Width - 10, this.Bottom - strsize.Height - 10); } //경로정보표시(임시) var pathstr = ""; - if (MapControlManager.agv.MainPath.Any()) + if (Manager.agv.MainPath.Any()) { - pathstr = "● Path : " + string.Join("▶", MapControlManager.agv.MainPath.Select(t => t.Value).ToArray()); + pathstr = "● Path : " + string.Join("▶", Manager.agv.MainPath.Select(t => t.Value).ToArray()); //pathstr += "\n● Target Direction Match : " + (agv.IsTargetDirectionMatch ? "O" : "X"); } else pathstr = "● Path : no data"; @@ -984,11 +998,11 @@ namespace AGVControl e.Graphics.DrawString(pathstr, f, Brushes.DeepSkyBlue, this.Left + 65, this.Top + 10); var histstr = ""; - if (MapControlManager.agv.MovementHistory.Count > 1) + if (Manager.agv.MovementHistory.Count > 1) { - histstr = "● Route : " + string.Join("▶", MapControlManager.agv.MovementHistory.Select(t => t.Value.ToString() + $"[{t.Direction.ToString()[0]}]").ToArray()); + histstr = "● History : " + string.Join("▶", Manager.agv.MovementHistory.Select(t => t.Value.ToString() + $"[{t.Direction.ToString()[0]}]").ToArray()); } - else histstr = "● Route : no data"; + else histstr = "● History : no data"; using (var f = new Font("Arial", 10, FontStyle.Bold)) e.Graphics.DrawString(histstr, f, Brushes.DeepSkyBlue, this.Left + 65, this.Top + 30); @@ -997,7 +1011,7 @@ namespace AGVControl private void DrawRFIDPoints(Graphics g) { // RFID 포인트 그리기 - foreach (var rfid in MapControlManager.RFIDPoints) + foreach (var rfid in Manager.RFIDPoints) { var MarkerSize = 5; var half = MarkerSize / 2f; @@ -1070,16 +1084,16 @@ namespace AGVControl // AGV의 현재 위치를 중심으로 하는 원 var circleRect = new Rectangle( - MapControlManager.agv.CurrentRFID.Location.X - halfsize, - MapControlManager.agv.CurrentRFID.Location.Y - halfsize, + Manager.agv.CurrentRFID.Location.X - halfsize, + Manager.agv.CurrentRFID.Location.Y - halfsize, agvsize, agvsize); //이동경로정보를 따라서 리프트의 위치를 표시해준다. - if (MapControlManager.agv.MovementHistory.Any() && MapControlManager.agv.MovementHistory.Count > 1) + if (Manager.agv.MovementHistory.Any() && Manager.agv.MovementHistory.Count > 1) { - var prept = MapControlManager.agv.MovementHistory.Skip(MapControlManager.agv.MovementHistory.Count - 2).First(); - var lstpt = MapControlManager.agv.MovementHistory.Last(); + var prept = Manager.agv.MovementHistory.Skip(Manager.agv.MovementHistory.Count - 2).First(); + var lstpt = Manager.agv.MovementHistory.Last(); RFIDPoint TargetPT = null; @@ -1091,7 +1105,7 @@ namespace AGVControl else //앞으로이동한다면 이동방향과 동일하다 { //이전위치는 제거 하고 처음발견된 것을 대상으로 한다 - TargetPT = MapControlManager.GetNeighbors(lstpt).Where(t => t.Value != prept.Value).FirstOrDefault(); + TargetPT = Manager.GetNeighbors(lstpt).Where(t => t.Value != prept.Value).FirstOrDefault(); } if (TargetPT != null) @@ -1103,7 +1117,7 @@ namespace AGVControl var liftRect = new RectangleF(pt.X - circleRadius, pt.Y - circleRadius, circleRadius * 2, circleRadius * 2); g.FillEllipse(Brushes.Black, liftRect); - var liftColor = MapControlManager.agv.IsTargetDirectionMatch ? Color.White : Color.HotPink; + var liftColor = Manager.agv.IsTargetDirectionMatch ? Color.White : Color.HotPink; using (var pBorder = new Pen(liftColor, 3)) g.DrawEllipse(pBorder, liftRect); } @@ -1113,14 +1127,14 @@ namespace AGVControl // --- BodyAngle이 결정되지 않은 경우: 기본 방향으로 그림 --- - Color bgcolor = MapControlManager.agv.BatteryLevel > 80 ? Color.Lime : (MapControlManager.agv.BatteryLevel > 60 ? Color.Gold : Color.Tomato); + Color bgcolor = Manager.agv.BatteryLevel > 80 ? Color.Lime : (Manager.agv.BatteryLevel > 60 ? Color.Gold : Color.Tomato); using (var circleBrush = new SolidBrush(Color.FromArgb(150, bgcolor))) g.FillEllipse(circleBrush, circleRect); using (var circlePen = new Pen(Color.Black, 4)) g.DrawEllipse(circlePen, circleRect); //motor direction - var str = MapControlManager.agv.CurrentMOTDirection.ToString().Substring(0, 1); + var str = Manager.agv.CurrentMOTDirection.ToString().Substring(0, 1); var strsize = g.MeasureString(str, this.Font); g.DrawString(str, this.Font, Brushes.White, circleRect, new StringFormat { @@ -1128,12 +1142,6 @@ namespace AGVControl LineAlignment = StringAlignment.Center }); - //body direction - str = MapControlManager.agv.IsTargetDirectionMatch ? "O" : "X";// .CurrentAGVDirection.ToString().Substring(0, 1).ToUpper(); - strsize = g.MeasureString(str, this.Font); - g.DrawString(str, this.Font, Brushes.Gold, circleRect.X + (circleRect.Width / 2f) - (strsize.Width / 2f), circleRect.Bottom + 3); - - // 과거 이동 경로 화살표 그리기 //DrawMovementHistoryArrows(g); @@ -1161,24 +1169,24 @@ namespace AGVControl // 과거 이동 경로를 화살표로 표시 private void DrawMovementHistoryArrows(Graphics g) { - if (MapControlManager.agv.MovementHistory.Count < 2) + if (Manager.agv.MovementHistory.Count < 2) return; // 최근 3개의 이동 경로 표시 (가장 오래된 것부터) - int startIndex = Math.Max(0, MapControlManager.agv.MovementHistory.Count - 3); + int startIndex = Math.Max(0, Manager.agv.MovementHistory.Count - 3); - for (int i = startIndex; i < MapControlManager.agv.MovementHistory.Count - 1; i++) + for (int i = startIndex; i < Manager.agv.MovementHistory.Count - 1; i++) { - var startRFID = MapControlManager.agv.MovementHistory[i]; - var endRFID = MapControlManager.agv.MovementHistory[i + 1]; + var startRFID = Manager.agv.MovementHistory[i]; + var endRFID = Manager.agv.MovementHistory[i + 1]; //var startPos = agv.PositionHistory[i]; //var endPos = agv.PositionHistory[i + 1]; // 시간에 따른 투명도 계산 - int age = MapControlManager.agv.MovementHistory.Count - 1 - i; + int age = Manager.agv.MovementHistory.Count - 1 - i; int alpha = Math.Max(50, 255 - (age * 50)); - var directConnection = MapControlManager.rfidConnections.FirstOrDefault(c => + var directConnection = Manager.rfidConnections.FirstOrDefault(c => (c.P1.Value == startRFID.Value && c.P2.Value == endRFID.Value) || (c.P1.Value == endRFID.Value && c.P2.Value == startRFID.Value)); @@ -1192,16 +1200,16 @@ namespace AGVControl else { // 직접 연결되지 않은 경우: 경로 탐색 후 점선 화살표 체인 - var pathResult = MapControlManager.CalculatePath(startRFID, endRFID, false); + var pathResult = Manager.CalculatePath(startRFID, endRFID); if (pathResult.Success && pathResult.Path != null && pathResult.Path.Count > 1) { // 경로의 첫 단계 방향으로 전체 색상 결정 Color arrowColor = Color.Gray; var firstStepEndPoint = pathResult.Path[1]; - var firstStepEndRfidPoint = MapControlManager.RFIDPoints.FirstOrDefault(p => p.Location == firstStepEndPoint.Location); + var firstStepEndRfidPoint = Manager.RFIDPoints.FirstOrDefault(p => p.Location == firstStepEndPoint.Location); if (firstStepEndRfidPoint != null) { - var firstStepConnection = MapControlManager.rfidConnections.FirstOrDefault(c => + var firstStepConnection = Manager.rfidConnections.FirstOrDefault(c => (c.P1.Value == startRFID.Value && c.P2.Value == firstStepEndRfidPoint.Value) || (c.P1.Value == firstStepEndRfidPoint.Value && c.P2.Value == startRFID.Value)); @@ -1263,7 +1271,7 @@ namespace AGVControl } // 실선 화살표 그리기 헬퍼 메서드 - private void DrawArrow(Graphics g, Point start, Point end, Color color, int width) + private void DrawArrow(Graphics g, Point start, Point end, Color color, int width, int arrowSize = 8) { using (var pen = new Pen(color, width)) { @@ -1271,7 +1279,7 @@ namespace AGVControl g.DrawLine(pen, start, end); // 화살표 머리 그리기 - var arrowSize = 8; + //var arrowSize = 8; var angle = Math.Atan2(end.Y - start.Y, end.X - start.X); var arrowAngle = Math.PI / 6; // 30도 @@ -1349,6 +1357,13 @@ namespace AGVControl } } + public void ShowDesign() + { + using (var f = new Dialog.fMapDesign(this.Filename)) + if (f.ShowDialog() == DialogResult.OK) + this.LoadFromFile(this.Filename, out string ermsg); + } + private void DrawRFIDLines(Graphics g) { var idx = 0; @@ -1375,20 +1390,142 @@ namespace AGVControl //연결정보에서 그림을 그린다. var didx = 0; - foreach (var connection in MapControlManager.rfidConnections) + foreach (var connection in Manager.rfidConnections) { didx += 1; - var startPoint = MapControlManager.RFIDPoints.FirstOrDefault(p => p.Value == connection.P1.Value)?.Location ?? Point.Empty; - var endPoint = MapControlManager.RFIDPoints.FirstOrDefault(p => p.Value == connection.P2.Value)?.Location ?? Point.Empty; + var SP = Manager.RFIDPoints.FirstOrDefault(p => p.Value == connection.P1.Value)?.Location ?? Point.Empty; + var EP = Manager.RFIDPoints.FirstOrDefault(p => p.Value == connection.P2.Value)?.Location ?? Point.Empty; - if (startPoint.IsEmpty || endPoint.IsEmpty) continue; + if (SP.IsEmpty || EP.IsEmpty) continue; //var lcolor = didx % 2 == 0 ? Color.White : Color.LightSkyBlue; - using (Pen linePen = new Pen(Color.FromArgb(30, Color.White), 10)) + var lineColorP = connection.EnableP ? Color.White : Color.Red; + var lineColorN = connection.EnableN ? Color.White : Color.Red; + + var boundBoxP = new Rectangle(SP.X + 1, SP.Y - 6, EP.X - SP.X - 2, 10); + var boundBoxN = new Rectangle(SP.X + 1, SP.Y + 6, EP.X - SP.X - 2, 10); + + var RotatePts = GetRotatedRectangle(SP, EP, 6); + var RotatePtsP = GetRotatedRectangle(RotatePts[0], RotatePts[1], 4); + var RotatePtsN = GetRotatedRectangle(RotatePts[2], RotatePts[3], 4); + var RectP = this.GetRotatedRectanglePath(RotatePtsP); + var RectN = this.GetRotatedRectanglePath(RotatePtsN); + + //foreach (var item in RotatePts) + //{ + // var ballsize = 1f; + // var r = new Rectangle((int)(item.X - ballsize), (int)(item.Y - ballsize), (int)(ballsize * 2), (int)(ballsize * 2)); + // g.FillEllipse(Brushes.WhiteSmoke, r); + //} + + using(var p = new Pen(Color.FromArgb(130,Color.Red),1)) + g.DrawPath(p, RectP); + using (var p = new Pen(Color.FromArgb(130, Color.Blue), 1)) + g.DrawPath(p, RectN); + + using (Pen linePen = new Pen(Color.FromArgb(30, lineColorP), 1)) { - g.DrawLine(linePen, startPoint, endPoint); - g.DrawLine(Pens.SlateGray, startPoint, endPoint); + var DriveMethod = ""; + var nulChar = "■"; + if (connection.MoveDirectionP != null) + { + // if (DriveMethod.isEmpty() == false) DriveMethod += "|"; + DriveMethod += ((AgvRunDirection)connection.MoveDirectionP).ToString()[0]; + } + else DriveMethod += nulChar; + if (connection.MoveSpeedP != null) + { + // if (DriveMethod.isEmpty() == false) DriveMethod += "|"; + DriveMethod += ((AgvSpeed)connection.MoveSpeedP).ToString()[0]; + } + else DriveMethod += nulChar; + if (connection.LiftDirectionP != null) + { + //if (DriveMethod.isEmpty() == false) DriveMethod += "|"; + DriveMethod += ((AgvRunDirection)connection.LiftDirectionP).ToString()[0]; + } + else DriveMethod += nulChar; + + //g.DrawLine(linePen, SP, EP); + //g.DrawLine(Pens.SlateGray, SP, EP); + //g.DrawRectangle(linePen, boundBoxP); + + if (connection.EnableP == false) + { + g.DrawLine(linePen, boundBoxP.Left, boundBoxP.Top, boundBoxP.Right, boundBoxP.Bottom); + g.DrawLine(linePen, boundBoxP.Right, boundBoxP.Top, boundBoxP.Left, boundBoxP.Bottom); + } + else + { + //DrawArrow(g, + //new Point(boundBoxP.X, (int)(boundBoxP.Y + boundBoxP.Height / 2f)), + //new Point(boundBoxP.Right, (int)(boundBoxP.Y + boundBoxP.Height / 2f)), + //lineColorP, 1); + } + + if (DriveMethod.isEmpty() == false && DriveMethod.Equals($"{nulChar}{nulChar}{nulChar}") == false) + using (Font f = new Font("Consolas", 5, FontStyle.Bold)) + g.DrawString(DriveMethod, f, Brushes.Gold, boundBoxP, new StringFormat + { + Alignment = StringAlignment.Center, + LineAlignment = StringAlignment.Center, + }); + } + + + using (Pen linePen = new Pen(Color.FromArgb(30, lineColorN), 1)) + { + + var DriveMethod = ""; + var nulChar = "■"; + if (connection.MoveDirectionN != null) + { + //if (DriveMethod.isEmpty() == false) DriveMethod += "|"; + DriveMethod += ((AgvRunDirection)connection.MoveDirectionN).ToString()[0]; + } + else DriveMethod += nulChar; + if (connection.MoveSpeedN != null) + { + //if (DriveMethod.isEmpty() == false) DriveMethod += "|"; + DriveMethod += ((AgvSpeed)connection.MoveSpeedN).ToString()[0]; + } + else DriveMethod += nulChar; + if (connection.LiftDirectionN != null) + { + //if (DriveMethod.isEmpty() == false) DriveMethod += "|"; + DriveMethod += ((AgvRunDirection)connection.LiftDirectionN).ToString()[0]; + } + else DriveMethod += nulChar; + + + //g.DrawLine(linePen, SP, EP); + //g.DrawLine(Pens.SlateGray, SP, EP); + //g.DrawRectangle(linePen, boundBoxN); + if (connection.EnableP == false) + { + g.DrawLine(linePen, boundBoxN.Left, boundBoxN.Top, boundBoxN.Right, boundBoxN.Bottom); + g.DrawLine(linePen, boundBoxN.Right, boundBoxN.Top, boundBoxN.Left, boundBoxN.Bottom); + } + else + { + // DrawArrow(g, + //new Point(boundBoxN.Right, (int)(boundBoxN.Y + boundBoxN.Height / 2f)), + //new Point(boundBoxN.X, (int)(boundBoxN.Y + boundBoxN.Height / 2f)), + //lineColorN, 1); + } + + if (DriveMethod.isEmpty() == false && DriveMethod.Equals($"{nulChar}{nulChar}{nulChar}") == false) + using (Font f = new Font("Consolas", 5, FontStyle.Bold)) + g.DrawString(DriveMethod, f, Brushes.Gold, boundBoxN, new StringFormat + { + Alignment = StringAlignment.Center, + LineAlignment = StringAlignment.Center, + }); + + } + + //g.DrawLine(Pens.SlateGray, SP, EP); } // 미리보기 라인 그리기 @@ -1405,25 +1542,42 @@ namespace AGVControl private void DrawPath(Graphics g) { - if (MapControlManager.agv.MainPath == null || MapControlManager.agv.MainPath.Count < 2) + if (Manager.agv.MainPath == null || Manager.agv.MainPath.Count < 2) return; - Color pathColor = Color.FromArgb(100, Color.Lime); + Color pathColor = Color.FromArgb(150, Color.White); + if (Manager.agv.SubPath != null && Manager.agv.SubPath.Any()) + pathColor = Color.FromArgb(70, Color.LightGray); int pathWidth = 10; using (Pen pathPen = new Pen(pathColor, pathWidth)) { pathPen.DashStyle = System.Drawing.Drawing2D.DashStyle.Dash; - for (int i = 0; i < MapControlManager.agv.MainPath.Count - 1; i++) + for (int i = 0; i < Manager.agv.MainPath.Count - 1; i++) { - g.DrawLine(pathPen, MapControlManager.agv.MainPath[i].Location, MapControlManager.agv.MainPath[i + 1].Location); + g.DrawLine(pathPen, Manager.agv.MainPath[i].Location, Manager.agv.MainPath[i + 1].Location); + } + } + + if (Manager.agv.SubPath == null || Manager.agv.SubPath.Count < 2) + return; + + pathColor = Color.FromArgb(150, Color.DeepSkyBlue); + pathWidth = 10; + + using (Pen pathPen = new Pen(pathColor, pathWidth)) + { + pathPen.DashStyle = System.Drawing.Drawing2D.DashStyle.Dash; + for (int i = 0; i < Manager.agv.SubPath.Count - 1; i++) + { + g.DrawLine(pathPen, Manager.agv.SubPath[i].Location, Manager.agv.SubPath[i + 1].Location); } } } public List GetRFIDPoints() { - return MapControlManager.RFIDPoints; + return Manager.RFIDPoints; } public List GetRFIDLines() @@ -1437,55 +1591,67 @@ namespace AGVControl this.Invalidate(); } - public void AddRFIDLine(Point startPoint, Point endPoint) + public void AddRFIDConnection(RFIDConnection item) { - // 시작점과 끝점 사이의 모든 RFID 포인트 찾기 - var allPoints = new List<(RFIDPoint Point, float Distance)>(); - var lineVector = new Point(endPoint.X - startPoint.X, endPoint.Y - startPoint.Y); - var lineLength = (float)Math.Sqrt(lineVector.X * lineVector.X + lineVector.Y * lineVector.Y); + //item 의 rfid를 찾아서 연결해야함 + item.P1 = Manager.RFIDPoints.Where(t => t.Value == item.P1.Value).FirstOrDefault(); + item.P2 = Manager.RFIDPoints.Where(t => t.Value == item.P2.Value).FirstOrDefault(); - foreach (var rfid in MapControlManager.RFIDPoints) - { - if (rfid.Location == startPoint || rfid.Location == endPoint) - continue; - - // RFID 포인트가 선 위에 있는지 확인 - var pointVector = new Point(rfid.Location.X - startPoint.X, rfid.Location.Y - startPoint.Y); - var dotProduct = pointVector.X * lineVector.X + pointVector.Y * lineVector.Y; - var projectionLength = dotProduct / (lineLength * lineLength); - - if (projectionLength >= 0 && projectionLength <= 1) - { - // 선과 RFID 포인트 사이의 거리 계산 - var distance = GetDistanceToLine(rfid.Location, startPoint, endPoint); - if (distance <= SNAP_DISTANCE) - { - allPoints.Add((rfid, projectionLength)); - } - } - } - - // 시작점에서 끝점 방향으로 정렬 - allPoints.Sort((a, b) => a.Distance.CompareTo(b.Distance)); - - // 모든 연결 정보를 포함하는 RFID 라인 생성 - var line = new RFIDLine - { - StartPoint = startPoint, - EndPoint = endPoint, - }; - - - rfidLines.Add(line); + Manager.rfidConnections.Add(item); this.Invalidate(); } + + //public void AddRFIDLine(Point startPoint, Point endPoint) + //{ + // // 시작점과 끝점 사이의 모든 RFID 포인트 찾기 + // var allPoints = new List<(RFIDPoint Point, float Distance)>(); + // var lineVector = new Point(endPoint.X - startPoint.X, endPoint.Y - startPoint.Y); + // var lineLength = (float)Math.Sqrt(lineVector.X * lineVector.X + lineVector.Y * lineVector.Y); + + // foreach (var rfid in Manager.RFIDPoints) + // { + // if (rfid.Location == startPoint || rfid.Location == endPoint) + // continue; + + // // RFID 포인트가 선 위에 있는지 확인 + // var pointVector = new Point(rfid.Location.X - startPoint.X, rfid.Location.Y - startPoint.Y); + // var dotProduct = pointVector.X * lineVector.X + pointVector.Y * lineVector.Y; + // var projectionLength = dotProduct / (lineLength * lineLength); + + // if (projectionLength >= 0 && projectionLength <= 1) + // { + // // 선과 RFID 포인트 사이의 거리 계산 + // var distance = GetDistanceToLine(rfid.Location, startPoint, endPoint); + // if (distance <= SNAP_DISTANCE) + // { + // allPoints.Add((rfid, projectionLength)); + // } + // } + // } + + // // 시작점에서 끝점 방향으로 정렬 + // allPoints.Sort((a, b) => a.Distance.CompareTo(b.Distance)); + + // // 모든 연결 정보를 포함하는 RFID 라인 생성 + // var line = new RFIDLine + // { + // StartPoint = startPoint, + // EndPoint = endPoint, + // }; + + + // rfidLines.Add(line); + // this.Invalidate(); + //} + public void ClearMap() { - MapControlManager.RFIDPoints.Clear(); + Manager.RFIDPoints.Clear(); + Manager.rfidConnections.Clear(); mapTexts.Clear(); - customLines.Clear(); + // customLines.Clear(); rfidLines.Clear(); // 선택 상태도 초기화 @@ -1510,7 +1676,7 @@ namespace AGVControl Value = rfidValue }; - MapControlManager.RFIDPoints.Add(rfidPoint); + Manager.RFIDPoints.Add(rfidPoint); this.Invalidate(); } @@ -1520,19 +1686,26 @@ namespace AGVControl // RFID 포인트 저장 lines.Add("[RFID_POINTS]"); - foreach (var point in MapControlManager.RFIDPoints) + foreach (var point in Manager.RFIDPoints) { lines.Add($"{point.Location.X},{point.Location.Y},{point.Value},{point.IsRotatable},{point.FixedDirection},{point.IsTerminal}"); } - // RFID 라인 저장 - lines.Add("[RFID_LINES]"); - foreach (var connection in MapControlManager.rfidConnections) + //// RFID 라인 저장 + //lines.Add("[RFID_LINES]"); + //foreach (var connection in Manager.rfidConnections) + //{ + // var startPoint = Manager.RFIDPoints.First(p => p.Value == connection.P1.Value).Location; + // var endPoint = Manager.RFIDPoints.First(p => p.Value == connection.P2.Value).Location; + // lines.Add($"{startPoint.X},{startPoint.Y},{endPoint.X},{endPoint.Y}," + + // $"{connection.P1},{connection.P2},false,false,0"); + //} + + // RFID 연결 정보 + lines.Add("[RFID_CONNECTION]"); + foreach (var connection in Manager.rfidConnections) { - var startPoint = MapControlManager.RFIDPoints.First(p => p.Value == connection.P1.Value).Location; - var endPoint = MapControlManager.RFIDPoints.First(p => p.Value == connection.P2.Value).Location; - lines.Add($"{startPoint.X},{startPoint.Y},{endPoint.X},{endPoint.Y}," + - $"{connection.P1},{connection.P2},{connection.DisableP1_to_P2}{connection.DisableP2_to_P1},{connection.Distance}"); + lines.Add(connection.DataFileString); } // 텍스트 저장 @@ -1542,20 +1715,21 @@ namespace AGVControl lines.Add($"{text.Location.X},{text.Location.Y},{text.TextColor.ToArgb()},{text.BackgroundColor.ToArgb()},{text.Font.Name},{text.Font.Size},{text.Text}"); } - // 커스텀 라인 저장 - lines.Add("[CUSTOM_LINES]"); - foreach (var line in customLines) - { - lines.Add($"{line.StartPoint.X},{line.StartPoint.Y},{line.EndPoint.X},{line.EndPoint.Y},{line.LineColor.ToArgb()},{line.LineWidth}"); - } + //// 커스텀 라인 저장 + //lines.Add("[CUSTOM_LINES]"); + //foreach (var line in customLines) + //{ + // lines.Add($"{line.StartPoint.X},{line.StartPoint.Y},{line.EndPoint.X},{line.EndPoint.Y},{line.LineColor.ToArgb()},{line.LineWidth}"); + //} + File.WriteAllLines(filename, lines); - this.filename = filename; + this.Filename = filename; } public bool LoadFromFile(string filename, out string message) { - this.filename = filename; + this.Filename = filename; message = string.Empty; ClearMap(); @@ -1584,7 +1758,7 @@ namespace AGVControl if (validX && validY && validN) { - if (MapControlManager.RFIDPoints.Where(t => t.Value == valRfid).Any()) + if (Manager.RFIDPoints.Where(t => t.Value == valRfid).Any()) { //이미존재한다 var newvalue = @@ -1613,23 +1787,28 @@ namespace AGVControl rfidPoint.IsTerminal = isTerminal; } - MapControlManager.RFIDPoints.Add(rfidPoint); + Manager.RFIDPoints.Add(rfidPoint); } else sb.AppendLine($"[{section}] {line}"); } break; - case "[RFID_LINES]": - var rfidLineParts = line.Split(','); - if (rfidLineParts.Length >= 8) - { - AddRFIDLine( - new Point(int.Parse(rfidLineParts[0]), int.Parse(rfidLineParts[1])), - new Point(int.Parse(rfidLineParts[2]), int.Parse(rfidLineParts[3])) - ); - } + case "[RFID_CONNECTION]": + AddRFIDConnection(new RFIDConnection(line)); break; + + //case "[RFID_LINES]": + // var rfidLineParts = line.Split(','); + // if (rfidLineParts.Length >= 8) + // { + // AddRFIDLine( + // new Point(int.Parse(rfidLineParts[0]), int.Parse(rfidLineParts[1])), + // new Point(int.Parse(rfidLineParts[2]), int.Parse(rfidLineParts[3])) + // ); + // } + // break; + case "[MAP_TEXTS]": var textParts = line.Split(','); if (textParts.Length >= 7) @@ -1646,20 +1825,20 @@ namespace AGVControl } break; - case "[CUSTOM_LINES]": - var customLineParts = line.Split(','); - if (customLineParts.Length >= 6) - { - var customLine = new CustomLine - { - StartPoint = new Point(int.Parse(customLineParts[0]), int.Parse(customLineParts[1])), - EndPoint = new Point(int.Parse(customLineParts[2]), int.Parse(customLineParts[3])), - LineColor = Color.FromArgb(int.Parse(customLineParts[4])), - LineWidth = int.Parse(customLineParts[5]) - }; - customLines.Add(customLine); - } - break; + //case "[CUSTOM_LINES]": + // var customLineParts = line.Split(','); + // if (customLineParts.Length >= 6) + // { + // var customLine = new CustomLine + // { + // StartPoint = new Point(int.Parse(customLineParts[0]), int.Parse(customLineParts[1])), + // EndPoint = new Point(int.Parse(customLineParts[2]), int.Parse(customLineParts[3])), + // LineColor = Color.FromArgb(int.Parse(customLineParts[4])), + // LineWidth = int.Parse(customLineParts[5]) + // }; + // customLines.Add(customLine); + // } + // break; } } @@ -1674,7 +1853,8 @@ namespace AGVControl private void ProcessRFIDConnections() { - MapControlManager.rfidConnections.Clear(); + return; + Manager.rfidConnections.Clear(); var connectionSet = new HashSet(); foreach (var line in rfidLines) @@ -1683,7 +1863,7 @@ namespace AGVControl var end = line.EndPoint; // 1. 선 위의 모든 RFID 포인트(시작, 끝 포함)를 projectionRatio로 정렬 - var pointsOnThisLine = MapControlManager.RFIDPoints + var pointsOnThisLine = Manager.RFIDPoints .Where(p => IsPointOnLine(p.Location, start, end, 10f)) // 오차 허용치 넉넉히 .Select(p => new { @@ -1709,16 +1889,15 @@ namespace AGVControl var key = $"{Math.Min(from, to)}_{Math.Max(from, to)}"; if (connectionSet.Contains(key)) continue; - var fromItem = MapControlManager.RFIDPoints.FirstOrDefault(p => p.Value == from); - var toItem = MapControlManager.RFIDPoints.FirstOrDefault(p => p.Value == to); + var fromItem = Manager.RFIDPoints.FirstOrDefault(p => p.Value == from); + var toItem = Manager.RFIDPoints.FirstOrDefault(p => p.Value == to); var fromPt = fromItem?.Location ?? line.StartPoint; var toPt = toItem?.Location ?? line.EndPoint; - MapControlManager.rfidConnections.Add(new RFIDConnection + Manager.rfidConnections.Add(new RFIDConnection { P1 = fromItem, P2 = toItem, - Distance = MapControlManager.GetDistance(fromPt, toPt) }); connectionSet.Add(key); } @@ -1804,7 +1983,7 @@ namespace AGVControl private void DrawTargetFlag(Graphics g) { //대상이없다면 진행하지 않습니다 - if (MapControlManager.agv.TargetRFID.IsEmpty) return; + if (Manager.agv.TargetRFID.IsEmpty) return; // 바닥에 흰색 원 그리기 using (var baseBrush = new SolidBrush(Color.Red)) @@ -1812,12 +1991,12 @@ namespace AGVControl { var baseSize = 8; g.FillEllipse(baseBrush, - MapControlManager.agv.TargetRFID.Location.X - baseSize / 2, - MapControlManager.agv.TargetRFID.Location.Y - baseSize / 2, + Manager.agv.TargetRFID.Location.X - baseSize / 2, + Manager.agv.TargetRFID.Location.Y - baseSize / 2, baseSize, baseSize); g.DrawEllipse(basePen, - MapControlManager.agv.TargetRFID.Location.X - baseSize / 2, - MapControlManager.agv.TargetRFID.Location.Y - baseSize / 2, + Manager.agv.TargetRFID.Location.X - baseSize / 2, + Manager.agv.TargetRFID.Location.Y - baseSize / 2, baseSize, baseSize); } @@ -1826,17 +2005,17 @@ namespace AGVControl { var poleLength = 27; // 40 * 2/3 ≈ 27 g.DrawLine(polePen, - MapControlManager.agv.TargetRFID.Location.X, - MapControlManager.agv.TargetRFID.Location.Y, - MapControlManager.agv.TargetRFID.Location.X, - MapControlManager.agv.TargetRFID.Location.Y - poleLength); + Manager.agv.TargetRFID.Location.X, + Manager.agv.TargetRFID.Location.Y, + Manager.agv.TargetRFID.Location.X, + Manager.agv.TargetRFID.Location.Y - poleLength); } // 깃발 그리기 Point[] flagPoints = new Point[3]; - flagPoints[0] = new Point(MapControlManager.agv.TargetRFID.Location.X, MapControlManager.agv.TargetRFID.Location.Y - 27); // 깃대 길이에 맞춤 - flagPoints[1] = new Point(MapControlManager.agv.TargetRFID.Location.X + 20, MapControlManager.agv.TargetRFID.Location.Y - 22); - flagPoints[2] = new Point(MapControlManager.agv.TargetRFID.Location.X, MapControlManager.agv.TargetRFID.Location.Y - 17); + flagPoints[0] = new Point(Manager.agv.TargetRFID.Location.X, Manager.agv.TargetRFID.Location.Y - 27); // 깃대 길이에 맞춤 + flagPoints[1] = new Point(Manager.agv.TargetRFID.Location.X + 20, Manager.agv.TargetRFID.Location.Y - 22); + flagPoints[2] = new Point(Manager.agv.TargetRFID.Location.X, Manager.agv.TargetRFID.Location.Y - 17); using (var flagBrush = new SolidBrush(Color.Red)) using (var flagPen = new Pen(Color.DarkRed, 1)) @@ -1852,6 +2031,100 @@ namespace AGVControl #endregion + + #region Rotate Rectangle Helper + + + public System.Drawing.Drawing2D.GraphicsPath GetRotatedRectanglePath(PointF[] pts) + { + var p = new GraphicsPath(); + p.AddLine(pts[0], pts[1]); + p.AddLine(pts[1], pts[2]); + p.AddLine(pts[2], pts[3]); + p.AddLine(pts[0], pts[3]); + return p; + } + + /// + /// 두 점을 연결하는 선분을 중심으로 하는 회전된 사각형의 네 꼭지점을 구합니다. + /// + /// 첫 번째 점 + /// 두 번째 점 + /// 사각형의 세로 길이 (기본값: 5) + /// 사각형의 네 꼭지점 배열 (시계방향 순서) + public PointF[] GetRotatedRectangle(PointF point1, PointF point2, float height = 5f) + { + // 두 점 사이의 거리 (가로 길이) + float width = (float)Math.Sqrt(Math.Pow(point2.X - point1.X, 2) + Math.Pow(point2.Y - point1.Y, 2)); + + // 두 점을 연결하는 선분의 각도 (라디안) + float angle = (float)Math.Atan2(point2.Y - point1.Y, point2.X - point1.X); + + // 선분의 중점 + PointF center = new PointF((point1.X + point2.X) / 2f, (point1.Y + point2.Y) / 2f); + + // 사각형의 반 크기 + float halfWidth = width / 2f; + float halfHeight = height / 2f; + + // 회전하지 않은 상태의 사각형 꼭지점들 (중점 기준) + PointF[] localPoints = new PointF[] + { + new PointF(-halfWidth, -halfHeight), // 좌상단 + new PointF(halfWidth, -halfHeight), // 우상단 + new PointF(halfWidth, halfHeight), // 우하단 + new PointF(-halfWidth, halfHeight) // 좌하단 + }; + + // 회전 변환 적용 + PointF[] rotatedPoints = new PointF[4]; + float cos = (float)Math.Cos(angle); + float sin = (float)Math.Sin(angle); + + for (int i = 0; i < 4; i++) + { + // 회전 변환 공식 적용 + float rotatedX = localPoints[i].X * cos - localPoints[i].Y * sin; + float rotatedY = localPoints[i].X * sin + localPoints[i].Y * cos; + + // 중점으로 이동 + rotatedPoints[i] = new PointF(center.X + rotatedX, center.Y + rotatedY); + } + + return rotatedPoints; + } + + /// + /// 오버로드: 개별 좌표값으로 입력받는 버전 + /// + public PointF[] GetRotatedRectangle(float x1, float y1, float x2, float y2, float height = 5f) + { + return GetRotatedRectangle(new PointF(x1, y1), new PointF(x2, y2), height); + } + + /// + /// 회전된 사각형의 경계 사각형(Bounding Rectangle)을 구합니다. + /// + public static RectangleF GetBoundingRectangle(PointF[] rotatedPoints) + { + float minX = float.MaxValue; + float minY = float.MaxValue; + float maxX = float.MinValue; + float maxY = float.MinValue; + + foreach (var point in rotatedPoints) + { + minX = Math.Min(minX, point.X); + minY = Math.Min(minY, point.Y); + maxX = Math.Max(maxX, point.X); + maxY = Math.Max(maxY, point.Y); + } + + return new RectangleF(minX, minY, maxX - minX, maxY - minY); + } + + #endregion + /// /// 마지막으로 읽힌 연재위치에 해당하는 RFID 포인트값을 반환 합니다 /// @@ -1859,7 +2132,7 @@ namespace AGVControl { get { - return MapControlManager.agv.CurrentRFID; + return Manager.agv.CurrentRFID; } } @@ -1879,7 +2152,7 @@ namespace AGVControl private float GetProjectionRatio(Point point, Point lineStart, Point lineEnd) { - float lineLength = MapControlManager.GetDistance(lineStart, lineEnd); + float lineLength = Manager.GetDistance(lineStart, lineEnd); if (lineLength == 0) return 0; return ((point.X - lineStart.X) * (lineEnd.X - lineStart.X) + @@ -1889,8 +2162,8 @@ namespace AGVControl private float GetDistanceToLine(Point point, Point lineStart, Point lineEnd) { - float lineLength = MapControlManager.GetDistance(lineStart, lineEnd); - if (lineLength == 0) return MapControlManager.GetDistance(point, lineStart); + float lineLength = Manager.GetDistance(lineStart, lineEnd); + if (lineLength == 0) return Manager.GetDistance(point, lineStart); float t = ((point.X - lineStart.X) * (lineEnd.X - lineStart.X) + (point.Y - lineStart.Y) * (lineEnd.Y - lineStart.Y)) / (lineLength * lineLength); @@ -1900,7 +2173,7 @@ namespace AGVControl float projectionX = lineStart.X + t * (lineEnd.X - lineStart.X); float projectionY = lineStart.Y + t * (lineEnd.Y - lineStart.Y); - return MapControlManager.GetDistance(point, new Point((int)projectionX, (int)projectionY)); + return Manager.GetDistance(point, new Point((int)projectionX, (int)projectionY)); } #endregion } diff --git a/Cs_HMI/SubProject/AGVControl/MapControlManager.cs b/Cs_HMI/SubProject/AGVControl/MapControlManager.cs index 914f772..e509536 100644 --- a/Cs_HMI/SubProject/AGVControl/MapControlManager.cs +++ b/Cs_HMI/SubProject/AGVControl/MapControlManager.cs @@ -3,25 +3,37 @@ using System; using System.Collections.Generic; using System.Drawing; using System.Linq; +using System.Runtime.CompilerServices; +using System.Security.Cryptography.X509Certificates; using System.Threading; +using static System.Windows.Forms.VisualStyles.VisualStyleElement.TextBox; namespace AGVControl { - public static class MapControlManager + public class MapControlManager { - public static AGVActionPrediction PredictResult = null; - public static AGV agv = new AGV(); - public static List RFIDPoints = new List(); - public static HashSet rfidConnections = new HashSet(); + public AGVActionPrediction PredictResult = null; + public AGV agv = new AGV(); + public List RFIDPoints = new List(); + public HashSet rfidConnections = new HashSet(); - private static ManualResetEvent mrepredict = new ManualResetEvent(true); + private ManualResetEvent mrepredict = new ManualResetEvent(true); + + public MapControlManager() + { + + } + ~MapControlManager() + { + + } /// /// 목표지정으로 모터방향이 이동하고 있는가? /// history 데이터가 있어야 하며 기준데이터가 없는 경우 null 반환 /// /// - public static bool? IsMotDirection_To_Target() + public bool? IsMotDirection_To_Target() { if (agv.MovementHistory.Any() == false || agv.MovementHistory.Count < 2) return null; if (agv.MainPath.Any() == false) return null; @@ -38,27 +50,24 @@ namespace AGVControl //지정된경로 반대방향으로 이동하고 있다 return preidx < curidx; } - public static float GetDistance(Point p1, Point p2) + public float GetDistance(Point p1, Point p2) { float dx = p1.X - p2.X; float dy = p1.Y - p2.Y; return (float)Math.Sqrt(dx * dx + dy * dy); // double을 float로 명시적 캐스팅 } - public static AGVActionPrediction PredictNextAction() + public AGVActionPrediction PredictNextAction() { if (mrepredict.WaitOne(1) == false) { - PredictResult = new AGVActionPrediction - { - Reason = "이전 작업이 완료되지 않았습니다", - ReasonCode = AGVActionReasonCode.busy, - MoveState = AGVMoveState.Stop, - Direction = agv.CurrentMOTDirection, - }; + PredictResult = CreatePrediction("이전 작업이 완료되지 않았습니다", + AGVActionReasonCode.busy, + AGVMoveState.Stop, + agv.CurrentMOTDirection, false); return PredictResult; } - + mrepredict.Reset(); try { @@ -68,58 +77,70 @@ namespace AGVControl // 1. 위치를 모를 때 (CurrentRFID가 0 또는 미설정) if (agv.CurrentRFID.Value == 0) { - PredictResult = new AGVActionPrediction - { - Direction = Direction.Backward, - NextRFID = null, - Reason = "AGV 위치 미확정(처음 기동)", - ReasonCode = AGVActionReasonCode.NoPosition, - MoveState = AGVMoveState.Run - }; + PredictResult = CreatePrediction("AGV 위치 미확정(처음 기동)", + AGVActionReasonCode.NoPosition, + AGVMoveState.Run, + Direction.Backward, true, + moveSpeed: AgvSpeed.Low, + moveDiv: AgvRunDirection.Straight); return PredictResult; } //2. 이동방향을 모른다 if (agv.MovementHistory.Any() == false || agv.MovementHistory.Count < 2) { - PredictResult = new AGVActionPrediction - { - Direction = Direction.Backward, - NextRFID = null, - Reason = "AGV이동방향 알수없음", - ReasonCode = AGVActionReasonCode.NoDirection, - MoveState = AGVMoveState.Run - }; + PredictResult = CreatePrediction("AGV이동방향 알수없음", + AGVActionReasonCode.NoDirection, + AGVMoveState.Run, + Direction.Backward, true, + moveSpeed: AgvSpeed.Low, + moveDiv: AgvRunDirection.Straight); return PredictResult; } - // 3. 경로가 없거나 현재 위치가 경로에 없음 - if ((agv.MainPath?.Count ?? 0) < 2) + if ((agv.MainPath?.Count ?? 0) < 2 || agv.MainPath.Last().Value != agv.TargetRFID.Value) { - PredictResult = new AGVActionPrediction + //목적지가 없다면 진행할 수 없다 + if (agv.TargetRFID == null) { - Direction = agv.CurrentMOTDirection, - NextRFID = null, - Reason = "경로 없음 또는 현재 위치 미확정", - ReasonCode = AGVActionReasonCode.NoPath, - MoveState = AGVMoveState.Stop - }; - return PredictResult; + PredictResult = CreatePrediction("경로 없음 또는 현재 위치 미확정", + AGVActionReasonCode.NoPath, + AGVMoveState.Stop, + agv.CurrentMOTDirection, true); + return PredictResult; + } + else + { + //목적지가 있는데 경로가 없다면 경로 예측을 진행해야한다. + var CurPt = agv.MovementHistory.Last(); + var prlt = CalculatePath(CurPt, agv.TargetRFID); + if (prlt.Success == false) + { + PredictResult = CreatePrediction("목적지 경로 예측 실패", + AGVActionReasonCode.Unknown, + AGVMoveState.Stop, + agv.CurrentMOTDirection, true, + nextRFID: agv.TargetRFID); + return PredictResult; + } + else + { + //신규목적지에 대한 경로예측이 성공했다 + agv.SubPath.Clear(); + agv.MainPath = prlt.Path; + } + } } // 4. 경로상에서 다음 RFID 예측 int idx = agv.MainPath.FindIndex(p => p.Value == agv.CurrentRFID.Value); if (idx < 0) { - PredictResult = new AGVActionPrediction - { - Direction = agv.CurrentMOTDirection, - NextRFID = null, - Reason = "현재 위치가 경로에 없음", - ReasonCode = AGVActionReasonCode.NotOnPath, - MoveState = AGVMoveState.Stop - }; + PredictResult = CreatePrediction("현재 위치가 경로에 없음", + AGVActionReasonCode.NotOnPath, + AGVMoveState.Stop, + agv.CurrentMOTDirection, true); return PredictResult; } @@ -135,30 +156,25 @@ namespace AGVControl //모션이동방향이 맞는가? var IsMotDir = IsMotDirection_To_Target() ?? false; - var PrePT = agv.MovementHistory.Skip(agv.MovementHistory.Count - 1).First(); + var PrePT = agv.MovementHistory.Skip(agv.MovementHistory.Count - 2).First(); var curPT = agv.MovementHistory.Last(); - - //리프트방향이 맞지 않다면 회전가능한 위치로 이동을 해야한다 if (IsLiftDir == false) { + AgvSpeed? agv_spd = null; + AgvRunDirection? agv_dir = null; + //회전가능한 위치로 이동을 해야한다 - - //1. 가까운 회전위치를 찾는다 var nearTurnPoint = RFIDPoints.Where(t => t.IsRotatable)?.OrderBy(t => GetDistance(t.Location, agv.CurrentRFID.Location)).FirstOrDefault() ?? null; if (nearTurnPoint == null) { - PredictResult= new AGVActionPrediction - { - Direction = agv.CurrentMOTDirection, - NextRFID = null, - Reason = "회전 가능한 위치가 없습니다", - ReasonCode = AGVActionReasonCode.NoTurnPoint, - MoveState = AGVMoveState.Stop - }; + PredictResult = CreatePrediction("회전 가능한 위치가 없습니다", + AGVActionReasonCode.NoTurnPoint, + AGVMoveState.Stop, + agv.CurrentMOTDirection, true); return PredictResult; } @@ -168,22 +184,19 @@ namespace AGVControl if (agv.CurrentRFID.Value != nearTurnPoint.Value) { if (agv.SubPath.Any() == false || agv.SubPath.Count < 2 || - agv.SubPath.First().Value != PrePT.Value || + agv.SubPath.First().Value != agv.CurrentRFID.Value || agv.SubPath.Last().Value != nearTurnPoint.Value) { - var rlt = CalculatePath(PrePT, nearTurnPoint, true); //이전포인트도 추가를 해준다 + var rlt = CalculatePath(agv.CurrentRFID, nearTurnPoint); //이전포인트도 추가를 해준다 if (rlt.Success) agv.SubPath = rlt.Path; else { agv.SubPath.Clear(); - PredictResult= new AGVActionPrediction - { - Direction = agv.CurrentMOTDirection, - NextRFID = nearTurnPoint, - Reason = "회전 위치까지의 경로를 계산할 수 없습니다", - ReasonCode = AGVActionReasonCode.PathCalcError, - MoveState = AGVMoveState.Stop - }; + PredictResult = CreatePrediction("회전 위치까지의 경로를 계산할 수 없습니다", + AGVActionReasonCode.PathCalcError, + AGVMoveState.Stop, + agv.CurrentMOTDirection, true, + nextRFID: nearTurnPoint); return PredictResult; } } @@ -194,6 +207,9 @@ namespace AGVControl var preidx = agv.SubPath.FindIndex(t => t.Value == PrePT.Value); Direction newdirection = agv.CurrentMOTDirection; string message = "턴위치로 이동중"; + + + if (preidx > curidx) { //지정경로를 거꾸로 이동하고 있다 @@ -202,31 +218,44 @@ namespace AGVControl else newdirection = Direction.Forward; message += "(방향전환)"; + + } - PredictResult= new AGVActionPrediction - { - Direction = newdirection, - NextRFID = nearTurnPoint, - Reason = message, - ReasonCode = AGVActionReasonCode.MoveForTurn, - MoveState = AGVMoveState.Run, - }; + //도로정보를 확인하여 속도와 분기명령을 실행한다 + var roadinfo = GetRoadInfo(agv.SubPath, curPT); + agv_spd = roadinfo.spd; + agv_dir = roadinfo.dir; + + PredictResult = CreatePrediction(message, + AGVActionReasonCode.MoveForTurn, + AGVMoveState.Run, + newdirection, true, + moveSpeed: agv_spd, + moveDiv: agv_dir, + nextRFID: nearTurnPoint); return PredictResult; } + var roadinfo2 = GetRoadInfo(agv.SubPath.Any() ? agv.SubPath : agv.MainPath, curPT); + agv_spd = roadinfo2.spd; + agv_dir = roadinfo2.dir; - PredictResult = new AGVActionPrediction - { - Direction = agv.CurrentMOTDirection, - NextRFID = nearTurnPoint, - Reason = "턴 완료 대기", - ReasonCode = AGVActionReasonCode.NeedTurn, - MoveState = AGVMoveState.Stop - }; + + PredictResult = CreatePrediction("턴 완료 대기", + AGVActionReasonCode.NeedTurn, + AGVMoveState.Stop, + agv.CurrentMOTDirection, true, + moveSpeed: agv_spd, + moveDiv: agv_dir, + nextRFID: nearTurnPoint); return PredictResult; } + //보조이동선제거 + if (agv.SubPath != null && agv.SubPath.Any()) + agv.SubPath.Clear(); + //3. 목적지위치까지 이동이 완료되지 않았다면 계속 이동을 하게한다 if (agv.CurrentRFID.Value != destRFID.Value) { @@ -247,39 +276,35 @@ namespace AGVControl //경로상 바로 다음 위치를 확인한다 var nexstRFID = agv.MainPath.Skip(agv.MainPath.FindIndex(t => t.Value == curPT.Value) + 1).First(); - PredictResult = new AGVActionPrediction - { - Direction = newdirection, - NextRFID = nexstRFID, - Reason = message, - ReasonCode = AGVActionReasonCode.Normal, - MoveState = AGVMoveState.Run, - }; + var roadinfo = GetRoadInfo(agv.MainPath, curPT); + + + PredictResult = CreatePrediction(message, + AGVActionReasonCode.Normal, + AGVMoveState.Run, + newdirection, true, + moveSpeed: roadinfo.spd, + moveDiv: roadinfo.dir, + nextRFID: nexstRFID); return PredictResult; } // 5. 목적지 도달 시 - PredictResult = new AGVActionPrediction - { - Direction = agv.CurrentMOTDirection, - NextRFID = destRFID, - Reason = "경로의 마지막 지점(목적지 도달)", - ReasonCode = AGVActionReasonCode.Arrived, - MoveState = AGVMoveState.Stop - }; + PredictResult = CreatePrediction("경로의 마지막 지점(목적지 도달)", + AGVActionReasonCode.Arrived, + AGVMoveState.Stop, + agv.CurrentMOTDirection, true, + nextRFID: destRFID); return PredictResult; } catch (Exception ex) { - PredictResult = new AGVActionPrediction - { - Direction = agv.CurrentMOTDirection, - NextRFID = null, - Reason = $"ERR:{ex.Message}", - ReasonCode = AGVActionReasonCode.Unknown, - MoveState = AGVMoveState.Stop - }; + + PredictResult = CreatePrediction($"ERR:{ex.Message}", + AGVActionReasonCode.Unknown, + AGVMoveState.Stop, + agv.CurrentMOTDirection, true); return PredictResult; } finally @@ -289,13 +314,43 @@ namespace AGVControl } + (AgvSpeed? spd, AgvRunDirection? dir, RFIDConnection info) GetRoadInfo(List paths, RFIDPoint curPT) + { + //도로정보를 확인하여 속도와 분기명령을 실행한다 + AgvSpeed? agv_spd = null; + AgvRunDirection? agv_div = null; + RFIDConnection info = null; + + var nextpt = paths.Skip(paths.FindIndex(t => t.Value == curPT.Value) + 1).FirstOrDefault(); + if (nextpt != null) + { + var p1 = rfidConnections.Where(t => t.P1.Value == curPT.Value && t.P2.Value == nextpt.Value).FirstOrDefault(); + if (p1 != null) + { + //positive + agv_spd = p1.MoveSpeedP; + agv_div = p1.MoveDirectionP; + info = p1; + } + + var p2 = rfidConnections.Where(t => t.P2.Value == curPT.Value && t.P1.Value == nextpt.Value).FirstOrDefault(); + if (p2 != null) + { + //negative + agv_spd = p2.MoveSpeedN; + agv_div = p2.MoveDirectionN; + info = p2; + } + } + return (agv_spd, agv_div, info); + } /// /// 이웃포인터를 반환합니다 /// /// /// - public static List GetNeighbors(RFIDPoint pt) + public List GetNeighbors(RFIDPoint pt) { var neighbors = new List(); @@ -322,17 +377,17 @@ namespace AGVControl return neighbors.Distinct().ToList(); } - public static RFIDPoint FindRFIDPoint(uint rfidValue) + public RFIDPoint FindRFIDPoint(uint rfidValue) { if (RFIDPoints == null || RFIDPoints.Any() == false) return null; return RFIDPoints.FirstOrDefault(r => r.Value == rfidValue); } - private static float Heuristic(Point a, Point b) + private float Heuristic(Point a, Point b) { return (float)Math.Sqrt(Math.Pow(a.X - b.X, 2) + Math.Pow(a.Y - b.Y, 2)); } - private static PathResult ReconstructPath(Dictionary cameFrom, RFIDPoint current) + private PathResult ReconstructPath(Dictionary cameFrom, RFIDPoint current) { var path = new List { current }; while (cameFrom.ContainsKey(current.Value)) @@ -348,7 +403,7 @@ namespace AGVControl Path = path, }; } - public static PathResult CalculatePath(RFIDPoint start, RFIDPoint end, bool autorun) + public PathResult CalculatePath(RFIDPoint start, RFIDPoint end) { var openList = new List { start }; var closedList = new List(); @@ -410,7 +465,7 @@ namespace AGVControl }; } - public static PathResult CalculatePath(uint tagStrt, uint tagEnd) + public PathResult CalculatePath(uint tagStrt, uint tagEnd) { var retval = new PathResult { @@ -426,7 +481,7 @@ namespace AGVControl return retval; } - retval = CalculatePath(startPoint, endPoint, false); + retval = CalculatePath(startPoint, endPoint); if (retval.Success == false) retval.Message = "경로를 찾을 수 없습니다"; @@ -439,7 +494,7 @@ namespace AGVControl /// 이동경로정보가 없거나 목적지가 없으면 null 이 반환됨 /// /// - public static bool? IsLiftDirectionMatch() + public bool? IsLiftDirectionMatch() { if (agv.MovementHistory.Any() && agv.MovementHistory.Count > 1) @@ -498,7 +553,40 @@ namespace AGVControl } } + // Changed 속성 설정을 위한 헬퍼 메서드 + private bool IsPredictionChanged(AGVActionPrediction newPrediction) + { + if (PredictResult == null) return true; // 이전 예측이 없으면 변경됨 + // Idx와 Changed를 제외하고 비교 + return !PredictResult.Equals(newPrediction); + } + + private AGVActionPrediction CreatePrediction( + string reason, + AGVActionReasonCode reasonCode, + AGVMoveState moveState, + Direction direction, bool IDXUpdate = true, + AgvSpeed? moveSpeed = null, + AgvRunDirection? moveDiv = null, + RFIDPoint nextRFID = null + ) + { + var newPrediction = new AGVActionPrediction + { + NextRFID = nextRFID, + Reason = reason, + ReasonCode = reasonCode, + MoveState = moveState, + Direction = direction, + MoveSpeed = moveSpeed, + MoveDiv = moveDiv, + Idx = IDXUpdate ? (PredictResult?.Idx + 1 ?? 1) : (PredictResult?.Idx ?? 0) + }; + + newPrediction.Changed = IsPredictionChanged(newPrediction); + return newPrediction; + } } } diff --git a/Cs_HMI/SubProject/AGVControl/Models/AGV.cs b/Cs_HMI/SubProject/AGVControl/Models/AGV.cs index 636ff3d..5734467 100644 --- a/Cs_HMI/SubProject/AGVControl/Models/AGV.cs +++ b/Cs_HMI/SubProject/AGVControl/Models/AGV.cs @@ -1,248 +1,242 @@ -using System; -using System.Drawing; -using System.Collections.Generic; -using System.Linq; -using System.Security.Permissions; -using System.Windows.Forms; - -namespace AGVControl.Models -{ - public enum Direction - { - Forward = 0, - Backward = 1, - Stop = 2 - } - - //public class CRFIDData - //{ - // public UInt16 Value { get; set; } - // public Point Location { get; set; } - // public override string ToString() - // { - // return $"RFID:{Value},P:{Location.X},{Location.Y}"; - // } - //} - - public class movehistorydata : RFIDPoint - { - public Direction Direction { get; set; } - - public override string ToString() - { - return $"RFID:{Value},DIR:{Direction},P:{Location.X},{Location.Y}"; - } - } - - public class AGV - { - - /// - /// RFID 번호 - /// - public RFIDPoint CurrentRFID { get; set; } - - /// - /// 목적지가 셋팅된경우 해당 값 - /// - - public RFIDPoint TargetRFID { get; set; } - - /// - /// 배터리잔량(%) - /// - public float BatteryLevel { get; set; } = 0f; - - /// - /// 배터리온도(board) - /// - public double BatteryTemp1 { get; set; } = 0; - - /// - /// 배터리온도(cell) - /// - public double BatteryTemp2 { get; set; } = 0; - - /// - /// AGV - /// - public Direction CurrentAGVDirection { get; set; } - - /// - /// AGV모터 방향 - /// 외부에서 값이 상시 업데이트 됩니다. - /// - public Direction CurrentMOTDirection { get; set; } - - /// - /// 현재위치가 수산되면 목적지까지의 방향값이 계산됩니다. - /// - public Direction TargetDirection { get; set; } = Direction.Stop; - public bool IsMoving { get; set; } - public bool IsMarkCheck { get; set; } - public bool IsTargetDirectionMatch { get; set; } - - /// - /// 메인경로 - /// 경로검색으로 입력된 경로 - /// - public List MainPath { get; set; } = new List(); - - /// - /// 메인경로외에 거쳐가는 중간 경로 - /// - public List SubPath { get; set; } - - - public List PathRFIDs { get; set; } - - // 이동 경로 기록을 위한 새로운 속성들 - public List MovementHistory { get; } = new List(); - - public const int HISTORY_SIZE = 10; // 최근 4개 위치 기록 - - public AGV() - { - MainPath = new List(); - SubPath = new List(); - PathRFIDs = new List(); - - CurrentRFID = new RFIDPoint(); - TargetRFID = new RFIDPoint(); - - TargetDirection = Direction.Forward; - // BodyAngle = null; - } - - - // 이동 경로에 새로운 RFID 추가 - public void AddToMovementHistory(UInt16 rfidValue, Point position, Direction direction) - { - // 중복 RFID가 연속으로 들어오는 경우 무시 - if (MovementHistory.Count > 0 && MovementHistory.Last().Value == rfidValue) - return; - - MovementHistory.Add(new movehistorydata { Value = rfidValue, Direction = direction, Location = position }); - - // 기록 크기 제한 - if (MovementHistory.Count > HISTORY_SIZE) - { - MovementHistory.RemoveAt(0); - } - - //최초방향과 마지막 방향이 일치하지 않으면 그 이전의 데이터는 삭제한다. - if (MovementHistory.Count > 2 && MovementHistory.First().Direction != MovementHistory.Last().Direction) - { - var lastTwo = MovementHistory.Skip(MovementHistory.Count - 2).Take(2).ToArray(); // [9, 10] - MovementHistory.Clear(); - MovementHistory.AddRange(lastTwo); - } - } - - // 연결 정보 기반 실제 이동 방향 계산 - public Direction? CalculateActualDirectionByConnection(uint currentRFID, uint previousRFID, List connections) - { - if (connections == null || connections.Count == 0) - return null; - - // 이전 RFID에서 현재 RFID로의 연결 확인 - var connection = connections.FirstOrDefault(c => - (c.P1.Value == previousRFID && c.P2.Value == currentRFID) || - (c.P1.Value == currentRFID && c.P2.Value == previousRFID)); - - if (connection == null) - return null; // 연결되지 않은 경로 - - // 연결 방향에 따라 실제 이동 방향 결정 - if (connection.P1.Value == previousRFID && connection.P2.Value == currentRFID) - { - return Direction.Forward; // Start -> End 방향으로 이동 - } - else - { - return Direction.Backward; // End -> Start 방향으로 이동 - } - } - - // 연결 정보 기반 방향 불일치 검증 및 정정 - public bool ValidateAndCorrectDirectionByConnection(Direction expectedDirection, List connections) - { - if (MovementHistory.Count < 2 || connections == null) - return true; // 검증 불가능한 경우 - - // 최근 두 RFID 값 가져오기 - var recentRFIDs = MovementHistory.Skip(MovementHistory.Count - 2).Take(2).ToList(); - if (recentRFIDs.Count < 2) - return true; - - var previousRFID = recentRFIDs[0]; - var currentRFID = recentRFIDs[1]; - - var actualDirection = CalculateActualDirectionByConnection(currentRFID.Value, previousRFID.Value, connections); - if (!actualDirection.HasValue) - return true; // 연결 정보로 방향 판단 불가 - - // 방향이 일치하지 않는 경우 - if (actualDirection.Value != expectedDirection) - { - // AGV 모터 방향을 실제 이동 방향으로 정정 - CurrentAGVDirection = actualDirection.Value; - TargetDirection = actualDirection.Value; - - return false; // 정정됨을 알림 - } - - return true; // 방향 일치 - } - - // RFID 순서 기반 실제 이동 방향 계산 (기존 메서드 - 호환성 유지) - public Direction? CalculateActualDirectionByRFID() - { - if (MovementHistory.Count < 2) - return null; - - // 최근 두 RFID 값으로부터 실제 이동 방향 계산 - var recentRFIDs = MovementHistory.Skip(Math.Max(0, MovementHistory.Count - 2)).Take(2).ToList(); - if (recentRFIDs.Count < 2) - return null; - - var prevRFID = recentRFIDs[0]; - var currentRFID = recentRFIDs[1]; - - // RFID 값의 증가/감소로 방향 판단 - if (currentRFID.Value > prevRFID.Value) - { - return Direction.Forward; // RFID 값이 증가하면 전진 - } - else if (currentRFID.Value < prevRFID.Value) - { - return Direction.Backward; // RFID 값이 감소하면 후진 - } - else - { - return null; // 같은 RFID 값이면 방향 판단 불가 - } - } - - - } - - public class PathNode - { - public Point Location { get; set; } - public string RFID { get; set; } - public double G { get; set; } // 시작점에서 현재 노드까지의 비용 - public double H { get; set; } // 현재 노드에서 목표점까지의 예상 비용 - public double F => G + H; // 총 비용 - public PathNode Parent { get; set; } - - public PathNode(Point location, string rfid) - { - Location = location; - RFID = rfid; - G = 0; - H = 0; - Parent = null; - } - } +using System; +using System.Drawing; +using System.Collections.Generic; +using System.Linq; +using System.Security.Permissions; +using System.Windows.Forms; + +namespace AGVControl.Models +{ + + //public class CRFIDData + //{ + // public UInt16 Value { get; set; } + // public Point Location { get; set; } + // public override string ToString() + // { + // return $"RFID:{Value},P:{Location.X},{Location.Y}"; + // } + //} + + public class movehistorydata : RFIDPoint + { + public Direction Direction { get; set; } + + public override string ToString() + { + return $"RFID:{Value},DIR:{Direction},P:{Location.X},{Location.Y}"; + } + } + + public class AGV + { + + /// + /// RFID 번호 + /// + public RFIDPoint CurrentRFID { get; set; } + + /// + /// 목적지가 셋팅된경우 해당 값 + /// + + public RFIDPoint TargetRFID { get; set; } + + /// + /// 배터리잔량(%) + /// + public float BatteryLevel { get; set; } = 0f; + + /// + /// 배터리온도(board) + /// + public double BatteryTemp1 { get; set; } = 0; + + /// + /// 배터리온도(cell) + /// + public double BatteryTemp2 { get; set; } = 0; + + /// + /// AGV + /// + public Direction CurrentAGVDirection { get; set; } + + /// + /// AGV모터 방향 + /// 외부에서 값이 상시 업데이트 됩니다. + /// + public Direction CurrentMOTDirection { get; set; } + + /// + /// 현재위치가 수산되면 목적지까지의 방향값이 계산됩니다. + /// + public Direction TargetDirection { get; set; } = Direction.Stop; + public bool IsMoving { get; set; } + public bool IsMarkCheck { get; set; } + public bool IsTargetDirectionMatch { get; set; } + + /// + /// 메인경로 + /// 경로검색으로 입력된 경로 + /// + public List MainPath { get; set; } = new List(); + + /// + /// 메인경로외에 거쳐가는 중간 경로 + /// + public List SubPath { get; set; } + + + public List PathRFIDs { get; set; } + + // 이동 경로 기록을 위한 새로운 속성들 + public List MovementHistory { get; } = new List(); + + public const int HISTORY_SIZE = 10; // 최근 4개 위치 기록 + + public AGV() + { + MainPath = new List(); + SubPath = new List(); + PathRFIDs = new List(); + + CurrentRFID = new RFIDPoint(); + TargetRFID = new RFIDPoint(); + + TargetDirection = Direction.Forward; + // BodyAngle = null; + } + + + // 이동 경로에 새로운 RFID 추가 + public void AddToMovementHistory(UInt16 rfidValue, Point position, Direction direction) + { + // 중복 RFID가 연속으로 들어오는 경우 무시 + if (MovementHistory.Count > 0 && MovementHistory.Last().Value == rfidValue) + return; + + MovementHistory.Add(new movehistorydata { Value = rfidValue, Direction = direction, Location = position }); + + // 기록 크기 제한 + if (MovementHistory.Count > HISTORY_SIZE) + { + MovementHistory.RemoveAt(0); + } + + //최초방향과 마지막 방향이 일치하지 않으면 그 이전의 데이터는 삭제한다. + if (MovementHistory.Count > 2 && MovementHistory.First().Direction != MovementHistory.Last().Direction) + { + var lastTwo = MovementHistory.Skip(MovementHistory.Count - 2).Take(2).ToArray(); // [9, 10] + MovementHistory.Clear(); + MovementHistory.AddRange(lastTwo); + } + } + + // 연결 정보 기반 실제 이동 방향 계산 + public Direction? CalculateActualDirectionByConnection(uint currentRFID, uint previousRFID, List connections) + { + if (connections == null || connections.Count == 0) + return null; + + // 이전 RFID에서 현재 RFID로의 연결 확인 + var connection = connections.FirstOrDefault(c => + (c.P1.Value == previousRFID && c.P2.Value == currentRFID) || + (c.P1.Value == currentRFID && c.P2.Value == previousRFID)); + + if (connection == null) + return null; // 연결되지 않은 경로 + + // 연결 방향에 따라 실제 이동 방향 결정 + if (connection.P1.Value == previousRFID && connection.P2.Value == currentRFID) + { + return Direction.Forward; // Start -> End 방향으로 이동 + } + else + { + return Direction.Backward; // End -> Start 방향으로 이동 + } + } + + // 연결 정보 기반 방향 불일치 검증 및 정정 + public bool ValidateAndCorrectDirectionByConnection(Direction expectedDirection, List connections) + { + if (MovementHistory.Count < 2 || connections == null) + return true; // 검증 불가능한 경우 + + // 최근 두 RFID 값 가져오기 + var recentRFIDs = MovementHistory.Skip(MovementHistory.Count - 2).Take(2).ToList(); + if (recentRFIDs.Count < 2) + return true; + + var previousRFID = recentRFIDs[0]; + var currentRFID = recentRFIDs[1]; + + var actualDirection = CalculateActualDirectionByConnection(currentRFID.Value, previousRFID.Value, connections); + if (!actualDirection.HasValue) + return true; // 연결 정보로 방향 판단 불가 + + // 방향이 일치하지 않는 경우 + if (actualDirection.Value != expectedDirection) + { + // AGV 모터 방향을 실제 이동 방향으로 정정 + CurrentAGVDirection = actualDirection.Value; + TargetDirection = actualDirection.Value; + + return false; // 정정됨을 알림 + } + + return true; // 방향 일치 + } + + // RFID 순서 기반 실제 이동 방향 계산 (기존 메서드 - 호환성 유지) + public Direction? CalculateActualDirectionByRFID() + { + if (MovementHistory.Count < 2) + return null; + + // 최근 두 RFID 값으로부터 실제 이동 방향 계산 + var recentRFIDs = MovementHistory.Skip(Math.Max(0, MovementHistory.Count - 2)).Take(2).ToList(); + if (recentRFIDs.Count < 2) + return null; + + var prevRFID = recentRFIDs[0]; + var currentRFID = recentRFIDs[1]; + + // RFID 값의 증가/감소로 방향 판단 + if (currentRFID.Value > prevRFID.Value) + { + return Direction.Forward; // RFID 값이 증가하면 전진 + } + else if (currentRFID.Value < prevRFID.Value) + { + return Direction.Backward; // RFID 값이 감소하면 후진 + } + else + { + return null; // 같은 RFID 값이면 방향 판단 불가 + } + } + + + } + + public class PathNode + { + public Point Location { get; set; } + public string RFID { get; set; } + public double G { get; set; } // 시작점에서 현재 노드까지의 비용 + public double H { get; set; } // 현재 노드에서 목표점까지의 예상 비용 + public double F => G + H; // 총 비용 + public PathNode Parent { get; set; } + + public PathNode(Point location, string rfid) + { + Location = location; + RFID = rfid; + G = 0; + H = 0; + Parent = null; + } + } } \ No newline at end of file diff --git a/Cs_HMI/SubProject/AGVControl/Models/AGVActionPrediction.cs b/Cs_HMI/SubProject/AGVControl/Models/AGVActionPrediction.cs index 1baf77b..c0d9aa7 100644 --- a/Cs_HMI/SubProject/AGVControl/Models/AGVActionPrediction.cs +++ b/Cs_HMI/SubProject/AGVControl/Models/AGVActionPrediction.cs @@ -1,4 +1,5 @@ using AGVControl.Models; +using System; namespace AGVControl { @@ -9,6 +10,48 @@ namespace AGVControl public string Reason { get; set; } public AGVActionReasonCode ReasonCode { get; set; } public AGVMoveState MoveState { get; set; } // RUN 또는 STOP - } + public AgvSpeed? MoveSpeed { get; set; } + public AgvRunDirection? MoveDiv { get; set; } + public UInt32 Idx { get; set; } + public bool Changed { get; set; } + // override object.Equals + public bool Equals(AGVActionPrediction obj) + { + // null 체크 + if (obj == null) return false; + + // 참조가 같으면 true + if (ReferenceEquals(this, obj)) return true; + + // 핵심 속성들만 비교 (Idx, Changed 제외) + if (obj.Direction != this.Direction) return false; + if (obj.ReasonCode != this.ReasonCode) return false; + if (obj.MoveState != this.MoveState) return false; + if (obj.MoveSpeed != this.MoveSpeed) return false; + if (obj.MoveDiv != this.MoveDiv) return false; + + // NextRFID 비교 (null 체크 포함) + if (obj.NextRFID == null || this.NextRFID == null) + { + if (obj.NextRFID != this.NextRFID) return false; // 하나만 null이면 false + } + else + { + if (obj.NextRFID.Value != this.NextRFID.Value) return false; + } + + // Reason 비교 (null 체크 포함) + if (obj.Reason == null || this.Reason == null) + { + if (obj.Reason != this.Reason) return false; // 하나만 null이면 false + } + else + { + if (obj.Reason != this.Reason) return false; + } + + return true; + } + } } diff --git a/Cs_HMI/SubProject/AGVControl/Models/MagnetLine.cs b/Cs_HMI/SubProject/AGVControl/Models/MagnetLine.cs index 37e3808..2b2e23e 100644 --- a/Cs_HMI/SubProject/AGVControl/Models/MagnetLine.cs +++ b/Cs_HMI/SubProject/AGVControl/Models/MagnetLine.cs @@ -1,9 +1,75 @@ using System.Drawing; using System; using System.Collections.Generic; +using System.Windows.Forms; namespace AGVControl.Models -{ +{ + + + /// + /// Ư + /// + public class RoadInformation + { + /// + /// + /// + public RFIDPoint P1 { get; set; } + + /// + /// + /// + public RFIDPoint P2 { get; set; } + + /// + /// 뿩 + /// + public bool Enable { get; set; } + + /// + /// AGV ̵(Ʈ) + /// ġ ش ֵ + /// + public Direction? LiftDirection { get; set; } + + /// + /// AGV̵ ӵ (high, middle, low) + /// + public AgvSpeed? MoveSpeed { get; set; } + + + + /// + /// AGV̵ (ºб, , б) + /// + public AgvRunDirection? MoveDirection { get; set; } + + public RoadInformation() + { + P1 = null; + P2 = null; + LiftDirection = null; + MoveSpeed = null; + MoveDirection = null; + Enable = false; + } + + /// + /// Ǿִ + /// + public bool HasValue + { + get + { + if (P1 == null || P2 == null) return false; + if (LiftDirection == null && MoveSpeed == null && MoveDirection == null) return false; + return true; + } + } + } + + public class MagnetLine { public Point StartPoint { get; set; } diff --git a/Cs_HMI/SubProject/AGVControl/Models/RFIDConnection.cs b/Cs_HMI/SubProject/AGVControl/Models/RFIDConnection.cs index 49fefcb..3ad5be2 100644 --- a/Cs_HMI/SubProject/AGVControl/Models/RFIDConnection.cs +++ b/Cs_HMI/SubProject/AGVControl/Models/RFIDConnection.cs @@ -1,14 +1,195 @@ using AGVControl.Models; +using AR; +using System.Collections.Specialized; +using System.ComponentModel; +using System.Diagnostics.Tracing; namespace AGVControl { public class RFIDConnection { + /// + /// 시작지점 + /// public RFIDPoint P1 { get; set; } + + /// + /// 종료지점 + /// public RFIDPoint P2 { get; set; } - public bool DisableP1_to_P2 { get; set; } - public bool DisableP2_to_P1 { get; set; } - public float Distance { get; set; } + + /// + /// 도로의 사용여부 + /// + public bool EnableP { get; set; } + public bool EnableN { get; set; } + + /// + /// AGV의 이동방향(리프트방향) + /// 목적지 방향과의 일치를 위해 해당 방향을 설정할 수 있따 + /// + public Direction? LiftDirectionP { get; set; } + public Direction? LiftDirectionN { get; set; } + + /// + /// AGV이동시 속도 (high, middle, low) + /// + public AgvSpeed? MoveSpeedP { get; set; } + public AgvSpeed? MoveSpeedN { get; set; } + + /// + /// AGV이동시 방향모드(좌분기, 전진, 우분기) + /// + public AgvRunDirection? MoveDirectionP { get; set; } + public AgvRunDirection? MoveDirectionN { get; set; } + + /// + /// 파일저장 및 불러오기시 사용하는 문자열로 반환 + /// + [Browsable(false)] + public string DataFileString + { + get + { + var str_enbP = EnableP ? "1" : "0"; + var str_liftP = ""; + if (LiftDirectionP != null) str_liftP = ((int)LiftDirectionP).ToString(); + + var str_movespeedP = ""; + if (MoveSpeedP != null) str_movespeedP = ((int)MoveSpeedP).ToString(); + + var str_movdirP = ""; + if (MoveDirectionP != null) str_movdirP = ((int)MoveDirectionP).ToString(); + + var str_enbN = EnableP ? "1" : "0"; + var str_liftN = ""; + if (LiftDirectionN != null) str_liftN = ((int)LiftDirectionN).ToString(); + + var str_movespeedN = ""; + if (MoveSpeedN != null) str_movespeedN = ((int)MoveSpeedN).ToString(); + + var str_movdirN = ""; + if (MoveDirectionN != null) str_movdirN = ((int)MoveDirectionN).ToString(); + + + var PStr= $"{P1.Location.X},{P1.Location.Y},{P2.Location.X},{P2.Location.Y}," + //location + $"{P1.Value},{P2.Value}," + //rfid values + $"{str_enbP};{str_liftP};{str_movespeedP};{str_movdirP}," + + $"{str_enbN};{str_liftN};{str_movespeedN};{str_movdirN}"; + + + return $"{PStr}"; + + + } + set + { + var buf = value.Split(','); + if (buf.Length >= 2) + { + var p1x = int.Parse(buf[0]); + var p1y = int.Parse(buf[1]); + var p2x = int.Parse(buf[2]); + var p2y = int.Parse(buf[3]); + var p1v = uint.Parse(buf[4]); + var p2v = uint.Parse(buf[5]); + + if (P1 == null) P1 = new RFIDPoint(); + P1.Location = new System.Drawing.Point(p1x, p1y); + P1.Value = p1v; + + if (P2 == null) P2 = new RFIDPoint(); + P2.Location = new System.Drawing.Point(p2x, p2y); + P2.Value = p2v; + + + if (buf[6].Contains(";")) //양방향 정보 + { + var StrP = buf[6].Split(';'); + var StrN = buf[7].Split(';'); + + //Positive + this.EnableP = StrP[0] == "1"; + + if (StrP[1].isEmpty()) LiftDirectionP = null; + else LiftDirectionP = (Direction)int.Parse(StrP[1]); + + if (StrP[2].isEmpty()) MoveSpeedP = null; + else MoveSpeedP = (AgvSpeed)int.Parse(StrP[2]); + + if (StrP[3].isEmpty()) MoveDirectionP = null; + else MoveDirectionP = (AgvRunDirection)int.Parse(StrP[3]); + + //Negative + this.EnableN = StrN[0] == "1"; + + if (StrN[1].isEmpty()) LiftDirectionN = null; + else LiftDirectionN = (Direction)int.Parse(StrN[1]); + + if (StrN[2].isEmpty()) MoveSpeedN = null; + else MoveSpeedN = (AgvSpeed)int.Parse(StrN[2]); + + if (StrN[3].isEmpty()) MoveDirectionN = null; + else MoveDirectionN = (AgvRunDirection)int.Parse(StrN[3]); + } + else + { + this.EnableP = buf[6] == "1"; + + if (buf[7].isEmpty()) LiftDirectionP = null; + else LiftDirectionP = (Direction)int.Parse(buf[7]); + + if (buf[8].isEmpty()) MoveSpeedP = null; + else MoveSpeedP = (AgvSpeed)int.Parse(buf[8]); + + if (buf[9].isEmpty()) MoveDirectionP = null; + else MoveDirectionP = (AgvRunDirection)int.Parse(buf[9]); + + this.EnableN = this.EnableP; + this.LiftDirectionN = this.LiftDirectionP; + this.MoveSpeedN = this.MoveSpeedP; + this.MoveDirectionN = this.MoveDirectionP; + } + + + + + + } + } + } + + public RFIDConnection(string dataline = "") + { + P1 = null; + P2 = null; + LiftDirectionP = null; + MoveSpeedP = null; + MoveDirectionP = null; + EnableP = false; + + LiftDirectionN = null; + MoveSpeedN = null; + MoveDirectionP = null; + EnableP = false; + + + if (dataline.isEmpty() == false) DataFileString = dataline; + } + + /// + /// 값이 설정되어있는지 + /// + public bool HasValue + { + get + { + if (P1 == null || P2 == null) return false; + if (LiftDirectionP == null && MoveSpeedP == null && MoveDirectionP == null && + LiftDirectionN == null && MoveSpeedN == null && MoveDirectionN == null) return false; + return true; + } + } public override bool Equals(object obj) @@ -27,7 +208,7 @@ namespace AGVControl public override string ToString() { //연결정보를 확인 - return $"{P1.Value} ↔ {P2.Value},P1-2:{(DisableP1_to_P2 ? "X" : "O")},P2-1:{(DisableP2_to_P1 ? "X" : "O")}"; + return $"{P1.Value} ↔ {P2.Value},ENB:{(EnableP ? "O" : "X")}|{(EnableN ? "O" : "X")}"; } } } diff --git a/Cs_HMI/SubProject/AGVControl/Models/RFIDPoint.cs b/Cs_HMI/SubProject/AGVControl/Models/RFIDPoint.cs index 9853446..e63b5b1 100644 --- a/Cs_HMI/SubProject/AGVControl/Models/RFIDPoint.cs +++ b/Cs_HMI/SubProject/AGVControl/Models/RFIDPoint.cs @@ -1,6 +1,7 @@ using System.Drawing; using System; using System.Collections.Generic; +using System.ComponentModel; namespace AGVControl.Models { public class RFIDPoint @@ -11,7 +12,9 @@ namespace AGVControl.Models public bool IsBidirectional { get; set; } // 양방향 연결 여부 public bool IsRotatable { get; set; } // 회전 가능 여부 public Direction? FixedDirection { get; set; } // 고정 방향(없으면 null) - public bool IsTerminal { get; set; } // 종단 여부 + public bool IsTerminal { get; set; } // 종단 여부 + + [Browsable(false)] public RectangleF Bounds { get; set; } public void Clear() { diff --git a/Cs_HMI/SubProject/AGVControl/Models/enumStruct.cs b/Cs_HMI/SubProject/AGVControl/Models/enumStruct.cs index d718263..7834cf5 100644 --- a/Cs_HMI/SubProject/AGVControl/Models/enumStruct.cs +++ b/Cs_HMI/SubProject/AGVControl/Models/enumStruct.cs @@ -6,12 +6,32 @@ using System.Threading.Tasks; namespace AGVControl { + public enum Direction + { + Forward = 0, + Backward = 1, + Stop = 2 + } + + public enum AGVMoveState { Stop = 0, Run } + public enum AgvSpeed + { + High, + Middle, + Low, + } + public enum AgvRunDirection + { + Straight, + Left, + Right, + } public enum AGVActionReasonCode { diff --git a/Cs_HMI/SubProject/AGVControl/agvControl.csproj b/Cs_HMI/SubProject/AGVControl/agvControl.csproj index 5cd191e..8790cfe 100644 --- a/Cs_HMI/SubProject/AGVControl/agvControl.csproj +++ b/Cs_HMI/SubProject/AGVControl/agvControl.csproj @@ -45,6 +45,18 @@ + + Form + + + fMapDesign.cs + + + Form + + + fPropertyRFIDPoint.cs + @@ -103,6 +115,12 @@ + + fMapDesign.cs + + + fPropertyRFIDPoint.cs + MapControl.cs diff --git a/Cs_HMI/SubProject/BMS/BMS.cs b/Cs_HMI/SubProject/BMS/BMS.cs index ad2967c..c10bdb9 100644 --- a/Cs_HMI/SubProject/BMS/BMS.cs +++ b/Cs_HMI/SubProject/BMS/BMS.cs @@ -109,15 +109,16 @@ namespace arDev return false; } - if (QueryIndex == 0) + + if (data[1] == 0x03) { return ParseBMSInfo(); } - else + else if (data[1] == 0x04) { return ParseBMSCellVoltage(); } - + else return false; } bool ParseBMSCellVoltage() @@ -376,6 +377,7 @@ namespace arDev } else { + return SendQuery_ReadStatue(); } } @@ -398,14 +400,14 @@ namespace arDev { Recv0 = false; var cmd = new List(); - cmd.Add(0xDD); - cmd.Add(0xA5); - cmd.Add(0x03); + cmd.Add(0xDD); //stx + cmd.Add(0xA5); //read + cmd.Add(0x03); //command cmd.Add(0x00); cmd.Add(0xFF); - cmd.Add(0xFD); - cmd.Add(0x77); - cmd.Add(0x0D); + cmd.Add(0xFD); //checksum1 + cmd.Add(0x77); //checksum2 + cmd.Add(0x0D); //etx return WriteData(cmd.ToArray()); } diff --git a/Emulator/AGVEmulator/Form1.Designer.cs b/Emulator/AGVEmulator/Form1.Designer.cs index 0a14bb7..46da549 100644 --- a/Emulator/AGVEmulator/Form1.Designer.cs +++ b/Emulator/AGVEmulator/Form1.Designer.cs @@ -1,4 +1,6 @@  +using System.Windows.Forms; + namespace AGVEmulator { partial class Form1 @@ -116,7 +118,7 @@ namespace AGVEmulator this.chkSimulation = new System.Windows.Forms.CheckBox(); this.checkBox3 = new System.Windows.Forms.CheckBox(); this.panel10 = new System.Windows.Forms.Panel(); - this.numericUpDown1 = new System.Windows.Forms.NumericUpDown(); + this.numericUpDown1 = new System.Windows.Forms.TextBox(); this.button18 = new System.Windows.Forms.Button(); this.button17 = new System.Windows.Forms.Button(); this.button15 = new System.Windows.Forms.Button(); @@ -178,7 +180,6 @@ namespace AGVEmulator this.groupBox5.SuspendLayout(); this.panel13.SuspendLayout(); this.panel10.SuspendLayout(); - ((System.ComponentModel.ISupportInitialize)(this.numericUpDown1)).BeginInit(); this.groupBox3.SuspendLayout(); this.tabControl1.SuspendLayout(); this.tabPage1.SuspendLayout(); @@ -878,20 +879,11 @@ namespace AGVEmulator // this.numericUpDown1.Font = new System.Drawing.Font("굴림", 20F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(129))); this.numericUpDown1.Location = new System.Drawing.Point(19, 220); - this.numericUpDown1.Maximum = new decimal(new int[] { - 9999999, - 0, - 0, - 0}); this.numericUpDown1.Name = "numericUpDown1"; this.numericUpDown1.Size = new System.Drawing.Size(130, 38); this.numericUpDown1.TabIndex = 9; + this.numericUpDown1.Text = "101"; this.numericUpDown1.TextAlign = System.Windows.Forms.HorizontalAlignment.Center; - this.numericUpDown1.Value = new decimal(new int[] { - 9900, - 0, - 0, - 0}); this.numericUpDown1.KeyDown += new System.Windows.Forms.KeyEventHandler(this.numericUpDown1_KeyDown); // // button18 @@ -1533,7 +1525,7 @@ namespace AGVEmulator this.groupBox5.PerformLayout(); this.panel13.ResumeLayout(false); this.panel10.ResumeLayout(false); - ((System.ComponentModel.ISupportInitialize)(this.numericUpDown1)).EndInit(); + this.panel10.PerformLayout(); this.groupBox3.ResumeLayout(false); this.tabControl1.ResumeLayout(false); this.tabPage1.ResumeLayout(false); @@ -1615,7 +1607,7 @@ namespace AGVEmulator private System.Windows.Forms.Button button15; private System.Windows.Forms.Button button17; private System.Windows.Forms.Button button18; - private System.Windows.Forms.NumericUpDown numericUpDown1; + private TextBox numericUpDown1; private System.Windows.Forms.Panel panel12; private UC.AgvViewer agvViewer1; private System.Windows.Forms.Panel panel13; diff --git a/Emulator/AGVEmulator/Form1.cs b/Emulator/AGVEmulator/Form1.cs index c3286bc..e3948ae 100644 --- a/Emulator/AGVEmulator/Form1.cs +++ b/Emulator/AGVEmulator/Form1.cs @@ -338,7 +338,7 @@ namespace AGVEmulator private void AgvViewer1_TagTouched(object sender, UC.AgvViewer.TagArgs e) { logAGV.Add($"tag touch:{e.Data}"); - numericUpDown1.Value = decimal.Parse(e.Data); + numericUpDown1.Text = e.Data;// decimal.Parse(e.Data); button18.PerformClick(); } @@ -552,7 +552,12 @@ namespace AGVEmulator private void button18_Click(object sender, EventArgs e) { - AGV.SendTag(numericUpDown1.Value.ToString()); + if(int.TryParse(numericUpDown1.Text, out int tagno)) + { + AGV.SendTag(tagno.ToString()); + numericUpDown1.SelectAll(); + numericUpDown1.Focus(); + } } private void agvViewer1_MouseDown(object sender, MouseEventArgs e)