Warehouse Simulation
Do you have questions or comments about this model? Ask them here! (You'll first need to log in.)
WHAT IS IT?
(a general understanding of what the model is trying to show or explain)
HOW IT WORKS
(what rules the agents use to create the overall behavior of the model)
HOW TO USE IT
(how to use the model, including a description of each of the items in the Interface tab)
THINGS TO NOTICE
(suggested things for the user to notice while running the model)
THINGS TO TRY
(suggested things for the user to try to do (move sliders, switches, etc.) with the model)
EXTENDING THE MODEL
(suggested things to add or change in the Code tab to make the model more complicated, detailed, accurate, etc.)
NETLOGO FEATURES
(interesting or unusual features of NetLogo that the model uses, particularly in the Code tab; or where workarounds were needed for missing features)
RELATED MODELS
(models in the NetLogo Models Library and elsewhere which are of related interest)
CREDITS AND REFERENCES
(a reference to the model's URL on the web if it has one, as well as any other necessary credits, citations, and links)
Comments and Questions
; ========================================================== ; SORTATION WAREHOUSE (NETLOGO WEB SAFE) + CONGESTION METRICS ; ---------------------------------------------------------- ; Inbound trucks = RED (unload pallets into BLUE zone) [finite supply] ; Transfer cars = GREY (move pallets BLUE -> READY) ; Humans = PINK (assist sorting, stay in BLUE normally) ; Outbound carriers = GREEN (move pallets READY -> OUTFEED doors) ; ; Collisions can happen on FLOOR corridors (if enabled). ; Broken vehicles are towed by BUGs to SERVICE for repair. ; Dead vehicles (battery = 0) are towed by TURTLES to CHARGE to revive. ; After charge/repair, vehicles RESUME their jobs (restore-vehicle-job). ; ; NOTE: ; - NetLogo Web: do plots in Interface (not via code). ; - Congestion metrics go into globals: ; mean-blocked-now, max-blocked-now ; ========================================================== ; --------------------------- ; BREEDS ; --------------------------- breed [inbound-trucks inbound-truck] breed [carriers carrier] breed [transfer-cars transfer-car] breed [humans human] breed [repair-tows repair-tow] breed [charge-tows charge-tow] ; --------------------------- ; GLOBAL STATE ; --------------------------- globals [ deliveries toilet-zone door-spacing ready-zone-color ; congestion monitors mean-blocked-now max-blocked-now infeed-bays outfeed-bays blue-zone ready-zone last-mouse-down? last-mouse-patch service-stations charge-stations charge-lot broken-queue dead-queue target-reached? shutdown-tick initial-pallets deliveries-log ; --- publish / diagnostics metrics pallet-births lead-times lead-window moved-by-humans moved-by-transfer ] ; --------------------------- ; PATCH STATE ; --------------------------- patches-own [ celltype wall? items ready? ] ; --------------------------- ; TURTLE STATE ; --------------------------- turtles-own [ mstate goal-patch path reserved-next blocked-steps battery service-left charge-left carry? work-left ] repair-tows-own [ tstate target-truck goal2 path2 blocked2 ] charge-tows-own [ tstate target-truck goal2 path2 blocked2 ] ; ========================================================== ; SETUP ; ========================================================== to setup clear-all set door-spacing 2 set ready-zone-color violet set deliveries 0 set broken-queue [] set dead-queue [] set target-reached? false set shutdown-tick -1 set deliveries-log [] ; --- publish diagnostics set pallet-births [] set lead-times [] set lead-window 200 set moved-by-humans 0 set moved-by-transfer 0 ; --- reproducibility (optional) if not is-boolean? use-fixed-seed? [ set use-fixed-seed? false ] if not is-number? seed [ set seed 12345 ] if use-fixed-seed? [ random-seed seed ] ; --- slider safety if not is-number? robot-speed [ set robot-speed 2 ] if robot-speed <= 0 [ set robot-speed 2 ] if not is-number? collision-prob [ set collision-prob 0.01 ] if collision-prob < 0 [ set collision-prob 0.01 ] if not is-number? max-ticks [ set max-ticks 0 ] if max-ticks < 0 [ set max-ticks 0 ] if not is-number? battery-max [ set battery-max 2000 ] if battery-max <= 0 [ set battery-max 2000 ] if not is-number? battery-drain-per-tick [ set battery-drain-per-tick 2 ] if battery-drain-per-tick < 0 [ set battery-drain-per-tick 2 ] if not is-number? charge-time [ set charge-time 25 ] if charge-time <= 0 [ set charge-time 25 ] if not is-number? service-time [ set service-time 35 ] if service-time <= 0 [ set service-time 35 ] if not is-number? sort-time [ set sort-time 2 ] if sort-time <= 0 [ set sort-time 2 ] if not is-number? inbound-unload-time [ set inbound-unload-time 3 ] if inbound-unload-time <= 0 [ set inbound-unload-time 3 ] if not is-number? max-items-per-patch [ set max-items-per-patch 6 ] if max-items-per-patch <= 0 [ set max-items-per-patch 6 ] if not is-number? inbound-pallets-left [ set inbound-pallets-left 500 ] if inbound-pallets-left < 0 [ set inbound-pallets-left 500 ] set initial-pallets inbound-pallets-left if not is-number? deliveries-target [ set deliveries-target 0 ] if deliveries-target < 0 [ set deliveries-target 0 ] if deliveries-target > initial-pallets [ set deliveries-target initial-pallets ] if not is-number? target-loss-count [ set target-loss-count 4 ] if target-loss-count < 0 [ set target-loss-count 0 ] if not is-boolean? enable-battery? [ set enable-battery? true ] if not is-boolean? enable-collisions? [ set enable-collisions? true ] if not is-string? mouse-tool [ set mouse-tool "none" ] set last-mouse-down? false set last-mouse-patch nobody if not is-number? num-inbound-trucks [ set num-inbound-trucks 10 ] if num-inbound-trucks < 0 [ set num-inbound-trucks 0 ] if not is-number? num-carriers [ set num-carriers 14 ] if num-carriers < 0 [ set num-carriers 0 ] if not is-number? num-transfer-cars [ set num-transfer-cars 6 ] if num-transfer-cars < 0 [ set num-transfer-cars 0 ] if not is-number? num-humans [ set num-humans 8 ] if num-humans < 0 [ set num-humans 0 ] if not is-number? num-repair-tows [ set num-repair-tows 1 ] if num-repair-tows < 0 [ set num-repair-tows 0 ] if not is-number? num-charge-tows [ set num-charge-tows 2 ] if num-charge-tows < 0 [ set num-charge-tows 0 ] setup-layout setup-agents set mean-blocked-now 0 set max-blocked-now 0 reset-ticks end ; ========================================================== ; MAIN LOOP ; ========================================================== to go if (max-ticks > 0) and (ticks >= max-ticks) [ stop ] if not enable-battery? [ ask (turtle-set inbound-trucks carriers transfer-cars) [ set battery battery-max ] ] handle-mouse service-and-charge-timers inbound-logic human-sorting-logic transfer-logic carrier-logic plan-all-vehicle-steps resolve-collisions move-all-vehicles move-repair-tows move-charge-tows ask (turtle-set inbound-trucks carriers transfer-cars) [ update-vehicle-appearance ] update-monitors set deliveries-log lput deliveries deliveries-log if length deliveries-log > 51 [ set deliveries-log but-first deliveries-log ] if system-done? [ if not target-reached? [ set target-reached? true set shutdown-tick ticks finish-and-shutdown ] let vehicles (turtle-set inbound-trucks carriers transfer-cars) if (not any? vehicles with [not member? mstate ["charging" "parked"]]) and (not any? humans with [mstate != "resting"]) [ stop ] ] tick end to-report target-met? let eff-target effective-delivery-target report (eff-target > 0 and deliveries >= eff-target) end to-report system-drained? if inbound-pallets-left > 0 [ report false ] if any? blue-zone with [items > 0] [ report false ] if any? ready-zone with [items > 0] [ report false ] if any? (turtle-set inbound-trucks carriers transfer-cars) with [carry?] [ report false ] report true end ; ========================================================== ; INTERACTIVE MOUSE HANDLER ; ========================================================== to handle-mouse if not mouse-down? [ set last-mouse-down? false set last-mouse-patch nobody ] if mouse-down? [ let p patch mouse-xcor mouse-ycor if p != nobody [ if (not last-mouse-down?) or (p != last-mouse-patch) [ set last-mouse-down? true set last-mouse-patch p if mouse-tool = "toggle-wall" [ ask p [ if not (pxcor = min-pxcor or pxcor = max-pxcor or pycor = min-pycor or pycor = max-pycor) [ if celltype = "floor" [ set wall? true set celltype "wall" set pcolor gray ] if celltype = "wall" [ set wall? false set celltype "floor" set pcolor 7 ] ] ] ] if mouse-tool = "add-items-blue" [ if [celltype] of p = "blue" [ ask p [ set items min list max-items-per-patch (items + 1) ] ] ] if mouse-tool = "remove-items" [ ask p [ set items max list 0 (items - 1) ] ] if mouse-tool = "add-inbound" [ if (not [wall?] of p) and not any? turtles-on p [ create-inbound-trucks 1 [ init-vehicle "to-infeed" safe-move-to p update-vehicle-appearance ] ] ] if mouse-tool = "add-transfer" [ if (not [wall?] of p) and not any? turtles-on p [ create-transfer-cars 1 [ init-vehicle "idle" set shape "car" set color gray set label "T" safe-move-to p update-vehicle-appearance ] ] ] if mouse-tool = "add-carrier" [ if (not [wall?] of p) and not any? turtles-on p [ create-carriers 1 [ init-vehicle "idle" safe-move-to p update-vehicle-appearance ] ] ] let v one-of (turtle-set inbound-trucks carriers transfer-cars) with [patch-here = p] if v != nobody [ if mouse-tool = "break-vehicle" [ ask v [ become-broken update-vehicle-appearance ] ] if mouse-tool = "kill-battery" [ ask v [ if enable-battery? [ set battery 0 become-dead update-vehicle-appearance ] ] ] if mouse-tool = "repair-now" [ ask v [ set mstate "servicing" set service-left 1 ] ] if mouse-tool = "charge-now" [ ask v [ set mstate "charging" set charge-left 1 set battery battery-max ] ] ] ] ] ] end ; ========================================================== ; LAYOUT ; ========================================================== to setup-layout ask patches [ set celltype "floor" set pcolor 7 set wall? false set items 0 set ready? false set plabel "" ] ask patches with [ pxcor = min-pxcor or pxcor = max-pxcor or pycor = min-pycor or pycor = max-pycor ] [ set wall? true set celltype "wall" set pcolor gray ] set infeed-bays patches with [ pxcor = min-pxcor + 1 and (pycor mod door-spacing = 0) and not wall? ] set outfeed-bays patches with [ pxcor = max-pxcor - 1 and (pycor mod door-spacing = 0) and not wall? ] ask infeed-bays [ set celltype "infeed" set pcolor red ] ask outfeed-bays [ set celltype "outfeed" set pcolor green ] set blue-zone patches with [ pxcor >= -10 and pxcor <= -2 and pycor >= -8 and pycor <= 8 and celltype = "floor" and not wall? ] ask blue-zone [ set celltype "blue" set pcolor blue ] set ready-zone patches with [ pxcor >= 3 and pxcor <= 11 and pycor >= -8 and pycor <= 8 and celltype = "floor" and not wall? ] ask ready-zone [ set celltype "ready" set pcolor ready-zone-color ] let zoneH 4 let bottom-y1 (min-pycor + 2) let bottom-y2 (bottom-y1 + zoneH - 1) let zoneW 5 let gapW 2 let tripleW (3 * zoneW + 2 * gapW) let centerX round ((min-pxcor + max-pxcor) / 2) let leftX (centerX - int (tripleW / 2)) let sL leftX let sR (sL + zoneW - 1) let tL (sR + gapW + 1) let tR (tL + zoneW - 1) let cL (tR + gapW + 1) let cR (cL + zoneW - 1) set service-stations patches with [ pxcor >= sL and pxcor <= sR and pycor >= bottom-y1 and pycor <= bottom-y2 and celltype = "floor" and not wall? and pxcor != (min-pxcor + 1) and pxcor != (max-pxcor - 1) ] ask service-stations [ set celltype "service" set pcolor orange ] set toilet-zone patches with [ pxcor >= tL and pxcor <= tR and pycor >= bottom-y1 and pycor <= bottom-y2 and celltype = "floor" and not wall? and pxcor != (min-pxcor + 1) and pxcor != (max-pxcor - 1) ] ask toilet-zone [ set celltype "rest" set pcolor 25 ] set charge-stations patches with [ pxcor >= cL and pxcor <= cR and pycor >= bottom-y1 and pycor <= bottom-y2 and celltype = "floor" and not wall? and pxcor != (min-pxcor + 1) and pxcor != (max-pxcor - 1) ] ask charge-stations [ set celltype "charge" set pcolor yellow ] let parkH 3 let top-y2 (max-pycor - 2) let top-y1 (top-y2 - parkH - 1 + 1) set charge-lot patches with [ pxcor >= (centerX - 4) and pxcor <= (centerX + 4) and pycor >= top-y1 and pycor <= top-y2 and celltype = "floor" and not wall? ] ask charge-lot [ set celltype "charge-lot" set pcolor 53 ] label-doors-and-zones end to label-doors-and-zones ask patches [ set plabel "" ] let inlist sort-by [[a b] -> [pycor] of a < [pycor] of b] (sort infeed-bays) let n 1 foreach inlist [p -> ask p [ set plabel (word "IN" n) set plabel-color white ] set n n + 1 ] let outlist sort-by [[a b] -> [pycor] of a < [pycor] of b] (sort outfeed-bays) set n 1 foreach outlist [p -> ask p [ set plabel (word "OUT" n) set plabel-color white ] set n n + 1 ] if any? blue-zone [ let bx round mean [pxcor] of blue-zone let by max [pycor] of blue-zone ask patch bx by [ set plabel "BLUE" set plabel-color white ] ] if any? ready-zone [ let rx round mean [pxcor] of ready-zone let ry max [pycor] of ready-zone ask patch rx ry [ set plabel "READY" set plabel-color white ] ] if any? service-stations [ let sx round mean [pxcor] of service-stations let sy max [pycor] of service-stations ask patch sx sy [ set plabel "SERVICE" set plabel-color white ] ] if any? charge-stations [ let cx round mean [pxcor] of charge-stations let cy max [pycor] of charge-stations ask patch cx cy [ set plabel "CHARGE" set plabel-color black ] ] if any? charge-lot [ let px round mean [pxcor] of charge-lot let py min [pycor] of charge-lot + 1 ask patch px py [ set plabel "PARK" set plabel-color black ] ] if any? toilet-zone [ let tx round mean [pxcor] of toilet-zone let ty max [pycor] of toilet-zone ask patch tx ty [ set plabel "REST AREA" set plabel-color white ] ] end ; ========================================================== ; AGENT CREATION ; ========================================================== to setup-agents create-inbound-trucks num-inbound-trucks [ init-vehicle "to-infeed" safe-move-to (safe-one-of-patches (patches with [celltype = "floor" and not wall? and not any? turtles-here])) update-vehicle-appearance ] create-carriers num-carriers [ init-vehicle "idle" safe-move-to (safe-one-of-patches (patches with [celltype = "floor" and not wall? and not any? turtles-here])) update-vehicle-appearance ] create-transfer-cars num-transfer-cars [ init-vehicle "idle" set shape "car" set color gray set label "T" safe-move-to (safe-one-of-patches (patches with [celltype = "floor" and not wall? and not any? turtles-here])) update-vehicle-appearance ] create-humans num-humans [ set size 1.1 set shape "person" set color pink set label "" set mstate "sorting" set goal-patch nobody set path [] set reserved-next nobody set blocked-steps 0 set carry? false set work-left 0 safe-move-to (safe-one-of-patches (blue-zone with [not any? turtles-here])) ] create-repair-tows num-repair-tows [ set size 1.0 set shape "bug" set color red set label "S" set tstate "idle" set target-truck nobody set goal2 nobody set path2 [] set blocked2 0 safe-move-to (safe-one-of-patches service-stations) ] create-charge-tows num-charge-tows [ set size 1.0 set shape "turtle" set color violet set label "C" set tstate "idle" set target-truck nobody set goal2 nobody set path2 [] set blocked2 0 safe-move-to (safe-one-of-patches charge-stations) ] end to init-vehicle [initial-state] set size 1.2 set mstate initial-state set goal-patch nobody set path [] set reserved-next nobody set blocked-steps 0 set battery battery-max set service-left 0 set charge-left 0 set carry? false set work-left 0 end ; ========================================================== ; BATTERY POLICY ; ========================================================== to-report low-battery? report enable-battery? and (battery <= (0.15 * battery-max)) end to maybe-go-charge if not enable-battery? [ stop ] if member? mstate ["charging" "to-charge-home" "towed-to-charge" "dead" "broken" "servicing" "parked"] [ stop ] if not low-battery? [ stop ] let c safe-one-of-patches charge-stations if c != nobody [ set goal-patch c set path find-path patch-here goal-patch set mstate "to-charge-home" ] end ; ========================================================== ; INBOUND LOGIC ; ========================================================== to inbound-logic ask inbound-trucks [ if is-stopped-vehicle? self [ stop ] if enable-battery? and battery <= 0 [ become-dead stop ] maybe-go-charge if mstate = "to-charge-home" [ if goal-patch != nobody and patch-here = goal-patch [ set mstate "charging" set charge-left charge-time ] stop ] if inbound-pallets-left <= 0 [ set mstate "idle" set goal-patch nobody set path [] stop ] if mstate = "to-infeed" [ let door safe-one-of-patches infeed-bays if door != nobody [ set goal-patch door set path find-path patch-here goal-patch set mstate "to-infeed-driving" ] stop ] if mstate = "to-infeed-driving" [ if patch-here = goal-patch [ let b safe-one-of-patches blue-zone if b != nobody [ set goal-patch b set path find-path patch-here goal-patch set mstate "to-blue" ] ] stop ] if mstate = "to-blue" [ if patch-here = goal-patch [ set mstate "unloading" set work-left inbound-unload-time ] stop ] if mstate = "unloading" [ set work-left work-left - 1 if work-left <= 0 [ if inbound-pallets-left > 0 [ ifelse [items] of patch-here < max-items-per-patch [ ask patch-here [ set items items + 1 set ready? false set pcolor blue ] set pallet-births lput ticks pallet-births set inbound-pallets-left inbound-pallets-left - 1 set mstate "to-infeed" set goal-patch nobody set path [] ] [ let b safe-one-of-patches (blue-zone with [items < max-items-per-patch]) ifelse b != nobody [ set goal-patch b set path find-path patch-here goal-patch set mstate "to-blue" ] [ ; wait and retry soon set work-left 1 ] ] ] if inbound-pallets-left <= 0 [ set mstate "idle" set goal-patch nobody set path [] ] ] stop ] ] end ; ========================================================== ; HUMANS: sort BLUE -> READY, rest when done ; ========================================================== to human-sorting-logic ask humans [ if mstate = "resting" [ stop ] ; --- Sorting countdown (when carrying a pallet) if work-left > 0 [ set work-left work-left - 1 if work-left <= 0 [ if carry? [ let readyspot safe-one-of-patches (ready-zone with [items < max-items-per-patch]) if readyspot != nobody [ let before [items] of readyspot ask readyspot [ if items < max-items-per-patch [ set items items + 1 set ready? true set pcolor 45 ] ] if [items] of readyspot > before [ set carry? false set moved-by-humans moved-by-humans + 1 ] ] ] ] stop ] ; --- Finished sorting but READY was full -> keep trying to drop (do NOT re-sort) if carry? and work-left <= 0 [ let readyspot safe-one-of-patches (ready-zone with [items < max-items-per-patch]) if readyspot != nobody [ let before [items] of readyspot ask readyspot [ if items < max-items-per-patch [ set items items + 1 set ready? true set pcolor 45 ] ] if [items] of readyspot > before [ set carry? false set moved-by-humans moved-by-humans + 1 ] ] stop ] ; --- Resting logic (target reached) if deliveries-target > 0 and deliveries >= effective-delivery-target and work-left <= 0 and not carry? [ if [celltype] of patch-here = "rest" [ set mstate "resting" stop ] let t safe-one-of-patches toilet-zone if t != nobody [ set goal-patch t set path find-path patch-here goal-patch step-along-path-safe ] if [celltype] of patch-here = "rest" [ set mstate "resting" ] stop ] ; --- Resting logic (system done) if system-done? and work-left <= 0 and not carry? [ if [celltype] of patch-here != "rest" [ let t safe-one-of-patches toilet-zone if t != nobody [ safe-move-to t ] ] set mstate "resting" stop ] ; --- Keep humans in BLUE zone if [celltype] of patch-here != "blue" [ let b safe-one-of-patches (blue-zone with [not any? turtles-here]) if b != nobody [ safe-move-to b ] stop ] ; --- Yield to a transfer-car that is about to enter this patch let blocker one-of transfer-cars with [ mstate = "to-blue" and not empty? path and first path = [patch-here] of myself ] if blocker != nobody [ let opts neighbors with [celltype = "blue" and not any? turtles-here] if any? opts [ let dest max-one-of opts [distance blocker] safe-move-to dest ] stop ] ; --- Pick from BLUE and start sorting if not carry? [ let src safe-one-of-patches (blue-zone with [items > 0]) if src != nobody [ set goal-patch src set path find-path patch-here goal-patch step-along-path-safe if patch-here = goal-patch [ ask patch-here [ set items items - 1 if items < 0 [ set items 0 ] ] set carry? true set work-left sort-time ] ] stop ] ] end ; ========================================================== ; TRANSFER CARS: BLUE -> READY ; ========================================================== to transfer-logic ask transfer-cars [ if is-stopped-vehicle? self [ stop ] if enable-battery? and battery <= 0 [ become-dead stop ] maybe-go-charge if mstate = "to-charge-home" [ if goal-patch != nobody and patch-here = goal-patch [ set mstate "charging" set charge-left charge-time ] stop ] if mstate = "idle" [ let src safe-one-of-patches (blue-zone with [items > 0]) if src != nobody [ set goal-patch src set path find-path patch-here goal-patch set mstate "to-blue" ] stop ] if mstate = "to-blue" [ if patch-here = goal-patch [ let dst safe-one-of-patches (ready-zone with [items < max-items-per-patch]) ifelse (dst != nobody) and ([items] of patch-here > 0) [ ask patch-here [ set items items - 1 if items < 0 [ set items 0 ] ] set carry? true set goal-patch dst set path find-path patch-here goal-patch set mstate "to-ready" ] [ set carry? false set mstate "idle" set goal-patch nobody set path [] ] ] stop ] if mstate = "to-ready" [ if goal-patch = nobody [ set mstate "idle" set goal-patch nobody set path [] stop ] if patch-here = goal-patch [ ifelse carry? [ ; ✅ FIX: this must be IFELSE (no standalone ELSE in NetLogo) ifelse [items] of patch-here < max-items-per-patch [ ask patch-here [ set items items + 1 set ready? true set pcolor 45 ] set carry? false set moved-by-transfer moved-by-transfer + 1 ] [ let dst2 safe-one-of-patches (ready-zone with [items < max-items-per-patch]) ifelse dst2 != nobody [ set goal-patch dst2 set path find-path patch-here goal-patch ] [ set path [] ] ] set mstate "idle" set goal-patch nobody set path [] ] [ set mstate "idle" set goal-patch nobody set path [] ] ] stop ] ] end ; ========================================================== ; CARRIERS: READY -> OUTFEED ; ========================================================== to carrier-logic ask carriers [ if is-stopped-vehicle? self [ stop ] if enable-battery? and battery <= 0 [ become-dead stop ] maybe-go-charge if mstate = "to-charge-home" [ if goal-patch != nobody and patch-here = goal-patch [ set mstate "charging" set charge-left charge-time ] stop ] if mstate = "idle" [ let src safe-one-of-patches (ready-zone with [items > 0]) if src != nobody [ set goal-patch src set path find-path patch-here goal-patch set mstate "to-ready" ] stop ] if mstate = "to-ready" [ if goal-patch = nobody [ set mstate "idle" set path [] stop ] if patch-here = goal-patch [ ifelse [items] of patch-here > 0 [ ask patch-here [ set items items - 1 if items <= 0 [ set items 0 set ready? false set pcolor ready-zone-color ] ] set carry? true let out safe-one-of-patches outfeed-bays ifelse out != nobody [ set goal-patch out set path find-path patch-here goal-patch set mstate "to-outfeed" ] [ set carry? false set mstate "idle" set goal-patch nobody set path [] ] ] [ set mstate "idle" set goal-patch nobody set path [] ] ] stop ] if mstate = "to-outfeed" [ if goal-patch = nobody [ set mstate "idle" set path [] stop ] if patch-here = goal-patch [ if carry? [ set deliveries deliveries + 1 if not empty? pallet-births [ let birth first pallet-births set pallet-births but-first pallet-births set lead-times lput (ticks - birth) lead-times if length lead-times > lead-window [ set lead-times but-first lead-times ] ] set carry? false ] set mstate "idle" set goal-patch nobody set path [] ] stop ] ] end ; ========================================================== ; TARGET CLAMP ; ========================================================== to-report effective-delivery-target if deliveries-target <= 0 [ report 0 ] let max-target initial-pallets - target-loss-count if max-target < 0 [ set max-target 0 ] if deliveries-target > max-target [ report max-target ] report deliveries-target end ; ========================================================== ; MOVE + COLLISION ; ========================================================== to plan-all-vehicle-steps ask (turtle-set inbound-trucks carriers transfer-cars) [ set reserved-next nobody if is-stopped-vehicle? self [ stop ] if (path = nobody) or empty? path [ stop ] let nxt first path if (nxt = nobody) or (not is-patch? nxt) [ set path [] stop ] set reserved-next nxt ] end to resolve-collisions if system-done? [ stop ] if not enable-collisions? [ stop ] let movers (turtle-set inbound-trucks carriers transfer-cars) let targets [reserved-next] of movers with [reserved-next != nobody and is-patch? reserved-next] if empty? targets [ stop ] let contested remove-duplicates filter [pp -> (occurrences pp targets) > 1] targets foreach contested [pp -> ifelse ([celltype] of pp = "floor") [ let group movers with [reserved-next = pp] if any? group [ ifelse (random-float 1 < collision-prob) [ ask one-of group [ become-broken ] ask group [ set reserved-next nobody ] ] [ let winner one-of group ask group with [self != winner] [ set reserved-next nobody ] ] ] ] [ let group2 movers with [reserved-next = pp] if any? group2 [ let winner2 one-of group2 ask group2 with [self != winner2] [ set reserved-next nobody ] ] ] ] end to move-all-vehicles ask (turtle-set inbound-trucks carriers transfer-cars) [ if is-stopped-vehicle? self [ stop ] let moved? false repeat robot-speed [ if enable-battery? and (battery <= 0) [ become-dead stop ] if reserved-next != nobody [ if not is-patch? reserved-next [ set reserved-next nobody set path [] stop ] ifelse (not [wall?] of reserved-next) and (not any? turtles-on reserved-next) [ safe-move-to reserved-next set moved? true if not empty? path [ set path but-first path ] set blocked-steps 0 ] [ set blocked-steps blocked-steps + 1 let side safe-one-of-patches (neighbors4 with [not wall? and not any? turtles-here]) if side != nobody [ safe-move-to side set moved? true ] if blocked-steps > 10 and goal-patch != nobody [ set path find-path patch-here goal-patch set blocked-steps 0 ] ] ] set reserved-next nobody if (path != nobody) and not empty? path [ let nxt first path ifelse is-patch? nxt [ set reserved-next nxt ] [ set path [] set reserved-next nobody ] ] ] if enable-battery? and moved? and not system-done? [ set battery battery - battery-drain-per-tick if battery < 0 [ set battery 0 ] ] ] end ; ========================================================== ; BROKEN / DEAD ; ========================================================== to become-broken if member? mstate ["broken" "dead"] [ stop ] set mstate "broken" set broken-queue lput self broken-queue pull-over end to become-dead if mstate = "dead" [ stop ] set mstate "dead" set dead-queue lput self dead-queue pull-over end to pull-over let opts patches in-radius 6 with [ not wall? and celltype = "floor" and not any? turtles-here ] ifelse any? opts [ safe-move-to (min-one-of opts [distance myself]) ] [ let s safe-one-of-patches (neighbors4 with [not wall? and not any? turtles-here]) if s != nobody [ safe-move-to s ] ] end ; ========================================================== ; TOW SYSTEM ; ========================================================== to move-repair-tows ask repair-tows [ if system-done? [ stop ] if tstate = "idle" [ if any? (turtle-set inbound-trucks carriers transfer-cars) with [mstate = "broken"] [ set broken-queue remove-duplicates (sentence broken-queue [self] of (turtle-set inbound-trucks carriers transfer-cars) with [mstate = "broken"]) ] if not empty? broken-queue [ let t first broken-queue set broken-queue but-first broken-queue if is-vehicle? t and ([mstate] of t = "broken") [ set target-truck t set goal2 [patch-here] of t set path2 find-path patch-here goal2 set tstate "to-truck" ] ] stop ] if tstate = "to-truck" [ if (target-truck = nobody) or (not is-vehicle? target-truck) or ([mstate] of target-truck != "broken") [ set tstate "idle" set path2 [] set target-truck nobody stop ] set goal2 [patch-here] of target-truck if empty? path2 [ set path2 find-path patch-here goal2 ] tow-step-safe if patch-here = goal2 [ ask target-truck [ set mstate "towed-to-service" ] set goal2 safe-one-of-patches service-stations set path2 find-path patch-here goal2 set tstate "to-service" ] stop ] if tstate = "to-service" [ if empty? path2 [ set path2 find-path patch-here goal2 ] tow-step-safe if target-truck != nobody and is-vehicle? target-truck [ ask target-truck [ safe-move-to [patch-here] of myself ] ] if patch-here = goal2 [ if target-truck != nobody and is-vehicle? target-truck [ ask target-truck [ safe-move-to (safe-one-of-patches service-stations) set mstate "servicing" set service-left service-time ] ] set tstate "idle" set target-truck nobody set goal2 nobody set path2 [] ] stop ] ] end to move-charge-tows ask charge-tows [ if system-done? [ stop ] if tstate = "idle" [ if any? (turtle-set inbound-trucks carriers transfer-cars) with [mstate = "dead"] [ set dead-queue remove-duplicates (sentence dead-queue [self] of (turtle-set inbound-trucks carriers transfer-cars) with [mstate = "dead"]) ] if not empty? dead-queue [ let t first dead-queue set dead-queue but-first dead-queue if is-vehicle? t and ([mstate] of t = "dead") [ set target-truck t set goal2 [patch-here] of t set path2 find-path patch-here goal2 set tstate "to-truck" ] ] stop ] if tstate = "to-truck" [ if (target-truck = nobody) or (not is-vehicle? target-truck) or ([mstate] of target-truck != "dead") [ set tstate "idle" set path2 [] set target-truck nobody stop ] set goal2 [patch-here] of target-truck if empty? path2 [ set path2 find-path patch-here goal2 ] tow-step-safe if patch-here = goal2 [ ask target-truck [ set mstate "towed-to-charge" ] set goal2 safe-one-of-patches charge-stations set path2 find-path patch-here goal2 set tstate "to-charge" ] stop ] if tstate = "to-charge" [ if empty? path2 [ set path2 find-path patch-here goal2 ] tow-step-safe if target-truck != nobody and is-vehicle? target-truck [ ask target-truck [ safe-move-to [patch-here] of myself ] ] if patch-here = goal2 [ if target-truck != nobody and is-vehicle? target-truck [ ask target-truck [ safe-move-to (safe-one-of-patches charge-stations) set mstate "charging" set charge-left charge-time set battery battery-max ] ] set tstate "idle" set target-truck nobody set goal2 nobody set path2 [] ] stop ] ] end ; ========================================================== ; RESTORE JOB AFTER SERVICE/CHARGE ; ========================================================== to restore-vehicle-job set reserved-next nobody set blocked-steps 0 set goal-patch nobody set path [] if member? mstate ["broken" "dead" "towed-to-service" "towed-to-charge" "parked"] [ stop ] if breed = inbound-trucks [ ifelse inbound-pallets-left > 0 [ set mstate "to-infeed" ] [ set mstate "idle" set carry? false ] stop ] if breed = carriers [ ifelse carry? [ let out safe-one-of-patches outfeed-bays ifelse out != nobody [ set goal-patch out set path find-path patch-here goal-patch set mstate "to-outfeed" ] [ set carry? false set mstate "idle" ] ] [ set mstate "idle" ] stop ] if breed = transfer-cars [ ifelse carry? [ let dst safe-one-of-patches (ready-zone with [items < max-items-per-patch]) ifelse dst != nobody [ set goal-patch dst set path find-path patch-here goal-patch set mstate "to-ready" ] [ set carry? false set mstate "idle" ] ] [ set mstate "idle" ] stop ] set mstate "idle" end ; ========================================================== ; SERVICE & CHARGE TIMERS ; ========================================================== to service-and-charge-timers ask (turtle-set inbound-trucks carriers transfer-cars) with [mstate = "servicing"] [ set service-left service-left - 1 if service-left <= 0 [ set service-left 0 set battery battery-max set mstate "idle" restore-vehicle-job ] ] if system-done? [ ask (turtle-set inbound-trucks carriers transfer-cars) with [mstate = "charging"] [ set charge-left 999999 set battery battery-max ] stop ] ask (turtle-set inbound-trucks carriers transfer-cars) with [mstate = "charging"] [ set charge-left charge-left - 1 if charge-left <= 0 [ set charge-left 0 set battery battery-max set mstate "idle" restore-vehicle-job ] ] end ; ========================================================== ; DONE? + SHUTDOWN ; ========================================================== to-report system-done? let eff-target effective-delivery-target if eff-target > 0 and deliveries >= eff-target [ report true ] if inbound-pallets-left > 0 [ report false ] if any? blue-zone with [items > 0] [ report false ] if any? ready-zone with [items > 0] [ report false ] if any? (turtle-set inbound-trucks carriers transfer-cars) with [carry?] [ report false ] report true end to finish-and-shutdown ask (turtle-set inbound-trucks carriers transfer-cars) with [ not member? mstate ["charging" "parked" "broken" "dead" "towed-to-service" "towed-to-charge" "servicing"] ] [ let cs one-of charge-lot with [not any? turtles-here] ifelse cs != nobody [ set goal-patch cs set path find-path patch-here goal-patch set mstate "to-charge-home" ] [ set mstate "parked" set path [] set reserved-next nobody ] ] ask (turtle-set inbound-trucks carriers transfer-cars) [ if mstate = "to-charge-home" and goal-patch != nobody [ if patch-here = goal-patch [ set mstate "charging" set charge-left 999999 set battery battery-max set path [] set reserved-next nobody ] ] ] ask (turtle-set inbound-trucks carriers transfer-cars) with [ member? mstate ["broken" "dead" "towed-to-service" "towed-to-charge" "servicing"] ] [ set mstate "parked" set path [] set reserved-next nobody set battery battery-max ] ask humans with [mstate != "resting"] [ if [celltype] of patch-here != "rest" [ let rest-patch safe-one-of-patches (toilet-zone with [not any? turtles-here]) if rest-patch != nobody [ safe-move-to rest-patch ] ] set mstate "resting" ] end ; ========================================================== ; APPEARANCE ; ========================================================== to update-vehicle-appearance ifelse mstate = "broken" [ set shape "x" set color red set label "B" set label-color white ] [ ifelse mstate = "dead" [ set shape "face sad" set color gray set label "D" set label-color black ] [ ifelse breed = transfer-cars [ set shape "car" ifelse carry? [ set color cyan ] [ set color gray ] set label "T" ] [ set shape "truck" ifelse breed = inbound-trucks [ set color red set label "IN" ] [ set color green ifelse carry? [ set label "OUT*" ] [ set label "OUT" ] ] ] set label-color black ] ] end ; ========================================================== ; SAFE HELPERS ; ========================================================== to safe-move-to [dest] if (dest = nobody) or (not is-patch? dest) [ stop ] move-to dest end to-report safe-one-of-patches [pset] if pset = nobody [ report nobody ] if not any? pset [ report nobody ] report one-of pset end to-report is-vehicle? [t] if t = nobody [ report false ] if not is-turtle? t [ report false ] report member? [breed] of t (list inbound-trucks carriers transfer-cars) end to-report is-stopped-vehicle? [t] if not is-vehicle? t [ report false ] let s [mstate] of t report member? s ["broken" "dead" "towed-to-service" "towed-to-charge" "servicing" "charging" "parked"] end to step-along-path-safe if (path = nobody) or empty? path [ set path [] stop ] let nxt first path if (nxt = nobody) or (not is-patch? nxt) [ set path [] stop ] if [wall?] of nxt [ set path [] stop ] if not any? turtles-on nxt [ safe-move-to nxt set path but-first path ] end to tow-step-safe if (path2 = nobody) or empty? path2 [ set path2 [] stop ] let nxt first path2 if (nxt = nobody) or (not is-patch? nxt) [ set path2 [] stop ] if [wall?] of nxt [ set path2 [] stop ] ifelse (not any? turtles-on nxt) or (nxt = goal2) [ safe-move-to nxt set path2 but-first path2 set blocked2 0 ] [ set blocked2 blocked2 + 1 let side safe-one-of-patches (neighbors4 with [not wall? and not any? turtles-here]) if side != nobody [ safe-move-to side ] if blocked2 > 6 and goal2 != nobody [ set path2 find-path patch-here goal2 set blocked2 0 ] ] end to-report occurrences [target lst] report length filter [x -> x = target] lst end ; ========================================================== ; PATHFINDING (BFS) ; ========================================================== to-report find-path [start goal] if start = nobody or goal = nobody [ report [] ] if not is-patch? start or not is-patch? goal [ report [] ] if start = goal [ report [] ] let frontier (list start) let visited (list start) let parents [] while [not empty? frontier] [ let current first frontier set frontier but-first frontier if current = goal [ report reconstruct-path start goal parents ] let nbrs [neighbors4] of current foreach sort nbrs [n -> if (not member? n visited) and (not [wall?] of n) [ set visited lput n visited set frontier lput n frontier set parents lput (list n current) parents ] ] ] report [] end to-report reconstruct-path [start goal parents] let path-list (list goal) let current goal while [current != start] [ let matches filter [pr -> first pr = current] parents if empty? matches [ report [] ] let pair first matches let parent last pair set current parent if current != start [ set path-list fput current path-list ] ] report path-list end ; ========================================================== ; CONGESTION REPORTERS + MONITOR UPDATER ; ========================================================== to-report active-movers report (turtle-set inbound-trucks carriers transfer-cars) with [ not member? mstate ["broken" "dead" "towed-to-service" "towed-to-charge" "servicing" "charging" "parked"] ] end to-report mean-blocked let ms active-movers if not any? ms [ report 0 ] report mean [blocked-steps] of ms end to-report max-blocked let ms active-movers if not any? ms [ report 0 ] report max [blocked-steps] of ms end to update-monitors set mean-blocked-now mean-blocked set max-blocked-now max-blocked end ; ========================================================== ; PUBLISH / DIAGNOSTICS REPORTERS ; ========================================================== to-report mean-lead-time if empty? lead-times [ report 0 ] report mean lead-times end to-report median-lead-time if empty? lead-times [ report 0 ] report median lead-times end to-report p90-lead-time if empty? lead-times [ report 0 ] let s sort lead-times let idx floor ((length s - 1) * 0.9) if idx < 0 [ set idx 0 ] report item idx s end to-report pct-moved-by-humans let total (moved-by-humans + moved-by-transfer) if total <= 0 [ report 0 ] report 100 * moved-by-humans / total end to-report pct-moved-by-transfer let total (moved-by-humans + moved-by-transfer) if total <= 0 [ report 0 ] report 100 * moved-by-transfer / total end to-report pallet-balance-error let blue-items 0 let ready-items 0 if blue-zone != nobody [ set blue-items sum [items] of blue-zone ] if ready-zone != nobody [ set ready-items sum [items] of ready-zone ] let carried count turtles with [carry?] report initial-pallets - (inbound-pallets-left + blue-items + ready-items + carried + deliveries) end
There is only one version of this model, created about 3 hours ago by HARISH ULAGANATHAN INDHUMATHI HARISH.
Attached files
| File | Type | Description | Last updated | |
|---|---|---|---|---|
| Warehouse Simulation.png | preview | Preview for 'Warehouse Simulation' | about 3 hours ago, by HARISH ULAGANATHAN INDHUMATHI HARISH | Download |
This model does not have any ancestors.
This model does not have any descendants.
Download this model