|
|
@@ -3,6 +3,7 @@ from pypdevs.DEVS import AtomicDEVS, CoupledDEVS
|
|
|
from pypdevs.infinity import INFINITY
|
|
|
|
|
|
from dataclasses import dataclass, field
|
|
|
+import random
|
|
|
import pandas as pd
|
|
|
|
|
|
from de2.routing import get_graph, get_closest_vertex
|
|
|
@@ -77,7 +78,7 @@ class Pool(AtomicDEVS):
|
|
|
self.vessel_in = self.addInPort("vessel_in")
|
|
|
self.vessel_out = self.addOutPort("vessel_out")
|
|
|
|
|
|
-
|
|
|
+ # prefill with all vessels of the simulation
|
|
|
for mmsi in TUGS["MMSI"]:
|
|
|
if isinstance(mmsi, str):
|
|
|
self.state["waiting"][mmsi] = Vessel(mmsi)
|
|
|
@@ -86,7 +87,6 @@ class Pool(AtomicDEVS):
|
|
|
self.state["time"] += self.elapsed
|
|
|
if self.req_in in inputs:
|
|
|
for request in inputs[self.req_in]:
|
|
|
- # TODO: prefill with all vessels of the simulation?
|
|
|
if request["mmsi"] in self.state["waiting"]:
|
|
|
vessel = self.state["waiting"][request["mmsi"]]
|
|
|
else:
|
|
|
@@ -105,11 +105,10 @@ class Pool(AtomicDEVS):
|
|
|
# vessel.location = request["location"]
|
|
|
|
|
|
vessel.velocity = request["velocity"]
|
|
|
- if vessel.velocity > 0:
|
|
|
- # requests for idle times should be ignored!
|
|
|
+ if vessel.velocity > 0: # requests for idling should be ignored!
|
|
|
vessel.distance_left = request["distance"]
|
|
|
vessel.total_distance = vessel.distance_left
|
|
|
- vessel.time_until_departure = vessel.distance_left / vessel.velocity
|
|
|
+ # vessel.time_until_departure = vessel.distance_left / vessel.velocity
|
|
|
vessel.source = request["source_lon"], request["source_lat"]
|
|
|
vessel.target = request["target_lon"], request["target_lat"]
|
|
|
vessel.task = request["task"]
|
|
|
@@ -164,15 +163,20 @@ class Pool(AtomicDEVS):
|
|
|
|
|
|
|
|
|
class Sailer(AtomicDEVS):
|
|
|
- def __init__(self, name):
|
|
|
+ def __init__(self, name, v_tugging, v_sailing, v_max):
|
|
|
super(Sailer, self).__init__(name)
|
|
|
|
|
|
+ self.v_tugging = v_tugging
|
|
|
+ self.v_sailing = v_sailing
|
|
|
+ self.v_max = v_max
|
|
|
+
|
|
|
self.state = {
|
|
|
"vessels": [],
|
|
|
"time": 0.0
|
|
|
}
|
|
|
|
|
|
self.vessel_in = self.addInPort("vessel_in")
|
|
|
+ self.update = self.addInPort("update")
|
|
|
self.vessel_out = self.addOutPort("vessel_out")
|
|
|
|
|
|
def extTransition(self, inputs):
|
|
|
@@ -180,6 +184,15 @@ class Sailer(AtomicDEVS):
|
|
|
self.update_vessels(self.elapsed)
|
|
|
if self.vessel_in in inputs:
|
|
|
for vessel in inputs[self.vessel_in]:
|
|
|
+ if vessel.task == "tugging" and self.v_tugging is not None:
|
|
|
+ vessel.velocity = -1
|
|
|
+ while vessel.velocity <= 0 or vessel.velocity > self.v_max:
|
|
|
+ vessel.velocity = random.normalvariate(*self.v_tugging)
|
|
|
+ elif vessel.task == "sailing" and self.v_sailing is not None:
|
|
|
+ vessel.velocity = -1
|
|
|
+ while vessel.velocity <= 0 or vessel.velocity > self.v_max:
|
|
|
+ vessel.velocity = random.normalvariate(*self.v_sailing)
|
|
|
+ vessel.time_until_departure = vessel.distance_left / vessel.velocity
|
|
|
self.state["vessels"].append(vessel)
|
|
|
self.state["vessels"].sort(key=lambda v: v.time_until_departure)
|
|
|
return self.state
|
|
|
@@ -312,17 +325,23 @@ class Clock(AtomicDEVS):
|
|
|
self.state = {
|
|
|
"time": 0.0
|
|
|
}
|
|
|
+ self.outp = self.addOutPort("outp")
|
|
|
|
|
|
def timeAdvance(self):
|
|
|
return self.interval
|
|
|
|
|
|
+ def outputFnc(self):
|
|
|
+ return {
|
|
|
+ self.outp: [True]
|
|
|
+ }
|
|
|
+
|
|
|
def intTransition(self):
|
|
|
self.state["time"] += self.timeAdvance()
|
|
|
return self.state
|
|
|
|
|
|
|
|
|
class Port(CoupledDEVS):
|
|
|
- def __init__(self, name, ivef):
|
|
|
+ def __init__(self, name, ivef, v_tugging=None, v_sailing=None, v_max=None):
|
|
|
super(Port, self).__init__(name)
|
|
|
|
|
|
self.clock = self.addSubModel(Clock("clock"))
|
|
|
@@ -330,7 +349,7 @@ class Port(CoupledDEVS):
|
|
|
self.planner = self.addSubModel(RoutePlanner("planner"))
|
|
|
# self.tracer = self.addSubModel(Tracer("tracer", ivef))
|
|
|
self.pool = self.addSubModel(Pool("pool"))
|
|
|
- self.sailer = self.addSubModel(Sailer("sailer"))
|
|
|
+ self.sailer = self.addSubModel(Sailer("sailer", v_tugging, v_sailing, v_max))
|
|
|
|
|
|
# self.connectPorts(self.tracer.reqs, self.pool.req_in)
|
|
|
self.connectPorts(self.scheduler.reqs, self.planner.req_in)
|
|
|
@@ -338,6 +357,8 @@ class Port(CoupledDEVS):
|
|
|
self.connectPorts(self.pool.vessel_out, self.sailer.vessel_in)
|
|
|
self.connectPorts(self.sailer.vessel_out, self.pool.vessel_in)
|
|
|
|
|
|
+ self.connectPorts(self.clock.outp, self.sailer.update)
|
|
|
+
|
|
|
def select(self, imm_children):
|
|
|
for child in imm_children:
|
|
|
if isinstance(child, Sailer):
|