Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion WeatherRoutingTool/execute_routing.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ def merge_figures_to_gif(path, nof_figures):
graphics.merge_figs(path, nof_figures)


def execute_routing(config, ship_config):
def execute_routing(config, ship_config, csv_export_path: str = None):
"""
Execute route optimization based on the user-defined configuration.
After a successful run the final route is saved into the configured folder.
Expand Down Expand Up @@ -67,6 +67,8 @@ def execute_routing(config, ship_config):
min_fuel_route, error_code = alg.execute_routing(boat, wt, constraint_list)
# min_fuel_route.print_route()
min_fuel_route.write_to_geojson(routepath / f"{min_fuel_route.route_type}.geojson")
if csv_export_path:
min_fuel_route.write_summary_to_csv(csv_export_path)

if config.ROUTE_POSTPROCESSING:
postprocessed_route = RoutePostprocessing(min_fuel_route, boat)
Expand Down
50 changes: 50 additions & 0 deletions WeatherRoutingTool/routeparams.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
from fileinput import filename
import json
from datetime import datetime, timedelta

Expand Down Expand Up @@ -204,6 +205,55 @@ def write_to_geojson(self, filename):

with open(filename, 'w') as file:
json.dump(rp_dict, file, cls=NumpyArrayEncoder, indent=4)
def write_summary_to_csv(self, filename: str) -> None:
import csv

with open(filename, mode="w", newline="") as csvfile:
writer = csv.writer(csvfile)

writer.writerow([
"waypoint_id",
"latitude_deg",
"longitude_deg",
"timestamp",
"speed_mps",
"engine_power_kW",
"fuel_rate_kg_per_s",
"wave_height_m",
"wind_resistance_N",
"dist_to_next_m",
"status"
])
for i in range(0, self.count + 2):
if i == (self.count + 1):
# Destination row with sentinel values
writer.writerow([
i,
self.lats_per_step[i],
self.lons_per_step[i],
self.starttime_per_step[i],
-99,
-99,
-99,
-99,
-99,
-99,
-99
])
else:
writer.writerow([
i,
self.lats_per_step[i],
self.lons_per_step[i],
self.starttime_per_step[i],
self.ship_params_per_step.speed[i].value,
self.ship_params_per_step.power[i].to("kW").value,
self.ship_params_per_step.fuel_rate[i].value,
self.ship_params_per_step.wave_height[i].value,
self.ship_params_per_step.r_wind[i].value,
-99,
self.ship_params_per_step.status[i]
])

@classmethod
def from_file(cls, filename):
Expand Down
9 changes: 8 additions & 1 deletion cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,13 @@
required=False, type=str, default='False')
parser.add_argument('--filter-warnings', help="Filter action. <default|error|ignore|always|module|once>."
"Defaults to 'default'.", required=False, type=str, default='default')
parser.add_argument(
'--export-csv',
help="Path for a per-waypoint CSV summary of the optimised route.",
required=False,
type=str,
default=None
)
args = parser.parse_args()
if not args.file:
raise RuntimeError("No config file name provided!")
Expand All @@ -37,7 +44,7 @@
# Validate config with pydantic and run route optimization
config = Config.assign_config(args.file)
ship_config = ShipConfig.assign_config(args.file)
execute_routing(config, ship_config)
execute_routing(config, ship_config, csv_export_path=args.export_csv)

# set warning filter action (https://docs.python.org/3/library/warnings.html)
warnings.filterwarnings(args.filter_warnings)
Binary file added gdfDB.sqlite
Binary file not shown.
40 changes: 40 additions & 0 deletions tests/test_route_utils.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import numpy as np
from geographiclib.geodesic import Geodesic

from WeatherRoutingTool.algorithms.data_utils import distance, time_diffs


def test_distance_two_point_meridian():
"""
Route: (0,0) -> (1,0)
Expected distance ≈ geodesic distance between the two points.
"""
route = np.array([
[0.0, 0.0],
[1.0, 0.0]
])

dists = distance(route)

expected = Geodesic.WGS84.Inverse(0, 0, 1, 0)['s12']

assert np.isclose(dists[-1], expected, rtol=1e-4)


def test_time_diffs_constant_speed():
"""
Same route but convert distance to time using speed.
"""
route = np.array([
[0.0, 0.0],
[1.0, 0.0]
])

speed = 10.0 # m/s

times = time_diffs(speed, route)

expected_dist = Geodesic.WGS84.Inverse(0, 0, 1, 0)['s12']
expected_time = expected_dist / speed

assert np.isclose(times[-1], expected_time, rtol=1e-4)