diff --git a/Cs_HMI/Project/StateMachine/_AGV.cs b/Cs_HMI/Project/StateMachine/_AGV.cs index e8770db..4734f0e 100644 --- a/Cs_HMI/Project/StateMachine/_AGV.cs +++ b/Cs_HMI/Project/StateMachine/_AGV.cs @@ -39,178 +39,189 @@ namespace Project bool _charging = false; private void AGV_DataReceive(object sender, arDev.Narumi.DataEventArgs e) { - if (PUB.mapctl != null) - PUB.mapctl.PredictNextAction(); - - switch (e.DataType) + try { - case arDev.Narumi.DataType.STS: - { - //마크센서 확인 - var chg_mark1 = PUB.AGV.signal.GetChanged(arDev.Narumi.Signal.eflag.mark_sensor_1); - var chg_mark2 = PUB.AGV.signal.GetChanged(arDev.Narumi.Signal.eflag.mark_sensor_1); - var chg_run = PUB.AGV.system1.GetChanged(arDev.Narumi.SystemFlag1.eflag.agv_run); - var chg_stop = PUB.AGV.system1.GetChanged(arDev.Narumi.SystemFlag1.eflag.agv_stop); - //if (chg_run && PUB.AGV.system1.agv_run) PUB.Speak("이동을 시작 합니다"); - VAR.BOOL[eVarBool.AGVDIR_UP] = PUB.AGV.data.Direction == 'B'; - // PUB.AGV.signal.mark_sensor = PUB.AGV.signal.mark_sensor; - VAR.BOOL[eVarBool.AGV_ERROR] = PUB.AGV.error.Value > 0; - VAR.BOOL[eVarBool.EMERGENCY] = PUB.AGV.error.Emergency; - //모터방향 입력 - if (PUB.AGV.data.Direction == 'B') - PUB.mapctl.agv.CurrentMOTDirection = AGVControl.Models.Direction.Backward; - else - PUB.mapctl.agv.CurrentMOTDirection = AGVControl.Models.Direction.Forward; - if (PUB.AGV.signal.mark_sensor == false) + if (PUB.mapctl != null) + PUB.mapctl.PredictNextAction(); + + switch (e.DataType) + { + case arDev.Narumi.DataType.STS: { - if (VAR.BOOL[eVarBool.MARK_SENSOROFF] == false) + //마크센서 확인 + var chg_mark1 = PUB.AGV.signal.GetChanged(arDev.Narumi.Signal.eflag.mark_sensor_1); + var chg_mark2 = PUB.AGV.signal.GetChanged(arDev.Narumi.Signal.eflag.mark_sensor_1); + var chg_run = PUB.AGV.system1.GetChanged(arDev.Narumi.SystemFlag1.eflag.agv_run); + var chg_stop = PUB.AGV.system1.GetChanged(arDev.Narumi.SystemFlag1.eflag.agv_stop); + //if (chg_run && PUB.AGV.system1.agv_run) PUB.Speak("이동을 시작 합니다"); + VAR.BOOL[eVarBool.AGVDIR_UP] = PUB.AGV.data.Direction == 'B'; + // PUB.AGV.signal.mark_sensor = PUB.AGV.signal.mark_sensor; + VAR.BOOL[eVarBool.AGV_ERROR] = PUB.AGV.error.Value > 0; + VAR.BOOL[eVarBool.EMERGENCY] = PUB.AGV.error.Emergency; + + //모터방향 입력 + if (PUB.AGV.data.Direction == 'B') + PUB.mapctl.agv.CurrentMOTDirection = AGVControl.Models.Direction.Backward; + else + PUB.mapctl.agv.CurrentMOTDirection = AGVControl.Models.Direction.Forward; + + PUB.mapctl.agv.IsMoving = PUB.AGV.system1.agv_run; + PUB.mapctl.agv.IsMarkCheck = PUB.AGV.system1.Mark1_check || PUB.AGV.system1.Mark2_check; + + if (PUB.AGV.signal.mark_sensor == false) { - VAR.BOOL[eVarBool.MARK_SENSOROFF] = true; - VAR.TIME[eVarTime.MarkSensorOff] = DateTime.Now; - PUB.log.Add($"마크센서off를 설정"); - } - } - else - { - if (VAR.BOOL[eVarBool.MARK_SENSOROFF] == true) - { - VAR.BOOL[eVarBool.MARK_SENSOROFF] = false; - VAR.TIME[eVarTime.MarkSensorOff] = DateTime.Now; - PUB.log.Add($"마크센서off를 해제"); - } - } - - - //차징상태변경 - if (_charging != PUB.AGV.system1.Battery_charging) - { - if (PUB.AGV.system1.Battery_charging) - { - VAR.TIME[eVarTime.ChargeStart] = DateTime.Now; - PUB.logagv.Add($"충전시작:{VAR.TIME[eVarTime.ChargeStart]}"); - } - _charging = PUB.AGV.system1.Battery_charging; - } - - //배터리충전상태 - if (VAR.BOOL[eVarBool.FLAG_CHARGEONA] != PUB.AGV.system1.Battery_charging) - { - PUB.log.Add($"충전상태전환 {PUB.AGV.system1.Battery_charging}"); - VAR.BOOL[eVarBool.FLAG_CHARGEONA] = PUB.AGV.system1.Battery_charging; - } - //자동충전해제시 곧바로 수동 충전되는 경우가 있어 자동 상태를 BMS에 넣는다 230118 - PUB.BMS.AutoCharge = PUB.AGV.system1.Battery_charging; - - if (PUB.AGV.error.Charger_pos_error != VAR.BOOL[eVarBool.CHG_POSERR]) - { - if (PUB.AGV.error.Charger_pos_error) - { - PUB.Speak(Lang.충전기위치오류); - } - VAR.BOOL[eVarBool.CHG_POSERR] = PUB.AGV.error.Charger_pos_error; - } - - if (VAR.BOOL[eVarBool.MARK_SENSOROFF] == true && PUB.AGV.signal.mark_sensor == false) - { - //현재 활성화된 위치를 꺼준다 - if (this.ctlPos1.GetPositionActive(PUB.Result.CurrentPos)) - { - var ts = VAR.TIME.RUN(eVarTime.MarkSensorOff); - if (ts.TotalSeconds >= 2) + if (VAR.BOOL[eVarBool.MARK_SENSOROFF] == false) { - ctlPos1.SetPositionDeActive(); - PUB.log.Add($"현재 활성위치를 해제 함"); + VAR.BOOL[eVarBool.MARK_SENSOROFF] = true; + VAR.TIME[eVarTime.MarkSensorOff] = DateTime.Now; + PUB.log.Add($"마크센서off를 설정"); + } + } + else + { + if (VAR.BOOL[eVarBool.MARK_SENSOROFF] == true) + { + VAR.BOOL[eVarBool.MARK_SENSOROFF] = false; + VAR.TIME[eVarTime.MarkSensorOff] = DateTime.Now; + PUB.log.Add($"마크센서off를 해제"); } } - } - //나르미가 멈췄다면 다음 마크 이동 기능이 OFF 된다 - if (PUB.AGV.system1.agv_stop) - VAR.BOOL[eVarBool.NEXTSTOP_MARK] = false; - - if (VAR.BOOL[eVarBool.MARK_SENSOR] != PUB.AGV.signal.mark_sensor) - { - if (PUB.AGV.signal.mark_sensor) + //차징상태변경 + if (_charging != PUB.AGV.system1.Battery_charging) { - //현재위치를 확정한다 - var curact = ctlPos1.GetPositionActive(PUB.Result.CurrentPos); - if (curact == false) + if (PUB.AGV.system1.Battery_charging) { - PUB.log.Add($"마크센서로인해 현재위치 설정완료:{PUB.Result.CurrentPos}"); - ctlPos1.SetPositionActive(PUB.Result.CurrentPos); - ctlPos1.SetDirection(""); - ctlPos1.Invalidate(); + VAR.TIME[eVarTime.ChargeStart] = DateTime.Now; + PUB.logagv.Add($"충전시작:{VAR.TIME[eVarTime.ChargeStart]}"); } + _charging = PUB.AGV.system1.Battery_charging; } - VAR.BOOL[eVarBool.MARK_SENSOR] = PUB.AGV.signal.mark_sensor; - } - } - break; - case arDev.Narumi.DataType.TAG: - { - //자동 실행 중이다. - PUB.log.Add($"AGV 태그수신 : {PUB.AGV.data.TagNo}"); - PUB.Result.LastTAG = PUB.AGV.data.TagNo.ToString(); - //POT/NOT 보면 일단 바로 멈추게한다 - if (PUB.Result.CurrentPos == ePosition.POT || PUB.Result.CurrentPos == ePosition.NOT) + //배터리충전상태 + if (VAR.BOOL[eVarBool.FLAG_CHARGEONA] != PUB.AGV.system1.Battery_charging) + { + PUB.log.Add($"충전상태전환 {PUB.AGV.system1.Battery_charging}"); + VAR.BOOL[eVarBool.FLAG_CHARGEONA] = PUB.AGV.system1.Battery_charging; + } + //자동충전해제시 곧바로 수동 충전되는 경우가 있어 자동 상태를 BMS에 넣는다 230118 + PUB.BMS.AutoCharge = PUB.AGV.system1.Battery_charging; + + if (PUB.AGV.error.Charger_pos_error != VAR.BOOL[eVarBool.CHG_POSERR]) + { + if (PUB.AGV.error.Charger_pos_error) + { + PUB.Speak(Lang.충전기위치오류); + } + VAR.BOOL[eVarBool.CHG_POSERR] = PUB.AGV.error.Charger_pos_error; + } + + if (VAR.BOOL[eVarBool.MARK_SENSOROFF] == true && PUB.AGV.signal.mark_sensor == false) + { + //현재 활성화된 위치를 꺼준다 + if (this.ctlPos1.GetPositionActive(PUB.Result.CurrentPos)) + { + var ts = VAR.TIME.RUN(eVarTime.MarkSensorOff); + if (ts.TotalSeconds >= 2) + { + ctlPos1.SetPositionDeActive(); + PUB.log.Add($"현재 활성위치를 해제 함"); + } + } + + } + + //나르미가 멈췄다면 다음 마크 이동 기능이 OFF 된다 + if (PUB.AGV.system1.agv_stop) + VAR.BOOL[eVarBool.NEXTSTOP_MARK] = false; + + if (VAR.BOOL[eVarBool.MARK_SENSOR] != PUB.AGV.signal.mark_sensor) + { + if (PUB.AGV.signal.mark_sensor) + { + //현재위치를 확정한다 + var curact = ctlPos1.GetPositionActive(PUB.Result.CurrentPos); + if (curact == false) + { + PUB.log.Add($"마크센서로인해 현재위치 설정완료:{PUB.Result.CurrentPos}"); + ctlPos1.SetPositionActive(PUB.Result.CurrentPos); + ctlPos1.SetDirection(""); + ctlPos1.Invalidate(); + } + } + VAR.BOOL[eVarBool.MARK_SENSOR] = PUB.AGV.signal.mark_sensor; + } + } + break; + case arDev.Narumi.DataType.TAG: { - var logEMsg = $"Stop by [POT/NOT]"; - PUB.AGV.AGVMoveStop(logEMsg); - PUB.log.AddE(logEMsg); - } + //자동 실행 중이다. + PUB.log.Add($"AGV 태그수신 : {PUB.AGV.data.TagNo}"); + PUB.Result.LastTAG = PUB.AGV.data.TagNo.ToString(); - //맵데이터에서 현재 위치를 찾는다 - if (PUB.mapctl.SetCurrentPosition(PUB.AGV.data.TagNo) == false) - { - if (VAR.BOOL[eVarBool.FLAG_AUTORUN] && PUB.AGV.system1.agv_run) - PUB.AGV.AGVMoveStop("unknown tag no"); + //POT/NOT 보면 일단 바로 멈추게한다 + if (PUB.Result.CurrentPos == ePosition.POT || PUB.Result.CurrentPos == ePosition.NOT) + { + var logEMsg = $"Stop by [POT/NOT]"; + PUB.AGV.AGVMoveStop(logEMsg); + PUB.log.AddE(logEMsg); + } - //존재하지 않는 태그가 읽히면 관련 오류를 표시한다. - } - else - { - //위치는 찾았다 해당 위치가 내 목적지라면 mark stop기능으로 전환한다 + //맵데이터에서 현재 위치를 찾는다 + if (PUB.mapctl.SetCurrentPosition(PUB.AGV.data.TagNo) == false) + { + if (VAR.BOOL[eVarBool.FLAG_AUTORUN] && PUB.AGV.system1.agv_run) + PUB.AGV.AGVMoveStop("unknown tag no"); + + //존재하지 않는 태그가 읽히면 관련 오류를 표시한다. + } + else + { + //위치는 찾았다 해당 위치가 내 목적지라면 mark stop기능으로 전환한다 + + } + + + ////자동, 상하차 모드일때 RFID 가 타겟위치에 올때는 - 멈춤을 설정해준다 + //if (VAR.BOOL[eVarBool.FLAG_AUTORUN] == true && + // PUB.Result.CurrentPos == PUB.Result.TargetPos && + // PUB.Result.TargetPos != ePosition.NONE && + // (PUB.sm.RunStep == ERunStep.GODOWN || + // PUB.sm.RunStep == ERunStep.GOUP || + // PUB.sm.RunStep == ERunStep.GOHOME || + // PUB.sm.RunStep == ERunStep.GOCHARGE)) + //{ + // if (PUB.AGV.data.Sts == 'F' && dirForward == "0") //아래로 내려오고있음 + // { + // PUB.AGV.AGVMoveStop("AGV_DataReceive", arDev.Narumi.eStopOpt.MarkStop); + // PUB.Speak( Lang.다음마크위치에서정지합니다); + // } + // else if (PUB.AGV.data.Sts == 'B' && dirForward == "1") + // { + // //VAR.BOOL[eVarBool.FLAG_NEXTSTOP_MARK] = true; + // PUB.AGV.AGVMoveStop("AGV_DataReceive", arDev.Narumi.eStopOpt.MarkStop); + // PUB.Speak(Lang.다음마크위치에서정지합니다); + // } + //} } + break; + case arDev.Narumi.DataType.ACK: + PUB.logagv.Add($"AGV_[ACK]Receive : {PUB.AGV.ACKData}"); + break; + default: + PUB.logagv.Add($"AGV_DataReceive : {e.DataType}"); + break; - - ////자동, 상하차 모드일때 RFID 가 타겟위치에 올때는 - 멈춤을 설정해준다 - //if (VAR.BOOL[eVarBool.FLAG_AUTORUN] == true && - // PUB.Result.CurrentPos == PUB.Result.TargetPos && - // PUB.Result.TargetPos != ePosition.NONE && - // (PUB.sm.RunStep == ERunStep.GODOWN || - // PUB.sm.RunStep == ERunStep.GOUP || - // PUB.sm.RunStep == ERunStep.GOHOME || - // PUB.sm.RunStep == ERunStep.GOCHARGE)) - //{ - // if (PUB.AGV.data.Sts == 'F' && dirForward == "0") //아래로 내려오고있음 - // { - // PUB.AGV.AGVMoveStop("AGV_DataReceive", arDev.Narumi.eStopOpt.MarkStop); - // PUB.Speak( Lang.다음마크위치에서정지합니다); - // } - // else if (PUB.AGV.data.Sts == 'B' && dirForward == "1") - // { - // //VAR.BOOL[eVarBool.FLAG_NEXTSTOP_MARK] = true; - // PUB.AGV.AGVMoveStop("AGV_DataReceive", arDev.Narumi.eStopOpt.MarkStop); - // PUB.Speak(Lang.다음마크위치에서정지합니다); - // } - //} - - } - break; - case arDev.Narumi.DataType.ACK: - PUB.logagv.Add($"AGV_[ACK]Receive : {PUB.AGV.ACKData}"); - break; - default: - PUB.logagv.Add($"AGV_DataReceive : {e.DataType}"); - break; - + } + } + catch (Exception ex) + { + Console.WriteLine($"[AGV_DataReceive] {ex.Message}"); } - } } diff --git a/Cs_HMI/Project/StateMachine/_SPS.cs b/Cs_HMI/Project/StateMachine/_SPS.cs index ab2f615..20fba04 100644 --- a/Cs_HMI/Project/StateMachine/_SPS.cs +++ b/Cs_HMI/Project/StateMachine/_SPS.cs @@ -4,6 +4,7 @@ using System.Data; using System.Drawing; using System.Linq; using System.Text; +using System.Windows.Media.Animation; using AR; using arCtl; using COMM; @@ -113,9 +114,29 @@ namespace Project var ts = VAR.TIME.RUN(eVarTime.LastConn_BAT); if (ts.TotalSeconds > 3) { + Console.WriteLine($"bms connect to {PUB.setting.Port_BAT}"); PUB.BMS.PortName = PUB.setting.Port_BAT; PUB.BMS.Open(); + + PUB.BMS.BMSDataReceive += Bms_BMSDataReceive; + PUB.BMS.Message += Bms_Message; + PUB.BMS.ChargeDetect += BMS_ChargeDetect; + VAR.TIME.Update(eVarTime.LastConn_BAT); + VAR.TIME.Update(eVarTime.LastConnTry_BAT); + } + } + else if (PUB.BMS.IsValid == false) + { + var ts = VAR.TIME.RUN(eVarTime.LastConnTry_BAT); + if (ts.TotalSeconds > 10) + { + Console.WriteLine("bms auto disconnect"); + PUB.BMS.BMSDataReceive -= Bms_BMSDataReceive; + PUB.BMS.Message -= Bms_Message; + PUB.BMS.ChargeDetect -= BMS_ChargeDetect; + PUB.BMS.Close(); + VAR.TIME.Set(eVarTime.LastConn_BAT,DateTime.Now.AddSeconds(5)); } } //ConnectSerialPort(PUB.BMS, PUB.setting.Port_BAT, PUB.setting.Baud_BAT, diff --git a/Cs_HMI/Project/StateMachine/_Xbee.cs b/Cs_HMI/Project/StateMachine/_Xbee.cs index 020f08a..51c8a6b 100644 --- a/Cs_HMI/Project/StateMachine/_Xbee.cs +++ b/Cs_HMI/Project/StateMachine/_Xbee.cs @@ -35,7 +35,7 @@ namespace Project var targID = dataStr.Substring(0, 2); var targstr = dataStr.Substring(2); - if(byte.TryParse(targID,out byte tID)) + if (byte.TryParse(targID, out byte tID)) { if (PUB.setting.XBE_ID == tID) { @@ -61,13 +61,10 @@ namespace Project if (uint.TryParse(dataStr, out uint tagno2)) { var currPos = PUB.mapctl.agv.CurrentRFID;///.AGVMoveToRFID(; - if (currPos == 0) currPos = 10; - var pathRlt = PUB.mapctl.CalculatePath(currPos, tagno2); - if (pathRlt.Success == true) - { - PUB.log.AddI($"New Target:{tagno2}"); - } - else PUB.log.AddE($"Path Error {pathRlt.Message} : {tagno2}"); + if (PUB.mapctl.SetTargetPosition(tagno2)) + PUB.log.AddI($"New Target {tagno2}"); + else + PUB.log.AddE($"Path Error {tagno2}"); } else PUB.log.AddE($"Path Param Error :{dataStr}"); break; diff --git a/Cs_HMI/SubProject/AGVControl/MapControl.cs b/Cs_HMI/SubProject/AGVControl/MapControl.cs index b3d5807..f07898d 100644 --- a/Cs_HMI/SubProject/AGVControl/MapControl.cs +++ b/Cs_HMI/SubProject/AGVControl/MapControl.cs @@ -4,74 +4,15 @@ using System.Drawing; using System.Drawing.Drawing2D; using System.IO; using System.Linq; -using System.Security.Cryptography.X509Certificates; using System.Text.RegularExpressions; using System.Windows.Forms; using AGVControl.Models; using AR; +using COMM; namespace AGVControl { - public class RFIDConnection - { - public uint StartRFID { get; set; } - public uint EndRFID { get; set; } - public bool IsBidirectional { get; set; } - public float Distance { get; set; } - public List IntermediateRFIDs { get; set; } = new List(); - public override bool Equals(object obj) - { - if (obj is RFIDConnection other) - { - return (StartRFID == other.StartRFID && EndRFID == other.EndRFID) || - (IsBidirectional && other.IsBidirectional && - StartRFID == other.EndRFID && EndRFID == other.StartRFID); - } - return false; - } - - public override int GetHashCode() - { - return StartRFID.GetHashCode() ^ EndRFID.GetHashCode(); - } - } - public class PathResult - - { - public bool Success { get; set; } = false; - public string Message { get; set; } - public List Path { get; set; } - - - } - - public enum AGVMoveState - { - Stop = 0, - Run - } - - public enum AGVActionReasonCode - { - Unknown = 0, - NoPosition, // 위치 미확정(처음 기동) - NoPath, // 경로 없음 또는 현재 위치 미확정 - NotOnPath, // 현재 위치가 경로에 없음 - Arrived, // 경로의 마지막 지점(목적지 도달) - Normal, // 정상(다음 RFID 있음) - NeedTurn, - NoTurnPoint, - } - - public class AGVActionPrediction - { - public Direction Direction { get; set; } - public uint? NextRFID { get; set; } - public string Reason { get; set; } - public AGVActionReasonCode ReasonCode { get; set; } - public AGVMoveState MoveState { get; set; } // RUN 또는 STOP - } public partial class MapControl : Control { @@ -198,6 +139,9 @@ namespace AGVControl case "line": MouseMode = (eMouseMode.addrfidline); break; case "cline": MouseMode = (eMouseMode.addcustomline); break; case "point": MouseMode = (eMouseMode.addrfidpoint); break; + case "clear": + this.agv.MainPath.Clear(); + break; case "path": var input1 = AR.UTIL.InputBox("input start"); @@ -218,7 +162,6 @@ namespace AGVControl } var rlt = CalculatePath(vstart, vend); - if (rlt.Success == false) { MessageBox.Show(rlt.Message, "경로 계산", MessageBoxButtons.OK, MessageBoxIcon.Warning); @@ -640,6 +583,36 @@ namespace AGVControl #endregion #region 기타 메서드 + + private PointF DrawLineWithLength(Graphics graphics, Pen pen, PointF p1, PointF p2, float length) + { + // 두 점 사이의 벡터 계산 + float dx = p2.X - p1.X; + float dy = p2.Y - p1.Y; + + // 두 점 사이의 거리 계산 + float distance = (float)Math.Sqrt(dx * dx + dy * dy); + + // 거리가 0이면 선을 그릴 수 없음 + if (distance == 0) + return PointF.Empty; + + // 단위 벡터 계산 (방향) + float unitX = dx / distance; + float unitY = dy / distance; + + // 시작점에서 지정된 길이만큼 떨어진 끝점 계산 + PointF endPoint = new PointF( + p1.X + unitX * length, + p1.Y + unitY * length + ); + + // 선 그리기 + graphics.DrawLine(pen, p1, endPoint); + return endPoint; + } + + private void UpdateToolbarRects() { int x, y, c, row; @@ -651,44 +624,50 @@ namespace AGVControl //left toolbar x = TOOLBAR_MARGIN; y = 10; - toolbarRects.Add(new ToolBarItem { Idx = idx++, Title = "+", Bounds = new Rectangle(x, y, TOOLBAR_WIDTH - 2 * TOOLBAR_MARGIN, TOOLBAR_BUTTON_HEIGHT) }); - y += TOOLBAR_BUTTON_HEIGHT + TOOLBAR_MARGIN; - toolbarRects.Add(new ToolBarItem { Idx = idx++, Title = "-", Bounds = new Rectangle(x, y, TOOLBAR_WIDTH - 2 * TOOLBAR_MARGIN, TOOLBAR_BUTTON_HEIGHT) }); - - y += TOOLBAR_BUTTON_HEIGHT + TOOLBAR_MARGIN; - toolbarRects.Add(new ToolBarItem { Idx = idx++, Title = "1:1", Bounds = new Rectangle(x, y, TOOLBAR_WIDTH - 2 * TOOLBAR_MARGIN, TOOLBAR_BUTTON_HEIGHT) }); - - y += TOOLBAR_BUTTON_HEIGHT + TOOLBAR_MARGIN; - toolbarRects.Add(new ToolBarItem { Idx = idx++, Title = "Cut", Bounds = new Rectangle(x, y, TOOLBAR_WIDTH - 2 * TOOLBAR_MARGIN, TOOLBAR_BUTTON_HEIGHT) }); + var menu_left = new string[] { "+", "-", "1:1", "Cut" }; + foreach (var item in menu_left) + { + toolbarRects.Add(new ToolBarItem { Idx = idx++, Title = item, Bounds = new Rectangle(x, y, TOOLBAR_WIDTH - 2 * TOOLBAR_MARGIN, TOOLBAR_BUTTON_HEIGHT) }); + y += TOOLBAR_BUTTON_HEIGHT + TOOLBAR_MARGIN; + } //right toolbar y = 10; row = 0; x = DisplayRectangle.Right - TOOLBAR_WIDTHR - TOOLBAR_MARGIN; - toolbarRects.Add(new ToolBarItem { Idx = idx++, Title = "Text", Bounds = new Rectangle(x, y, TOOLBAR_WIDTHR - 2 * TOOLBAR_MARGIN, TOOLBAR_BUTTON_HEIGHT) }); - y += TOOLBAR_BUTTON_HEIGHT + TOOLBAR_MARGIN; - toolbarRects.Add(new ToolBarItem { Idx = idx++, Title = "Line", Bounds = new Rectangle(x, y, TOOLBAR_WIDTHR - 2 * TOOLBAR_MARGIN, TOOLBAR_BUTTON_HEIGHT) }); + var menu_right = new string[] { "Text", "Line", "Point", "Magnet", "Load", "Save", "Pos", "Path", "Clear" }; + foreach (var item in menu_right) + { + toolbarRects.Add(new ToolBarItem { Idx = idx++, Title = item, Bounds = new Rectangle(x, y, TOOLBAR_WIDTHR - 2 * TOOLBAR_MARGIN, TOOLBAR_BUTTON_HEIGHT) }); + y += TOOLBAR_BUTTON_HEIGHT + TOOLBAR_MARGIN; + } - y += TOOLBAR_BUTTON_HEIGHT + TOOLBAR_MARGIN; - toolbarRects.Add(new ToolBarItem { Idx = idx++, Title = "Point", Bounds = new Rectangle(x, y, TOOLBAR_WIDTHR - 2 * TOOLBAR_MARGIN, TOOLBAR_BUTTON_HEIGHT) }); - y += TOOLBAR_BUTTON_HEIGHT + TOOLBAR_MARGIN; - toolbarRects.Add(new ToolBarItem { Idx = idx++, Title = "Magnet", Bounds = new Rectangle(x, y, TOOLBAR_WIDTHR - 2 * TOOLBAR_MARGIN, TOOLBAR_BUTTON_HEIGHT) }); + //toolbarRects.Add(new ToolBarItem { Idx = idx++, Title = "Line", Bounds = new Rectangle(x, y, TOOLBAR_WIDTHR - 2 * TOOLBAR_MARGIN, TOOLBAR_BUTTON_HEIGHT) }); - y += TOOLBAR_BUTTON_HEIGHT + TOOLBAR_MARGIN; - toolbarRects.Add(new ToolBarItem { Idx = idx++, Title = "Load", Bounds = new Rectangle(x, y, TOOLBAR_WIDTHR - 2 * TOOLBAR_MARGIN, TOOLBAR_BUTTON_HEIGHT) }); + //y += TOOLBAR_BUTTON_HEIGHT + TOOLBAR_MARGIN; + //toolbarRects.Add(new ToolBarItem { Idx = idx++, Title = "Point", Bounds = new Rectangle(x, y, TOOLBAR_WIDTHR - 2 * TOOLBAR_MARGIN, TOOLBAR_BUTTON_HEIGHT) }); - y += TOOLBAR_BUTTON_HEIGHT + TOOLBAR_MARGIN; - toolbarRects.Add(new ToolBarItem { Idx = idx++, Title = "Save", Bounds = new Rectangle(x, y, TOOLBAR_WIDTHR - 2 * TOOLBAR_MARGIN, TOOLBAR_BUTTON_HEIGHT) }); + //y += TOOLBAR_BUTTON_HEIGHT + TOOLBAR_MARGIN; + //toolbarRects.Add(new ToolBarItem { Idx = idx++, Title = "Magnet", Bounds = new Rectangle(x, y, TOOLBAR_WIDTHR - 2 * TOOLBAR_MARGIN, TOOLBAR_BUTTON_HEIGHT) }); - y += TOOLBAR_BUTTON_HEIGHT + TOOLBAR_MARGIN; - toolbarRects.Add(new ToolBarItem { Idx = idx++, Title = "Pos", Bounds = new Rectangle(x, y, TOOLBAR_WIDTHR - 2 * TOOLBAR_MARGIN, TOOLBAR_BUTTON_HEIGHT) }); + //y += TOOLBAR_BUTTON_HEIGHT + TOOLBAR_MARGIN; + //toolbarRects.Add(new ToolBarItem { Idx = idx++, Title = "Load", Bounds = new Rectangle(x, y, TOOLBAR_WIDTHR - 2 * TOOLBAR_MARGIN, TOOLBAR_BUTTON_HEIGHT) }); - y += TOOLBAR_BUTTON_HEIGHT + TOOLBAR_MARGIN; - toolbarRects.Add(new ToolBarItem { Idx = idx++, Title = "Path", Bounds = new Rectangle(x, y, TOOLBAR_WIDTHR - 2 * TOOLBAR_MARGIN, TOOLBAR_BUTTON_HEIGHT) }); + //y += TOOLBAR_BUTTON_HEIGHT + TOOLBAR_MARGIN; + //toolbarRects.Add(new ToolBarItem { Idx = idx++, Title = "Save", Bounds = new Rectangle(x, y, TOOLBAR_WIDTHR - 2 * TOOLBAR_MARGIN, TOOLBAR_BUTTON_HEIGHT) }); + + //y += TOOLBAR_BUTTON_HEIGHT + TOOLBAR_MARGIN; + //toolbarRects.Add(new ToolBarItem { Idx = idx++, Title = "Pos", Bounds = new Rectangle(x, y, TOOLBAR_WIDTHR - 2 * TOOLBAR_MARGIN, TOOLBAR_BUTTON_HEIGHT) }); + + //y += TOOLBAR_BUTTON_HEIGHT + TOOLBAR_MARGIN; + //toolbarRects.Add(new ToolBarItem { Idx = idx++, Title = "Path", Bounds = new Rectangle(x, y, TOOLBAR_WIDTHR - 2 * TOOLBAR_MARGIN, TOOLBAR_BUTTON_HEIGHT) }); + + //y += TOOLBAR_BUTTON_HEIGHT + TOOLBAR_MARGIN; + //toolbarRects.Add(new ToolBarItem { Idx = idx++, Title = "Clear", Bounds = new Rectangle(x, y, TOOLBAR_WIDTHR - 2 * TOOLBAR_MARGIN, TOOLBAR_BUTTON_HEIGHT) }); } @@ -742,10 +721,10 @@ namespace AGVControl agv.CurrentRFID = rfidPoint; // 목적지가 설정되어 있고 경로가 있는 경우 검증 - if (agv.TargetRFID.IsEmpty == false && agv.CurrentPath.Count > 0) + if (agv.TargetRFID.IsEmpty == false && agv.MainPath.Count > 0) { // 현재 위치가 경로에 있는지 확인 - bool isOnPath = agv.CurrentPath.Contains(agv.CurrentRFID); + bool isOnPath = agv.MainPath.Contains(agv.CurrentRFID); if (!isOnPath) { @@ -795,6 +774,8 @@ namespace AGVControl var gScore = new Dictionary { { start, 0 } }; var fScore = new Dictionary { { start, Heuristic(start.Location, end.Location) } }; + var maxcount = 50; + var loopcount = 0; while (openList.Count > 0) { var current = openList.OrderBy(p => fScore.ContainsKey(p) ? fScore[p] : float.MaxValue).First(); @@ -827,7 +808,6 @@ namespace AGVControl return new PathResult { - Success = true, Path = openList, }; } @@ -841,7 +821,6 @@ namespace AGVControl } return new PathResult { - Success = true, Path = path, }; } @@ -853,53 +832,53 @@ namespace AGVControl private float Distance(Point a, Point b) { - var rfidA = RFIDPoints.FirstOrDefault(p => p.Location == a); - var rfidB = RFIDPoints.FirstOrDefault(p => p.Location == b); + return (float)Math.Sqrt(Math.Pow(a.X - b.X, 2) + Math.Pow(a.Y - b.Y, 2)); + //var rfidA = RFIDPoints.FirstOrDefault(p => p.Location == a); + //var rfidB = RFIDPoints.FirstOrDefault(p => p.Location == b); - if (rfidA == null || rfidB == null) return float.MaxValue; + //if (rfidA == null || rfidB == null) return float.MaxValue; - var connection = rfidConnections.FirstOrDefault(c => - (c.StartRFID == rfidA.Value && c.EndRFID == rfidB.Value) || - (c.IsBidirectional && c.StartRFID == rfidB.Value && c.EndRFID == rfidA.Value)); + //var connection = rfidConnections.FirstOrDefault(c => + // (c.P1.Value == rfidA.Value && c.P2.Value == rfidB.Value) || + // (c.IsBidirectional && c.P1.Value == rfidB.Value && c.P2.Value == rfidA.Value)); - if (connection != null) - { - return connection.Distance; - } + //if (connection != null) + //{ + // return connection.Distance; + //} - return float.MaxValue; + //return float.MaxValue; } - private List GetNeighbors(RFIDPoint point) + /// + /// 이웃포인터를 반환합니다 + /// + /// + /// + private List GetNeighbors(RFIDPoint pt) { var neighbors = new List(); - var currentRfidPoint = RFIDPoints.FirstOrDefault(p => p.Location == point.Location); - if (currentRfidPoint == null) return neighbors; - uint currentRfid = currentRfidPoint.Value; + //값이 없는 경우 오류 반환 + if (pt == null) return neighbors; + //연결정보에서 데이터를 찾은 후 반환한다 foreach (var connection in rfidConnections) { - uint neighborRfidVal = 0; - if (connection.StartRFID == currentRfid) + RFIDPoint nPT = null; + if (connection.P1.Value == pt.Value) { - neighborRfidVal = connection.EndRFID; + nPT = connection.P2; } - else if (connection.EndRFID == currentRfid && connection.IsBidirectional) + else if (connection.P2.Value == pt.Value) { - neighborRfidVal = connection.StartRFID; + nPT = connection.P1; } - if (neighborRfidVal != 0) - { - var neighborRfidPoint = RFIDPoints.FirstOrDefault(p => p.Value == neighborRfidVal); - if (neighborRfidPoint != null) - { - neighbors.Add(neighborRfidPoint); - } - } + if (nPT != null) neighbors.Add(nPT); } + //중복제거후 반한 return neighbors.Distinct().ToList(); } @@ -908,7 +887,6 @@ namespace AGVControl var retval = new PathResult { Message = string.Empty, - Success = false, Path = new List(), }; @@ -925,89 +903,13 @@ namespace AGVControl } retval = CalculatePath(startPoint, endPoint); - if (retval.Path != null && retval.Path.Any()) - { - //SetCurrentPath(retval.Path); - - //// 경로 상의 모든 RFID 값을 가져옴 - //var rfidPath = new List(); - //foreach (var point in path) - //{ - // var rfid = GetRFIDPoints() - // .FirstOrDefault(r => r.Location == point); - // if (rfid != null) - // { - // rfidPath.Add(rfid.RFIDValue); - // } - //} - retval.Success = true; - } - else - { + if (retval.Success == false) retval.Message = "경로를 찾을 수 없습니다"; - } + return retval; } - private void AddNearbyRFIDPoints(RFIDLine line) - { - const float NEARBY_DISTANCE = 20.0f; // 근처로 간주하는 거리를 50에서 20으로 줄임 - // 선 근처의 RFID 포인트들을 찾아서 거리에 따라 정렬 - var nearbyPoints = new List<(RFIDPoint Point, float Distance, float ProjectionRatio)>(); - - foreach (var rfid in RFIDPoints) - { - if (rfid.Location == line.StartPoint || rfid.Location == line.EndPoint) - continue; - - // 선분과 RFID 포인트 사이의 최단 거리 계산 - float distance = GetDistanceToLine(rfid.Location, line.StartPoint, line.EndPoint); - - if (distance <= NEARBY_DISTANCE) - { - // 시작점으로부터의 투영 비율 계산 (0~1 사이 값) - float projectionRatio = GetProjectionRatio(rfid.Location, line.StartPoint, line.EndPoint); - if (projectionRatio >= 0 && projectionRatio <= 1) // 선분 위에 있는 점만 포함 - { - nearbyPoints.Add((rfid, distance, projectionRatio)); - } - } - } - - // 시작점에서 끝점 방향으로 정렬 - nearbyPoints.Sort((a, b) => a.ProjectionRatio.CompareTo(b.ProjectionRatio)); - - // 이전 RFID 값과 위치를 저장 - //uint prevRFID = line.StartRFID; - Point prevPoint = line.StartPoint; - - // 정렬된 포인트들을 순차적으로 연결 - foreach (var item in nearbyPoints) - { - var rfidLine = new RFIDLine - { - StartPoint = prevPoint, - EndPoint = item.Point.Location, - - }; - rfidLines.Add(rfidLine); - - // 현재 포인트를 다음 선분의 시작점으로 설정 - prevPoint = item.Point.Location; - } - - // 마지막 포인트와 원래 선의 끝점을 연결 - var finalLine = new RFIDLine - { - StartPoint = prevPoint, - EndPoint = line.EndPoint, - }; - rfidLines.Add(finalLine); - - // 원래 선은 제거 - rfidLines.Remove(line); - } public void SetRFIDPoints(List points) @@ -1149,7 +1051,7 @@ namespace AGVControl public void SetCurrentPath(List path) { - agv.CurrentPath = path; + agv.MainPath = path; this.Invalidate(); } @@ -1167,7 +1069,7 @@ namespace AGVControl DrawPath(e.Graphics); DrawAGV(e.Graphics); - DrawAGVMotor(e.Graphics); + //DrawAGVMotor(e.Graphics); DrawTargetFlag(e.Graphics); // 목적지 깃발 그리기 추가 // 선택된 개체 강조 표시 @@ -1218,6 +1120,27 @@ namespace AGVControl e.Graphics.DrawString(str, this.Font, Brushes.Red, this.Right - strsize.Width - 10, this.Bottom - strsize.Height - 10); } + + //경로정보표시(임시) + var pathstr = ""; + if (agv.MainPath.Any()) + { + pathstr = "● Path : " + string.Join("▶", agv.MainPath.Select(t => t.Value).ToArray()); + //pathstr += "\n● Target Direction Match : " + (agv.IsTargetDirectionMatch ? "O" : "X"); + } + else pathstr = "● Path : no data"; + using (var f = new Font("Arial", 10, FontStyle.Bold)) + e.Graphics.DrawString(pathstr, f, Brushes.DeepSkyBlue, this.Left + 65, this.Top + 10); + + var histstr = ""; + if (agv.MovementHistory.Count > 1) + { + histstr = "● Route : " + string.Join("▶", agv.MovementHistory.Select(t => t.Value.ToString() + $"[{t.Direction.ToString()[0]}]").ToArray()); + } + else histstr = "● Route : no data"; + using (var f = new Font("Arial", 10, FontStyle.Bold)) + e.Graphics.DrawString(histstr, f, Brushes.DeepSkyBlue, this.Left + 65, this.Top + 30); + } private void DrawRFIDPoints(Graphics g) @@ -1249,6 +1172,19 @@ namespace AGVControl g.FillEllipse(brush, rfid.Bounds); } + // 회전가능 항목 테두리 색상 표시 + if (rfid.IsRotatable) + { + Color borderColor = Color.Yellow; + using (var pen = new Pen(borderColor, 2)) + { + g.DrawEllipse(pen, rfid.Bounds.Expand(16, 16)); + g.DrawEllipse(pen, rfid.Bounds.Expand(10, 10)); + g.DrawEllipse(pen, rfid.Bounds.Expand(4, 4)); + } + } + + // 고정방향이 있으면 테두리 색상 표시 if (rfid.FixedDirection.HasValue) { @@ -1288,11 +1224,48 @@ namespace AGVControl agvsize, agvsize); + //이동경로정보를 따라서 리프트의 위치를 표시해준다. + if (agv.MovementHistory.Any() && agv.MovementHistory.Count > 1) + { + var prept = agv.MovementHistory.Skip(agv.MovementHistory.Count - 2).First(); + var lstpt = agv.MovementHistory.Last(); + + RFIDPoint TargetPT = null; + + //뒤로이동하는경우라면 이전위치에 리프트가 있다. + if (lstpt.Direction == Direction.Backward) + { + TargetPT = prept; + } + else //앞으로이동한다면 이동방향과 동일하다 + { + //이전위치는 제거 하고 처음발견된 것을 대상으로 한다 + TargetPT = this.GetNeighbors(lstpt).Where(t => t.Value != prept.Value).FirstOrDefault(); + } + + if (TargetPT != null) + { + using (var p = new Pen(Color.Black, 3)) + { + var circleRadius = 6; + var pt = DrawLineWithLength(g, p, lstpt.Location, TargetPT.Location, 25); + var liftRect = new RectangleF(pt.X - circleRadius, pt.Y - circleRadius, circleRadius * 2, circleRadius * 2); + g.FillEllipse(Brushes.Black, liftRect); + + var liftColor = agv.IsTargetDirectionMatch ? Color.White : Color.HotPink; + using (var pBorder = new Pen(liftColor, 3)) + g.DrawEllipse(pBorder, liftRect); + } + } + } + + + // --- BodyAngle이 결정되지 않은 경우: 기본 방향으로 그림 --- Color bgcolor = agv.BatteryLevel > 80 ? Color.Lime : (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, 2)) + using (var circlePen = new Pen(Color.Black, 4)) g.DrawEllipse(circlePen, circleRect); //motor direction @@ -1305,13 +1278,14 @@ namespace AGVControl }); //body direction - str = agv.CurrentAGVDirection.ToString().Substring(0, 1).ToUpper(); + str = 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); + //DrawMovementHistoryArrows(g); } private void DrawAGVMotor(Graphics g) @@ -1354,20 +1328,20 @@ namespace AGVControl int alpha = Math.Max(50, 255 - (age * 50)); var directConnection = rfidConnections.FirstOrDefault(c => - (c.StartRFID == startRFID.rfid && c.EndRFID == endRFID.rfid) || - (c.IsBidirectional && c.StartRFID == endRFID.rfid && c.EndRFID == startRFID.rfid)); + (c.P1.Value == startRFID.Value && c.P2.Value == endRFID.Value) || + (c.P1.Value == endRFID.Value && c.P2.Value == startRFID.Value)); if (directConnection != null) { // 직접 연결된 경우: 실선 화살표 - Color arrowColor = (directConnection.StartRFID == startRFID.rfid) ? Color.Lime : Color.Red; + Color arrowColor = (directConnection.P1.Value == startRFID.Value) ? Color.Lime : Color.Red; arrowColor = Color.FromArgb(alpha, arrowColor); - DrawArrow(g, startRFID.Position, endRFID.Position, arrowColor, 3); + DrawArrow(g, startRFID.Location, endRFID.Location, arrowColor, 3); } else { // 직접 연결되지 않은 경우: 경로 탐색 후 점선 화살표 체인 - var pathResult = CalculatePath(startRFID.rfid, endRFID.rfid); + var pathResult = CalculatePath(startRFID.Value, endRFID.Value); if (pathResult.Success && pathResult.Path != null && pathResult.Path.Count > 1) { // 경로의 첫 단계 방향으로 전체 색상 결정 @@ -1377,12 +1351,12 @@ namespace AGVControl if (firstStepEndRfidPoint != null) { var firstStepConnection = rfidConnections.FirstOrDefault(c => - (c.StartRFID == startRFID.rfid && c.EndRFID == firstStepEndRfidPoint.Value) || - (c.IsBidirectional && c.StartRFID == firstStepEndRfidPoint.Value && c.EndRFID == startRFID.rfid)); + (c.P1.Value == startRFID.Value && c.P2.Value == firstStepEndRfidPoint.Value) || + (c.P1.Value == firstStepEndRfidPoint.Value && c.P2.Value == startRFID.Value)); if (firstStepConnection != null) { - arrowColor = (firstStepConnection.StartRFID == startRFID.rfid) ? Color.Lime : Color.Red; + arrowColor = (firstStepConnection.P1.Value == startRFID.Value) ? Color.Lime : Color.Red; } } @@ -1452,8 +1426,8 @@ namespace AGVControl // 화살표 끝점에서 약간 뒤로 이동 var arrowStart = new PointF( - end.X - (float)(arrowSize * Math.Cos(angle)), - end.Y - (float)(arrowSize * Math.Sin(angle)) + end.X - (float)(arrowSize / 4f * Math.Cos(angle)), + end.Y - (float)(arrowSize / 4f * Math.Sin(angle)) ); // 화살표 날개 그리기 @@ -1471,17 +1445,17 @@ namespace AGVControl } } - private void DrawCustomLines(Graphics g) - { - if (customLines == null) return; - foreach (var line in customLines) - { - using (Pen linePen = new Pen(line.LineColor, line.LineWidth)) - { - g.DrawLine(linePen, line.StartPoint, line.EndPoint); - } - } - } + //private void DrawCustomLines(Graphics g) + //{ + // if (customLines == null) return; + // foreach (var line in customLines) + // { + // using (Pen linePen = new Pen(line.LineColor, line.LineWidth)) + // { + // g.DrawLine(linePen, line.StartPoint, line.EndPoint); + // } + // } + //} private void DrawMapTexts(Graphics g) { @@ -1529,64 +1503,40 @@ namespace AGVControl var idx = 0; using (Font f = new Font("arial", 4)) { - foreach (var item in rfidLines) - { - var sp = item.StartPoint; - var ep = item.EndPoint; - using (var p = new Pen(Color.FromArgb(50, Color.White), 10)) - { - g.DrawLine(p, sp, ep); - var x = sp.X; - var y = sp.Y; - g.DrawString($"{idx}", f, Brushes.Gold, x, y); + //foreach (var item in rfidLines) + //{ + // var sp = item.StartPoint; + // var ep = item.EndPoint; + // using (var p = new Pen(Color.FromArgb(50, Color.White), 10)) + // { + // g.DrawLine(p, sp, ep); + // var x = sp.X; + // var y = sp.Y; + // g.DrawString($"{idx}", f, Brushes.Gold, x, y); - x = ep.X; - y = ep.Y; - g.DrawString($"{idx}", f, Brushes.Pink, x, y); - idx++; - } - } + // x = ep.X; + // y = ep.Y; + // g.DrawString($"{idx}", f, Brushes.Pink, x, y); + // idx++; + // } + //} } - + //연결정보에서 그림을 그린다. + var didx = 0; foreach (var connection in rfidConnections) { - var startPoint = RFIDPoints.FirstOrDefault(p => p.Value == connection.StartRFID)?.Location ?? Point.Empty; - var endPoint = RFIDPoints.FirstOrDefault(p => p.Value == connection.EndRFID)?.Location ?? Point.Empty; + didx += 1; + var startPoint = RFIDPoints.FirstOrDefault(p => p.Value == connection.P1.Value)?.Location ?? Point.Empty; + var endPoint = RFIDPoints.FirstOrDefault(p => p.Value == connection.P2.Value)?.Location ?? Point.Empty; if (startPoint.IsEmpty || endPoint.IsEmpty) continue; - using (Pen linePen = new Pen(Color.FromArgb(50, Color.Wheat), 2)) + //var lcolor = didx % 2 == 0 ? Color.White : Color.LightSkyBlue; + using (Pen linePen = new Pen(Color.FromArgb(30, Color.White), 10)) { - if (connection.IsBidirectional) - { - // 단방향 화살표 그리기 - var arrowSize = 10; - var angle = Math.Atan2(endPoint.Y - startPoint.Y, endPoint.X - startPoint.X); - var arrowPoint = new PointF( - endPoint.X - (float)(arrowSize * Math.Cos(angle)), - endPoint.Y - (float)(arrowSize * Math.Sin(angle)) - ); - g.DrawLine(linePen, startPoint, arrowPoint); - - // 화살표 머리 그리기 - var arrowAngle = Math.PI / 6; - var arrowLength = 15; - var arrow1 = new PointF( - arrowPoint.X - (float)(arrowLength * Math.Cos(angle - arrowAngle)), - arrowPoint.Y - (float)(arrowLength * Math.Sin(angle - arrowAngle)) - ); - var arrow2 = new PointF( - arrowPoint.X - (float)(arrowLength * Math.Cos(angle + arrowAngle)), - arrowPoint.Y - (float)(arrowLength * Math.Sin(angle + arrowAngle)) - ); - g.DrawLine(linePen, arrowPoint, arrow1); - g.DrawLine(linePen, arrowPoint, arrow2); - } - else - { - g.DrawLine(linePen, startPoint, endPoint); - } + g.DrawLine(linePen, startPoint, endPoint); + g.DrawLine(Pens.SlateGray, startPoint, endPoint); } } @@ -1604,7 +1554,7 @@ namespace AGVControl private void DrawPath(Graphics g) { - if (agv.CurrentPath == null || agv.CurrentPath.Count < 2) + if (agv.MainPath == null || agv.MainPath.Count < 2) return; Color pathColor = Color.FromArgb(100, Color.Lime); @@ -1613,9 +1563,9 @@ namespace AGVControl using (Pen pathPen = new Pen(pathColor, pathWidth)) { pathPen.DashStyle = System.Drawing.Drawing2D.DashStyle.Dash; - for (int i = 0; i < agv.CurrentPath.Count - 1; i++) + for (int i = 0; i < agv.MainPath.Count - 1; i++) { - g.DrawLine(pathPen, agv.CurrentPath[i].Location, agv.CurrentPath[i + 1].Location); + g.DrawLine(pathPen, agv.MainPath[i].Location, agv.MainPath[i + 1].Location); } } } @@ -1727,10 +1677,10 @@ namespace AGVControl lines.Add("[RFID_LINES]"); foreach (var connection in rfidConnections) { - var startPoint = RFIDPoints.First(p => p.Value == connection.StartRFID).Location; - var endPoint = RFIDPoints.First(p => p.Value == connection.EndRFID).Location; + var startPoint = RFIDPoints.First(p => p.Value == connection.P1.Value).Location; + var endPoint = RFIDPoints.First(p => p.Value == connection.P2.Value).Location; lines.Add($"{startPoint.X},{startPoint.Y},{endPoint.X},{endPoint.Y}," + - $"{connection.StartRFID},{connection.EndRFID},{connection.IsBidirectional},{connection.Distance}"); + $"{connection.P1},{connection.P2},{connection.DisableP1_to_P2}{connection.DisableP2_to_P1},{connection.Distance}"); } // 텍스트 저장 @@ -1907,13 +1857,15 @@ namespace AGVControl var key = $"{Math.Min(from, to)}_{Math.Max(from, to)}"; if (connectionSet.Contains(key)) continue; - var fromPt = RFIDPoints.FirstOrDefault(p => p.Value == from)?.Location ?? line.StartPoint; - var toPt = RFIDPoints.FirstOrDefault(p => p.Value == to)?.Location ?? line.EndPoint; + var fromItem = RFIDPoints.FirstOrDefault(p => p.Value == from); + var toItem = RFIDPoints.FirstOrDefault(p => p.Value == to); + var fromPt = fromItem?.Location ?? line.StartPoint; + var toPt = toItem?.Location ?? line.EndPoint; rfidConnections.Add(new RFIDConnection { - StartRFID = from, - EndRFID = to, + P1 = fromItem, + P2 = toItem, Distance = GetDistance(fromPt, toPt) }); connectionSet.Add(key); @@ -2040,134 +1992,305 @@ namespace AGVControl } } + /// + /// 목표지정으로 모터방향이 이동하고 있는가? + /// history 데이터가 있어야 하며 기준데이터가 없는 경우 null 반환 + /// + /// + public bool? IsMotDirection_To_Target() + { + if (agv.MovementHistory.Any() == false || agv.MovementHistory.Count < 2) return null; + if (agv.MainPath.Any() == false) return null; + var prept = agv.MovementHistory.Skip(agv.MovementHistory.Count - 2).First(); + var lstpt = agv.MovementHistory.Last(); + + //현재 이후의 경로를 가져온다 + var curidx = agv.MainPath.FindIndex(t => t.Value == lstpt.Value); + var preidx = agv.MainPath.FindIndex(t => t.Value == prept.Value); + if (curidx == -1 || preidx == -1) return null; + + //지정된경로 반대방향으로 이동하고 있다 + return preidx < curidx; + } + + /// + /// 리프트방향과 대상위치와의 방향이 일치하는가? + /// 목적지경로가 셋팅된 경우 현재 이동방향이 목적지방향과 일치하는가? + /// 이동경로정보가 없거나 목적지가 없으면 null 이 반환됨 + /// + /// + public bool? IsLiftDirectionMatch() + { + + if (agv.MovementHistory.Any() && agv.MovementHistory.Count > 1) + { + RFIDPoint TargetPT = null; + var prept = agv.MovementHistory.Skip(agv.MovementHistory.Count - 2).First(); + var lstpt = agv.MovementHistory.Last(); + + //뒤로이동하는경우라면 이전위치에 리프트가 있다. + if (lstpt.Direction == Direction.Backward) + { + TargetPT = prept; + } + else //앞으로 이동한다면 이동방향과 동일하다 + { + //이전위치는 제거 하고 처음발견된 것을 대상으로 한다 + TargetPT = this.GetNeighbors(lstpt).Where(t => t.Value != prept.Value).FirstOrDefault(); + } + + //목적지가 있다면 목적지의 방향과 일치하는지 확인해야한다 + //남은경로중에 방향이 고정된 핀이 있다면 그것과 일치하는지 확인해야 한다 + if (agv.MainPath.Any()) + { + //지정된경로 반대방향으로 이동하고 있다 + if ((IsMotDirection_To_Target() ?? false) == false) + { + return false; + } + else + { + var nextRoutes = agv.MainPath.Skip(agv.MainPath.FindIndex(t => t.Value == lstpt.Value) + 1).ToList(); + var DirectionMatch = true; + foreach (var item in nextRoutes) + { + if (item.FixedDirection != null && item.FixedDirection != lstpt.Direction) + { + DirectionMatch = false; + break; + } + } + return DirectionMatch; + } + } + else + { + //대상포인트와의 방향만 체크한다. + //고정대상이없다면 방향이 맞는것으로 한다 + return (TargetPT.FixedDirection ?? lstpt.Direction) == lstpt.Direction; + } + } + else + { + //이동된경로정보가 없다면 리프트 방향을 체크할 수 없으므로 대상과 위치가 맞지 않는걸로 기본값을 설정한다 + //이렇게 설정하면 대상으로 이동불가하고 뒤로 가도록 유도된다 + return null; + } + } + public AGVActionPrediction PredictResult = null; - // AGV 행동 예측 함수 + + //public static double Distance(this Point pt1, Point pt2) + //{ + // return Math.Sqrt(Math.Pow(pt1.X-pt2.X,2)+Math.Pow(pt1.Y-pt2.Y,2)); + //} + + // AGV 다음행동 예측 함수 public AGVActionPrediction PredictNextAction() { - // 1. 위치를 모를 때 (CurrentRFID가 0 또는 미설정) - if (agv.CurrentRFID.Value == 0) + try { - PredictResult = new AGVActionPrediction - { - Direction = Direction.Backward, - NextRFID = null, - Reason = "AGV 위치 미확정(처음 기동)", - ReasonCode = AGVActionReasonCode.NoPosition, - MoveState = AGVMoveState.Run - }; - return PredictResult; - } - // 2. 경로가 없거나 현재 위치가 경로에 없음 - if ((agv.CurrentPath?.Count ?? 0) < 2 ) - { - PredictResult = new AGVActionPrediction - { - Direction = agv.CurrentMOTDirection, - NextRFID = null, - Reason = "경로 없음 또는 현재 위치 미확정", - ReasonCode = AGVActionReasonCode.NoPath, - MoveState = AGVMoveState.Stop - }; - return PredictResult; - } + - // 3. 경로상에서 다음 RFID 예측 - int idx = agv.CurrentPath.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 - }; - return PredictResult; - } + // 0. 설정경로와 리프트 방향 체크 (경로설정이 없을때에는 직선이동경로내의 방향들과 체크한다) + agv.IsTargetDirectionMatch = IsLiftDirectionMatch() ?? false; - // 4. 목적지 도달 전, 방향 미리 판단 및 회전 위치 예측 - // 목적지 RFID 정보 - var destPoint = agv.CurrentPath.Last(); - var destRFID = RFIDPoints.FirstOrDefault(r => r.Value == destPoint.Value); // - if (destRFID != null && destRFID.FixedDirection.HasValue) //대상에 진입방향이 고정되어 있는지? - { - // 목적지에 도달할 때의 방향 예측 - if (agv.CurrentPath.Count >= 2) + + + // 1. 위치를 모를 때 (CurrentRFID가 0 또는 미설정) + if (agv.CurrentRFID.Value == 0) { - // 목적지 바로 전 위치에서 목적지로 이동할 때의 방향 - var beforeDest = agv.CurrentPath[agv.CurrentPath.Count - 2]; - float arriveDeltaX = destPoint.Location.X - beforeDest.Location.X; - float arriveDeltaY = destPoint.Location.Y - beforeDest.Location.Y; - Direction arriveDir = (Math.Abs(arriveDeltaX) > Math.Abs(arriveDeltaY)) ? - (arriveDeltaX > 0 ? Direction.Forward : Direction.Backward) : - (arriveDeltaY > 0 ? Direction.Forward : Direction.Backward); - if (arriveDir != destRFID.FixedDirection.Value) + PredictResult = new AGVActionPrediction { - // 목적지 도달 전, 마지막 회전 가능한 RFID를 찾음 - int lastRotatableIdx = -1; - for (int i = 0; i < agv.CurrentPath.Count - 1; i++) - { - var rfid = RFIDPoints.FirstOrDefault(r => r.Location == agv.CurrentPath[i].Location); - if (rfid != null && rfid.IsRotatable) - lastRotatableIdx = i; - } - if (lastRotatableIdx >= 0) - { - // 회전 가능한 위치에 도달하면 NeedTurn 반환 (STOP) - if (idx == lastRotatableIdx) - { - var rfid = RFIDPoints.FirstOrDefault(r => r.Location == agv.CurrentPath[lastRotatableIdx].Location); - PredictResult = new AGVActionPrediction - { - Direction = agv.CurrentMOTDirection, - NextRFID = rfid?.Value, - Reason = "목적지 진입방향 맞추기 위해 회전 필요", - ReasonCode = AGVActionReasonCode.NeedTurn, - MoveState = AGVMoveState.Stop - }; - return PredictResult; - } - else if (idx < lastRotatableIdx) - { - // 회전 가능한 위치까지 이동 안내 (RUN) - var rfid = RFIDPoints.FirstOrDefault(r => r.Location == agv.CurrentPath[lastRotatableIdx].Location); - float moveDeltaX = agv.CurrentPath[lastRotatableIdx].Location.X - agv.CurrentRFID.Location.X; - float moveDeltaY = agv.CurrentPath[lastRotatableIdx].Location.Y - agv.CurrentRFID.Location.Y; - Direction moveDir = (Math.Abs(moveDeltaX) > Math.Abs(moveDeltaY)) ? - (moveDeltaX > 0 ? Direction.Forward : Direction.Backward) : - (moveDeltaY > 0 ? Direction.Forward : Direction.Backward); - PredictResult = new AGVActionPrediction - { - Direction = moveDir, - NextRFID = rfid?.Value, - Reason = "회전 가능한 위치로 이동 중", - ReasonCode = AGVActionReasonCode.Normal, - MoveState = AGVMoveState.Run - }; - return PredictResult; - } - } - // 회전 가능한 위치가 없음 (STOP) - PredictResult = new AGVActionPrediction + Direction = Direction.Backward, + NextRFID = null, + Reason = "AGV 위치 미확정(처음 기동)", + ReasonCode = AGVActionReasonCode.NoPosition, + MoveState = AGVMoveState.Run + }; + 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 + }; + return PredictResult; + } + + + // 3. 경로가 없거나 현재 위치가 경로에 없음 + if ((agv.MainPath?.Count ?? 0) < 2) + { + PredictResult = new AGVActionPrediction + { + Direction = agv.CurrentMOTDirection, + NextRFID = null, + Reason = "경로 없음 또는 현재 위치 미확정", + ReasonCode = AGVActionReasonCode.NoPath, + MoveState = AGVMoveState.Stop + }; + return PredictResult; + } + + // 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 + }; + return PredictResult; + } + + + + // 4. 목적지 도달 전, 회전이 필요한경우인가? + // 목적지 RFID 정보 + var destRFID = agv.MainPath.Last(); + + //리프트 방향이 맞는가? + var IsLiftDir = IsLiftDirectionMatch() ?? false; + + //모션이동방향이 맞는가? + var IsMotDir = IsMotDirection_To_Target() ?? false; + + var PrePT = agv.MovementHistory.Skip(agv.MovementHistory.Count - 1).First(); + var curPT = agv.MovementHistory.Last(); + + + + //리프트방향이 맞지 않다면 회전가능한 위치로 이동을 해야한다 + if (IsLiftDir == false) + { + //회전가능한 위치로 이동을 해야한다 + + + + //1. 가까운 회전위치를 찾는다 + var nearTurnPoint = RFIDPoints.Where(t => t.IsRotatable)?.OrderBy(t => GetDistance(t.Location, agv.CurrentRFID.Location)).FirstOrDefault() ?? null; + if (nearTurnPoint == null) + { + return new AGVActionPrediction { Direction = agv.CurrentMOTDirection, NextRFID = null, - Reason = "경로상에 회전 가능한 위치가 없음", + Reason = "회전 가능한 위치가 없습니다", ReasonCode = AGVActionReasonCode.NoTurnPoint, MoveState = AGVMoveState.Stop }; - return PredictResult; } - } - } - // 5. 목적지 도달 시(방향이 맞는 경우) (STOP) - if (idx == agv.CurrentPath.Count - 1) - { + //2. 이동하기위한 경로계산 및 이동을 한다 (생성조건) + //2-1. 서브경로가없는경우 + //2-2. 시작과 종료번호가 다른 경우(경로가 변경이 되는 조건이다) + if (agv.SubPath.Any() == false || agv.SubPath.Count < 2 || + agv.SubPath.First().Value != PrePT.Value || + agv.SubPath.Last().Value != nearTurnPoint.Value) + { + var rlt = CalculatePath(PrePT, nearTurnPoint); //이전포인트도 추가를 해준다 + if (rlt.Success) agv.SubPath = rlt.Path; + else + { + agv.SubPath.Clear(); + return new AGVActionPrediction + { + Direction = agv.CurrentMOTDirection, + NextRFID = null, + Reason = "회전 위치까지의 경로를 계산할 수 없습니다", + ReasonCode = AGVActionReasonCode.PathCalcError, + MoveState = AGVMoveState.Stop + }; + } + } + + + //3. 턴위치까지 이동이 완료되지 않았다면 계속 이동을 하게한다 + if (agv.CurrentRFID.Value != nearTurnPoint.Value) + { + //현재 모터방향을 확인하여 대상까지 이동하도록 해야한다 + var curidx = agv.SubPath.FindIndex(t => t.Value == curPT.Value); + var preidx = agv.SubPath.FindIndex(t => t.Value == PrePT.Value); + Direction newdirection = agv.CurrentMOTDirection; + string message = "턴위치로 이동중"; + if (preidx > curidx) + { + //지정경로를 거꾸로 이동하고 있다 + if (agv.CurrentMOTDirection == Direction.Forward) + newdirection = Direction.Backward; + else + newdirection = Direction.Forward; + message += "(방향전환)"; + } + + return new AGVActionPrediction + { + Direction = newdirection, + NextRFID = null, + Reason = message, + ReasonCode = AGVActionReasonCode.MoveForTurn, + MoveState = AGVMoveState.Run, + }; + } + + + return new AGVActionPrediction + { + Direction = agv.CurrentMOTDirection, + NextRFID = null, + Reason = "턴 완료 대기", + ReasonCode = AGVActionReasonCode.NeedTurn, + MoveState = AGVMoveState.Stop + }; + } + + //리프트 방향이 맞다 + //모션방향이 맞지 않다면 이동방향을 변경해준다 + + //3. 턴위치까지 이동이 완료되지 않았다면 계속 이동을 하게한다 + if (agv.CurrentRFID.Value != destRFID.Value) + { + //현재 모터방향을 확인하여 대상까지 이동하도록 해야한다 + var curidx = agv.MainPath.FindIndex(t => t.Value == curPT.Value); + var preidx = agv.MainPath.FindIndex(t => t.Value == PrePT.Value); + Direction newdirection = agv.CurrentMOTDirection; + string message = "목적지 이동중"; + if (preidx > curidx) + { + //지정경로를 거꾸로 이동하고 있다 + if (agv.CurrentMOTDirection == Direction.Forward) + newdirection = Direction.Backward; + else + newdirection = Direction.Forward; + message += "(방향전환)"; + } + return new AGVActionPrediction + { + Direction = newdirection, + NextRFID = null, + Reason = message, + ReasonCode = AGVActionReasonCode.Normal, + MoveState = AGVMoveState.Run, + }; + } + + + // 5. 목적지 도달 시 PredictResult = new AGVActionPrediction { Direction = agv.CurrentMOTDirection, @@ -2178,27 +2301,19 @@ namespace AGVControl }; return PredictResult; } - - // 6. 일반 경로 주행 (RUN) - var nextPoint = agv.CurrentPath[idx + 1]; - var nextRFID = RFIDPoints.FirstOrDefault(r => r.Value == nextPoint.Value)?.Value; - - // X, Y 좌표 모두 고려한 방향 판단 - float deltaX = nextPoint.Location.X - agv.CurrentRFID.Location.X; - float deltaY = nextPoint.Location.Y - agv.CurrentRFID.Location.Y; - Direction nextDir = (Math.Abs(deltaX) > Math.Abs(deltaY)) ? - (deltaX > 0 ? Direction.Forward : Direction.Backward) : - (deltaY > 0 ? Direction.Forward : Direction.Backward); - - PredictResult = new AGVActionPrediction + catch (Exception ex) { - Direction = nextDir, - NextRFID = nextRFID, - Reason = null, - ReasonCode = AGVActionReasonCode.Normal, - MoveState = AGVMoveState.Run - }; - return PredictResult; + PredictResult = new AGVActionPrediction + { + Direction = agv.CurrentMOTDirection, + NextRFID = null, + Reason = $"ERR:{ex.Message}", + ReasonCode = AGVActionReasonCode.Unknown, + MoveState = AGVMoveState.Stop + }; + return PredictResult; + } + } #endregion diff --git a/Cs_HMI/SubProject/AGVControl/Models/AGV.cs b/Cs_HMI/SubProject/AGVControl/Models/AGV.cs index 8880fe3..636ff3d 100644 --- a/Cs_HMI/SubProject/AGVControl/Models/AGV.cs +++ b/Cs_HMI/SubProject/AGVControl/Models/AGV.cs @@ -3,6 +3,7 @@ using System.Drawing; using System.Collections.Generic; using System.Linq; using System.Security.Permissions; +using System.Windows.Forms; namespace AGVControl.Models { @@ -13,23 +14,23 @@ namespace AGVControl.Models Stop = 2 } - public class CRFIDData - { - public UInt16 rfid { get; set; } - public Point Position { get; set; } - public override string ToString() - { - return $"RFID:{rfid},P:{Position.X},{Position.Y}"; - } - } + //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 : CRFIDData + public class movehistorydata : RFIDPoint { - public Direction direction { get; set; } + public Direction Direction { get; set; } public override string ToString() { - return $"RFID:{rfid},DIR:{direction},P:{Position.X},{Position.Y}"; + return $"RFID:{Value},DIR:{Direction},P:{Location.X},{Location.Y}"; } } @@ -78,24 +79,32 @@ namespace AGVControl.Models /// public Direction TargetDirection { get; set; } = Direction.Stop; public bool IsMoving { get; set; } + public bool IsMarkCheck { get; set; } + public bool IsTargetDirectionMatch { get; set; } /// + /// 메인경로 /// 경로검색으로 입력된 경로 /// - public List CurrentPath { get; set; } = new List(); + public List MainPath { get; set; } = new List(); + + /// + /// 메인경로외에 거쳐가는 중간 경로 + /// + public List SubPath { get; set; } + - public List PlannedPath { get; set; } public List PathRFIDs { get; set; } // 이동 경로 기록을 위한 새로운 속성들 public List MovementHistory { get; } = new List(); - public const int HISTORY_SIZE = 4; // 최근 4개 위치 기록 + public const int HISTORY_SIZE = 10; // 최근 4개 위치 기록 public AGV() { - CurrentPath = new List(); - PlannedPath = new List(); + MainPath = new List(); + SubPath = new List(); PathRFIDs = new List(); CurrentRFID = new RFIDPoint(); @@ -110,10 +119,10 @@ namespace AGVControl.Models public void AddToMovementHistory(UInt16 rfidValue, Point position, Direction direction) { // 중복 RFID가 연속으로 들어오는 경우 무시 - if (MovementHistory.Count > 0 && MovementHistory.Last().rfid == rfidValue) + if (MovementHistory.Count > 0 && MovementHistory.Last().Value == rfidValue) return; - MovementHistory.Add(new movehistorydata { rfid = rfidValue, direction = direction, Position = position }); + MovementHistory.Add(new movehistorydata { Value = rfidValue, Direction = direction, Location = position }); // 기록 크기 제한 if (MovementHistory.Count > HISTORY_SIZE) @@ -122,7 +131,7 @@ namespace AGVControl.Models } //최초방향과 마지막 방향이 일치하지 않으면 그 이전의 데이터는 삭제한다. - if (MovementHistory.Count > 2 && MovementHistory.First().direction != MovementHistory.Last().direction) + if (MovementHistory.Count > 2 && MovementHistory.First().Direction != MovementHistory.Last().Direction) { var lastTwo = MovementHistory.Skip(MovementHistory.Count - 2).Take(2).ToArray(); // [9, 10] MovementHistory.Clear(); @@ -138,14 +147,14 @@ namespace AGVControl.Models // 이전 RFID에서 현재 RFID로의 연결 확인 var connection = connections.FirstOrDefault(c => - (c.StartRFID == previousRFID && c.EndRFID == currentRFID) || - (c.IsBidirectional && c.StartRFID == currentRFID && c.EndRFID == previousRFID)); + (c.P1.Value == previousRFID && c.P2.Value == currentRFID) || + (c.P1.Value == currentRFID && c.P2.Value == previousRFID)); if (connection == null) return null; // 연결되지 않은 경로 // 연결 방향에 따라 실제 이동 방향 결정 - if (connection.StartRFID == previousRFID && connection.EndRFID == currentRFID) + if (connection.P1.Value == previousRFID && connection.P2.Value == currentRFID) { return Direction.Forward; // Start -> End 방향으로 이동 } @@ -169,7 +178,7 @@ namespace AGVControl.Models var previousRFID = recentRFIDs[0]; var currentRFID = recentRFIDs[1]; - var actualDirection = CalculateActualDirectionByConnection(currentRFID.rfid, previousRFID.rfid, connections); + var actualDirection = CalculateActualDirectionByConnection(currentRFID.Value, previousRFID.Value, connections); if (!actualDirection.HasValue) return true; // 연결 정보로 방향 판단 불가 @@ -201,11 +210,11 @@ namespace AGVControl.Models var currentRFID = recentRFIDs[1]; // RFID 값의 증가/감소로 방향 판단 - if (currentRFID.rfid > prevRFID.rfid) + if (currentRFID.Value > prevRFID.Value) { return Direction.Forward; // RFID 값이 증가하면 전진 } - else if (currentRFID.rfid < prevRFID.rfid) + else if (currentRFID.Value < prevRFID.Value) { return Direction.Backward; // RFID 값이 감소하면 후진 } diff --git a/Cs_HMI/SubProject/AGVControl/Models/AGVActionPrediction.cs b/Cs_HMI/SubProject/AGVControl/Models/AGVActionPrediction.cs new file mode 100644 index 0000000..ca00e9e --- /dev/null +++ b/Cs_HMI/SubProject/AGVControl/Models/AGVActionPrediction.cs @@ -0,0 +1,14 @@ +using AGVControl.Models; + +namespace AGVControl +{ + public class AGVActionPrediction + { + public Direction Direction { get; set; } + public uint? NextRFID { get; set; } + public string Reason { get; set; } + public AGVActionReasonCode ReasonCode { get; set; } + public AGVMoveState MoveState { get; set; } // RUN 또는 STOP + } + +} diff --git a/Cs_HMI/SubProject/AGVControl/Models/PathResult.cs b/Cs_HMI/SubProject/AGVControl/Models/PathResult.cs new file mode 100644 index 0000000..463bdbe --- /dev/null +++ b/Cs_HMI/SubProject/AGVControl/Models/PathResult.cs @@ -0,0 +1,23 @@ +using AGVControl.Models; +using System.Collections.Generic; +using System.Linq; + +namespace AGVControl +{ + public class PathResult + + { + public bool Success + { + get + { + return Path != null && Path.Any(); + } + } + public string Message { get; set; } + public List Path { get; set; } + + + } + +} diff --git a/Cs_HMI/SubProject/AGVControl/Models/RFIDConnection.cs b/Cs_HMI/SubProject/AGVControl/Models/RFIDConnection.cs new file mode 100644 index 0000000..49fefcb --- /dev/null +++ b/Cs_HMI/SubProject/AGVControl/Models/RFIDConnection.cs @@ -0,0 +1,33 @@ +using AGVControl.Models; + +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 override bool Equals(object obj) + { + if (obj is RFIDConnection other) + { + return (P1 == other.P1 && P2 == other.P2); + } + return false; + } + + public override int GetHashCode() + { + return P1.GetHashCode() ^ P2.GetHashCode(); + } + public override string ToString() + { + //연결정보를 확인 + return $"{P1.Value} ↔ {P2.Value},P1-2:{(DisableP1_to_P2 ? "X" : "O")},P2-1:{(DisableP2_to_P1 ? "X" : "O")}"; + } + } +} diff --git a/Cs_HMI/SubProject/AGVControl/Models/RFIDPoint.cs b/Cs_HMI/SubProject/AGVControl/Models/RFIDPoint.cs index a511473..9853446 100644 --- a/Cs_HMI/SubProject/AGVControl/Models/RFIDPoint.cs +++ b/Cs_HMI/SubProject/AGVControl/Models/RFIDPoint.cs @@ -13,7 +13,6 @@ namespace AGVControl.Models public Direction? FixedDirection { get; set; } // 고정 방향(없으면 null) public bool IsTerminal { get; set; } // 종단 여부 public RectangleF Bounds { get; set; } - public void Clear() { this.Location = Point.Empty; @@ -38,5 +37,10 @@ namespace AGVControl.Models IsTerminal = false; // 기본값은 종단 아님 Clear(); } + + public override string ToString() + { + return $"[RFIDPoint] {Value},P:{Location.X},{Location.Y}"; + } } } \ No newline at end of file diff --git a/Cs_HMI/SubProject/AGVControl/Models/enumStruct.cs b/Cs_HMI/SubProject/AGVControl/Models/enumStruct.cs new file mode 100644 index 0000000..97c14d8 --- /dev/null +++ b/Cs_HMI/SubProject/AGVControl/Models/enumStruct.cs @@ -0,0 +1,30 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace AGVControl +{ + + public enum AGVMoveState + { + Stop = 0, + Run + } + + public enum AGVActionReasonCode + { + Unknown = 0, + NoPosition, // 위치 미확정(처음 기동) + NoPath, // 경로 없음 또는 현재 위치 미확정 + NotOnPath, // 현재 위치가 경로에 없음 + Arrived, // 경로의 마지막 지점(목적지 도달) + Normal, // 정상(다음 RFID 있음) + NeedTurn, + NoTurnPoint, + PathCalcError, + NoDirection, + MoveForTurn, + } +} \ No newline at end of file diff --git a/Cs_HMI/SubProject/AGVControl/agvControl.csproj b/Cs_HMI/SubProject/AGVControl/agvControl.csproj index 2a190a0..c7300d7 100644 --- a/Cs_HMI/SubProject/AGVControl/agvControl.csproj +++ b/Cs_HMI/SubProject/AGVControl/agvControl.csproj @@ -45,6 +45,7 @@ + Component @@ -57,16 +58,20 @@ GuideSensor.cs - + + Component + MapControl.cs + + @@ -82,6 +87,7 @@ True Resources.resx + Component @@ -105,6 +111,10 @@ + + {14e8c9a5-013e-49ba-b435-efefc77dd623} + CommData + {14e8c9a5-013e-49ba-b435-ffffff7dd623} arCommUtil diff --git a/Cs_HMI/SubProject/CommData/Enum.cs b/Cs_HMI/SubProject/CommData/Enum.cs index 295b01a..f1a89c8 100644 --- a/Cs_HMI/SubProject/CommData/Enum.cs +++ b/Cs_HMI/SubProject/CommData/Enum.cs @@ -112,6 +112,8 @@ namespace COMM /// 충전시작명령을 전송했다 /// WAIT_CHARGEACK, + + MARKSTOP_ON, //agv area start ( 64 ~ 95) diff --git a/Emulator/AGVEmulator/Form1.Designer.cs b/Emulator/AGVEmulator/Form1.Designer.cs index b71d024..0a14bb7 100644 --- a/Emulator/AGVEmulator/Form1.Designer.cs +++ b/Emulator/AGVEmulator/Form1.Designer.cs @@ -30,38 +30,44 @@ namespace AGVEmulator private void InitializeComponent() { this.components = new System.ComponentModel.Container(); - AGVEmulator.UC.AgvViewer.ptdata ptdata85 = new AGVEmulator.UC.AgvViewer.ptdata(); - AGVEmulator.UC.AgvViewer.ptdata ptdata86 = new AGVEmulator.UC.AgvViewer.ptdata(); - AGVEmulator.UC.AgvViewer.ptdata ptdata87 = new AGVEmulator.UC.AgvViewer.ptdata(); - AGVEmulator.UC.AgvViewer.ptdata ptdata88 = new AGVEmulator.UC.AgvViewer.ptdata(); - AGVEmulator.UC.AgvViewer.ptdata ptdata89 = new AGVEmulator.UC.AgvViewer.ptdata(); - AGVEmulator.UC.AgvViewer.ptdata ptdata90 = new AGVEmulator.UC.AgvViewer.ptdata(); - AGVEmulator.UC.AgvViewer.ptdata ptdata91 = new AGVEmulator.UC.AgvViewer.ptdata(); - AGVEmulator.UC.AgvViewer.ptdata ptdata92 = new AGVEmulator.UC.AgvViewer.ptdata(); - AGVEmulator.UC.AgvViewer.ptdata ptdata93 = new AGVEmulator.UC.AgvViewer.ptdata(); - AGVEmulator.UC.AgvViewer.ptdata ptdata94 = new AGVEmulator.UC.AgvViewer.ptdata(); - AGVEmulator.UC.AgvViewer.ptdata ptdata95 = new AGVEmulator.UC.AgvViewer.ptdata(); - AGVEmulator.UC.AgvViewer.ptdata ptdata96 = new AGVEmulator.UC.AgvViewer.ptdata(); - AGVEmulator.UC.AgvViewer.ptdata ptdata97 = new AGVEmulator.UC.AgvViewer.ptdata(); - AGVEmulator.UC.AgvViewer.ptdata ptdata98 = new AGVEmulator.UC.AgvViewer.ptdata(); - AGVEmulator.UC.AgvViewer.ptdata ptdata99 = new AGVEmulator.UC.AgvViewer.ptdata(); - AGVEmulator.UC.AgvViewer.ptdata ptdata100 = new AGVEmulator.UC.AgvViewer.ptdata(); - AGVEmulator.UC.AgvViewer.ptdata ptdata101 = new AGVEmulator.UC.AgvViewer.ptdata(); - AGVEmulator.UC.AgvViewer.ptdata ptdata102 = new AGVEmulator.UC.AgvViewer.ptdata(); - AGVEmulator.UC.AgvViewer.ptdata ptdata103 = new AGVEmulator.UC.AgvViewer.ptdata(); - AGVEmulator.UC.AgvViewer.ptdata ptdata104 = new AGVEmulator.UC.AgvViewer.ptdata(); - AGVEmulator.UC.AgvViewer.ptdata ptdata105 = new AGVEmulator.UC.AgvViewer.ptdata(); - AGVEmulator.UC.AgvViewer.ptdata ptdata106 = new AGVEmulator.UC.AgvViewer.ptdata(); - AGVEmulator.UC.AgvViewer.ptdata ptdata107 = new AGVEmulator.UC.AgvViewer.ptdata(); - AGVEmulator.UC.AgvViewer.ptdata ptdata108 = new AGVEmulator.UC.AgvViewer.ptdata(); - AGVEmulator.UC.AgvViewer.ptdata ptdata109 = new AGVEmulator.UC.AgvViewer.ptdata(); - AGVEmulator.UC.AgvViewer.ptdata ptdata110 = new AGVEmulator.UC.AgvViewer.ptdata(); - AGVEmulator.UC.AgvViewer.ptdata ptdata111 = new AGVEmulator.UC.AgvViewer.ptdata(); - AGVEmulator.UC.AgvViewer.ptdata ptdata112 = new AGVEmulator.UC.AgvViewer.ptdata(); + AGVEmulator.UC.AgvViewer.ptdata ptdata1 = new AGVEmulator.UC.AgvViewer.ptdata(); + AGVEmulator.UC.AgvViewer.ptdata ptdata2 = new AGVEmulator.UC.AgvViewer.ptdata(); + AGVEmulator.UC.AgvViewer.ptdata ptdata3 = new AGVEmulator.UC.AgvViewer.ptdata(); + AGVEmulator.UC.AgvViewer.ptdata ptdata4 = new AGVEmulator.UC.AgvViewer.ptdata(); + AGVEmulator.UC.AgvViewer.ptdata ptdata5 = new AGVEmulator.UC.AgvViewer.ptdata(); + AGVEmulator.UC.AgvViewer.ptdata ptdata6 = new AGVEmulator.UC.AgvViewer.ptdata(); + AGVEmulator.UC.AgvViewer.ptdata ptdata7 = new AGVEmulator.UC.AgvViewer.ptdata(); + AGVEmulator.UC.AgvViewer.ptdata ptdata8 = new AGVEmulator.UC.AgvViewer.ptdata(); + AGVEmulator.UC.AgvViewer.ptdata ptdata9 = new AGVEmulator.UC.AgvViewer.ptdata(); + AGVEmulator.UC.AgvViewer.ptdata ptdata10 = new AGVEmulator.UC.AgvViewer.ptdata(); + AGVEmulator.UC.AgvViewer.ptdata ptdata11 = new AGVEmulator.UC.AgvViewer.ptdata(); + AGVEmulator.UC.AgvViewer.ptdata ptdata12 = new AGVEmulator.UC.AgvViewer.ptdata(); + AGVEmulator.UC.AgvViewer.ptdata ptdata13 = new AGVEmulator.UC.AgvViewer.ptdata(); + AGVEmulator.UC.AgvViewer.ptdata ptdata14 = new AGVEmulator.UC.AgvViewer.ptdata(); + AGVEmulator.UC.AgvViewer.ptdata ptdata15 = new AGVEmulator.UC.AgvViewer.ptdata(); + AGVEmulator.UC.AgvViewer.ptdata ptdata16 = new AGVEmulator.UC.AgvViewer.ptdata(); + AGVEmulator.UC.AgvViewer.ptdata ptdata17 = new AGVEmulator.UC.AgvViewer.ptdata(); + AGVEmulator.UC.AgvViewer.ptdata ptdata18 = new AGVEmulator.UC.AgvViewer.ptdata(); + AGVEmulator.UC.AgvViewer.ptdata ptdata19 = new AGVEmulator.UC.AgvViewer.ptdata(); + AGVEmulator.UC.AgvViewer.ptdata ptdata20 = new AGVEmulator.UC.AgvViewer.ptdata(); + AGVEmulator.UC.AgvViewer.ptdata ptdata21 = new AGVEmulator.UC.AgvViewer.ptdata(); + AGVEmulator.UC.AgvViewer.ptdata ptdata22 = new AGVEmulator.UC.AgvViewer.ptdata(); + AGVEmulator.UC.AgvViewer.ptdata ptdata23 = new AGVEmulator.UC.AgvViewer.ptdata(); + AGVEmulator.UC.AgvViewer.ptdata ptdata24 = new AGVEmulator.UC.AgvViewer.ptdata(); + AGVEmulator.UC.AgvViewer.ptdata ptdata25 = new AGVEmulator.UC.AgvViewer.ptdata(); + AGVEmulator.UC.AgvViewer.ptdata ptdata26 = new AGVEmulator.UC.AgvViewer.ptdata(); + AGVEmulator.UC.AgvViewer.ptdata ptdata27 = new AGVEmulator.UC.AgvViewer.ptdata(); + AGVEmulator.UC.AgvViewer.ptdata ptdata28 = new AGVEmulator.UC.AgvViewer.ptdata(); System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(Form1)); this.groupBox1 = new System.Windows.Forms.GroupBox(); this.rtBMS = new arCtl.LogTextBox(); this.panel1 = new System.Windows.Forms.Panel(); + this.label11 = new System.Windows.Forms.Label(); + this.label10 = new System.Windows.Forms.Label(); + this.label9 = new System.Windows.Forms.Label(); + this.label8 = new System.Windows.Forms.Label(); + this.trbT2 = new System.Windows.Forms.TrackBar(); + this.trbT1 = new System.Windows.Forms.TrackBar(); this.btc8 = new System.Windows.Forms.Label(); this.btc4 = new System.Windows.Forms.Label(); this.btc7 = new System.Windows.Forms.Label(); @@ -154,14 +160,10 @@ namespace AGVEmulator this.sbBMS = new System.Windows.Forms.ToolStripStatusLabel(); this.toolStripStatusLabel2 = new System.Windows.Forms.ToolStripStatusLabel(); this.sbCAL = new System.Windows.Forms.ToolStripStatusLabel(); - this.trbT1 = new System.Windows.Forms.TrackBar(); - this.trbT2 = new System.Windows.Forms.TrackBar(); - this.label8 = new System.Windows.Forms.Label(); - this.label9 = new System.Windows.Forms.Label(); - this.label10 = new System.Windows.Forms.Label(); - this.label11 = new System.Windows.Forms.Label(); this.groupBox1.SuspendLayout(); this.panel1.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.trbT2)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.trbT1)).BeginInit(); ((System.ComponentModel.ISupportInitialize)(this.trackBar1)).BeginInit(); this.panel4.SuspendLayout(); this.groupBox9.SuspendLayout(); @@ -190,8 +192,6 @@ namespace AGVEmulator ((System.ComponentModel.ISupportInitialize)(this.nudTagNo)).BeginInit(); this.toolStrip1.SuspendLayout(); this.statusStrip1.SuspendLayout(); - ((System.ComponentModel.ISupportInitialize)(this.trbT1)).BeginInit(); - ((System.ComponentModel.ISupportInitialize)(this.trbT2)).BeginInit(); this.SuspendLayout(); // // groupBox1 @@ -257,6 +257,70 @@ namespace AGVEmulator this.panel1.Size = new System.Drawing.Size(1134, 103); this.panel1.TabIndex = 4; // + // label11 + // + this.label11.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(64)))), ((int)(((byte)(64)))), ((int)(((byte)(64))))); + this.label11.ForeColor = System.Drawing.Color.White; + this.label11.Location = new System.Drawing.Point(620, 68); + this.label11.Name = "label11"; + this.label11.Size = new System.Drawing.Size(75, 24); + this.label11.TabIndex = 19; + this.label11.Text = "Curr"; + this.label11.TextAlign = System.Drawing.ContentAlignment.MiddleCenter; + // + // label10 + // + this.label10.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(64)))), ((int)(((byte)(64)))), ((int)(((byte)(64))))); + this.label10.ForeColor = System.Drawing.Color.White; + this.label10.Location = new System.Drawing.Point(620, 12); + this.label10.Name = "label10"; + this.label10.Size = new System.Drawing.Size(75, 24); + this.label10.TabIndex = 18; + this.label10.Text = "Curr"; + this.label10.TextAlign = System.Drawing.ContentAlignment.MiddleCenter; + // + // label9 + // + this.label9.AutoSize = true; + this.label9.Location = new System.Drawing.Point(391, 72); + this.label9.Name = "label9"; + this.label9.Size = new System.Drawing.Size(44, 12); + this.label9.TabIndex = 17; + this.label9.Text = "Temp2"; + // + // label8 + // + this.label8.AutoSize = true; + this.label8.Location = new System.Drawing.Point(392, 18); + this.label8.Name = "label8"; + this.label8.Size = new System.Drawing.Size(44, 12); + this.label8.TabIndex = 16; + this.label8.Text = "Temp1"; + // + // trbT2 + // + this.trbT2.LargeChange = 10; + this.trbT2.Location = new System.Drawing.Point(442, 58); + this.trbT2.Maximum = 990; + this.trbT2.Name = "trbT2"; + this.trbT2.Size = new System.Drawing.Size(172, 45); + this.trbT2.SmallChange = 5; + this.trbT2.TabIndex = 15; + this.trbT2.Value = 200; + this.trbT2.Scroll += new System.EventHandler(this.trbT2_Scroll); + // + // trbT1 + // + this.trbT1.LargeChange = 10; + this.trbT1.Location = new System.Drawing.Point(442, 7); + this.trbT1.Maximum = 990; + this.trbT1.Name = "trbT1"; + this.trbT1.Size = new System.Drawing.Size(172, 45); + this.trbT1.SmallChange = 5; + this.trbT1.TabIndex = 14; + this.trbT1.Value = 200; + this.trbT1.Scroll += new System.EventHandler(this.trbT1_Scroll); + // // btc8 // this.btc8.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(64)))), ((int)(((byte)(64)))), ((int)(((byte)(64))))); @@ -828,6 +892,7 @@ namespace AGVEmulator 0, 0, 0}); + this.numericUpDown1.KeyDown += new System.Windows.Forms.KeyEventHandler(this.numericUpDown1_KeyDown); // // button18 // @@ -1030,120 +1095,120 @@ namespace AGVEmulator this.agvViewer1.lastmarkdir = ""; this.agvViewer1.lasttag = ""; this.agvViewer1.lasttagdir = ""; - ptdata85.active = false; - ptdata85.data = "NOT"; - ptdata85.pos = 30F; - ptdata86.active = false; - ptdata86.data = "QA"; - ptdata86.pos = 200F; - ptdata87.active = false; - ptdata87.data = "CHG"; - ptdata87.pos = 300F; - ptdata88.active = false; - ptdata88.data = "QC"; - ptdata88.pos = 400F; - ptdata89.active = false; - ptdata89.data = "#FVI-1"; - ptdata89.pos = 500F; - ptdata90.active = false; - ptdata90.data = "#FVI-2"; - ptdata90.pos = 600F; - ptdata91.active = false; - ptdata91.data = "#FVI-3"; - ptdata91.pos = 700F; - ptdata92.active = false; - ptdata92.data = "#FVI-4"; - ptdata92.pos = 800F; - ptdata93.active = false; - ptdata93.data = "#FVI-5"; - ptdata93.pos = 900F; - ptdata94.active = false; - ptdata94.data = "POT"; - ptdata94.pos = 970F; + ptdata1.active = false; + ptdata1.data = "NOT"; + ptdata1.pos = 30F; + ptdata2.active = false; + ptdata2.data = "QA"; + ptdata2.pos = 200F; + ptdata3.active = false; + ptdata3.data = "CHG"; + ptdata3.pos = 300F; + ptdata4.active = false; + ptdata4.data = "QC"; + ptdata4.pos = 400F; + ptdata5.active = false; + ptdata5.data = "#FVI-1"; + ptdata5.pos = 500F; + ptdata6.active = false; + ptdata6.data = "#FVI-2"; + ptdata6.pos = 600F; + ptdata7.active = false; + ptdata7.data = "#FVI-3"; + ptdata7.pos = 700F; + ptdata8.active = false; + ptdata8.data = "#FVI-4"; + ptdata8.pos = 800F; + ptdata9.active = false; + ptdata9.data = "#FVI-5"; + ptdata9.pos = 900F; + ptdata10.active = false; + ptdata10.data = "POT"; + ptdata10.pos = 970F; this.agvViewer1.listMRK = new AGVEmulator.UC.AgvViewer.ptdata[] { - ptdata85, - ptdata86, - ptdata87, - ptdata88, - ptdata89, - ptdata90, - ptdata91, - ptdata92, - ptdata93, - ptdata94}; - ptdata95.active = false; - ptdata95.data = "9000"; - ptdata95.pos = 80F; - ptdata96.active = false; - ptdata96.data = "9001"; - ptdata96.pos = 120F; - ptdata97.active = false; - ptdata97.data = "9010"; - ptdata97.pos = 180F; - ptdata98.active = false; - ptdata98.data = "9011"; - ptdata98.pos = 220F; - ptdata99.active = false; - ptdata99.data = "9020"; - ptdata99.pos = 280F; - ptdata100.active = false; - ptdata100.data = "9021"; - ptdata100.pos = 320F; - ptdata101.active = false; - ptdata101.data = "9030"; - ptdata101.pos = 380F; - ptdata102.active = false; - ptdata102.data = "9031"; - ptdata102.pos = 420F; - ptdata103.active = false; - ptdata103.data = "9040"; - ptdata103.pos = 480F; - ptdata104.active = false; - ptdata104.data = "9041"; - ptdata104.pos = 520F; - ptdata105.active = false; - ptdata105.data = "9050"; - ptdata105.pos = 580F; - ptdata106.active = false; - ptdata106.data = "9051"; - ptdata106.pos = 620F; - ptdata107.active = false; - ptdata107.data = "9060"; - ptdata107.pos = 680F; - ptdata108.active = false; - ptdata108.data = "9061"; - ptdata108.pos = 720F; - ptdata109.active = false; - ptdata109.data = "9070"; - ptdata109.pos = 780F; - ptdata110.active = false; - ptdata110.data = "9071"; - ptdata110.pos = 820F; - ptdata111.active = false; - ptdata111.data = "9000"; - ptdata111.pos = 10F; - ptdata112.active = false; - ptdata112.data = "9001"; - ptdata112.pos = 50F; + ptdata1, + ptdata2, + ptdata3, + ptdata4, + ptdata5, + ptdata6, + ptdata7, + ptdata8, + ptdata9, + ptdata10}; + ptdata11.active = false; + ptdata11.data = "9000"; + ptdata11.pos = 80F; + ptdata12.active = false; + ptdata12.data = "9001"; + ptdata12.pos = 120F; + ptdata13.active = false; + ptdata13.data = "9010"; + ptdata13.pos = 180F; + ptdata14.active = false; + ptdata14.data = "9011"; + ptdata14.pos = 220F; + ptdata15.active = false; + ptdata15.data = "9020"; + ptdata15.pos = 280F; + ptdata16.active = false; + ptdata16.data = "9021"; + ptdata16.pos = 320F; + ptdata17.active = false; + ptdata17.data = "9030"; + ptdata17.pos = 380F; + ptdata18.active = false; + ptdata18.data = "9031"; + ptdata18.pos = 420F; + ptdata19.active = false; + ptdata19.data = "9040"; + ptdata19.pos = 480F; + ptdata20.active = false; + ptdata20.data = "9041"; + ptdata20.pos = 520F; + ptdata21.active = false; + ptdata21.data = "9050"; + ptdata21.pos = 580F; + ptdata22.active = false; + ptdata22.data = "9051"; + ptdata22.pos = 620F; + ptdata23.active = false; + ptdata23.data = "9060"; + ptdata23.pos = 680F; + ptdata24.active = false; + ptdata24.data = "9061"; + ptdata24.pos = 720F; + ptdata25.active = false; + ptdata25.data = "9070"; + ptdata25.pos = 780F; + ptdata26.active = false; + ptdata26.data = "9071"; + ptdata26.pos = 820F; + ptdata27.active = false; + ptdata27.data = "9000"; + ptdata27.pos = 10F; + ptdata28.active = false; + ptdata28.data = "9001"; + ptdata28.pos = 50F; this.agvViewer1.listTAG = new AGVEmulator.UC.AgvViewer.ptdata[] { - ptdata95, - ptdata96, - ptdata97, - ptdata98, - ptdata99, - ptdata100, - ptdata101, - ptdata102, - ptdata103, - ptdata104, - ptdata105, - ptdata106, - ptdata107, - ptdata108, - ptdata109, - ptdata110, - ptdata111, - ptdata112}; + ptdata11, + ptdata12, + ptdata13, + ptdata14, + ptdata15, + ptdata16, + ptdata17, + ptdata18, + ptdata19, + ptdata20, + ptdata21, + ptdata22, + ptdata23, + ptdata24, + ptdata25, + ptdata26, + ptdata27, + ptdata28}; this.agvViewer1.Location = new System.Drawing.Point(241, 0); this.agvViewer1.Name = "agvViewer1"; this.agvViewer1.Size = new System.Drawing.Size(899, 120); @@ -1430,70 +1495,6 @@ namespace AGVEmulator this.sbCAL.Size = new System.Drawing.Size(19, 17); this.sbCAL.Text = "●"; // - // trbT1 - // - this.trbT1.LargeChange = 10; - this.trbT1.Location = new System.Drawing.Point(442, 7); - this.trbT1.Maximum = 990; - this.trbT1.Name = "trbT1"; - this.trbT1.Size = new System.Drawing.Size(172, 45); - this.trbT1.SmallChange = 5; - this.trbT1.TabIndex = 14; - this.trbT1.Value = 200; - this.trbT1.Scroll += new System.EventHandler(this.trbT1_Scroll); - // - // trbT2 - // - this.trbT2.LargeChange = 10; - this.trbT2.Location = new System.Drawing.Point(442, 58); - this.trbT2.Maximum = 990; - this.trbT2.Name = "trbT2"; - this.trbT2.Size = new System.Drawing.Size(172, 45); - this.trbT2.SmallChange = 5; - this.trbT2.TabIndex = 15; - this.trbT2.Value = 200; - this.trbT2.Scroll += new System.EventHandler(this.trbT2_Scroll); - // - // label8 - // - this.label8.AutoSize = true; - this.label8.Location = new System.Drawing.Point(392, 18); - this.label8.Name = "label8"; - this.label8.Size = new System.Drawing.Size(44, 12); - this.label8.TabIndex = 16; - this.label8.Text = "Temp1"; - // - // label9 - // - this.label9.AutoSize = true; - this.label9.Location = new System.Drawing.Point(391, 72); - this.label9.Name = "label9"; - this.label9.Size = new System.Drawing.Size(44, 12); - this.label9.TabIndex = 17; - this.label9.Text = "Temp2"; - // - // label10 - // - this.label10.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(64)))), ((int)(((byte)(64)))), ((int)(((byte)(64))))); - this.label10.ForeColor = System.Drawing.Color.White; - this.label10.Location = new System.Drawing.Point(620, 12); - this.label10.Name = "label10"; - this.label10.Size = new System.Drawing.Size(75, 24); - this.label10.TabIndex = 18; - this.label10.Text = "Curr"; - this.label10.TextAlign = System.Drawing.ContentAlignment.MiddleCenter; - // - // label11 - // - this.label11.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(64)))), ((int)(((byte)(64)))), ((int)(((byte)(64))))); - this.label11.ForeColor = System.Drawing.Color.White; - this.label11.Location = new System.Drawing.Point(620, 68); - this.label11.Name = "label11"; - this.label11.Size = new System.Drawing.Size(75, 24); - this.label11.TabIndex = 19; - this.label11.Text = "Curr"; - this.label11.TextAlign = System.Drawing.ContentAlignment.MiddleCenter; - // // Form1 // this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 12F); @@ -1509,6 +1510,8 @@ namespace AGVEmulator this.groupBox1.ResumeLayout(false); this.panel1.ResumeLayout(false); this.panel1.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.trbT2)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.trbT1)).EndInit(); ((System.ComponentModel.ISupportInitialize)(this.trackBar1)).EndInit(); this.panel4.ResumeLayout(false); this.groupBox9.ResumeLayout(false); @@ -1547,8 +1550,6 @@ namespace AGVEmulator this.toolStrip1.PerformLayout(); this.statusStrip1.ResumeLayout(false); this.statusStrip1.PerformLayout(); - ((System.ComponentModel.ISupportInitialize)(this.trbT1)).EndInit(); - ((System.ComponentModel.ISupportInitialize)(this.trbT2)).EndInit(); this.ResumeLayout(false); this.PerformLayout(); diff --git a/Emulator/AGVEmulator/Form1.cs b/Emulator/AGVEmulator/Form1.cs index 337ad4a..c3286bc 100644 --- a/Emulator/AGVEmulator/Form1.cs +++ b/Emulator/AGVEmulator/Form1.cs @@ -590,6 +590,12 @@ namespace AGVEmulator } + private void numericUpDown1_KeyDown(object sender, KeyEventArgs e) + { + if (e.KeyCode == Keys.Enter) + button18.PerformClick(); + } + private void trbT2_Scroll(object sender, EventArgs e) { Temp2 = (UInt16)trbT2.Value;