Browse Source

Added velocities + bugfixes

rparedis 2 years ago
parent
commit
63cb3d3e02

BIN
__pycache__/mapper.cpython-38.pyc


+ 5 - 1
config.ini

@@ -25,10 +25,14 @@ end_time = 0
 schedule_file = results-de2/plan.csv
 
 [movement]
+; When true, the velocities below are ignored and the ETA is used instead
+use_eta = false
+
 ; Both tugging and sailing are sampled from a normal distribution
 ;    with the parameters defined below.
 ; Everything is using SI units, so m/s instead of knots!
 velocity_mean_tugging = 3.343889
 velocity_std_tugging = 0.2572222
 velocity_mean_sailing = 3.343889
-velocity_std_sailing = 0.2572222
+velocity_std_sailing = 0.2572222
+velocity_max = 10.28889

BIN
de2/__pycache__/elements.cpython-38.pyc


BIN
de2/__pycache__/tracer.cpython-38.pyc


+ 29 - 8
de2/elements.py

@@ -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):

+ 7 - 1
main.py

@@ -5,7 +5,13 @@ from pypdevs.simulator import Simulator
 config = configparser.ConfigParser()
 config.read('config.ini')
 
-port = Port("PoAB", config.get('simulation', 'schedule_file'))
+tugging = config.getfloat('movement', 'velocity_mean_tugging'), config.getfloat('movement', 'velocity_std_tugging')
+sailing = config.getfloat('movement', 'velocity_mean_sailing'), config.getfloat('movement', 'velocity_std_sailing')
+vel_max = config.getfloat('movement', 'velocity_max')
+if config.getboolean('movement', 'use_eta'):
+	tugging = sailing = vel_max = None
+
+port = Port("PoAB", config.get('simulation', 'schedule_file'), tugging, sailing, vel_max)
 
 sim = Simulator(port)
 if config.getboolean('simulation', 'verbose'):

+ 10 - 8
mapper.py

@@ -103,7 +103,6 @@ class PoABLayer(BaseLayer):
         #     self.painter.lines(cx1, cy1, cx2, cy2, width=2)
 
 
-
         if not self.sim_active:
             ui_manager.status("Press Space to Start Simulation")
         else:
@@ -117,7 +116,7 @@ class PoABLayer(BaseLayer):
 
             # Get all sailing vessels
             for vessel in self.streamer.vessels:
-                if vessel.source is not None or vessel.target is not None:
+                if vessel.source is not None and vessel.target is not None:
                     if vessel.task == "sailing":
                         self.painter.set_color(self.__colors__["sailing"])
                     else:
@@ -127,17 +126,15 @@ class PoABLayer(BaseLayer):
                     if vessel.mmsi not in self.vcache or self.vcache[vessel.mmsi] != vessel.source:
                         self.vcache[vessel.mmsi] = vessel.source
                         self.pcache[vessel.mmsi] = pathfinder(self.graph, vessel.source, vessel.target)
-                        self.tcache[vessel.mmsi] = time
+                        # self.tcache[vessel.mmsi] = time
 
                     path, dists = self.pcache[vessel.mmsi]
 
-                    self.draw_path(path, proj)
-
                     # Compute distance traveled and draw a vessel there
                     tot_distance = vessel.total_distance
                     traveled_approx = tot_distance - vessel.distance_left
-                    delta = time - self.tcache[vessel.mmsi]
-                    traveled_approx += delta * vessel.velocity
+                    # delta = time - self.tcache[vessel.mmsi]
+                    # traveled_approx += delta * vessel.velocity
                     percentage = traveled_approx / tot_distance
 
                     if sum(dists) == 0:
@@ -153,7 +150,12 @@ class PoABLayer(BaseLayer):
                     if euler_distance(sx + dx, sy + dy, mouse_x, mouse_y) < 10:
                         self.painter.set_color(self.__colors__["highlight"])
                         tooltips.append("%s (MMSI: %s)" % (str(vessel.name), str(vessel.mmsi)))
-                        tooltips.append("%.3f m/s" % vessel.velocity)
+                        tooltips.append("velocity: %.3f m/s" % vessel.velocity)
+                        tooltips.append("distance total: %.3f m" % vessel.total_distance)
+                        tooltips.append("distance left:  %.3f m" % vessel.distance_left)
+                        tooltips.append("ETA: %s" % epoch_to_str(vessel.distance_left / vessel.velocity + ts))
+
+                        self.draw_path(path, proj)
                     self.draw_shape(sx + dx, sy + dy)
 
         ui_manager.tooltip("\n".join(tooltips))