(Created page with "== SEL == A brief explanation of the Shipping Model (SEL) config. SEL can be almost completely configured within the config file for the scenario. All fields in this document are attached to the 'SEL' object of the config file, unless explicitly said otherwise. The characteristics of SEL's pathfinding logic are explained in the conference paper listed on the Research Publications page. Something more specific to add to that paper concerns the...") |
No edit summary |
||
Line 1: | Line 1: | ||
== SEL == | == SEL == | ||
The Shipping simulation (SEL) can be almost completely configured within the config file for the scenario. All fields in this document are attached to the 'SEL' object of the config file, unless explicitly said otherwise. | |||
The characteristics of SEL's pathfinding logic are explained [[Research publications|in the conference paper listed on the Research Publications page]]. Something more specific to add to that paper concerns the exact configuration options with which you can control pathfinding. | The characteristics of SEL's pathfinding logic are explained [[Research publications|in the conference paper listed on the Research Publications page]]. Something more specific to add to that paper concerns the exact configuration options with which you can control pathfinding. |
Revision as of 14:52, 8 April 2024
SEL
The Shipping simulation (SEL) can be almost completely configured within the config file for the scenario. All fields in this document are attached to the 'SEL' object of the config file, unless explicitly said otherwise.
The characteristics of SEL's pathfinding logic are explained in the conference paper listed on the Research Publications page. Something more specific to add to that paper concerns the exact configuration options with which you can control pathfinding.
Always keep in mind that SEL ideally finds straight lines between port of origin and port of destination (as ship captains in real life also would like to do), but that there are always things influencing / altering that straight line:
- Things that disallow a route from going through there, e.g. a real restriction - an island, a wind farm, a no-shipping zone, ... To configure something like this, just add the data layer as a restriction, see the first instructions explained further below under 'Restrictions'.
- Things that (strongly) encourage a route to go through there rather than just around it or slightly to the left or right from it, such as an IMO route. To configure something like this, just add the data layers as a shipping_lane_layers as explained under 'General' immediately below.
- Things that (strongly) discourage a route to go through there, e.g. shallow areas. To configure something like this, add the data layer as a restriction, and then again as a restriction exception to set a cost / penalty, as explained under 'Restrictions' too.
Common practices in e.g. the North Sea or Baltic Sea configs is to use the above system as follows:
- Make a vector version of bathymetry layer with which to discourage SEL to go through shallow waters, i.e. ...
- This means turning the bathymetry raster into a bathymetry polygon layer, based on above or below ~20m depth only.
- and then adding that new bathymetry vector layer to the config file, but making it invisible by setting layer_active, layer_selectable, layer_editable, layer_toggleable, and layer_active_on_start to 0 in the layer's definition under 'meta',
- and finally adding the layer to the 'restrictions' definition (outside of the 'SEL' object in the config file) as well as the 'restriction_exceptions' definition (back inside the 'SEL' object again). See the 'Restrictions' section further below for more information and an example.
- Make an 'invisible shipping lanes' layer with which to encourage SEL to use certain common routes that don't involve e.g. any IMO lanes or something else, i.e., ...
- a layer of lines in areas that SEL tends to avoid even though they are in real life commonly used,
- making that layer again invisible to players (see above)
- and finally adding the layer to shipping_lane_layers. Note that you can also set ship_types and then map this layer's types to those ship types using layer_type_ship_type_mapping (see below).
- Make a 'connection points' layer to help SEL find paths around areas that disallow it to use, e.g. when a port of destination is 'hiding' behind a bit of land from the perspective of the port of origin (e.g. an island or peninsula), i.e., ...
- a layer of points equally spaced, e.g. every 5 kilometers apart, horizontally and vertically, up until the shorelines, a perhaps some more going up a river
- making that layer again invisible to players (see above)
- and finally adding the layer to shipping_lane_layers. Note that you can also set ship_types and then map this layer's types to those ship types using layer_type_ship_type_mapping (see below).
- Make a 'fairways' layer to help SEL find paths up an estuary (or other land-locked, narrow bits), as an alternative for adding a big bunch of connection points (see previous point), i.e., ...
- a layer of lines, could actually be lines that are dredged in real life to ensure deep enough entrances into big ports for container or tanker vessels for example
- you could decide to keep this layer visible and editable for players. We did that with the Baltic Sea config.
- and finally adding the layer to shipping_lane_layers. Note that you can also set ship_types and then map this layer's types to those ship types using layer_type_ship_type_mapping (see below).
General
"shipping_lane_layers": [ "NS_Shipping_Routes" ],
Field | Type | Description |
---|---|---|
shipping_lane_layers | string[] | The "shipping_lane_layers" specify what layers define the geometry for the shipping lanes. There needs to be at least one layer defined for the shipping model to work correctly, but any number of additional layers can be defined as an array. |
"country_border_layer": "NS_EEZ",
Field | Type | Description |
---|---|---|
country_border_layer | string | Layer which defines the area of each country. This was required for figuring out what country each port belongs to in order to correctly submit the KPI values. |
Regional Config Settings
"shipping_lane_point_merge_distance": 10000, "shipping_lane_subdivide_distance": 50000, "shipping_lane_implicit_distance_limit": 200000, "port_lane_max_merge_distance": 1000,
Field | Type | Description |
---|---|---|
shipping_lane_point_merge_distance | double | Merge distance for simplification. All nodes on a single geometry instance will be merged if their distance to the previous node is lower than this value |
shipping_lane_subdivide_distance | double | Edges in defined geometry will be subdivided across this length so we have segments that are approximately this length. |
shipping_lane_implicit_distance_limit | double | Maximum distance we consider for creating implicit edges. |
port_lane_max_merge_distance | double | Distance at which ports can be merged / connected to shipping lane vertices. Shipping ports on land can only create new connections through this merge method. |
Ports
Definitions
"port_layers": [ { "layer_name": "BS_Ports_Model", "port_type": "DefinedPort" }, { "layer_name": "BS_Wind_Farms_Edit", "port_type": "MaintenanceDestination" } ],
Field | Type | Description |
---|---|---|
port_layers | object[] | Collection of layers that hold the shipping port geometry. |
→ layer_name | string | The layer_name field defines the name of the layer which hold the geometry for the ports. |
→ port_type | enum | Accepted Values: "DefinedPort", "MaintenanceDestination"
|
Intensities
"port_intensity": [ { "port_id": "Port0", "ship_intensity_values": [ { "start_time": 0, "ship_type_id": 0, "ship_intensity": 500 }, { "start_time": 10, "ship_type_id": 0, "ship_intensity": 1000 } ] } ]
Field | Type | Description |
---|---|---|
port_intensity | object[] | Description of the port intensities per port |
→ port_id | string | Persistent identifier of the ports we are going to specify the intensity for. |
→ ship_intensity_values | object[] | Array of intensity per ship type and per time |
→→ start_time | int | Month at which this intensity should be in full effect |
→→ ship_type_id | int | The unique ID of the ship type we are defining the intensity for |
→→ ship_intensity | int | The intensity value at the specified time and for the specified ID on the port. Intensities will be linearly interpolated in the months that are not defined. So for our example config month 5 will result in 750 intensity. Month 11 will result in 1000 intensity. |
Maintenance destinations and intensities
"maintenance_destinations": { "construction_intensity_multiplier": 2.5, "base_intensity_per_square_km": 1, "point_construction_intensity": 10, "point_intensity": 2, },
Field | Type | Description |
---|---|---|
maintenance_destinations | object | Object describing the intensities for ports that are marked with the MaintenanceDestination type |
→ construction_intensity_multiplier | float | Multiplier for intensity when a port is still in construction. (In our case this means in an Approved plan when game time is the implementation date - assembly time) |
→ base_intensity_per_square_km | float | Intensity multiplier that is applied to the square km area of the polygon. This defines the intensity of the port when the layer is fully constructed and active. |
→ point_construction_intensity | float | Intensity per month for point geometry while the geometry is sitll being constructed. |
→ point_intensity | float | Intensity per month for point geometry that are marked as maintenance destinations. |
Preconfigured Routes
"configured_routes": [ { "source_port_id": "Port1", "destination_port_id": "Port0", "ship_type_id": 4, "intensity_percentage": 1 } ]
Field | Type | Description |
---|---|---|
configured_routes | object[] | An array of preconfigured routes and their relative intensities |
→ source_port_id | string | ID of the port that the route starts |
→ destination_port_id | string | ID of the port that the route ends |
→ ship_type_id | int | ID of the ship type that should take this route |
→ intensity_percentage | float | Values 0..1. The percentage of ships that are generated on source_port that should take this route. Any ship that is not allocated via a preconfigured route will be distributed over all the other available ports depending on their intensities. Ports that have a higher intensity will be sent more ships. |
→ start_time | int | OPTIONAL: the month from when the route should become active. The simulation will always take the route that has the most recent start_time if there's multiple routes defined for the same source, destination and ship type id. |
Restrictions
The system uses the restrictions setup in the config file which intersect with the shipping lane layers. This means that SEL looks at the 'restrictions' object in the config file (so outside of the SEL section!) to find the geometry of layers mentioned in there as being restricted by layers defined under SEL's 'shipping_lane_layers'.
So for example, in the North Sea Basic config of v4.0.1, you'll find this restriction definition:
"NS_IMO_Routes|NS_Countries": [ { "message": "Shipping routes should not cross over land.", "value": 0.0, "type": "WARNING", "startlayer": "NS_IMO_Routes", "starttype": "", "endlayer": "NS_Countries", "endtype": "", "sort": "Inclusion" } ],
Notice the 'startlayer' of NS_IMO_Routes and the 'endlayer' of NS_Countries. The NS_IMO_Routes layer is defined as a shipping lane layer:
"shipping_lane_layers": [ "NS_IMO_Routes", "NS_Connection_Points_25km_2", "NS_National_shipping_lanes", "NS_Shipping_Invisible_Lanes" ],
Because of this, SEL picks up all the geometry under the NS_Countries layer and considers that as something that cannot be crossed when it tries to find the shipping paths.
Here's another example of a restriction definition in the north Sea Basic config of v4.0.1:
"NS_IMO_Routes|NS_Bat_20_shipping": [ { "message": "Bathymetry under 20m is not ideal for shipping.", "value": 0.0, "type": "INFO", "startlayer": "NS_IMO_Routes", "starttype": "", "endlayer": "NS_Bat_20_shipping", "endtype": "", "sort": "Inclusion" } ],
Again, SEL picks this up too, because NS_IMO_Routes is a shipping lane layer. So SEL also picks up all the geometry of NS_Bat_20_shipping and considers that as something that cannot be crossed when it tries to find the shipping paths.
So SEL doesn't care if the shipping lane layer in the restriction was defined under 'startlayer' or 'endlayer', and it also doesn't care about the 'type' of restriction (warning, info, error, doesn't matter), or the 'value', or 'sort'. All of that doesn't matter.
For exceptions to the shipping restriction layers and their geometry, SEL looks at the next object: 'restriction_layer_exceptions'.
Here's an example of an exception involving that same NS_Bat_20_shipping layer:
"restriction_layer_exceptions": [ { "layer_name": "NS_Bat_20_shipping", "layer_types": [ "default" ], "allowed_ships": [ { "ship_type_ids": [ 1, 2, 3, 4, 5 ], "cost_multiplier": 20.0 } ] } ]
Have a look at the definitions of the values below. As you can see, by adding NS_Bat_20_shipping as an exception for basically all ship types (IDs 1-5), all of a sudden ships are allowed into the geometry of that layer again when SEL wants to calculate its routes, except that doing so makes it expensive, so SEL will first look for alternatives before it does that. This is exactly the kind of behaviour we want when it concerns shallow waters (which is what the NS_Bat_20_shipping geometry depicts).
Field | Type | Description |
---|---|---|
restriction_layer_exceptions | object[] | Restriction layer exceptions define what exceptions there are to the restrictions to allow certain ship types to move over certain layer types. |
→ layer_name | string | The name of the layer this exception applies to |
→ layer_types | string[] | The types within the layer the exception applies to. Each corresponds to the 'displayName' of a specific layer_type of a layers as defined under 'meta' outside of the SEL config. |
→ allowed_ships | an array of allowed ships (containing the ID, and the Cost multiplier) can be created for more flexible use of the system
so Type 1,2,3 can have a multiplier of 1 and Type 4,5 can have a multiplier of 20 | |
→ →
ship_type_ids |
int[] | IDs of the ship restriction groups that should be allowed to cross over the layer and type defined. |
→ → cost_multiplier | float | Cost multiplier traveling over an edge that is affected by this exception. This can be used to make routes more costly that go over these areas while not blocking them off completely.
Defaults to 1.0. |