question

Ankith T avatar image
0 Likes"
Ankith T asked Jason Lightfoot edited

How to block opposite traffic while a specific vehicle is traveling on AGV Path

In My model a Big forklift (Transporter) is traveling on the aisles where other vehicles (TaskExecuter) such as tuggers or Electric pallet jacks use. when ever this forklift in on the aisles it should occupy whole aisle so that what ever coming in opposite direction should stop or do not enter the aisle until forklift exits that aisle. But what ever vehicles going in the same direction of Forklift can do there operations as usual.


Please refer to attached images regarding more clarity about the question. Here i would like to know the logic how to stop opposite flow traffic when Big Forklift is on that specific aisles.


1678979297537.png


1678979332545.png

FlexSim 21.0.10
agvnetworkblocking
1678979297537.png (93.6 KiB)
1678979332545.png (88.3 KiB)
· 3
5 |100000

Up to 12 attachments (including images) can be used with a maximum of 23.8 MiB each and 47.7 MiB total.

Kavika F avatar image
0 Likes"
Kavika F answered Kavika F commented

Hey @Ankith T, I've got a possible solution. It's a simplified version, but maybe it could translate to your model.

1679615991152.png

I I have two parallel lines of work. I only want the smaller AGVs to use the lane when the Forklift isn't using it (and vice versa). I setup the Control Points (CPs) to have several labels on them:

1679616089832.png

  • LaneEnd - a reference to the CP that denotes the other end of the lane (in this case CP3; if you look at CP3, it will have this CP as its LaneEnd reference).
  • NeighborCP - a reference to the CP in the other lane at the same position as this CP.
  • Occupants - an array that keeps track of how many AGVs are currently in this lane

I added a label on each AGV; a "Type" label for either "small" or "large" to help distinguish whether an AGV needed to occupy both lanes.

1679616429923.png

I added these CPs to a group "LaneEnds" and made a small Process Flow to activate some traffic controlling when an AGV arrives at a CP.

1679616255987.png

Here is the code for the Traffic Controller Custom Code:

  1. /**Custom Code*/
  2. Object current = param(1);
  3. treenode activity = param(2);
  4. Token token = param(3);
  5. treenode processFlow = ownerobject(activity);
  6.  
  7. Object currentCP = token.currentCP;
  8. Object trafficManager = Model.find("TrafficManager");
  9. AGV agv = AGV(token.agv);
  10. token.labels.assert("Stopped", 0);
  11.  
  12. treenode laneEnd = currentCP.labels["LaneEnd"].value;
  13. treenode neighborCP = currentCP.labels["NeighborCP"].value;
  14. Array curTEs = currentCP.labels["Occupants"].value;
  15.  
  16. // I (TE) arrive at CP
  17. // Check to see if I am leaving the lane
  18. int isLeavingLane = 0;
  19. for (int i = 1; i <= curTEs.length; i++) {
  20. if (curTEs[i].name == agv.object.name) {
  21. isLeavingLane = 1;
  22. break;
  23. }
  24. }
  25.  
  26. if (isLeavingLane) {
  27. curTEs = curTEs.splice(1, 1);
  28. currentCP.labels["Occupants"].value = curTEs;
  29. laneEnd.labels["Occupants"].value = curTEs;
  30. sendmessage(trafficManager, currentCP);
  31. return 0;
  32. }
  33.  
  34. // Check to see if the neighbor has occupants
  35. Array neighborTEs = neighborCP.labels["Occupants"].value;
  36.  
  37. // If there are no occupants in the neighbor lane, then proceed normally
  38. if (neighborTEs.length == 0) {
  39. curTEs.push(agv.object);
  40. currentCP.labels["Occupants"].value = curTEs;
  41. laneEnd.labels["Occupants"].value = curTEs;
  42. return 0;
  43. }
  44.  
  45. // The neighbor lane has occupants; do I need to wait? (Yes if either TE is "large")
  46. int curTEIsLarge = agv.object.labels["Type"].value == "large" ? 1 : 0;
  47. int neighborIsLarge = 0;
  48. for (int i = 1; i <= neighborTEs.length; i++) {
  49. TaskExecuter neighborTE = neighborTEs[i];
  50. if (neighborTE.labels["Type"].value == "large") {
  51. neighborIsLarge = 1;
  52. break;
  53. }
  54. }
  55.  
  56. // If you don't need to wait, then proceed normally
  57. if (!curTEIsLarge && !neighborIsLarge) {
  58. curTEs.push(agv.object);
  59. currentCP.labels["Occupants"].value = curTEs;
  60. laneEnd.labels["Occupants"].value = curTEs;
  61. return 0;
  62. }
  63.  
  64. // Either I'm large or my neighbor has a large occupant;
  65. // Stop traveling until I get a message saying the neighbor is clear
  66. agv.object.stop(STATE_STOPPED, 1);
  67. token.labels["Stopped"].value = 1;
  68. trafficManager.labels["stoppedAGVs"].value.as(Array).push(agv.object);
  69.  
  70. return 1;

I hope the comments I have help you understand what's happening. Basically, I'm running checks on each CP and lane to make sure it's okay for them to travel. If not, I stop them.

If an AGV is stopped, it will need to resume somehow. That's where the "TrafficManager" comes in. If an AGV is leaving the area, it will send a message to the "TrafficManager" fixed resource - just a cube I used to send a message to. It has an OnMessage trigger that fires this code when it gets a message from a CP:

  1. /**Custom Code*/
  2. Object current = ownerobject(c);
  3. Object fromObject = param(1);
  4. Variant msgparam1 = param(2);
  5. Variant msgparam2 = param(3);
  6. Variant msgparam3 = param(4);
  7.  
  8. Array stoppedAGVs = current.labels["stoppedAGVs"].value;
  9. if (stoppedAGVs.length == 0) {
  10. return 0;
  11. }
  12.  
  13. AGV agv = AGV(stoppedAGVs[1]);
  14. Object currentLaneCP1 = fromObject.labels["NeighborCP"].value;
  15. Object currentLaneCP2 = currentLaneCP1.labels["LaneEnd"].value;
  16.  
  17. agv.object.resume(1);
  18. stoppedAGVs.pop();
  19. //current.labels["stoppedAGVs"].value = stoppedAGVs;
  20. currentLaneCP1.labels["Occupants"].value = [agv.object];
  21. currentLaneCP2.labels["Occupants"].value = [agv.object];
  22.  
  23. return 1;

Basically, it resumes the stopped AGV and sets the Occupants to contain the newly resumed AGV.

This is what it looks like in action:

2-lane-stopping.gif

blocking-traffic.fsm


· 1
5 |100000

Up to 12 attachments (including images) can be used with a maximum of 23.8 MiB each and 47.7 MiB total.

Jason Lightfoot avatar image
0 Likes"
Jason Lightfoot answered Ankith T commented

You show where the TEs should stop, but not where the Transporter should stop if the TEs have already occupied part of the circuit - by identifying both I think you may see how many shared resources you need and how you might manage the stop/continue logic using a process flow.

(It looks like the outer loop is anticlockwise travel, with the inner loop being clockwise)

· 5
5 |100000

Up to 12 attachments (including images) can be used with a maximum of 23.8 MiB each and 47.7 MiB total.