Skip to content

Commit

Permalink
#27 Now possible to have several WP for own ship. The encounter is se…
Browse files Browse the repository at this point in the history
…t at the start of the situation.
  • Loading branch information
tomarnepedersen committed Apr 15, 2024
1 parent f2c42f8 commit 38925ec
Show file tree
Hide file tree
Showing 8 changed files with 208 additions and 96 deletions.
79 changes: 50 additions & 29 deletions src/trafficgen/encounter.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@
SituationInput,
)
from trafficgen.utils import (
calculate_bearing_between_waypoints,
calculate_position_along_track_using_waypoints,
calculate_position_at_certain_time,
convert_angle_0_to_2_pi_to_minus_pi_to_pi,
convert_angle_minus_pi_to_pi_to_0_to_2_pi,
Expand Down Expand Up @@ -98,11 +100,14 @@ def generate_encounter(

# Own ship
assert own_ship.initial is not None
own_ship_position_future = calculate_position_at_certain_time(
own_ship.initial.position,
lat_lon0,
assert own_ship.waypoints is not None
# Assuming ship is pointing in the direction of wp1
own_ship_cog = calculate_bearing_between_waypoints(
own_ship.waypoints[0].position, own_ship.waypoints[1].position
)
own_ship_position_future = calculate_position_along_track_using_waypoints(
own_ship.waypoints,
own_ship.initial.sog,
own_ship.initial.cog,
vector_time,
)

Expand All @@ -118,7 +123,7 @@ def generate_encounter(
min_target_ship_sog = (
calculate_min_vector_length_target_ship(
own_ship.initial.position,
own_ship.initial.cog,
own_ship_cog,
target_ship_position_future,
beta,
lat_lon0,
Expand All @@ -142,7 +147,7 @@ def generate_encounter(
start_position_target_ship, position_found = find_start_position_target_ship(
own_ship.initial.position,
lat_lon0,
own_ship.initial.cog,
own_ship_cog,
target_ship_position_future,
target_ship_vector_length,
beta,
Expand All @@ -157,7 +162,8 @@ def generate_encounter(
)
encounter_ok: bool = check_encounter_evolvement(
own_ship,
own_ship_position_future,
own_ship_cog,
own_ship.initial.position,
lat_lon0,
target_ship_sog,
target_ship_cog,
Expand All @@ -166,15 +172,17 @@ def generate_encounter(
settings,
)

# Check if trajectory passes land
trajectory_on_land = path_crosses_land(
target_ship_initial_position,
target_ship_sog,
target_ship_cog,
lat_lon0,
)

encounter_found = encounter_ok and not trajectory_on_land
if settings.disable_land_check is False:
# Check if trajectory passes land
trajectory_on_land = path_crosses_land(
target_ship_initial_position,
target_ship_sog,
target_ship_cog,
lat_lon0,
)
encounter_found = encounter_ok and not trajectory_on_land
else:
encounter_found = encounter_ok

if encounter_found:
target_ship_static.id = uuid4()
Expand Down Expand Up @@ -213,6 +221,7 @@ def generate_encounter(

def check_encounter_evolvement(
own_ship: OwnShip,
own_ship_cog: float,
own_ship_position_future: Position,
lat_lon0: Position,
target_ship_sog: float,
Expand Down Expand Up @@ -243,7 +252,6 @@ def check_encounter_evolvement(
assert own_ship.initial is not None

own_ship_sog: float = own_ship.initial.sog
own_ship_cog: float = own_ship.initial.cog
evolve_time: float = settings.evolve_time

# Calculating position back in time to ensure that the encounter do not change from one type
Expand Down Expand Up @@ -299,22 +307,35 @@ def define_own_ship(
* own_ship: Own ship
"""
own_ship_initial: Initial = desired_traffic_situation.own_ship.initial
own_ship_waypoint0 = Waypoint(
position=own_ship_initial.position.model_copy(deep=True), turn_radius=None, data=None
)
ship_position_future = calculate_position_at_certain_time(
own_ship_initial.position,
lat_lon0,
own_ship_initial.sog,
own_ship_initial.cog,
encounter_settings.situation_length,
)
own_ship_waypoint1 = Waypoint(position=ship_position_future, turn_radius=None, data=None)
if desired_traffic_situation.own_ship.waypoints is None:
# If waypoints are not given, let initial position be the first waypoint,
# then calculate second waypoint some time in the future
own_ship_waypoint0 = Waypoint(
position=own_ship_initial.position.model_copy(deep=True), turn_radius=None, data=None
)
ship_position_future = calculate_position_at_certain_time(
own_ship_initial.position,
lat_lon0,
own_ship_initial.sog,
own_ship_initial.cog,
encounter_settings.situation_length,
)
own_ship_waypoint1 = Waypoint(position=ship_position_future, turn_radius=None, data=None)
own_ship_waypoints: List[Waypoint] = [own_ship_waypoint0, own_ship_waypoint1]
elif len(desired_traffic_situation.own_ship.waypoints) == 1:
# If one waypoint is given, use initial position as first waypoint
own_ship_waypoint0 = Waypoint(
position=own_ship_initial.position.model_copy(deep=True), turn_radius=None, data=None
)
own_ship_waypoint1 = desired_traffic_situation.own_ship.waypoints[0]
own_ship_waypoints: List[Waypoint] = [own_ship_waypoint0, own_ship_waypoint1]
else:
own_ship_waypoints: List[Waypoint] = desired_traffic_situation.own_ship.waypoints

own_ship = OwnShip(
static=own_ship_static,
initial=own_ship_initial,
waypoints=[own_ship_waypoint0, own_ship_waypoint1],
waypoints=own_ship_waypoints,
)

return own_ship
Expand Down
24 changes: 13 additions & 11 deletions src/trafficgen/read_files.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,11 @@
TrafficSituation,
)

from trafficgen.types import (
EncounterSettings,
SituationInput,
UnitType,
)
from trafficgen.types import EncounterSettings, SituationInput
from trafficgen.utils import deg_2_rad, knot_2_m_pr_s, min_2_s, nm_2_m


def read_situation_files(situation_folder: Path, input_units: UnitType) -> List[SituationInput]:
def read_situation_files(situation_folder: Path) -> List[SituationInput]:
"""
Read traffic situation files.
Expand All @@ -43,8 +39,7 @@ def read_situation_files(situation_folder: Path, input_units: UnitType) -> List[
data["num_situations"] = 1

situation: SituationInput = SituationInput(**data)
if input_units.value == "maritime":
situation = convert_situation_data_from_maritime_to_si_units(situation)
situation = convert_situation_data_from_maritime_to_si_units(situation)

situation.input_file_name = file_name
situations.append(situation)
Expand Down Expand Up @@ -98,6 +93,15 @@ def convert_situation_data_from_maritime_to_si_units(situation: SituationInput)
situation.own_ship.initial.heading = deg_2_rad(situation.own_ship.initial.heading)
situation.own_ship.initial.sog = knot_2_m_pr_s(situation.own_ship.initial.sog)

if situation.own_ship.waypoints is not None:
for waypoint in situation.own_ship.waypoints:
waypoint.position.latitude = deg_2_rad(waypoint.position.latitude)
waypoint.position.longitude = deg_2_rad(waypoint.position.longitude)
if waypoint.data is not None:
assert waypoint.data.model_extra
if waypoint.data.model_extra.get("sog") is not None:
waypoint.data.model_extra["sog"]["value"] = knot_2_m_pr_s(waypoint.data.model_extra["sog"]["value"]) # type: ignore

assert situation.encounters is not None
for encounter in situation.encounters:
beta: Union[float, None] = encounter.beta
Expand Down Expand Up @@ -176,9 +180,7 @@ def read_encounter_settings_file(settings_file: Path) -> EncounterSettings:
data = check_input_units(data)
encounter_settings: EncounterSettings = EncounterSettings(**data)

# assert encounter_settings.input_units is not None
if encounter_settings.input_units.value == "maritime":
encounter_settings = convert_settings_data_from_maritime_to_si_units(encounter_settings)
encounter_settings = convert_settings_data_from_maritime_to_si_units(encounter_settings)

return encounter_settings

Expand Down
8 changes: 4 additions & 4 deletions src/trafficgen/settings/encounter_settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,9 @@
10.0,
30.0
],
"situation_length": 60.0,
"situation_length": 10.0,
"max_meeting_distance": 0.0,
"common_vector": 10.0,
"evolve_time": 120.0,
"input_units": "maritime"
"common_vector": 5.0,
"evolve_time": 5.0,
"disable_land_check": true
}
4 changes: 1 addition & 3 deletions src/trafficgen/ship_traffic_generator.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,9 +50,7 @@ def generate_traffic_situations(
own_ship_static: ShipStatic = read_own_ship_static_file(own_ship_file)
target_ships_static: List[ShipStatic] = read_target_ship_static_files(target_ship_folder)
encounter_settings: EncounterSettings = read_encounter_settings_file(settings_file)
desired_traffic_situations: List[SituationInput] = read_situation_files(
situation_folder, encounter_settings.input_units
)
desired_traffic_situations: List[SituationInput] = read_situation_files(situation_folder)
traffic_situations: List[TrafficSituation] = []

for desired_traffic_situation in desired_traffic_situations:
Expand Down
15 changes: 5 additions & 10 deletions src/trafficgen/types.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
"""Domain specific data types used in trafficgen."""

from enum import Enum
from typing import List, Union
from typing import List, Optional, Union

from maritime_schema.types.caga import Initial
from maritime_schema.types.caga import Initial, Waypoint
from pydantic import BaseModel
from pydantic.fields import Field


def to_camel(string: str) -> str:
Expand Down Expand Up @@ -71,13 +72,6 @@ class Config:
populate_by_name = True


class UnitType(Enum):
"""Enumeration of encounter types."""

SI_UNITS = "si"
MARITIME_UNITS = "maritime"


class EncounterSettings(BaseModel):
"""Data type for encounter settings."""

Expand All @@ -88,7 +82,7 @@ class EncounterSettings(BaseModel):
situation_length: float
max_meeting_distance: float
evolve_time: float
input_units: UnitType
disable_land_check: bool

class Config:
"""For converting parameters written to file from snake to camel case."""
Expand All @@ -101,6 +95,7 @@ class OwnShipInitial(BaseModel):
"""Data type for initial data for the own ship used for generating a situation."""

initial: Initial
waypoints: Optional[List[Waypoint]] = Field(None, description="An array of `Waypoint` objects.")


class SituationInput(BaseModel):
Expand Down
Loading

0 comments on commit 38925ec

Please sign in to comment.