Simulating traffic passing multiple locks#
In this notebook, we simulate two locks on a network which vessels from opposing direction shave to pass. Vessels are locked together if they can fit inside the lock, and arrive within the clustering time window.
0. Import libraries#
# package(s) used for creating and geo-locating the graph
import networkx as nx
import pyproj
from shapely.geometry import Point, LineString
from shapely.ops import transform
# package(s) related to the simulation (creating the vessel, running the simulation)
import datetime
import simpy
import opentnsim
from opentnsim.core.logutils import logbook2eventtable
from opentnsim.core.plotutils import generate_vessel_gantt_chart
from scipy.stats import norm, uniform, expon
# import of modules important for locking
from opentnsim.lock import lock as lock_module
from opentnsim.vessel_traffic_service import vessel_traffic_service as vessel_traffic_service_module
from opentnsim.graph import mixins as graph_module
# package(s) needed for inspecting the output
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
print("This notebook is executed with OpenTNSim version {}".format(opentnsim.__version__))
This notebook is executed with OpenTNSim version 1.3.7
1. Define object classes#
# make your preferred Vessel class out of available mix-ins.
Vessel = type(
"Vessel",
(
lock_module.PassesLockComplex, # allows to interact with a lock
opentnsim.core.Identifiable, # allows to give the object a name and a random ID,
opentnsim.core.Movable, # allows the object to move, with a fixed speed, while logging this activity
opentnsim.core.VesselProperties, # allows vessel to have dimensions, namely a length (L), width (B), and draught (T)
opentnsim.core.ExtraMetadata, # allow additional information, such as an arrival time (required for passing a lock)
graph_module.HasMultiDiGraph, # allow to operate on a graph that can include parallel edges from and to the same nodes
opentnsim.output.HasOutput, # allow additional output to be stored
),
{}
)
2. Create graph#
# define reference systems
wgs84eqd = pyproj.CRS('4087')
wgs84rad = pyproj.CRS('4326')
# define transformer functions
wgs84eqd_to_wgs84rad = pyproj.transformer.Transformer.from_crs(wgs84eqd,wgs84rad,always_xy=True).transform #equidistant wgs84 to radial wgs84
wgs84rad_to_wgs84eqd = pyproj.transformer.Transformer.from_crs(wgs84rad,wgs84eqd,always_xy=True).transform #radial wgs84 to equidistant wgs84
# create a directed graph
graph = nx.DiGraph()
# add nodes
graph.add_node('-2',geometry=transform(wgs84eqd_to_wgs84rad,Point(-350600,0)))
graph.add_node('-1',geometry=transform(wgs84eqd_to_wgs84rad,Point( -15000,0)))
graph.add_node('0',geometry=transform(wgs84eqd_to_wgs84rad,Point( -5000,0)))
graph.add_node('1',geometry=transform(wgs84eqd_to_wgs84rad,Point( 5000,0)))
graph.add_node('+1',geometry=transform(wgs84eqd_to_wgs84rad,Point( 15000,0)))
graph.add_node('+2',geometry=transform(wgs84eqd_to_wgs84rad,Point( 350600,0)))
# add edges
graph.add_edge('-2','-1', weight=1)
graph.add_edge('-1','-2', weight=1)
graph.add_edge('-1','0', weight=1)
graph.add_edge('0','-1', weight=1)
graph.add_edge('0','1', weight=1)
graph.add_edge('1','0', weight=1)
graph.add_edge('1','+1', weight=1)
graph.add_edge('+1','1', weight=1)
graph.add_edge('+2','+1', weight=1)
graph.add_edge('+1','+2', weight=1)
graph_module.plot_graph(graph)
3. Run simulation#
def generate_vessel(
env,
name,
start_node,
end_node,
arrival_time,
vessel_speed=4,
vessel_length=100,
vessel_beam=20,
vessel_draft=10,
vessel_type="tanker"):
"""
Creates and returns a Vessel object with a computed route through the environment graph.
Parameters:
----------
env : Environment
The simulation environment containing the graph and other context.
name : str
Human readabile identifier for the vessel.
start_node : str or int
The starting node in the graph (converted to string).
end_node : str or int
The destination node in the graph (converted to string).
arrival_time : pd.Timestamp
The scheduled arrival time of the vessel at the start node.
vessel_speed : float, optional
Speed of the vessel in knots or simulation units (default is 4).
vessel_length : float, optional
Length of the vessel in meters (default is 100).
vessel_beam : float, optional
Beam (width) of the vessel in meters (default is 20).
vessel_draft : float, optional
Draught (depth below waterline) of the vessel in meters (default is 10).
vessel_type : str, optional
Type of vessel (e.g., "tanker", "cargo", "container") (default is "tanker").
Returns:
-------
Vessel or None
A Vessel object initialized with the given parameters and route.
Returns None if no valid path exists between start_node and end_node.
"""
# Ensure nodes are strings
start_node = str(start_node)
end_node = str(end_node)
try:
route = nx.dijkstra_path(env.graph, start_node, end_node)
except nx.NetworkXNoPath:
print(f"⚠️ No path from {start_node} to {end_node}. Vessel {name} not created.")
return None
geometry = env.graph.nodes[start_node]['geometry']
data_vessel = {
"env": env,
"name": name,
"geometry": geometry,
"route": route,
"v": vessel_speed,
"L": vessel_length,
"B": vessel_beam,
"T": vessel_draft,
"type": vessel_type,
"arrival_time": arrival_time,
}
vessel = Vessel(**data_vessel)
return vessel
def generate_vessels_with_distributions(
env,
num_vessels,
start_time,
arrival_dist_up=None,
arrival_dist_down=None,
seed_up=None,
seed_down=None):
"""
Generates a list of vessels with interarrival times drawn from specified distributions
for upward and downward directions. Supports independent seeding for reproducibility.
Parameters
----------
env : Environment
The simulation environment containing the graph and vessel context.
num_vessels : int
Total number of vessels to generate. Vessels alternate between up and down directions.
start_time : pd.Timestamp
The initial timestamp from which vessel arrivals begin.
arrival_dist_up : callable, optional
A function returning interarrival times (in minutes) for upward-moving vessels.
If None, defaults to an exponential distribution with mean 20 minutes.
arrival_dist_down : callable, optional
A function returning interarrival times (in minutes) for downward-moving vessels.
If None, defaults to an exponential distribution with mean 20 minutes.
seed_up : int or None, optional
Seed for the random number generator used in upward direction.
seed_down : int or None, optional
Seed for the random number generator used in downward direction.
Returns
-------
list of Vessel
A list of Vessel objects with assigned routes and arrival times.
Vessels for which no valid path exists are skipped.
"""
vessels = []
# Create independent random generators
rng_up = np.random.default_rng(seed_up)
rng_down = np.random.default_rng(seed_down)
# Default to exponential distribution with mean 20 minutes
if arrival_dist_up is None:
arrival_dist_up = lambda: rng_up.exponential(scale=20)
if arrival_dist_down is None:
arrival_dist_down = lambda: rng_down.exponential(scale=20)
up_time = start_time
down_time = start_time
for i in range(num_vessels):
if i % 2 == 0:
# Upward direction: -1 → +1
start_node, end_node = "-2", "+2"
delta_minutes = arrival_dist_up()
arrival_time = up_time + pd.Timedelta(minutes=delta_minutes)
up_time = arrival_time
else:
# Downward direction: +1 → -1
start_node, end_node = "+2", "-2"
delta_minutes = arrival_dist_down()
arrival_time = down_time + pd.Timedelta(minutes=delta_minutes)
down_time = arrival_time
vessel = generate_vessel(
env=env,
name=f"Vessel {i + 1}",
start_node=start_node,
end_node=end_node,
arrival_time=arrival_time
)
if vessel:
vessels.append(vessel)
return vessels
def mission(env, vessel):
"""
Method that defines the mission of the vessel.
In this case:
keep moving along the path until its end point is reached
"""
while True:
yield from vessel.move()
if vessel.geometry == nx.get_node_attributes(env.graph, "geometry")[vessel.route[-1]]:
break
# start simpy environment
simulation_start = datetime.datetime(2025, 1, 1, 0, 0, 0)
env = simpy.Environment(initial_time=simulation_start.timestamp())
env.epoch = simulation_start
# add graph to environment
env.graph = graph
# add components important for locking to the environment
env.vessel_traffic_service = vessel_traffic_service_module.VesselTrafficService(graph=graph)
lock_1 = lock_module.IsLockComplex(
env=env,
name='Lock_1',
node_open='-1',
node_A = '-1',
node_B = '0',
distance_lock_doors_A_to_waiting_area_A = 4800,
distance_lock_doors_B_to_waiting_area_B = 4800,
distance_from_start_node_to_lock_doors_A = 4800,
distance_from_end_node_to_lock_doors_B = 4800,
lock_length = 400,
lock_width = 50,
lock_depth = 15,
levelling_time = 300,
sailing_distance_to_crossing_point = 1800,
doors_opening_time= 300,
doors_closing_time= 300,
speed_reduction_factor_lock_chamber=0.5,
sailing_in_time_gap_through_doors = 300,
sailing_in_speed_sea = 1.5,
sailing_in_speed_canal = 1.5,
sailing_out_time_gap_through_doors = 120,
sailing_time_before_opening_lock_doors = 600,
sailing_time_before_closing_lock_doors = 120,
registration_nodes = ['-2','1'],
predictive=False
)
lock_2 = lock_module.IsLockComplex(
env=env,
name='Lock_2',
node_open='1',
node_A = '1',
node_B = '+1',
distance_lock_doors_A_to_waiting_area_A = 4800,
distance_lock_doors_B_to_waiting_area_B = 4800,
distance_from_start_node_to_lock_doors_A = 4800,
distance_from_end_node_to_lock_doors_B = 4800,
lock_length = 400,
lock_width = 50,
lock_depth = 15,
levelling_time = 300,
sailing_distance_to_crossing_point = 1800,
doors_opening_time= 300,
doors_closing_time= 300,
speed_reduction_factor_lock_chamber=0.5,
sailing_in_time_gap_through_doors = 300,
sailing_in_speed_sea = 1.5,
sailing_in_speed_canal = 1.5,
sailing_out_time_gap_through_doors = 120,
sailing_time_before_opening_lock_doors = 600,
sailing_time_before_closing_lock_doors = 120,
registration_nodes = ['0','+2'],
predictive=False
)
# create vessels from dict
data_vessel_1 = {
"env": env, # needed for simpy simulation
"name": "Vessel 1", # required by Identifiable
"geometry": env.graph.nodes['-2']['geometry'], # required by Locatable
"route": nx.dijkstra_path(env.graph, "-2", "+2"), # required by Routeable
"v": 4, # required by Movable, 4 m/s to check if the distance is covered in the expected time
"L": 100, # required by VesselProperties, interacts with the lock capacity
"B": 20, # required by VesselProperties
"T": 10, # required by VesselProperties
"type": 'tanker', # required by VesselProperties
"arrival_time": pd.Timestamp('2025-01-01 00:00:00') # required by PassesLockComplex
}
vessel_1 = Vessel(**data_vessel_1)
vessel_1.name = 'Vessel 1'
data_vessel_2 = {
"env": env, # needed for simpy simulation
"name": "Vessel 2", # required by Identifiable
"geometry": env.graph.nodes['+2']['geometry'], # required by Locatable
"route": nx.dijkstra_path(env.graph, "+2", "-2"), # required by Routeable
"v": 4, # required by Movable, 4 m/s to check if the distance is covered in the expected time
"L": 100, # required by VesselProperties, interacts with the lock capacity
"B": 20, # required by VesselProperties
"T": 10, # required by VesselProperties
"type": 'tanker', # required by VesselProperties
"arrival_time": pd.Timestamp('2025-01-01 00:05:00') # required by PassesLockComplex
}
vessel_2 = Vessel(**data_vessel_2)
vessel_2.name = 'Vessel 2'
#start the simulation
env.process(mission(env, vessel_1));
env.process(mission(env, vessel_2));
env.run()
df = pd.DataFrame(vessel_1.logbook)
df
| Message | Timestamp | Value | Geometry | |
|---|---|---|---|---|
| 0 | Sailing from node -2 to node -1 start | 2025-01-01 00:00:00.000000 | 0 | POINT (-3.149493386123042 0) |
| 1 | Sailing from node -2 to node -1 stop | 2025-01-01 23:18:20.000000 | 335600.0 | POINT (-0.1347472926179282 0) |
| 2 | Sailing from node -1 to node 0 start | 2025-01-01 23:18:20.000000 | 335600.0 | POINT (-0.1347472926179282 0) |
| 3 | Sailing to first lock doors start | 2025-01-01 23:18:20.000000 | {'origin': '', 'destination': '', 'route': [],... | POINT (-0.1347472926179282 0) |
| 4 | Sailing to first lock doors stop | 2025-01-01 23:38:20.000000 | {'origin': '', 'destination': '', 'route': [],... | POINT (-0.0916281589801912 0) |
| 5 | Sailing to position in lock start | 2025-01-01 23:38:20.000000 | {'origin': '', 'destination': '', 'route': [],... | POINT (-0.0916281589801912 0) |
| 6 | Sailing to position in lock stop | 2025-01-01 23:44:00.172786 | {'origin': '', 'destination': '', 'route': [],... | POINT (-0.0884840554857729 0) |
| 7 | Levelling start | 2025-01-01 23:49:00.172786 | {'origin': '', 'destination': '', 'route': [],... | POINT (-0.0884840554857729 0) |
| 8 | Levelling stop | 2025-01-01 23:54:00.172786 | {'origin': '', 'destination': '', 'route': [],... | POINT (-0.0884840554857729 0) |
| 9 | Sailing to second lock doors start | 2025-01-01 23:59:00.172786 | {'origin': '', 'destination': '', 'route': [],... | POINT (-0.0884840554857729 0) |
| 10 | Sailing to second lock doors stop | 2025-01-01 23:59:48.768899 | {'origin': '', 'destination': '', 'route': [],... | POINT (-0.0880348978437131 0) |
| 11 | Sailing to lock complex exit start | 2025-01-01 23:59:48.768899 | {'origin': '', 'destination': '', 'route': [],... | POINT (-0.0880348978437131 0) |
| 12 | Sailing to lock complex exit stop | 2025-01-02 00:19:48.768899 | {'origin': '', 'destination': '', 'route': [],... | POINT (-0.0449157642059761 0) |
| 13 | Sailing from node -1 to node 0 stop | 2025-01-02 00:19:48.768899 | 335600.0 | POINT (-0.0449157642059761 0) |
| 14 | Sailing from node 0 to node 1 start | 2025-01-02 00:19:48.768899 | 335600.0 | POINT (-0.0449157642059761 0) |
| 15 | Sailing from node 0 to node 1 stop | 2025-01-02 01:01:28.768899 | 345600.0 | POINT (0.0449157642059761 0) |
| 16 | Sailing from node 1 to node +1 start | 2025-01-02 01:01:28.768899 | 345600.0 | POINT (0.0449157642059761 0) |
| 17 | Sailing to first lock doors start | 2025-01-02 01:01:28.768899 | {'origin': '', 'destination': '', 'route': [],... | POINT (0.0449157642059761 0) |
| 18 | Sailing to first lock doors stop | 2025-01-02 01:21:28.768899 | {'origin': '', 'destination': '', 'route': [],... | POINT (0.0880348978437131 0) |
| 19 | Sailing to position in lock start | 2025-01-02 01:21:28.768899 | {'origin': '', 'destination': '', 'route': [],... | POINT (0.0880348978437131 0) |
| 20 | Sailing to position in lock stop | 2025-01-02 01:27:08.941685 | {'origin': '', 'destination': '', 'route': [],... | POINT (0.0911790013381314 0) |
| 21 | Levelling start | 2025-01-02 01:32:09.000000 | {'origin': '', 'destination': '', 'route': [],... | POINT (0.0911790013381314 0) |
| 22 | Levelling stop | 2025-01-02 01:37:09.000000 | {'origin': '', 'destination': '', 'route': [],... | POINT (0.0911790013381314 0) |
| 23 | Sailing to second lock doors start | 2025-01-02 01:42:09.000000 | {'origin': '', 'destination': '', 'route': [],... | POINT (0.0911790013381314 0) |
| 24 | Sailing to second lock doors stop | 2025-01-02 01:42:57.596112 | {'origin': '', 'destination': '', 'route': [],... | POINT (0.0916281589801912 0) |
| 25 | Sailing to lock complex exit start | 2025-01-02 01:42:57.596112 | {'origin': '', 'destination': '', 'route': [],... | POINT (0.0916281589801912 0) |
| 26 | Sailing to lock complex exit stop | 2025-01-02 02:02:57.596112 | {'origin': '', 'destination': '', 'route': [],... | POINT (0.1347472926179282 0) |
| 27 | Sailing from node 1 to node +1 stop | 2025-01-02 02:02:57.596112 | 345600.0 | POINT (0.1347472926179282 0) |
| 28 | Sailing from node +1 to node +2 start | 2025-01-02 02:02:57.596112 | 345600.0 | POINT (0.1347472926179282 0) |
| 29 | Sailing from node +1 to node +2 stop | 2025-01-03 01:21:17.596112 | 681200.0 | POINT (3.149493386123042 0) |
vessels = [vessel_1, vessel_2]
4. Inspect output#
# load the logbook data into a dataframe
lock_df = pd.DataFrame.from_dict(lock_1.lock_chamber.logbook)
print("'{}' logbook data:".format(lock_1.name))
print('')
display(lock_df)
'Lock_1' logbook data:
| Message | Timestamp | Value | Geometry | |
|---|---|---|---|---|
| 0 | Lock doors closing start | 2025-01-01 23:44:00.172786 | {} | -1 |
| 1 | Lock doors closing stop | 2025-01-01 23:49:00.172786 | {} | -1 |
| 2 | Lock chamber converting start | 2025-01-01 23:49:00.172786 | {} | -1 |
| 3 | Lock chamber converting stop | 2025-01-01 23:54:00.172786 | {} | 0 |
| 4 | Lock doors opening start | 2025-01-01 23:54:00.172786 | {} | 0 |
| 5 | Lock doors opening stop | 2025-01-01 23:59:00.172786 | {} | 0 |
| 6 | Lock doors closing start | 2025-01-02 01:32:09.000000 | {} | 0 |
| 7 | Lock doors closing stop | 2025-01-02 01:37:09.000000 | {} | 0 |
| 8 | Lock chamber converting start | 2025-01-02 01:37:09.000000 | {} | 0 |
| 9 | Lock chamber converting stop | 2025-01-02 01:42:09.000000 | {} | -1 |
| 10 | Lock doors opening start | 2025-01-02 01:42:09.000000 | {} | -1 |
| 11 | Lock doors opening stop | 2025-01-02 01:47:09.000000 | {} | -1 |
# load the logbook data into a dataframe
lock_df = pd.DataFrame.from_dict(lock_2.lock_chamber.logbook)
print("'{}' logbook data:".format(lock_2.name))
print('')
display(lock_df)
'Lock_2' logbook data:
| Message | Timestamp | Value | Geometry | |
|---|---|---|---|---|
| 0 | Lock doors closing start | 2025-01-01 00:05:00.000000 | {} | 1 |
| 1 | Lock doors closing stop | 2025-01-01 00:10:00.000000 | {} | 1 |
| 2 | Lock chamber converting start | 2025-01-01 00:10:00.000000 | {} | 1 |
| 3 | Lock chamber converting stop | 2025-01-01 00:15:00.000000 | {} | +1 |
| 4 | Lock doors opening start | 2025-01-01 00:15:00.000000 | {} | +1 |
| 5 | Lock doors opening stop | 2025-01-01 00:20:00.000000 | {} | +1 |
| 6 | Lock doors closing start | 2025-01-01 23:49:00.172786 | {} | +1 |
| 7 | Lock doors closing stop | 2025-01-01 23:54:00.172786 | {} | +1 |
| 8 | Lock chamber converting start | 2025-01-01 23:54:00.172786 | {} | +1 |
| 9 | Lock chamber converting stop | 2025-01-01 23:59:00.172786 | {} | 1 |
| 10 | Lock doors opening start | 2025-01-01 23:59:00.172786 | {} | 1 |
| 11 | Lock doors opening stop | 2025-01-02 00:04:00.172786 | {} | 1 |
| 12 | Lock doors closing start | 2025-01-02 01:27:09.000000 | {} | 1 |
| 13 | Lock doors closing stop | 2025-01-02 01:32:09.000000 | {} | 1 |
| 14 | Lock chamber converting start | 2025-01-02 01:32:09.000000 | {} | 1 |
| 15 | Lock chamber converting stop | 2025-01-02 01:37:09.000000 | {} | +1 |
| 16 | Lock doors opening start | 2025-01-02 01:37:09.000000 | {} | +1 |
| 17 | Lock doors opening stop | 2025-01-02 01:42:09.000000 | {} | +1 |
Gantt chart of event table#
df_eventtable = opentnsim.core.logutils.logbook2eventtable([*vessels, lock_1.lock_chamber, lock_2.lock_chamber])
fig = generate_vessel_gantt_chart(df_eventtable)
Time-distance diagram of vessels passing the lock and planning info#
def cm_to_pixels(cm):
return cm * 37.8 # Set figure height to 10 cmfig.update_layout(height=cm_to_pixels(10))
# We can plot the time-distance diagram
fig = lock_1.create_time_distance_plot(vessels = vessels,
xlimmin = -6050,
xlimmax = 6050,
ylimmin = pd.Timestamp('2025-01-01 22:00:00'),
ylimmax = pd.Timestamp('2025-01-02 09:00:00'),
method='Plotly')
fig.update_layout(height=cm_to_pixels(20))
def cm_to_pixels(cm):
return cm * 37.8 # Set figure height to 10 cmfig.update_layout(height=cm_to_pixels(10))
# We can plot the time-distance diagram
fig = lock_2.create_time_distance_plot(vessels = vessels,
xlimmin = -6050,
xlimmax = 6050,
ylimmin = pd.Timestamp('2025-01-01 22:00:00'),
ylimmax = pd.Timestamp('2025-01-02 09:00:00'),
method='Plotly')
fig.update_layout(height=cm_to_pixels(20))
Vessel delays: individual delays and overall average#
delays = []
for vessel in vessels:
vessel_df = pd.DataFrame(vessel.logbook)
waiting_stop = vessel_df[vessel_df.Message == "Waiting stop"]
if not waiting_stop.empty:
delay = (waiting_stop.Timestamp-vessel.metadata["arrival_time"]).iloc[0]
else:
delay = pd.Timedelta(seconds=0)
delays.append(delay)
print(f"The average vessel delay is {np.round(np.average(delays).total_seconds()/60,1)} minutes")
The average vessel delay is 0.0 minutes
Simulated intensity (vessels per hour)#
‘get_vessels_during_leveling’:
Identify locking cycles (by looking at the lock logbook)
From the vessel list identify which vessels were in the lock during that locking cycle
‘calculate_cycle_looptimes’:
Using the info derived from ‘get_vessels_during_leveling’ calculate looptimes
‘calculate_detailed_cycle_time’:
using the info from ‘get_vessels_during_leveling’ and ‘calculate_cycle_looptimes’ calculate detailed cycle times
leveling_cycles = opentnsim.lock.logutils.get_vessels_during_leveling(lock_1.lock_chamber, vessels)
looptimes_df = opentnsim.lock.logutils.calculate_cycle_looptimes(leveling_cycles, vessels)
Tc_df = opentnsim.lock.logutils.calculate_detailed_cycle_time(lock_1.lock_chamber, vessels, leveling_cycles)
display(pd.DataFrame(leveling_cycles))
display(looptimes_df)
display(Tc_df)
| leveling_start | leveling_stop | vessels_present | |
|---|---|---|---|
| 0 | 2025-01-01 23:49:00.172786 | 2025-01-01 23:54:00.172786 | [Vessel 1, Vessel 2] |
| 1 | 2025-01-02 01:37:09.000000 | 2025-01-02 01:42:09.000000 | [Vessel 1, Vessel 2] |
| cycle | looptime_seconds | |
|---|---|---|
| 0 | 1 | 0.000000 |
| 1 | 2 | -7777.596112 |
| t_l_up | sum_t_i_up | T_close_up | T_waterlevel_up | T_open_up | sum_t_u_up | t_l_down | sum_t_i_down | T_close_down | T_waterlevel_down | T_open_down | sum_t_u_down | Tc_seconds | up_vessels | down_vessels | I_s | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | 0 | 6828.941685 | 300.0 | 300.0 | 300.0 | 6537.423326 | -7777.596112 | 6828.941685 | 300.0 | 300.0 | 300.0 | 6537.423326 | 20755.13391 | [Vessel 1, Vessel 2] | [Vessel 1, Vessel 2] | 0.693804 |
for index, row in Tc_df.iterrows():
print('Locking cycle {} has an intensity of {:.2f} vessels per hour'.format(index+1, row['I_s']))
Locking cycle 1 has an intensity of 0.69 vessels per hour
Estimated capacity (vessels per hour)#
n_max = 4
vessel_speed_outside_of_lock = 4
# Part III, Ch3, Eq. 3.2 (NB: de helft van de looptime wordt hier effectief geimplementeerd door de sailing to lock te berekenen)
t_sailing_to_lock = lock_1.sailing_distance_to_crossing_point/vessel_speed_outside_of_lock
T_entering = t_sailing_to_lock + (n_max-1)*lock_1.sailing_in_time_gap_through_doors + 50/2
# Part III, Ch3, Eq. 3.3
T_operation = lock_1.lock_chamber.doors_closing_time + lock_1.lock_chamber.levelling_time + lock_1.lock_chamber.doors_opening_time
# Part III, Ch3, Eq. 3.4 (NB: de helft van de looptime wordt hier effectief geimplementeerd door de sailing out of lock te berekenen)
t_sailing_out_of_lock = lock_1.sailing_distance_to_crossing_point/vessel_speed_outside_of_lock
T_exiting = t_sailing_out_of_lock + (n_max-1)*lock_1.sailing_out_time_gap_through_doors + 350/2
# Part III, Ch3, Eq. 3.1
T_locking = T_entering + T_operation + T_exiting
T_c = 2 * T_locking
C_s = 2*n_max / (T_c/3600)
print(f"The capacity of the lock is {np.round(C_s,1)} vessels per hour")
The capacity of the lock is 4.4 vessels per hour
lock_1.vessel_planning.iloc[-1]
id 01685b5a-fc5b-4643-85f9-5486b5875a1f
node_from 0
node_to -1
lock_chamber NaN
L 100
B 20
T 10
operation_index 1
time_of_registration 2025-01-02 00:24:48.768899
time_of_acceptance 2025-01-02 00:24:48.768899
time_potential_lock_door_opening_stop 2025-01-02 01:16:28.768899
time_arrival_at_waiting_area 2025-01-02 01:06:28.768899
time_arrival_at_lineup_area NaN
time_lock_passing_start 2025-01-02 01:18:58.768899
time_lock_entry_start 2025-01-02 01:26:28.768899
time_lock_entry_stop 2025-01-02 01:32:08.941685470
time_lock_departure_start 2025-01-02 01:47:08.941685470
time_lock_departure_stop 2025-01-02 01:47:57.537797822
time_lock_passing_stop 2025-01-02 01:55:27.537797822
time_potential_lock_door_closure_start 2025-01-02 01:32:08.941685470
direction 1.0
delay 0 days 00:00:00
Name: 1, dtype: object
lock_1.operation_planning.iloc[1]
node_from 0
node_to -1
direction 1
lock_chamber Lock_1
vessels [<__main__.Vessel object at 0x7f2adb13d6d0>]
capacity_L 300
capacity_B 30
time_potential_lock_door_opening_stop 2025-01-02 01:16:28.768899
time_operation_start 2025-01-02 01:18:58.768899
time_entry_start 2025-01-02 01:26:28.768899
time_entry_stop 2025-01-02 01:32:08.941685470
time_door_closing_start 2025-01-02 01:32:08.941685470
time_door_closing_stop 2025-01-02 01:37:08.941685470
time_levelling_start 2025-01-02 01:37:08.941685470
time_levelling_stop 2025-01-02 01:42:08.941685470
time_door_opening_start 2025-01-02 01:42:08.941685470
time_door_opening_stop 2025-01-02 01:47:08.941685470
time_departure_start 2025-01-02 01:47:08.941685470
time_departure_stop 2025-01-02 01:47:57.537797822
time_operation_stop 2025-01-02 01:55:27.537797822
time_potential_lock_door_closure_start 2025-01-02 01:49:57.537797822
wlev_A NaN
wlev_B NaN
maximum_individual_delay 0 days 00:00:00
total_delay 0 days 00:00:00
status unavailable
Name: 1, dtype: object
lock_1.operation_planning.iloc[1]
node_from 0
node_to -1
direction 1
lock_chamber Lock_1
vessels [<__main__.Vessel object at 0x7f2adb13d6d0>]
capacity_L 300
capacity_B 30
time_potential_lock_door_opening_stop 2025-01-02 01:16:28.768899
time_operation_start 2025-01-02 01:18:58.768899
time_entry_start 2025-01-02 01:26:28.768899
time_entry_stop 2025-01-02 01:32:08.941685470
time_door_closing_start 2025-01-02 01:32:08.941685470
time_door_closing_stop 2025-01-02 01:37:08.941685470
time_levelling_start 2025-01-02 01:37:08.941685470
time_levelling_stop 2025-01-02 01:42:08.941685470
time_door_opening_start 2025-01-02 01:42:08.941685470
time_door_opening_stop 2025-01-02 01:47:08.941685470
time_departure_start 2025-01-02 01:47:08.941685470
time_departure_stop 2025-01-02 01:47:57.537797822
time_operation_stop 2025-01-02 01:55:27.537797822
time_potential_lock_door_closure_start 2025-01-02 01:49:57.537797822
wlev_A NaN
wlev_B NaN
maximum_individual_delay 0 days 00:00:00
total_delay 0 days 00:00:00
status unavailable
Name: 1, dtype: object
vessels[0].__dict__
{'output': {'origin': '',
'destination': '',
'route': [],
'bound': '',
'anchorage': '',
'turning_basin': '',
'terminal': '',
'berth': '',
'length': nan,
'beam': nan,
'draught': nan,
'sailing_distance': nan,
'sailing_time': nan,
'waiting_time': {'Anchorage': [], 'Terminal': []},
'turning_times': [],
'(un)loading_times': [],
'current_node': '',
'next_node': '',
'speed': nan,
'heading': nan,
'water_level': nan,
'MBL': nan,
'net_ukc': nan,
'gross_ukc': nan,
'ship_related_ukc_factors': {},
'available_water_depth': nan,
'required_water_depth': nan,
'limiting current velocity': nan,
'sailed_routes': [],
'visited_anchorages': [],
'visited_turning_basins': [],
'visited_terminals': [],
'visited_berths': [],
'visited_waiting_areas': [],
'visited_lineup_areas': [],
'visited_lock_chambers': []},
'metadata': {'arrival_time': Timestamp('2025-01-01 00:00:00')},
'type': 'tanker',
'B': 20,
'L': 100,
'_T': 10,
'_h_min': None,
'safety_margin': None,
'h_squat': None,
'payload': None,
'vessel_type': None,
'renewable_fuel_mass': None,
'renewable_fuel_volume': None,
'renewable_fuel_required_space': None,
'bound': 'inbound',
'env': <simpy.core.Environment at 0x7f2add4d97f0>,
'logbook': [{'Message': 'Sailing from node -2 to node -1 start',
'Timestamp': datetime.datetime(2025, 1, 1, 0, 0),
'Value': 0,
'Geometry': <POINT (-3.149 0)>},
{'Message': 'Sailing from node -2 to node -1 stop',
'Timestamp': datetime.datetime(2025, 1, 1, 23, 18, 20),
'Value': 335600.0,
'Geometry': <POINT (-0.135 0)>},
{'Message': 'Sailing from node -1 to node 0 start',
'Timestamp': datetime.datetime(2025, 1, 1, 23, 18, 20),
'Value': 335600.0,
'Geometry': <POINT (-0.135 0)>},
{'Message': 'Sailing to first lock doors start',
'Timestamp': datetime.datetime(2025, 1, 1, 23, 18, 20),
'Value': {'origin': '',
'destination': '',
'route': [],
'bound': '',
'anchorage': '',
'turning_basin': '',
'terminal': '',
'berth': '',
'length': nan,
'beam': nan,
'draught': nan,
'sailing_distance': nan,
'sailing_time': nan,
'waiting_time': {'Anchorage': [], 'Terminal': []},
'turning_times': [],
'(un)loading_times': [],
'current_node': '',
'next_node': '',
'speed': nan,
'heading': nan,
'water_level': nan,
'MBL': nan,
'net_ukc': nan,
'gross_ukc': nan,
'ship_related_ukc_factors': {},
'available_water_depth': nan,
'required_water_depth': nan,
'limiting current velocity': nan,
'sailed_routes': [],
'visited_anchorages': [],
'visited_turning_basins': [],
'visited_terminals': [],
'visited_berths': [],
'visited_waiting_areas': [],
'visited_lineup_areas': [],
'visited_lock_chambers': []},
'Geometry': <POINT (-0.135 0)>},
{'Message': 'Sailing to first lock doors stop',
'Timestamp': datetime.datetime(2025, 1, 1, 23, 38, 20),
'Value': {'origin': '',
'destination': '',
'route': [],
'bound': '',
'anchorage': '',
'turning_basin': '',
'terminal': '',
'berth': '',
'length': nan,
'beam': nan,
'draught': nan,
'sailing_distance': nan,
'sailing_time': nan,
'waiting_time': {'Anchorage': [], 'Terminal': []},
'turning_times': [],
'(un)loading_times': [],
'current_node': '',
'next_node': '',
'speed': nan,
'heading': nan,
'water_level': nan,
'MBL': nan,
'net_ukc': nan,
'gross_ukc': nan,
'ship_related_ukc_factors': {},
'available_water_depth': nan,
'required_water_depth': nan,
'limiting current velocity': nan,
'sailed_routes': [],
'visited_anchorages': [],
'visited_turning_basins': [],
'visited_terminals': [],
'visited_berths': [],
'visited_waiting_areas': [],
'visited_lineup_areas': [],
'visited_lock_chambers': []},
'Geometry': <POINT (-0.092 0)>},
{'Message': 'Sailing to position in lock start',
'Timestamp': datetime.datetime(2025, 1, 1, 23, 38, 20),
'Value': {'origin': '',
'destination': '',
'route': [],
'bound': '',
'anchorage': '',
'turning_basin': '',
'terminal': '',
'berth': '',
'length': nan,
'beam': nan,
'draught': nan,
'sailing_distance': nan,
'sailing_time': nan,
'waiting_time': {'Anchorage': [], 'Terminal': []},
'turning_times': [],
'(un)loading_times': [],
'current_node': '',
'next_node': '',
'speed': nan,
'heading': nan,
'water_level': nan,
'MBL': nan,
'net_ukc': nan,
'gross_ukc': nan,
'ship_related_ukc_factors': {},
'available_water_depth': nan,
'required_water_depth': nan,
'limiting current velocity': nan,
'sailed_routes': [],
'visited_anchorages': [],
'visited_turning_basins': [],
'visited_terminals': [],
'visited_berths': [],
'visited_waiting_areas': [],
'visited_lineup_areas': [],
'visited_lock_chambers': []},
'Geometry': <POINT (-0.092 0)>},
{'Message': 'Sailing to position in lock stop',
'Timestamp': datetime.datetime(2025, 1, 1, 23, 44, 0, 172786),
'Value': {'origin': '',
'destination': '',
'route': [],
'bound': '',
'anchorage': '',
'turning_basin': '',
'terminal': '',
'berth': '',
'length': nan,
'beam': nan,
'draught': nan,
'sailing_distance': nan,
'sailing_time': nan,
'waiting_time': {'Anchorage': [], 'Terminal': []},
'turning_times': [],
'(un)loading_times': [],
'current_node': '',
'next_node': '',
'speed': nan,
'heading': nan,
'water_level': nan,
'MBL': nan,
'net_ukc': nan,
'gross_ukc': nan,
'ship_related_ukc_factors': {},
'available_water_depth': nan,
'required_water_depth': nan,
'limiting current velocity': nan,
'sailed_routes': [],
'visited_anchorages': [],
'visited_turning_basins': [],
'visited_terminals': [],
'visited_berths': [],
'visited_waiting_areas': [],
'visited_lineup_areas': [],
'visited_lock_chambers': []},
'Geometry': <POINT (-0.088 0)>},
{'Message': 'Levelling start',
'Timestamp': datetime.datetime(2025, 1, 1, 23, 49, 0, 172786),
'Value': {'origin': '',
'destination': '',
'route': [],
'bound': '',
'anchorage': '',
'turning_basin': '',
'terminal': '',
'berth': '',
'length': nan,
'beam': nan,
'draught': nan,
'sailing_distance': nan,
'sailing_time': nan,
'waiting_time': {'Anchorage': [], 'Terminal': []},
'turning_times': [],
'(un)loading_times': [],
'current_node': '',
'next_node': '',
'speed': nan,
'heading': nan,
'water_level': nan,
'MBL': nan,
'net_ukc': nan,
'gross_ukc': nan,
'ship_related_ukc_factors': {},
'available_water_depth': nan,
'required_water_depth': nan,
'limiting current velocity': nan,
'sailed_routes': [],
'visited_anchorages': [],
'visited_turning_basins': [],
'visited_terminals': [],
'visited_berths': [],
'visited_waiting_areas': [],
'visited_lineup_areas': [],
'visited_lock_chambers': []},
'Geometry': <POINT (-0.088 0)>},
{'Message': 'Levelling stop',
'Timestamp': datetime.datetime(2025, 1, 1, 23, 54, 0, 172786),
'Value': {'origin': '',
'destination': '',
'route': [],
'bound': '',
'anchorage': '',
'turning_basin': '',
'terminal': '',
'berth': '',
'length': nan,
'beam': nan,
'draught': nan,
'sailing_distance': nan,
'sailing_time': nan,
'waiting_time': {'Anchorage': [], 'Terminal': []},
'turning_times': [],
'(un)loading_times': [],
'current_node': '',
'next_node': '',
'speed': nan,
'heading': nan,
'water_level': nan,
'MBL': nan,
'net_ukc': nan,
'gross_ukc': nan,
'ship_related_ukc_factors': {},
'available_water_depth': nan,
'required_water_depth': nan,
'limiting current velocity': nan,
'sailed_routes': [],
'visited_anchorages': [],
'visited_turning_basins': [],
'visited_terminals': [],
'visited_berths': [],
'visited_waiting_areas': [],
'visited_lineup_areas': [],
'visited_lock_chambers': []},
'Geometry': <POINT (-0.088 0)>},
{'Message': 'Sailing to second lock doors start',
'Timestamp': datetime.datetime(2025, 1, 1, 23, 59, 0, 172786),
'Value': {'origin': '',
'destination': '',
'route': [],
'bound': '',
'anchorage': '',
'turning_basin': '',
'terminal': '',
'berth': '',
'length': nan,
'beam': nan,
'draught': nan,
'sailing_distance': nan,
'sailing_time': nan,
'waiting_time': {'Anchorage': [], 'Terminal': []},
'turning_times': [],
'(un)loading_times': [],
'current_node': '',
'next_node': '',
'speed': nan,
'heading': nan,
'water_level': nan,
'MBL': nan,
'net_ukc': nan,
'gross_ukc': nan,
'ship_related_ukc_factors': {},
'available_water_depth': nan,
'required_water_depth': nan,
'limiting current velocity': nan,
'sailed_routes': [],
'visited_anchorages': [],
'visited_turning_basins': [],
'visited_terminals': [],
'visited_berths': [],
'visited_waiting_areas': [],
'visited_lineup_areas': [],
'visited_lock_chambers': []},
'Geometry': <POINT (-0.088 0)>},
{'Message': 'Sailing to second lock doors stop',
'Timestamp': datetime.datetime(2025, 1, 1, 23, 59, 48, 768899),
'Value': {'origin': '',
'destination': '',
'route': [],
'bound': '',
'anchorage': '',
'turning_basin': '',
'terminal': '',
'berth': '',
'length': nan,
'beam': nan,
'draught': nan,
'sailing_distance': nan,
'sailing_time': nan,
'waiting_time': {'Anchorage': [], 'Terminal': []},
'turning_times': [],
'(un)loading_times': [],
'current_node': '',
'next_node': '',
'speed': nan,
'heading': nan,
'water_level': nan,
'MBL': nan,
'net_ukc': nan,
'gross_ukc': nan,
'ship_related_ukc_factors': {},
'available_water_depth': nan,
'required_water_depth': nan,
'limiting current velocity': nan,
'sailed_routes': [],
'visited_anchorages': [],
'visited_turning_basins': [],
'visited_terminals': [],
'visited_berths': [],
'visited_waiting_areas': [],
'visited_lineup_areas': [],
'visited_lock_chambers': []},
'Geometry': <POINT (-0.088 0)>},
{'Message': 'Sailing to lock complex exit start',
'Timestamp': datetime.datetime(2025, 1, 1, 23, 59, 48, 768899),
'Value': {'origin': '',
'destination': '',
'route': [],
'bound': '',
'anchorage': '',
'turning_basin': '',
'terminal': '',
'berth': '',
'length': nan,
'beam': nan,
'draught': nan,
'sailing_distance': nan,
'sailing_time': nan,
'waiting_time': {'Anchorage': [], 'Terminal': []},
'turning_times': [],
'(un)loading_times': [],
'current_node': '',
'next_node': '',
'speed': nan,
'heading': nan,
'water_level': nan,
'MBL': nan,
'net_ukc': nan,
'gross_ukc': nan,
'ship_related_ukc_factors': {},
'available_water_depth': nan,
'required_water_depth': nan,
'limiting current velocity': nan,
'sailed_routes': [],
'visited_anchorages': [],
'visited_turning_basins': [],
'visited_terminals': [],
'visited_berths': [],
'visited_waiting_areas': [],
'visited_lineup_areas': [],
'visited_lock_chambers': []},
'Geometry': <POINT (-0.088 0)>},
{'Message': 'Sailing to lock complex exit stop',
'Timestamp': datetime.datetime(2025, 1, 2, 0, 19, 48, 768899),
'Value': {'origin': '',
'destination': '',
'route': [],
'bound': '',
'anchorage': '',
'turning_basin': '',
'terminal': '',
'berth': '',
'length': nan,
'beam': nan,
'draught': nan,
'sailing_distance': nan,
'sailing_time': nan,
'waiting_time': {'Anchorage': [], 'Terminal': []},
'turning_times': [],
'(un)loading_times': [],
'current_node': '',
'next_node': '',
'speed': nan,
'heading': nan,
'water_level': nan,
'MBL': nan,
'net_ukc': nan,
'gross_ukc': nan,
'ship_related_ukc_factors': {},
'available_water_depth': nan,
'required_water_depth': nan,
'limiting current velocity': nan,
'sailed_routes': [],
'visited_anchorages': [],
'visited_turning_basins': [],
'visited_terminals': [],
'visited_berths': [],
'visited_waiting_areas': [],
'visited_lineup_areas': [],
'visited_lock_chambers': []},
'Geometry': <POINT (-0.045 0)>},
{'Message': 'Sailing from node -1 to node 0 stop',
'Timestamp': datetime.datetime(2025, 1, 2, 0, 19, 48, 768899),
'Value': 335600.0,
'Geometry': <POINT (-0.045 0)>},
{'Message': 'Sailing from node 0 to node 1 start',
'Timestamp': datetime.datetime(2025, 1, 2, 0, 19, 48, 768899),
'Value': 335600.0,
'Geometry': <POINT (-0.045 0)>},
{'Message': 'Sailing from node 0 to node 1 stop',
'Timestamp': datetime.datetime(2025, 1, 2, 1, 1, 28, 768899),
'Value': 345600.0,
'Geometry': <POINT (0.045 0)>},
{'Message': 'Sailing from node 1 to node +1 start',
'Timestamp': datetime.datetime(2025, 1, 2, 1, 1, 28, 768899),
'Value': 345600.0,
'Geometry': <POINT (0.045 0)>},
{'Message': 'Sailing to first lock doors start',
'Timestamp': datetime.datetime(2025, 1, 2, 1, 1, 28, 768899),
'Value': {'origin': '',
'destination': '',
'route': [],
'bound': '',
'anchorage': '',
'turning_basin': '',
'terminal': '',
'berth': '',
'length': nan,
'beam': nan,
'draught': nan,
'sailing_distance': nan,
'sailing_time': nan,
'waiting_time': {'Anchorage': [], 'Terminal': []},
'turning_times': [],
'(un)loading_times': [],
'current_node': '',
'next_node': '',
'speed': nan,
'heading': nan,
'water_level': nan,
'MBL': nan,
'net_ukc': nan,
'gross_ukc': nan,
'ship_related_ukc_factors': {},
'available_water_depth': nan,
'required_water_depth': nan,
'limiting current velocity': nan,
'sailed_routes': [],
'visited_anchorages': [],
'visited_turning_basins': [],
'visited_terminals': [],
'visited_berths': [],
'visited_waiting_areas': [],
'visited_lineup_areas': [],
'visited_lock_chambers': []},
'Geometry': <POINT (0.045 0)>},
{'Message': 'Sailing to first lock doors stop',
'Timestamp': datetime.datetime(2025, 1, 2, 1, 21, 28, 768899),
'Value': {'origin': '',
'destination': '',
'route': [],
'bound': '',
'anchorage': '',
'turning_basin': '',
'terminal': '',
'berth': '',
'length': nan,
'beam': nan,
'draught': nan,
'sailing_distance': nan,
'sailing_time': nan,
'waiting_time': {'Anchorage': [], 'Terminal': []},
'turning_times': [],
'(un)loading_times': [],
'current_node': '',
'next_node': '',
'speed': nan,
'heading': nan,
'water_level': nan,
'MBL': nan,
'net_ukc': nan,
'gross_ukc': nan,
'ship_related_ukc_factors': {},
'available_water_depth': nan,
'required_water_depth': nan,
'limiting current velocity': nan,
'sailed_routes': [],
'visited_anchorages': [],
'visited_turning_basins': [],
'visited_terminals': [],
'visited_berths': [],
'visited_waiting_areas': [],
'visited_lineup_areas': [],
'visited_lock_chambers': []},
'Geometry': <POINT (0.088 0)>},
{'Message': 'Sailing to position in lock start',
'Timestamp': datetime.datetime(2025, 1, 2, 1, 21, 28, 768899),
'Value': {'origin': '',
'destination': '',
'route': [],
'bound': '',
'anchorage': '',
'turning_basin': '',
'terminal': '',
'berth': '',
'length': nan,
'beam': nan,
'draught': nan,
'sailing_distance': nan,
'sailing_time': nan,
'waiting_time': {'Anchorage': [], 'Terminal': []},
'turning_times': [],
'(un)loading_times': [],
'current_node': '',
'next_node': '',
'speed': nan,
'heading': nan,
'water_level': nan,
'MBL': nan,
'net_ukc': nan,
'gross_ukc': nan,
'ship_related_ukc_factors': {},
'available_water_depth': nan,
'required_water_depth': nan,
'limiting current velocity': nan,
'sailed_routes': [],
'visited_anchorages': [],
'visited_turning_basins': [],
'visited_terminals': [],
'visited_berths': [],
'visited_waiting_areas': [],
'visited_lineup_areas': [],
'visited_lock_chambers': []},
'Geometry': <POINT (0.088 0)>},
{'Message': 'Sailing to position in lock stop',
'Timestamp': datetime.datetime(2025, 1, 2, 1, 27, 8, 941685),
'Value': {'origin': '',
'destination': '',
'route': [],
'bound': '',
'anchorage': '',
'turning_basin': '',
'terminal': '',
'berth': '',
'length': nan,
'beam': nan,
'draught': nan,
'sailing_distance': nan,
'sailing_time': nan,
'waiting_time': {'Anchorage': [], 'Terminal': []},
'turning_times': [],
'(un)loading_times': [],
'current_node': '',
'next_node': '',
'speed': nan,
'heading': nan,
'water_level': nan,
'MBL': nan,
'net_ukc': nan,
'gross_ukc': nan,
'ship_related_ukc_factors': {},
'available_water_depth': nan,
'required_water_depth': nan,
'limiting current velocity': nan,
'sailed_routes': [],
'visited_anchorages': [],
'visited_turning_basins': [],
'visited_terminals': [],
'visited_berths': [],
'visited_waiting_areas': [],
'visited_lineup_areas': [],
'visited_lock_chambers': []},
'Geometry': <POINT (0.091 0)>},
{'Message': 'Levelling start',
'Timestamp': datetime.datetime(2025, 1, 2, 1, 32, 9),
'Value': {'origin': '',
'destination': '',
'route': [],
'bound': '',
'anchorage': '',
'turning_basin': '',
'terminal': '',
'berth': '',
'length': nan,
'beam': nan,
'draught': nan,
'sailing_distance': nan,
'sailing_time': nan,
'waiting_time': {'Anchorage': [], 'Terminal': []},
'turning_times': [],
'(un)loading_times': [],
'current_node': '',
'next_node': '',
'speed': nan,
'heading': nan,
'water_level': nan,
'MBL': nan,
'net_ukc': nan,
'gross_ukc': nan,
'ship_related_ukc_factors': {},
'available_water_depth': nan,
'required_water_depth': nan,
'limiting current velocity': nan,
'sailed_routes': [],
'visited_anchorages': [],
'visited_turning_basins': [],
'visited_terminals': [],
'visited_berths': [],
'visited_waiting_areas': [],
'visited_lineup_areas': [],
'visited_lock_chambers': []},
'Geometry': <POINT (0.091 0)>},
{'Message': 'Levelling stop',
'Timestamp': datetime.datetime(2025, 1, 2, 1, 37, 9),
'Value': {'origin': '',
'destination': '',
'route': [],
'bound': '',
'anchorage': '',
'turning_basin': '',
'terminal': '',
'berth': '',
'length': nan,
'beam': nan,
'draught': nan,
'sailing_distance': nan,
'sailing_time': nan,
'waiting_time': {'Anchorage': [], 'Terminal': []},
'turning_times': [],
'(un)loading_times': [],
'current_node': '',
'next_node': '',
'speed': nan,
'heading': nan,
'water_level': nan,
'MBL': nan,
'net_ukc': nan,
'gross_ukc': nan,
'ship_related_ukc_factors': {},
'available_water_depth': nan,
'required_water_depth': nan,
'limiting current velocity': nan,
'sailed_routes': [],
'visited_anchorages': [],
'visited_turning_basins': [],
'visited_terminals': [],
'visited_berths': [],
'visited_waiting_areas': [],
'visited_lineup_areas': [],
'visited_lock_chambers': []},
'Geometry': <POINT (0.091 0)>},
{'Message': 'Sailing to second lock doors start',
'Timestamp': datetime.datetime(2025, 1, 2, 1, 42, 9),
'Value': {'origin': '',
'destination': '',
'route': [],
'bound': '',
'anchorage': '',
'turning_basin': '',
'terminal': '',
'berth': '',
'length': nan,
'beam': nan,
'draught': nan,
'sailing_distance': nan,
'sailing_time': nan,
'waiting_time': {'Anchorage': [], 'Terminal': []},
'turning_times': [],
'(un)loading_times': [],
'current_node': '',
'next_node': '',
'speed': nan,
'heading': nan,
'water_level': nan,
'MBL': nan,
'net_ukc': nan,
'gross_ukc': nan,
'ship_related_ukc_factors': {},
'available_water_depth': nan,
'required_water_depth': nan,
'limiting current velocity': nan,
'sailed_routes': [],
'visited_anchorages': [],
'visited_turning_basins': [],
'visited_terminals': [],
'visited_berths': [],
'visited_waiting_areas': [],
'visited_lineup_areas': [],
'visited_lock_chambers': []},
'Geometry': <POINT (0.091 0)>},
{'Message': 'Sailing to second lock doors stop',
'Timestamp': datetime.datetime(2025, 1, 2, 1, 42, 57, 596112),
'Value': {'origin': '',
'destination': '',
'route': [],
'bound': '',
'anchorage': '',
'turning_basin': '',
'terminal': '',
'berth': '',
'length': nan,
'beam': nan,
'draught': nan,
'sailing_distance': nan,
'sailing_time': nan,
'waiting_time': {'Anchorage': [], 'Terminal': []},
'turning_times': [],
'(un)loading_times': [],
'current_node': '',
'next_node': '',
'speed': nan,
'heading': nan,
'water_level': nan,
'MBL': nan,
'net_ukc': nan,
'gross_ukc': nan,
'ship_related_ukc_factors': {},
'available_water_depth': nan,
'required_water_depth': nan,
'limiting current velocity': nan,
'sailed_routes': [],
'visited_anchorages': [],
'visited_turning_basins': [],
'visited_terminals': [],
'visited_berths': [],
'visited_waiting_areas': [],
'visited_lineup_areas': [],
'visited_lock_chambers': []},
'Geometry': <POINT (0.092 0)>},
{'Message': 'Sailing to lock complex exit start',
'Timestamp': datetime.datetime(2025, 1, 2, 1, 42, 57, 596112),
'Value': {'origin': '',
'destination': '',
'route': [],
'bound': '',
'anchorage': '',
'turning_basin': '',
'terminal': '',
'berth': '',
'length': nan,
'beam': nan,
'draught': nan,
'sailing_distance': nan,
'sailing_time': nan,
'waiting_time': {'Anchorage': [], 'Terminal': []},
'turning_times': [],
'(un)loading_times': [],
'current_node': '',
'next_node': '',
'speed': nan,
'heading': nan,
'water_level': nan,
'MBL': nan,
'net_ukc': nan,
'gross_ukc': nan,
'ship_related_ukc_factors': {},
'available_water_depth': nan,
'required_water_depth': nan,
'limiting current velocity': nan,
'sailed_routes': [],
'visited_anchorages': [],
'visited_turning_basins': [],
'visited_terminals': [],
'visited_berths': [],
'visited_waiting_areas': [],
'visited_lineup_areas': [],
'visited_lock_chambers': []},
'Geometry': <POINT (0.092 0)>},
{'Message': 'Sailing to lock complex exit stop',
'Timestamp': datetime.datetime(2025, 1, 2, 2, 2, 57, 596112),
'Value': {'origin': '',
'destination': '',
'route': [],
'bound': '',
'anchorage': '',
'turning_basin': '',
'terminal': '',
'berth': '',
'length': nan,
'beam': nan,
'draught': nan,
'sailing_distance': nan,
'sailing_time': nan,
'waiting_time': {'Anchorage': [], 'Terminal': []},
'turning_times': [],
'(un)loading_times': [],
'current_node': '',
'next_node': '',
'speed': nan,
'heading': nan,
'water_level': nan,
'MBL': nan,
'net_ukc': nan,
'gross_ukc': nan,
'ship_related_ukc_factors': {},
'available_water_depth': nan,
'required_water_depth': nan,
'limiting current velocity': nan,
'sailed_routes': [],
'visited_anchorages': [],
'visited_turning_basins': [],
'visited_terminals': [],
'visited_berths': [],
'visited_waiting_areas': [],
'visited_lineup_areas': [],
'visited_lock_chambers': []},
'Geometry': <POINT (0.135 0)>},
{'Message': 'Sailing from node 1 to node +1 stop',
'Timestamp': datetime.datetime(2025, 1, 2, 2, 2, 57, 596112),
'Value': 345600.0,
'Geometry': <POINT (0.135 0)>},
{'Message': 'Sailing from node +1 to node +2 start',
'Timestamp': datetime.datetime(2025, 1, 2, 2, 2, 57, 596112),
'Value': 345600.0,
'Geometry': <POINT (0.135 0)>},
{'Message': 'Sailing from node +1 to node +2 stop',
'Timestamp': datetime.datetime(2025, 1, 3, 1, 21, 17, 596112),
'Value': 681200.0,
'Geometry': <POINT (3.149 0)>}],
'route': ['-2', '-1', '0', '1', '+1', '+2'],
'position_on_route': 5,
'complete_path': None,
'geometry': <POINT (3.149 0)>,
'node': None,
'wgs84': Geod(ellps='WGS84'),
'v': 4,
'distance': 681200.0,
'on_pass_node_functions': [<bound method PassesLockComplex.register_to_lock_master of <__main__.Vessel object at 0x7f2adb2fda90>>],
'on_pass_edge_functions': [<bound method PassesLockComplex.sail_to_waiting_area of <__main__.Vessel object at 0x7f2adb2fda90>>],
'on_complete_pass_edge_functions': [],
'on_look_ahead_to_node_functions': [],
'req': None,
'resource': None,
'distance_left_on_edge': 335600.0,
'name': 'Vessel 1',
'id': '70723064-4cc5-4bb2-a2c1-11ccf0bec8a4',
'overruled_speed': Empty DataFrame
Columns: [Speed]
Index: [],
'waiting_area_request': <Request() object at 0x7f2adb3e24e0>,
'distance_position_from_first_lock_doors': 350.0,
'position_in_lock': <POINT (0.091 0)>}