private void cbbPickNode_DropDownClosed(object sender, EventArgs e) { // If task type is Input, or type is Output and use palletcode to pick, do notthing if (cbbType.Text == "Input") { return; } if (cbbType.Text == "Output" && checkBox.Checked == true) { return; } List <RackColumn> listColumn = new List <RackColumn>(); switch (Display.Mode) { case "Real Time": listColumn = RackColumn.ListColumn; break; case "Simulation": listColumn = RackColumn.SimListColumn; break; } // If task type is Output, get palletCode and put it in txbPalletCode string[] textArr = cbbPickNode.Text.Split(new char[] { '-' }, StringSplitOptions.RemoveEmptyEntries); if (textArr.Length == 0) { return; } RackColumn column = listColumn.Find(c => c.AtNode.ToString() == textArr[0]); // textArr[0] is node txbPalletCode.Text = column.PalletCodes[Convert.ToInt16(textArr[1]) - 1]; // textArr[1] is level }
private void rdbtnSimulation_CheckedChanged(object sender, EventArgs e) { if (!rdbtnSimulation.Checked) { return; } rdbtnSimulation.ForeColor = Color.DarkRed; rdbtnRealTime.ForeColor = SystemColors.ActiveCaptionText; rdbtnSimulation.BackColor = Color.MintCream; rdbtnRealTime.BackColor = Color.Lavender; btnPauseRun.Visible = true; lbModeStatus.Text = " Simulation mode is running."; Display.Mode = "Simulation"; timerComStatus.Enabled = false; // Add label of columns at node RackColumn.ListColumn.ForEach(col => RackColumn.RemoveLabelColumn(pnFloor, col)); RackColumn.SimListColumn.ForEach(col => pnFloor.Controls.Add(col.ColumnLabel)); // Remove real time label, add simulation label AGV.ListAGV.ForEach(agv => Display.RemoveLabelAGV(pnFloor, agv.ID)); foreach (AGV agv in AGV.SimListAGV) { Display.AddLabelAGV(pnFloor, agv.ID, agv.ExitNode, agv.Orientation, agv.DistanceToExitNode); } // Clear draw path in panel Display.Points = new Point[] { new Point(), new Point() }; pnFloor.Refresh(); }
private void HomeScreenForm_Load(object sender, EventArgs e) { // Update existing pallets in stock and add to RackColumn Pallet.ListPallet = DBUtility.GetPalletInfoFromDB <List <Pallet> >("PalletInfoTable"); RackColumn.InitializePallet(RackColumn.ListColumn, Pallet.ListPallet); Pallet.SimListPallet = DBUtility.GetPalletInfoFromDB <List <Pallet> >("SimPalletInfoTable"); RackColumn.InitializePallet(RackColumn.SimListColumn, Pallet.SimListPallet); }
public static void RemoveLabelColumn(Panel panel, RackColumn col) { var label = panel.Controls.OfType <Label>().FirstOrDefault(lb => lb.Name == "ColumnAtNode" + col.AtNode.ToString()); if (label != null) { panel.Controls.Remove(label); } }
// Auto select drop node and rack level, return {0, 0} when warwhouse is full private static int[] AutoSelectDropNode(List <Task> listTask, List <RackColumn> listColumn) { int[] dropNode = new int[2]; // dropNode[0] is drop node, dropNode[1] is drop level // select block has the least number of pallet string selectedBlock; int blockA_PalletCount = PalletCountInBlock(listTask, listColumn, "A"); int blockB_PalletCount = PalletCountInBlock(listTask, listColumn, "B"); int blockC_PalletCount = PalletCountInBlock(listTask, listColumn, "C"); int blockD_PalletCount = PalletCountInBlock(listTask, listColumn, "D"); if (blockA_PalletCount < 6 * 3) { selectedBlock = "A"; // 6 column and 3 rack level in each block -> 18 pallet max } else if (blockB_PalletCount < 6 * 3) { selectedBlock = "B"; } else if (blockC_PalletCount < 6 * 3) { selectedBlock = "C"; } else if (blockD_PalletCount < 6 * 3) { selectedBlock = "D"; } else { return new int[2] { 0, 0 } }; // warehouse is full // find column number has the least pallet count int columnNumber = ColumnHasLeastPalletCount(listTask, listColumn, selectedBlock); // find node base on selected block & column number RackColumn col = listColumn.Find(c => c.Block == selectedBlock && c.Number == columnNumber); dropNode[0] = col.AtNode; // select level of that node for (int i = 0; i < col.PalletCodes.Length; i++) { List <int> dropLevelOnGoing = PalletOnGoing <List <int> >(col, listTask); // select level not have pallet code and no exist in dropLevelOnGoing if (col.PalletCodes[i] == null && dropLevelOnGoing.Contains(i + 1) == false) { dropNode[1] = i + 1; break; } } return(dropNode); }
private void WarehouseDataForm_FormClosed(object sender, FormClosedEventArgs e) { // Clear all list pallet and column for update Pallet.ListPallet.Clear(); Pallet.SimListPallet.Clear(); RackColumn.ListColumn.ForEach(c => Array.Clear(c.PalletCodes, 0, 3)); RackColumn.SimListColumn.ForEach(c => Array.Clear(c.PalletCodes, 0, 3)); // Update existing pallets in stock and add to RackColumn Pallet.ListPallet = DBUtility.GetPalletInfoFromDB <List <Pallet> >("PalletInfoTable"); RackColumn.InitializePallet(RackColumn.ListColumn, Pallet.ListPallet); Pallet.SimListPallet = DBUtility.GetPalletInfoFromDB <List <Pallet> >("SimPalletInfoTable"); RackColumn.InitializePallet(RackColumn.SimListColumn, Pallet.SimListPallet); }
public static void InitializePallet(List <RackColumn> listColumn, List <Pallet> listPallet) { foreach (Pallet pallet in listPallet) { // find location of this pallet RackColumn col = listColumn.Find(c => (c.Block == pallet.AtBlock) && (c.Number == pallet.AtColumn)); if (col == null) { continue; } // add to level at this column col.PalletCodes[pallet.AtLevel - 1] = pallet.Code; } }
// Update position AGV icon in simulation mode (speed: cm/s) public static Point UpdatePositionAGV(int agvID) { // Find AGV in ListAGV var index = AGV.ListAGV.FindIndex(a => a.ID == agvID); AGV agv = AGV.ListAGV[index]; Point position = new Point(); // If this node is pick node, remove pallet code that was picked and save this time if (agv.Tasks.Count != 0 && agv.ExitNode == agv.Tasks[0].PickNode) { RackColumn column = RackColumn.ListColumn.Find(c => c.AtNode == agv.ExitNode); Pallet.SaveDeliveryTime(column.PalletCodes[agv.Tasks[0].PickLevel - 1], Pallet.ListPallet); DBUtility.UpdatePalletDB("PalletInfoTable", column.PalletCodes[agv.Tasks[0].PickLevel - 1], false, DateTime.Now.ToString("dddd, MMMM dd, yyyy h:mm:ss tt"), Pallet.ListPallet); column.PalletCodes[agv.Tasks[0].PickLevel - 1] = null; } // Update label position List <Node> Nodes = Node.ListNode; int pixelDistance = (int)Math.Round(agv.DistanceToExitNode * Display.Scale); int x = Nodes[agv.ExitNode].X - Display.LabelAGV[agvID].Size.Width / 2; int y = Nodes[agv.ExitNode].Y - Display.LabelAGV[agvID].Size.Height / 2; switch (agv.Orientation) { case 'E': position.X = x + pixelDistance; position.Y = y; break; case 'W': position.X = x - pixelDistance; position.Y = y; break; case 'N': position.X = x; position.Y = y - pixelDistance; break; case 'S': position.X = x; position.Y = y + pixelDistance; break; } return(position); }
private void rdbtnRealTime_CheckedChanged(object sender, EventArgs e) { if (!rdbtnRealTime.Checked) { return; } rdbtnRealTime.ForeColor = Color.DarkRed; rdbtnSimulation.ForeColor = SystemColors.ActiveCaptionText; rdbtnRealTime.BackColor = Color.MintCream; rdbtnSimulation.BackColor = Color.Lavender; btnPauseRun.Visible = false; if (Communicator.SerialPort.IsOpen) { lbModeStatus.Text = " Connection: " + Communicator.SerialPort.PortName + " [" + Communicator.SerialPort.BaudRate.ToString() + "-" + Communicator.SerialPort.Parity + "-" + Communicator.SerialPort.DataBits.ToString() + "-" + Communicator.SerialPort.StopBits + "]"; } else { lbModeStatus.Text = " Please set communication to run."; } Display.Mode = "Real Time"; timerComStatus.Enabled = true; // Add label of columns at node RackColumn.SimListColumn.ForEach(col => RackColumn.RemoveLabelColumn(pnFloor, col)); RackColumn.ListColumn.ForEach(col => pnFloor.Controls.Add(col.ColumnLabel)); // Remove simulation label, add real time label AGV.SimListAGV.ForEach(agv => Display.RemoveLabelAGV(pnFloor, agv.ID)); foreach (AGV agv in AGV.ListAGV) { Display.AddLabelAGV(pnFloor, agv.ID, agv.ExitNode, agv.Orientation, agv.DistanceToExitNode); } // Clear draw path in panel Display.Points = new Point[] { new Point(), new Point() }; pnFloor.Refresh(); }
public static void OutputAutoAdd(string palletCode, List <Task> listTaskToAdd, List <AGV> listAGV, List <RackColumn> listColumn) { // auto select agv if (listAGV.Count == 0) { return; } int agvID = AutoSelectAGV(listAGV); // find pick node & level RackColumn col = listColumn.Find(c => c.PalletCodes.Contains(palletCode)); int pickNode = col.AtNode; int pickLevel = Array.IndexOf(col.PalletCodes, palletCode) + 1; // select drop node (output1 or output2) int dropNode = agvID % 2 == 1 ? 51 : 52; Task newTask = new Task("Auto " + palletCode, "Output", palletCode, agvID, pickNode, dropNode, pickLevel, 1, "Waiting"); listTaskToAdd.Add(newTask); }
public static dynamic PalletOnGoing <T>(RackColumn column, List <Task> listTask) { int count = 0; List <int> listDropLevel = new List <int>(); List <Task> listTaskOnGoing = listTask.FindAll(t => t.DropNode == column.AtNode); count = listTaskOnGoing.Count; listTaskOnGoing.ForEach(t => listDropLevel.Add(t.DropLevel)); if (typeof(T) == typeof(int)) { return(count); } else if (typeof(T) == typeof(List <int>)) { return(listDropLevel); } else { return(null); } }
// Get list of rack column private static List <RackColumn> GetRackColums() { List <RackColumn> listCol = new List <RackColumn>(); foreach (Node n in Node.ListNode) { if (n.LocationCode.Length == 0 || n.ID == 55 || n.ID == 56) { continue; } RackColumn col = new RackColumn(n.ID); if (col.Number == 1 || col.Number == 2 || col.Number == 3) { col.ColumnLabel.BackColor = SystemColors.ControlLight; col.ColumnLabel.Size = new Size(60 - 1, 35 - 2); col.ColumnLabel.Name = "ColumnAtNode" + n.ID.ToString(); int x = n.X - col.ColumnLabel.Size.Width / 2; int y = n.Y + 35 + 3; col.ColumnLabel.Location = new Point(x, y); } else if (col.Number == 4 || col.Number == 5 || col.Number == 6) { col.ColumnLabel.BackColor = SystemColors.ControlLight; col.ColumnLabel.Size = new Size(60 - 1, 35 - 2); col.ColumnLabel.Name = "ColumnAtNode" + n.ID.ToString(); int x = n.X - col.ColumnLabel.Size.Width / 2; int y = n.Y - 35 - 3 - col.ColumnLabel.Size.Height; col.ColumnLabel.Location = new Point(x, y); } listCol.Add(col); } return(listCol); }
private void timerGUI_Tick(object sender, EventArgs e) { // Show time now DateTime time = DateTime.Now; lbTime.Text = time.ToString("dddd, MMMM dd, yyyy h:mm:ss tt"); if (Display.Mode == "Real Time") { // Update data in listView AGVs Display.UpdateListViewAGVs(listViewAGVs, AGV.ListAGV); // Update data in listView Tasks Display.UpdateListViewTasks(listViewTasks, Task.ListTask); // Update column color of SimListColumn RackColumn.UpdateColumnColor(RackColumn.ListColumn); // Update location of AGV icon (label) foreach (AGV agv in AGV.ListAGV) { Display.LabelAGV[agv.ID].Location = Display.UpdatePositionAGV(agv.ID); // Display agv carrying pallet if (agv.Tasks.Count != 0 && agv.Tasks[0].Status == "Doing") { Display.LabelAGV[agv.ID].BackColor = Color.CornflowerBlue; } else { Display.LabelAGV[agv.ID].BackColor = Color.Silver; } // If goal was reached, remove old path, get next path (if exist) if (agv.Path.Count == 0) { continue; } if (agv.ExitNode == agv.Path.LastOrDefault()) { Task.AddNextPathOfAGV(agv); } } // Update button add pallet if (isPickPalletInput1 == true) { btnAddPallet1.Text = "Add"; btnAddPallet1.BackColor = Color.WhiteSmoke; } if (isPickPalletInput2 == true) { btnAddPallet2.Text = "Add"; btnAddPallet2.BackColor = Color.WhiteSmoke; } } else if (Display.Mode == "Simulation") { // Update data in listView AGVs Display.UpdateListViewAGVs(listViewAGVs, AGV.SimListAGV); // Update data in listView Tasks Display.UpdateListViewTasks(listViewTasks, Task.SimListTask); // Update column color of SimListColumn RackColumn.UpdateColumnColor(RackColumn.SimListColumn); // If pause simulation is selected if (Display.SimPause == true) { return; } // Detect collision Collision.Detect(AGV.SimListAGV); // Update position of AGV icon (label) foreach (AGV agv in AGV.SimListAGV) { if (agv.Path.Count != 0) { agv.Velocity = AGV.SimSpeed; } else { agv.Velocity = 0f; } Display.SimLabelAGV[agv.ID].Location = Display.SimUpdatePositionAGV(agv.ID, agv.Velocity); // Display agv carrying pallet if (agv.Tasks.Count != 0 && agv.Tasks[0].Status == "Doing") { Display.SimLabelAGV[agv.ID].BackColor = Color.CornflowerBlue; } else { Display.SimLabelAGV[agv.ID].BackColor = Color.Silver; } } // Update button add pallet if (isPickSimPalletInput1 == true) { btnAddPallet1.Text = "Add"; btnAddPallet1.BackColor = Color.WhiteSmoke; } if (isPickSimPalletInput2 == true) { btnAddPallet2.Text = "Add"; btnAddPallet2.BackColor = Color.WhiteSmoke; } } }
// Update position AGV icon in simulation mode (speed: cm/s) public static Point SimUpdatePositionAGV(int agvID, float speed) { // Find AGV in SimListAGV, get current point var index = AGV.SimListAGV.FindIndex(a => a.ID == agvID); AGV agv = AGV.SimListAGV[index]; Point position = Display.SimLabelAGV[agvID].Location; // Handle (waiting method) collision if it happens CollisionStatus status = Collision.SimHandle(agv, Collision.SimListCollision); if (status == CollisionStatus.Handling) { // Update agv status and velocity agv.Velocity = 0; agv.Status = "Stop"; return(position); } // return old point when agv has no path if (agv.Path.Count == 0) { return(position); } // Get navigation frame array. Note: string is a reference type, // so any change in navigationArr is also in AGV.SimListAGV[index].navigationArr string[] navigationArr = agv.navigationArr; // Check whether current point is a node or not // Note: shift position of label to center (+LabelAGV[].Width/2, +LabelAGV[].Height/2) var node = Node.ListNode.FirstOrDefault(n => { return((n.X == position.X + SimLabelAGV[agvID].Width / 2) && (n.Y == position.Y + SimLabelAGV[agvID].Height / 2)); }); // Current point is not a node and current position is start node, // it means initDistance to start node != 0, so go backward once then keep go ahead char orient = new char(); if (node == null && agv.ExitNode == agv.Path[0]) { switch (navigationArr[0]) { case "A": orient = UpdateOrient(agv.Orientation, "A"); break; case "B": orient = UpdateOrient(agv.Orientation, "B"); navigationArr[0] = "A"; break; } } // Current point is not a node and current position is not start node, // so keep go ahead else if (node == null) { orient = UpdateOrient(agv.Orientation, "A"); } // If goal was reached, no update position, remove old path, get next path (if exist) else if (node.ID == agv.Path.LastOrDefault()) { // Update AGV information agv.ExitNode = node.ID; // Update ExitNode orient = UpdateOrient(agv.Orientation, "A"); agv.Orientation = orient; // Update Orientation agv.DistanceToExitNode = 0f; // Update Distance to ExitNode agv.Status = "Stop"; // Update Status agv.Velocity = 0; // Update Velocity // Add next path Task.AddNextPathOfSimAGV(agv); return(position); } // Current point is at start node and initDistance to start node == 0 // Turn direction once then keep go ahead else if (node.ID == agv.Path[0] && agv.DistanceToExitNode == 0f) { switch (navigationArr[0]) { case "A": orient = UpdateOrient(agv.Orientation, "A"); break; case "B": orient = UpdateOrient(agv.Orientation, "B"); navigationArr[0] = "A"; break; case "L": orient = UpdateOrient(agv.Orientation, "L"); navigationArr[0] = "A"; break; case "R": orient = UpdateOrient(agv.Orientation, "R"); navigationArr[0] = "A"; break; } // If this node is pick node, remove pallet code that was picked and save this time if (agv.Tasks.Count != 0 && node.ID == agv.Tasks[0].PickNode) { RackColumn column = RackColumn.SimListColumn.Find(c => c.AtNode == agv.ExitNode); Pallet.SaveDeliveryTime(column.PalletCodes[agv.Tasks[0].PickLevel - 1], Pallet.SimListPallet); DBUtility.UpdatePalletDB("SimPalletInfoTable", column.PalletCodes[agv.Tasks[0].PickLevel - 1], false, DateTime.Now.ToString("dddd, MMMM dd, yyyy h:mm:ss tt"), Pallet.SimListPallet); column.PalletCodes[agv.Tasks[0].PickLevel - 1] = null; } } // Current point is a node but start node else { int idx = Array.IndexOf(navigationArr, node.ID.ToString()); string dir = navigationArr[idx + 1]; orient = UpdateOrient(agv.Orientation, dir); } // Modify speed to make sure AGV icon can reach next node int i = agv.Path.IndexOf(agv.ExitNode); int nextNode = agv.Path[i + 1]; int dnx = (position.X + SimLabelAGV[agvID].Width / 2) - Node.ListNode[nextNode].X; int dny = (position.Y + SimLabelAGV[agvID].Height / 2) - Node.ListNode[nextNode].Y; int nd = (int)Math.Sqrt(dnx * dnx + dny * dny); if (agv.ExitNode == agv.Path[0]) { // At first node of path, having 4 cases of agv position // (dnx * dny != 0) for 2 cases and (dnx * dnx0 > 0 || dny * dny0 > 0) for the others int dnx0 = (position.X + SimLabelAGV[agvID].Width / 2) - Node.ListNode[agv.Path[0]].X; int dny0 = (position.Y + SimLabelAGV[agvID].Height / 2) - Node.ListNode[agv.Path[0]].Y; int nd0 = (int)Math.Sqrt(dnx0 * dnx0 + dny0 * dny0); if (dnx * dny != 0 || dnx * dnx0 > 0 || dny * dny0 > 0) { nextNode = agv.Path[0]; nd = nd0; } } int sp = (int)Math.Round(speed * Display.Scale * (100.0 / 1000)); // timer1.Interval = 100ms int step = (nd % sp == 0) ? sp : (nd % sp); // Update AGV information before update position if (node != null) { agv.ExitNode = node.ID; // Update ExitNode } agv.Orientation = orient; // Update Orientation int exitNode = agv.ExitNode; int dx = (position.X + SimLabelAGV[agvID].Width / 2) - Node.ListNode[exitNode].X; int dy = (position.Y + SimLabelAGV[agvID].Height / 2) - Node.ListNode[exitNode].Y; agv.DistanceToExitNode = (float)Math.Sqrt(dx * dx + dy * dy) / Display.Scale; // Update Distance to ExitNode agv.Status = "Running"; // Update Status // Update next position of AGV icon in panel switch (orient) { case 'E': position = new Point(position.X + step, position.Y); break; case 'W': position = new Point(position.X - step, position.Y); break; case 'S': position = new Point(position.X, position.Y + step); break; case 'N': position = new Point(position.X, position.Y - step); break; } return(position); }
// Add next path to agv when previous path reach goal (agv.ExitNode is being goal) (Simulation Mode) public static void AddNextPathOfSimAGV(AGV agv) { // Clear old path agv.Path.Clear(); // Remove old task if (agv.Tasks.Count != 0 && agv.ExitNode == agv.Tasks[0].DropNode) { // Store pallet code to SimListColumn at this goal node RackColumn column = RackColumn.SimListColumn.Find(c => c.AtNode == agv.ExitNode); column.PalletCodes[agv.Tasks[0].DropLevel - 1] = agv.Tasks[0].PalletCode; if (column.AtNode != 51 & column.AtNode != 52) { Pallet pallet = new Pallet(agv.Tasks[0].PalletCode, true, DateTime.Now.ToString("dddd, MMMM dd, yyyy h:mm:ss tt"), column.Block, column.Number, agv.Tasks[0].DropLevel); Pallet.SimListPallet.Add(pallet); DBUtility.InsertNewPalletToDB("SimPalletInfoTable", pallet.Code, pallet.InStock, pallet.StoreTime, pallet.AtBlock, pallet.AtColumn, pallet.AtLevel); } // Note: remove task in agv.Tasks and also in Task.SimListTask Task.SimListTask.Remove(Task.SimListTask.Find(a => a.Name == agv.Tasks[0].Name)); agv.Tasks.RemoveAt(0); } // Add path to parking when don't have any task if (agv.Tasks.Count == 0) { // find all parking node List <int> parkingNode = new List <int>(); foreach (Node n in Node.ListNode) { if (n.LocationCode.Length == 0) { continue; } if (n.LocationCode[0] == 'P') { parkingNode.Add(n.ID); } } // If current node is parking node or don't have parking node for this agv, do nothing, // otherwise, add path to park agv (agv will park at location in order of index) if (parkingNode.Contains(agv.ExitNode)) { return; } int parkAtNode = parkingNode.Find(n => parkingNode.IndexOf(n) == AGV.SimListAGV.IndexOf(agv)); if (parkAtNode == 0) { return; // be careful: in my node definition, parking nodes don't have node 0 } agv.Path = Algorithm.A_starFindPath(agv.ExitNode, parkAtNode); // Add navigation frame of parking path string fr = Navigation.GetNavigationFrame(agv.Path, agv.Orientation, agv.DistanceToExitNode); agv.navigationArr = fr.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries); return; } // Add next path if (agv.ExitNode != agv.Tasks[0].PickNode) { agv.Path = Algorithm.A_starFindPath(agv.ExitNode, agv.Tasks[0].PickNode); } else { agv.Path = Algorithm.A_starFindPath(agv.Tasks[0].PickNode, agv.Tasks[0].DropNode); agv.Tasks[0].Status = "Doing"; // update button add pallet if (agv.Tasks[0].PickNode == 53) { HomeScreenForm.isPickSimPalletInput1 = true; } else if (agv.Tasks[0].PickNode == 54) { HomeScreenForm.isPickSimPalletInput2 = true; } } // Add next navigation frame of next path string frame = Navigation.GetNavigationFrame(agv.Path, agv.Orientation, agv.DistanceToExitNode); agv.navigationArr = frame.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries); }