Primary author
+Tom Arne Pedersen +Tom.Arne.Pedersen@dnv.com
+diff --git a/.nojekyll b/.nojekyll new file mode 100644 index 0000000..e69de29 diff --git a/branch/main/.buildinfo b/branch/main/.buildinfo new file mode 100644 index 0000000..9b76028 --- /dev/null +++ b/branch/main/.buildinfo @@ -0,0 +1,4 @@ +# Sphinx build info version 1 +# This file hashes the configuration used when building these files. When it is not found, a full rebuild will be done. +config: 1a384d26b701f081d2b50c24e12afe98 +tags: 645f666f9bcd5a90fca523b33c5a78b7 diff --git a/branch/main/_downloads/3f0d4d1fea704d8ffdd7fa89c1edb3ed/ICMASS23_verfying_caga_systems.pdf b/branch/main/_downloads/3f0d4d1fea704d8ffdd7fa89c1edb3ed/ICMASS23_verfying_caga_systems.pdf new file mode 100644 index 0000000..547c468 Binary files /dev/null and b/branch/main/_downloads/3f0d4d1fea704d8ffdd7fa89c1edb3ed/ICMASS23_verfying_caga_systems.pdf differ diff --git a/branch/main/_modules/index.html b/branch/main/_modules/index.html new file mode 100644 index 0000000..f2fc373 --- /dev/null +++ b/branch/main/_modules/index.html @@ -0,0 +1,119 @@ + + +
+ + +
+"""Module with helper functions to determine if a generated path is crossing land."""
+
+from typing import List
+
+from global_land_mask import globe
+
+from trafficgen.types import Position
+
+from . import calculate_position_at_certain_time, deg_2_rad, flat2llh, rad_2_deg
+
+
+
+[docs]
+def path_crosses_land(
+ position_1: Position,
+ speed: float,
+ course: float,
+ lat_lon_0: List[float],
+ time_interval: float = 50.0,
+) -> bool:
+ """
+ Find if path is crossing land.
+
+ Params:
+ position_1: Ship position in (north, east) [m].
+ speed: Ship speed [knots].
+ course: Ship course [degree].
+ lat_lon_0: Reference point, latitudinal [degree] and longitudinal [degree].
+ time_interval: The time interval the vessel should travel without crossing land [minutes]
+
+ Returns
+ -------
+ is_on_land: True if parts of the path crosses land.
+ """
+
+ north_1 = position_1.north
+ east_1 = position_1.east
+ lat_0 = lat_lon_0[0]
+ lon_0 = lat_lon_0[1]
+
+ num_checks = 10
+ for i in range(int(time_interval / num_checks)):
+ position_2 = calculate_position_at_certain_time(
+ Position(north=north_1, east=east_1), speed, course, i * time_interval / num_checks
+ )
+ lat, lon, _ = flat2llh(position_2.north, position_2.east, deg_2_rad(lat_0), deg_2_rad(lon_0))
+ lat = rad_2_deg(lat)
+ lon = rad_2_deg(lon)
+ if globe.is_land(lat, lon): # type: ignore (The global_land_mask package is unfortunately not typed.)
+ return True
+ return False
+
+
+"""
+Functions to generate encounters consisting of one own ship and one to many target ships.
+The generated encounters may be of type head-on, overtaking give-way and stand-on and
+crossing give-way and stand-on.
+"""
+
+import random
+from typing import List, Optional, Tuple, Union
+
+import numpy as np
+
+from trafficgen.types import (
+ EncounterRelativeSpeed,
+ EncounterSettings,
+ EncounterType,
+ Pose,
+ Position,
+ Ship,
+ TargetShip,
+)
+
+from . import (
+ calculate_position_at_certain_time,
+ convert_angle_minus_180_to_180_to_0_to_360,
+ deg_2_rad,
+ flat2llh,
+ knot_2_m_pr_min,
+ m_pr_min_2_knot,
+ nm_2_m,
+ path_crosses_land,
+ rad_2_deg,
+)
+
+
+
+[docs]
+def generate_encounter(
+ desired_encounter_type: EncounterType,
+ own_ship: Ship,
+ target_ships: List[TargetShip],
+ target_ship_id: int,
+ beta_default: Optional[float],
+ relative_speed_default: Optional[float],
+ vector_time_default: Optional[float],
+ settings: EncounterSettings,
+) -> Tuple[TargetShip, bool]:
+ """
+ Generate an encounter.
+
+ Params:
+ * desired_encounter_type: Desired encounter to be generated
+ * own_ship: Dict, information about own ship that will encounter a target ship
+ * target_ships: List of target ships that may be used in an encounter
+ * target_ship_id: ID which should be used on target ship
+ * beta_default: User defined beta. If not set, this is None.
+ * relative_speed_default: User defined relative speed between own ship and
+ target ship. If not set, this is None.
+ * vector_time_default: User defined vector time. If not set, this is None.
+ * settings: Encounter settings
+
+ Returns
+ -------
+ target_ship: target ship information, such as initial position, speed and course
+ encounter_found: True=encounter found, False=encounter not found
+ """
+ encounter_found: bool = False
+ outer_counter: int = 0
+
+ target_ship = decide_target_ship(target_ships)
+ assert target_ship.static is not None
+
+ # Searching for encounter. Two loops used. Only vector time is locked in the
+ # first loop. In the second loop, beta and speed are assigned.
+ while not encounter_found and outer_counter < 5:
+ outer_counter += 1
+ inner_counter: int = 0
+
+ # resetting vector_time, beta and relative_speed to default values before
+ # new search for situation is done
+ vector_time: Union[float, None] = vector_time_default
+ beta: Union[float, None] = beta_default
+
+ if vector_time is None:
+ vector_time = random.uniform(settings.vector_range[0], settings.vector_range[1])
+ if beta is None:
+ beta = assign_beta(desired_encounter_type, settings)
+
+ # Own ship
+ assert own_ship.start_pose is not None
+ own_ship_position_future = calculate_position_at_certain_time(
+ own_ship.start_pose.position,
+ own_ship.start_pose.speed,
+ own_ship.start_pose.course,
+ vector_time,
+ )
+ # @TODO: @TomArne: this variable is declared and assigned to but nowhere used. Delete?
+ # Claas, 2023-11-24
+ # own_ship_vector_length = knot_2_m_pr_min(own_ship.start_pose.speed) * vector_time
+
+ # Target ship
+ target_ship.id = target_ship_id
+ target_ship.start_pose = Pose() # reset start_pose of target_ship (if one existed)
+
+ target_ship_position_future = assign_future_position_to_target_ship(
+ own_ship_position_future, settings.max_meeting_distance
+ )
+
+ while not encounter_found and inner_counter < 5:
+ inner_counter += 1
+ relative_speed = relative_speed_default
+ if relative_speed is None:
+ min_target_ship_speed = m_pr_min_2_knot(
+ calculate_min_vector_length_target_ship(
+ own_ship.start_pose.position,
+ own_ship.start_pose.course,
+ target_ship_position_future,
+ beta,
+ )
+ / vector_time
+ )
+
+ target_ship.start_pose.speed = assign_speed_to_target_ship(
+ desired_encounter_type,
+ own_ship.start_pose.speed,
+ min_target_ship_speed,
+ settings.relative_speed,
+ )
+ else:
+ target_ship.start_pose.speed = relative_speed * own_ship.start_pose.speed
+
+ target_ship.start_pose.speed = np.minimum(
+ target_ship.start_pose.speed, target_ship.static.speed_max
+ )
+
+ target_ship_vector_length = knot_2_m_pr_min(target_ship.start_pose.speed) * vector_time
+ start_position_target_ship, position_found = find_start_position_target_ship(
+ own_ship.start_pose.position,
+ own_ship.start_pose.course,
+ target_ship_position_future,
+ target_ship_vector_length,
+ beta,
+ desired_encounter_type,
+ settings,
+ )
+
+ if position_found:
+ target_ship.start_pose.position = start_position_target_ship
+ target_ship.start_pose.course = calculate_ship_course(
+ target_ship.start_pose.position, target_ship_position_future
+ )
+ encounter_ok: bool = check_encounter_evolvement(
+ own_ship,
+ own_ship_position_future,
+ target_ship,
+ target_ship_position_future,
+ desired_encounter_type,
+ settings,
+ )
+
+ # Check if trajectory passes land
+ trajectory_on_land = path_crosses_land(
+ target_ship.start_pose.position,
+ target_ship.start_pose.speed,
+ target_ship.start_pose.course,
+ settings.lat_lon_0,
+ )
+
+ encounter_found = encounter_ok and not trajectory_on_land
+
+ if encounter_found:
+ target_ship = update_position_data_target_ship(target_ship, settings.lat_lon_0)
+ return target_ship, encounter_found
+
+
+
+
+[docs]
+def check_encounter_evolvement(
+ own_ship: Ship,
+ own_ship_position_future: Position,
+ target_ship: TargetShip,
+ target_ship_position_future: Position,
+ desired_encounter_type: EncounterType,
+ settings: EncounterSettings,
+) -> bool:
+ """
+ Check encounter evolvement. The generated encounter should be the same type of
+ encounter (head-on, crossing, give-way) also some time before the encounter is started.
+
+ Params:
+ * own_ship: Own ship information such as initial position, speed and course
+ * target_ship: Target ship information such as initial position, speed and course
+ * desired_encounter_type: Desired type of encounter to be generated
+ * settings: Encounter settings
+
+ Returns
+ -------
+ * returns True if encounter ok, False if encounter not ok
+ """
+ theta13_criteria: float = settings.classification.theta13_criteria
+ theta14_criteria: float = settings.classification.theta14_criteria
+ theta15_criteria: float = settings.classification.theta15_criteria
+ theta15: List[float] = settings.classification.theta15
+
+ assert own_ship.start_pose is not None
+ assert target_ship.start_pose is not None
+
+ own_ship_speed: float = own_ship.start_pose.speed
+ own_ship_course: float = own_ship.start_pose.course
+ target_ship_speed: float = target_ship.start_pose.speed
+ target_ship_course: float = target_ship.start_pose.course
+ evolve_time: float = settings.evolve_time
+
+ # Calculating position back in time to ensure that the encounter do not change from one type
+ # to another before the encounter is started
+ encounter_preposition_target_ship = calculate_position_at_certain_time(
+ target_ship_position_future,
+ target_ship_speed,
+ target_ship_course,
+ -evolve_time,
+ )
+ encounter_preposition_own_ship = calculate_position_at_certain_time(
+ own_ship_position_future,
+ own_ship_speed,
+ own_ship_course,
+ -evolve_time,
+ )
+ pre_beta, pre_alpha = calculate_relative_bearing(
+ encounter_preposition_own_ship,
+ own_ship_course,
+ encounter_preposition_target_ship,
+ target_ship_course,
+ )
+ pre_colreg_state = determine_colreg(
+ pre_alpha, pre_beta, theta13_criteria, theta14_criteria, theta15_criteria, theta15
+ )
+
+ encounter_ok: bool = pre_colreg_state == desired_encounter_type
+
+ return encounter_ok
+
+
+
+
+[docs]
+def calculate_min_vector_length_target_ship(
+ own_ship_position: Position,
+ own_ship_course: float,
+ target_ship_position_future: Position,
+ desired_beta: float,
+) -> float:
+ """
+ Calculate minimum vector length (target ship speed x vector). This will
+ ensure that ship speed is high enough to find proper situation.
+
+ Params:
+ * own_ship_position: Own ship initial position, speed and course
+ * own_ship_course: Own ship initial course
+ * target_ship_position_future: Target ship future position
+ * desired_beta: Desired relative bearing between
+
+ Returns: min_vector_length: Minimum vector length (target ship speed x vector)
+ """
+ psi: float = np.deg2rad(own_ship_course + desired_beta)
+
+ p_1 = np.array([own_ship_position.north, own_ship_position.east])
+ p_2 = np.array([own_ship_position.north + np.cos(psi), own_ship_position.east + np.sin(psi)])
+ p_3 = np.array([target_ship_position_future.north, target_ship_position_future.east])
+
+ min_vector_length: float = float(np.abs(np.cross(p_2 - p_1, p_3 - p_1) / np.linalg.norm(p_2 - p_1)))
+
+ return min_vector_length
+
+
+
+
+[docs]
+def find_start_position_target_ship(
+ own_ship_position: Position,
+ own_ship_course: float,
+ target_ship_position_future: Position,
+ target_ship_vector_length: float,
+ desired_beta: float,
+ desired_encounter_type: EncounterType,
+ settings: EncounterSettings,
+):
+ """
+ Find start position of target ship using desired beta and vector length.
+
+ Params:
+ * own_ship_position: Own ship initial position, speed and course
+ * own_ship_course: Own ship initial course
+ * target_ship_position_future: Target ship future position
+ * target_ship_vector_length: vector length (target ship speed x vector)
+ * desired_beta: Desired bearing between own ship and target ship seen from own ship
+ * desired_encounter_type: Desired type of encounter to be generated
+ * settings: Encounter settings
+
+ Returns
+ -------
+ * start_position_target_ship: Dict, initial position of target ship {north, east} [m]
+ * start_position_found: 0=position not found, 1=position found
+ """
+ theta13_criteria: float = settings.classification.theta13_criteria
+ theta14_criteria: float = settings.classification.theta14_criteria
+ theta15_criteria: float = settings.classification.theta15_criteria
+ theta15: List[float] = settings.classification.theta15
+
+ n_1: float = own_ship_position.north
+ e_1: float = own_ship_position.east
+ n_2: float = target_ship_position_future.north
+ e_2: float = target_ship_position_future.east
+ v_r: float = target_ship_vector_length
+ psi: float = np.deg2rad(own_ship_course + desired_beta)
+
+ n_4: float = n_1 + np.cos(psi)
+ e_4: float = e_1 + np.sin(psi)
+
+ b: float = (
+ -2 * e_2 * e_4
+ - 2 * n_2 * n_4
+ + 2 * e_1 * e_2
+ + 2 * n_1 * n_2
+ + 2 * e_1 * (e_4 - e_1)
+ + 2 * n_1 * (n_4 - n_1)
+ )
+ a: float = (e_4 - e_1) ** 2 + (n_4 - n_1) ** 2
+ c: float = e_2**2 + n_2**2 - 2 * e_1 * e_2 - 2 * n_1 * n_2 - v_r**2 + e_1**2 + n_1**2
+
+ # Assign conservative fallback values to return variables
+ start_position_found: bool = False
+ start_position_target_ship = target_ship_position_future.model_copy()
+
+ if b**2 - 4 * a * c <= 0.0:
+ # Do not run calculation of target ship start position. Return fallback values.
+ return start_position_target_ship, start_position_found
+
+ # Calculation of target ship start position
+ s_1 = (-b + np.sqrt(b**2 - 4 * a * c)) / (2 * a)
+ s_2 = (-b - np.sqrt(b**2 - 4 * a * c)) / (2 * a)
+
+ e_31 = e_1 + s_1 * (e_4 - e_1)
+ n_31 = n_1 + s_1 * (n_4 - n_1)
+ e_32 = e_1 + s_2 * (e_4 - e_1)
+ n_32 = n_1 + s_2 * (n_4 - n_1)
+
+ target_ship_course_1 = calculate_ship_course(
+ waypoint_0=Position(north=n_31, east=e_31),
+ waypoint_1=target_ship_position_future,
+ )
+ beta1, alpha1 = calculate_relative_bearing(
+ position_own_ship=own_ship_position,
+ heading_own_ship=own_ship_course,
+ position_target_ship=Position(north=n_31, east=e_31),
+ heading_target_ship=target_ship_course_1,
+ )
+ colreg_state1: EncounterType = determine_colreg(
+ alpha1, beta1, theta13_criteria, theta14_criteria, theta15_criteria, theta15
+ )
+ target_ship_course_2 = calculate_ship_course(
+ waypoint_0=Position(north=n_32, east=e_32),
+ waypoint_1=target_ship_position_future,
+ )
+ beta2, alpha2 = calculate_relative_bearing(
+ position_own_ship=own_ship_position,
+ heading_own_ship=own_ship_course,
+ position_target_ship=Position(north=n_32, east=e_32),
+ heading_target_ship=target_ship_course_2,
+ )
+ colreg_state2: EncounterType = determine_colreg(
+ alpha2, beta2, theta13_criteria, theta14_criteria, theta15_criteria, theta15
+ )
+ if desired_encounter_type is colreg_state1 and np.abs(beta1 - desired_beta % 360) < deg_2_rad(0.1):
+ start_position_target_ship = Position(north=n_31, east=e_31)
+ start_position_found = True
+ elif desired_encounter_type is colreg_state2 and np.abs(beta1 - desired_beta % 360) < deg_2_rad(0.1):
+ start_position_target_ship = Position(north=n_32, east=e_32)
+ start_position_found = True
+
+ return start_position_target_ship, start_position_found
+
+
+
+
+[docs]
+def assign_future_position_to_target_ship(
+ own_ship_position_future: Position,
+ max_meeting_distance: float,
+) -> Position:
+ """
+ Randomly assign future position of target ship. If drawing a circle with radius
+ max_meeting_distance around future position of own ship, future position of
+ target ship shall be somewhere inside this circle.
+
+ Params:
+ * own_ship_position_future: Dict, own ship position at a given time in the
+ future, {north, east}
+ * max_meeting_distance: Maximum distance between own ship and target ship at
+ a given time in the future [nm]
+
+ Returns
+ -------
+ future_position_target_ship: Future position of target ship {north, east} [m]
+ """
+ random_angle = random.uniform(0, 1) * 2 * np.pi
+ random_distance = random.uniform(0, 1) * nm_2_m(max_meeting_distance)
+
+ north: float = own_ship_position_future.north + random_distance * np.cos(deg_2_rad(random_angle))
+ east: float = own_ship_position_future.east + random_distance * np.sin(deg_2_rad(random_angle))
+ return Position(north=north, east=east)
+
+
+
+
+[docs]
+def determine_colreg(
+ alpha: float,
+ beta: float,
+ theta13_criteria: float,
+ theta14_criteria: float,
+ theta15_criteria: float,
+ theta15: List[float],
+) -> EncounterType:
+ """
+ Determine the colreg type based on alpha, relative bearing between target ship and own
+ ship seen from target ship, and beta, relative bearing between own ship and target ship
+ seen from own ship.
+
+ Params:
+ * alpha: relative bearing between target ship and own ship seen from target ship
+ * beta: relative bearing between own ship and target ship seen from own ship
+ * theta13_criteria: Tolerance for "coming up with" relative bearing
+ * theta14_criteria: Tolerance for "reciprocal or nearly reciprocal courses",
+ "when in any doubt... assume... [head-on]"
+ * theta15_criteria: Crossing aspect limit, used for classifying a crossing encounter
+ * theta15: 22.5 deg aft of the beam, used for classifying a crossing and an overtaking
+ encounter
+
+ Returns
+ -------
+ * encounter classification
+ """
+ # Mapping
+ alpha0360: float = alpha if alpha >= 0.0 else alpha + 360.0
+ beta0180: float = beta if (beta >= 0.0) & (beta <= 180.0) else beta - 360.0
+
+ # Find appropriate rule set
+ if (beta > theta15[0]) & (beta < theta15[1]) & (abs(alpha) - theta13_criteria <= 0.001):
+ return EncounterType.OVERTAKING_STAND_ON
+ if (alpha0360 > theta15[0]) & (alpha0360 < theta15[1]) & (abs(beta0180) - theta13_criteria <= 0.001):
+ return EncounterType.OVERTAKING_GIVE_WAY
+ if (abs(beta0180) - theta14_criteria <= 0.001) & (abs(alpha) - theta14_criteria <= 0.001):
+ return EncounterType.HEAD_ON
+ if (beta > 0) & (beta < theta15[0]) & (alpha > -theta15[0]) & (alpha - theta15_criteria <= 0.001):
+ return EncounterType.CROSSING_GIVE_WAY
+ if (
+ (alpha0360 > 0)
+ & (alpha0360 < theta15[0])
+ & (beta0180 > -theta15[0])
+ & (beta0180 - theta15_criteria <= 0.001)
+ ):
+ return EncounterType.CROSSING_STAND_ON
+ return EncounterType.NO_RISK_COLLISION
+
+
+
+
+[docs]
+def calculate_relative_bearing(
+ position_own_ship: Position,
+ heading_own_ship: float,
+ position_target_ship: Position,
+ heading_target_ship: float,
+) -> Tuple[float, float]:
+ """
+ Calculate relative bearing between own ship and target ship, both seen from
+ own ship and seen from target ship.
+
+ Params:
+ * position_own_ship: Dict, own ship position {north, east} [m]
+ * heading_own_ship: Own ship course [deg]
+ * position_target_ship: Dict, own ship position {north, east} [m]
+ * heading_target_ship: Target ship course [deg]
+
+ Returns
+ -------
+ * beta: relative bearing between own ship and target ship seen from own ship [deg]
+ * alpha: relative bearing between target ship and own ship seen from target ship [deg]
+ """
+ heading_own_ship = np.deg2rad(heading_own_ship)
+ heading_target_ship = np.deg2rad(heading_target_ship)
+
+ # POSE combination of relative bearing and contact angle
+ n_own_ship: float = position_own_ship.north
+ e_own_ship: float = position_own_ship.east
+ n_target_ship: float = position_target_ship.north
+ e_target_ship: float = position_target_ship.east
+
+ # Absolute bearing of target ship relative to own ship
+ bng_own_ship_target_ship: float = 0.0
+ if e_own_ship == e_target_ship:
+ if n_own_ship <= n_target_ship:
+ bng_own_ship_target_ship = 0.0
+ else:
+ bng_own_ship_target_ship = np.pi
+ else:
+ if e_own_ship < e_target_ship:
+ if n_own_ship <= n_target_ship:
+ bng_own_ship_target_ship = 1 / 2 * np.pi - np.arctan(
+ abs(n_target_ship - n_own_ship) / abs(e_target_ship - e_own_ship)
+ )
+ else:
+ bng_own_ship_target_ship = 1 / 2 * np.pi + np.arctan(
+ abs(n_target_ship - n_own_ship) / abs(e_target_ship - e_own_ship)
+ )
+ else:
+ if n_own_ship <= n_target_ship:
+ bng_own_ship_target_ship = 3 / 2 * np.pi + np.arctan(
+ abs(n_target_ship - n_own_ship) / abs(e_target_ship - e_own_ship)
+ )
+ else:
+ bng_own_ship_target_ship = 3 / 2 * np.pi - np.arctan(
+ abs(n_target_ship - n_own_ship) / abs(e_target_ship - e_own_ship)
+ )
+
+ # Bearing of own ship from the perspective of the contact
+ bng_target_ship_own_ship: float = bng_own_ship_target_ship + np.pi
+
+ # Relative bearing of contact ship relative to own ship
+ beta: float = bng_own_ship_target_ship - heading_own_ship
+ while beta < 0:
+ beta = beta + 2 * np.pi
+ while beta >= 2 * np.pi:
+ beta = beta - 2 * np.pi
+
+ # Relative bearing of own ship relative to target ship
+ alpha: float = bng_target_ship_own_ship - heading_target_ship
+ while alpha < -np.pi:
+ alpha = alpha + 2 * np.pi
+ while alpha >= np.pi:
+ alpha = alpha - 2 * np.pi
+
+ beta = np.rad2deg(beta)
+ alpha = np.rad2deg(alpha)
+
+ return beta, alpha
+
+
+
+
+[docs]
+def calculate_ship_course(waypoint_0: Position, waypoint_1: Position) -> float:
+ """
+ Calculate ship course between two waypoints.
+
+ Params:
+ * waypoint_0: Dict, waypoint {north, east} [m]
+ * waypoint_1: Dict, waypoint {north, east} [m]
+
+ Returns
+ -------
+ course: Ship course [deg]
+ """
+ course: float = np.arctan2(waypoint_1.east - waypoint_0.east, waypoint_1.north - waypoint_0.north)
+ if course < 0.0:
+ course = course + 2 * np.pi
+ return round(np.rad2deg(course), 1)
+
+
+
+
+[docs]
+def assign_vector_time(vector_time_range: List[float]):
+ """
+ Assign random (uniform) vector time.
+
+ Params:
+ * vector_range: Minimum and maximum value for vector time
+
+ Returns
+ -------
+ vector_time: Vector time [min]
+ """
+ vector_time: float = vector_time_range[0] + random.uniform(0, 1) * (
+ vector_time_range[1] - vector_time_range[0]
+ )
+ return vector_time
+
+
+
+
+[docs]
+def assign_speed_to_target_ship(
+ encounter_type: EncounterType,
+ own_ship_speed: float,
+ min_target_ship_speed: float,
+ relative_speed_setting: EncounterRelativeSpeed,
+):
+ """
+ Assign random (uniform) speed to target ship depending on type of encounter.
+
+ Params:
+ * encounter_type: Type of encounter
+ * own_ship_speed: Own ship speed [knot]
+ * min_target_ship_speed: Minimum target ship speed [knot]
+ * relative_speed_setting: Relative speed setting dependent on encounter [-]
+
+ Returns
+ -------
+ target_ship_speed: Target ship speed [knot]
+ """
+ if encounter_type is EncounterType.OVERTAKING_STAND_ON:
+ relative_speed = relative_speed_setting.overtaking_stand_on
+ elif encounter_type is EncounterType.OVERTAKING_GIVE_WAY:
+ relative_speed = relative_speed_setting.overtaking_give_way
+ elif encounter_type is EncounterType.HEAD_ON:
+ relative_speed = relative_speed_setting.head_on
+ elif encounter_type is EncounterType.CROSSING_GIVE_WAY:
+ relative_speed = relative_speed_setting.crossing_give_way
+ elif encounter_type is EncounterType.CROSSING_STAND_ON:
+ relative_speed = relative_speed_setting.crossing_stand_on
+ else:
+ relative_speed = [0.0, 0.0]
+
+ # Check that minimum target ship speed is in the relative speed range
+ if (
+ min_target_ship_speed / own_ship_speed > relative_speed[0]
+ and min_target_ship_speed / own_ship_speed < relative_speed[1]
+ ):
+ relative_speed[0] = min_target_ship_speed / own_ship_speed
+
+ target_ship_speed: float = (
+ relative_speed[0] + random.uniform(0, 1) * (relative_speed[1] - relative_speed[0])
+ ) * own_ship_speed
+
+ return target_ship_speed
+
+
+
+
+[docs]
+def assign_beta(encounter_type: EncounterType, settings: EncounterSettings) -> float:
+ """
+ Assign random (uniform) relative bearing beta between own ship
+ and target ship depending on type of encounter.
+
+ Params:
+ * encounter_type: Type of encounter
+ * settings: Encounter settings
+
+ Returns
+ -------
+ Relative bearing between own ship and target ship seen from own ship [deg]
+ """
+ theta13_crit: float = settings.classification.theta13_criteria
+ theta14_crit: float = settings.classification.theta14_criteria
+ theta15_crit: float = settings.classification.theta15_criteria
+ theta15: List[float] = settings.classification.theta15
+
+ if encounter_type is EncounterType.OVERTAKING_STAND_ON:
+ return theta15[0] + random.uniform(0, 1) * (theta15[1] - theta15[0])
+ if encounter_type is EncounterType.OVERTAKING_GIVE_WAY:
+ return -theta13_crit + random.uniform(0, 1) * (theta13_crit - (-theta13_crit))
+ if encounter_type is EncounterType.HEAD_ON:
+ return -theta14_crit + random.uniform(0, 1) * (theta14_crit - (-theta14_crit))
+ if encounter_type is EncounterType.CROSSING_GIVE_WAY:
+ return 0 + random.uniform(0, 1) * (theta15[0] - 0)
+ if encounter_type is EncounterType.CROSSING_STAND_ON:
+ return convert_angle_minus_180_to_180_to_0_to_360(
+ -theta15[1] + random.uniform(0, 1) * (theta15[1] + theta15_crit)
+ )
+ return 0.0
+
+
+
+
+[docs]
+def update_position_data_target_ship(
+ target_ship: TargetShip,
+ lat_lon_0: List[float],
+) -> TargetShip:
+ """
+ Update position data of the target ship to also include latitude and longitude
+ position of the target ship.
+
+ Params:
+ * target_ship: Target ship data
+ * lat_lon_0: Reference point, latitudinal [degree] and longitudinal [degree]
+
+ Returns
+ -------
+ ship: Updated target ship data
+ """
+ assert target_ship.start_pose is not None
+
+ lat_0 = lat_lon_0[0]
+ lon_0 = lat_lon_0[1]
+
+ lat, lon, _ = flat2llh(
+ target_ship.start_pose.position.north,
+ target_ship.start_pose.position.east,
+ deg_2_rad(lat_0),
+ deg_2_rad(lon_0),
+ )
+ target_ship.start_pose.position.latitude = round(rad_2_deg(lat), 6)
+ target_ship.start_pose.position.longitude = round(rad_2_deg(lon), 6)
+ return target_ship
+
+
+
+
+[docs]
+def update_position_data_own_ship(
+ ship: Ship,
+ lat_lon_0: List[float],
+ delta_time: float,
+) -> Ship:
+ """
+ Update position data of the target ship to also include latitude and longitude
+ position of the target ship.
+
+ Params:
+ * ship: Own ship data
+ * lat_lon_0: Reference point, latitudinal [degree] and longitudinal [degree]
+ * delta_time: Delta time from now to the time new position is being calculated [minutes]
+
+ Returns
+ -------
+ ship: Updated own ship data
+ """
+ assert ship.start_pose is not None
+
+ lat_0 = lat_lon_0[0]
+ lon_0 = lat_lon_0[1]
+
+ ship_position_future = calculate_position_at_certain_time(
+ ship.start_pose.position,
+ ship.start_pose.speed,
+ ship.start_pose.course,
+ delta_time,
+ )
+ lat, lon, _ = flat2llh(
+ ship.start_pose.position.north,
+ ship.start_pose.position.east,
+ deg_2_rad(lat_0),
+ deg_2_rad(lon_0),
+ )
+ ship.start_pose.position.latitude = round(rad_2_deg(lat), 6)
+ ship.start_pose.position.longitude = round(rad_2_deg(lon), 6)
+
+ lat_future, lon_future, _ = flat2llh(
+ ship_position_future.north,
+ ship_position_future.east,
+ deg_2_rad(lat_0),
+ deg_2_rad(lon_0),
+ )
+ ship_position_future.latitude = round(rad_2_deg(lat_future), 6)
+ ship_position_future.longitude = round(rad_2_deg(lon_future), 6)
+
+ ship.waypoints = [
+ ship.start_pose.position.model_copy(),
+ ship_position_future,
+ ]
+
+ return ship
+
+
+
+
+[docs]
+def decide_target_ship(target_ships: List[TargetShip]) -> TargetShip:
+ """
+ Randomly pick a target ship from a list of target ships.
+
+ Params:
+ * target_ships: list of target ships
+
+ Returns
+ -------
+ The target ship, info of type, size etc.
+ """
+ num_target_ships: int = len(target_ships)
+ target_ship_to_use: int = random.randint(1, num_target_ships)
+ target_ship: TargetShip = target_ships[target_ship_to_use - 1]
+ return target_ship.model_copy(deep=True)
+
+
+"""
+The Marine Systems Simulator (MSS) is a Matlab and Simulink library for marine systems.
+
+It includes models for ships, underwater vehicles, unmanned surface vehicles, and floating structures.
+The library also contains guidance, navigation, and control (GNC) blocks for real-time simulation.
+The algorithms are described in:
+
+T. I. Fossen (2021). Handbook of Marine Craft Hydrodynamics and Motion Control. 2nd. Edition,
+Wiley. ISBN-13: 978-1119575054
+
+Parts of the library have been re-implemented in Python and are found below.
+"""
+from typing import Tuple
+
+import numpy as np
+
+
+
+[docs]
+def flat2llh(
+ x_n: float,
+ y_n: float,
+ lat_0: float,
+ lon_0: float,
+ z_n: float = 0.0,
+ height_ref: float = 0.0,
+) -> Tuple[float, float, float]:
+ """
+ Compute longitude lon (rad), latitude lat (rad) and height h (m) for the
+ NED coordinates (xn,yn,zn).
+
+ Method taken from the MSS (Marine System Simulator) toolbox which is a Matlab/Simulink
+ library for marine systems.
+
+ The method computes longitude lon (rad), latitude lat (rad) and height h (m) for the
+ NED coordinates (xn,yn,zn) using a flat Earth coordinate system defined by the WGS-84
+ ellipsoid. The flat Earth coordinate origin is located at (lon_0, lat_0) with reference
+ height h_ref in meters above the surface of the ellipsoid. Both height and h_ref
+ are positive upwards, while zn is positive downwards (NED).
+ Author: Thor I. Fossen
+ Date: 20 July 2018
+ Revisions: 2023-02-04 updates the formulas for latitude and longitude
+
+ Params:
+ xn: Ship position, north [m]
+ yn: Ship position, east [m]
+ zn=0.0: Ship position, down [m]
+ lat_0, lon_0: Flat earth coordinate located at (lon_0, lat_0)
+ h_ref=0.0: Flat earth coordinate with reference h_ref in meters above the surface
+ of the ellipsoid
+
+ Returns
+ -------
+ lat: Latitude [rad]
+ lon: Longitude [rad]
+ h: Height [m]
+
+ """
+ # WGS-84 parameters
+ a_radius = 6378137 # Semi-major axis
+ f_factor = 1 / 298.257223563 # Flattening
+ e_eccentricity = np.sqrt(2 * f_factor - f_factor**2) # Earth eccentricity
+
+ r_n = a_radius / np.sqrt(1 - e_eccentricity**2 * np.sin(lat_0) ** 2)
+ r_m = r_n * ((1 - e_eccentricity**2) / (1 - e_eccentricity**2 * np.sin(lat_0) ** 2))
+
+ d_lat = x_n / (r_m + height_ref) # delta latitude dmu = mu - mu0
+ d_lon = y_n / ((r_n + height_ref) * np.cos(lat_0)) # delta longitude dl = l - l0
+
+ lat = ssa(lat_0 + d_lat)
+ lon = ssa(lon_0 + d_lon)
+ height = height_ref - z_n
+
+ return lat, lon, height
+
+
+
+
+[docs]
+def llh2flat(
+ lat: float,
+ lon: float,
+ lat_0: float,
+ lon_0: float,
+ height: float = 0.0,
+ height_ref: float = 0.0,
+) -> Tuple[float, float, float]:
+ """
+ Compute (north, east) for a flat Earth coordinate system from longitude
+ lon (rad) and latitude lat (rad).
+
+ Method taken from the MSS (Marine System Simulator) toolbox which is a Matlab/Simulink
+ library for marine systems.
+
+ The method computes (north, east) for a flat Earth coordinate system from longitude
+ lon (rad) and latitude lat (rad) of the WGS-84 elipsoid. The flat Earth coordinate
+ origin is located at (lon_0, lat_0).
+ Author: Thor I. Fossen
+ Date: 20 July 2018
+ Revisions: 2023-02-04 updates the formulas for latitude and longitude
+
+ Params:
+ lat: Ship position in latitude [rad]
+ lon: Ship position in longitude [rad]
+ h=0.0: Ship height in meters above the surface of the ellipsoid
+ lat_0, lon_0: Flat earth coordinate located at (lon_0, lat_0)
+ h_ref=0.0: Flat earth coordinate with reference h_ref in meters above
+ the surface of the ellipsoid
+
+ Returns
+ -------
+ x_n: Ship position, north [m]
+ y_n: Ship position, east [m]
+ z_n: Ship position, down [m]
+ """
+
+ # WGS-84 parameters
+ a_radius = 6378137 # Semi-major axis (equitorial radius)
+ f_factor = 1 / 298.257223563 # Flattening
+ e_eccentricity = np.sqrt(2 * f_factor - f_factor**2) # Earth eccentricity
+
+ d_lon = lon - lon_0
+ d_lat = lat - lat_0
+
+ r_n = a_radius / np.sqrt(1 - e_eccentricity**2 * np.sin(lat_0) ** 2)
+ r_m = r_n * ((1 - e_eccentricity**2) / (1 - e_eccentricity**2 * np.sin(lat_0) ** 2))
+
+ x_n = d_lat * (r_m + height_ref)
+ y_n = d_lon * ((r_n + height_ref) * np.cos(lat_0))
+ z_n = height_ref - height
+
+ return x_n, y_n, z_n
+
+
+
+
+[docs]
+def ssa(angle: float) -> float:
+ """
+ Return the "smallest signed angle" (SSA) or the smallest difference between two angles.
+
+ Method taken from the MSS (Marine System Simulator) toolbox which is a Matlab/Simulink
+ library for marine systems.
+
+ Examples
+ --------
+ angle = ssa(angle) maps an angle in rad to the interval [-pi pi)
+
+ Author: Thor I. Fossen
+ Date: 2018-09-21
+
+ Param:
+ angle: angle given in radius
+
+ Returns
+ -------
+ smallest_angle: "smallest signed angle" or the smallest difference between two angles
+ """
+
+ return np.mod(angle + np.pi, 2 * np.pi) - np.pi
+
+
+# The matplotlib package is unfortunately not fully typed. Hence the following pyright exemption.
+# pyright: reportUnknownMemberType=false
+"""Functions to prepare and plot traffic situations."""
+import math
+from typing import List, Optional, Tuple, Union
+
+import matplotlib.pyplot as plt
+import numpy as np
+from folium import Map, Polygon
+from matplotlib.patches import Circle
+
+from trafficgen.types import Position, Ship, Situation, TargetShip
+
+from . import deg_2_rad, flat2llh, knot_2_m_pr_min, m2nm, rad_2_deg
+
+
+
+[docs]
+def calculate_vector_arrow(
+ position: Position,
+ direction: float,
+ vector_length: float,
+ lat_lon_0: List[float],
+) -> List[Tuple[float, float]]:
+ """
+ Calculate the arrow with length vector pointing in the direction of ship course.
+
+ Params:
+ position: {north}, {east} position of the ship [m]
+ direction: direction the arrow is pointing [deg]
+ vector_length: length of vector
+ lat_lon_0: Reference point, latitudinal [degree] and longitudinal [degree]
+
+ Returns
+ -------
+ arrow_points: Polygon points to draw the arrow
+ """
+ north_start = position.north
+ east_start = position.east
+
+ side_length = vector_length / 10
+ sides_angle = 25
+
+ north_end = north_start + vector_length * np.cos(deg_2_rad(direction))
+ east_end = east_start + vector_length * np.sin(deg_2_rad(direction))
+
+ north_arrow_side_1 = north_end + side_length * np.cos(deg_2_rad(direction + 180 - sides_angle))
+ east_arrow_side_1 = east_end + side_length * np.sin(deg_2_rad(direction + 180 - sides_angle))
+ north_arrow_side_2 = north_end + side_length * np.cos(deg_2_rad(direction + 180 + sides_angle))
+ east_arrow_side_2 = east_end + side_length * np.sin(deg_2_rad(direction + 180 + sides_angle))
+
+ lat_start, lon_start, _ = flat2llh(
+ north_start, east_start, deg_2_rad(lat_lon_0[0]), deg_2_rad(lat_lon_0[1])
+ )
+ lat_end, lon_end, _ = flat2llh(north_end, east_end, deg_2_rad(lat_lon_0[0]), deg_2_rad(lat_lon_0[1]))
+ lat_arrow_side_1, lon_arrow_side_1, _ = flat2llh(
+ north_arrow_side_1, east_arrow_side_1, deg_2_rad(lat_lon_0[0]), deg_2_rad(lat_lon_0[1])
+ )
+ lat_arrow_side_2, lon_arrow_side_2, _ = flat2llh(
+ north_arrow_side_2, east_arrow_side_2, deg_2_rad(lat_lon_0[0]), deg_2_rad(lat_lon_0[1])
+ )
+
+ point_1 = (rad_2_deg(lat_start), rad_2_deg(lon_start))
+ point_2 = (rad_2_deg(lat_end), rad_2_deg(lon_end))
+ point_3 = (rad_2_deg(lat_arrow_side_1), rad_2_deg(lon_arrow_side_1))
+ point_4 = (rad_2_deg(lat_arrow_side_2), rad_2_deg(lon_arrow_side_2))
+
+ return [point_1, point_2, point_3, point_4, point_2]
+
+
+
+
+[docs]
+def calculate_ship_outline(
+ position: Position,
+ course: float,
+ lat_lon_0: List[float],
+ ship_length: float = 100.0,
+ ship_width: float = 15.0,
+) -> List[Tuple[float, float]]:
+ """
+ Calculate the outline of the ship pointing in the direction of ship course.
+
+ Params:
+ position: {north}, {east} position of the ship [m]
+ course: course of the ship [deg]
+ lat_lon_0: Reference point, latitudinal [degree] and longitudinal [degree]
+ ship_length: Ship length. If not given, ship length is set to 100
+ ship_width: Ship width. If not given, ship width is set to 15
+
+ Returns
+ -------
+ ship_outline_points: Polygon points to draw the ship
+ """
+ north_start = position.north
+ east_start = position.east
+
+ # increase size for visualizing
+ ship_length *= 10
+ ship_width *= 10
+
+ north_pos1 = (
+ north_start
+ + np.cos(deg_2_rad(course)) * (-ship_length / 2)
+ - np.sin(deg_2_rad(course)) * ship_width / 2
+ )
+ east_pos1 = (
+ east_start
+ + np.sin(deg_2_rad(course)) * (-ship_length / 2)
+ + np.cos(deg_2_rad(course)) * ship_width / 2
+ )
+ lat_pos1, lon_pos1, _ = flat2llh(
+ north_pos1, east_pos1, deg_2_rad(lat_lon_0[0]), deg_2_rad(lat_lon_0[1])
+ )
+
+ north_pos2 = (
+ north_start
+ + np.cos(deg_2_rad(course)) * (ship_length / 2 - ship_length * 0.1)
+ - np.sin(deg_2_rad(course)) * ship_width / 2
+ )
+ east_pos2 = (
+ east_start
+ + np.sin(deg_2_rad(course)) * (ship_length / 2 - ship_length * 0.1)
+ + np.cos(deg_2_rad(course)) * ship_width / 2
+ )
+ lat_pos2, lon_pos2, _ = flat2llh(
+ north_pos2, east_pos2, deg_2_rad(lat_lon_0[0]), deg_2_rad(lat_lon_0[1])
+ )
+
+ north_pos3 = north_start + np.cos(deg_2_rad(course)) * (ship_length / 2)
+ east_pos3 = east_start + np.sin(deg_2_rad(course)) * (ship_length / 2)
+ lat_pos3, lon_pos3, _ = flat2llh(
+ north_pos3, east_pos3, deg_2_rad(lat_lon_0[0]), deg_2_rad(lat_lon_0[1])
+ )
+
+ north_pos4 = (
+ north_start
+ + np.cos(deg_2_rad(course)) * (ship_length / 2 - ship_length * 0.1)
+ - np.sin(deg_2_rad(course)) * (-ship_width / 2)
+ )
+ east_pos4 = (
+ east_start
+ + np.sin(deg_2_rad(course)) * (ship_length / 2 - ship_length * 0.1)
+ + np.cos(deg_2_rad(course)) * (-ship_width / 2)
+ )
+ lat_pos4, lon_pos4, _ = flat2llh(
+ north_pos4, east_pos4, deg_2_rad(lat_lon_0[0]), deg_2_rad(lat_lon_0[1])
+ )
+
+ north_pos5 = (
+ north_start
+ + np.cos(deg_2_rad(course)) * (-ship_length / 2)
+ - np.sin(deg_2_rad(course)) * (-ship_width / 2)
+ )
+ east_pos5 = (
+ east_start
+ + np.sin(deg_2_rad(course)) * (-ship_length / 2)
+ + np.cos(deg_2_rad(course)) * (-ship_width / 2)
+ )
+ lat_pos5, lon_pos5, _ = flat2llh(
+ north_pos5, east_pos5, deg_2_rad(lat_lon_0[0]), deg_2_rad(lat_lon_0[1])
+ )
+
+ point_1 = (rad_2_deg(lat_pos1), rad_2_deg(lon_pos1))
+ point_2 = (rad_2_deg(lat_pos2), rad_2_deg(lon_pos2))
+ point_3 = (rad_2_deg(lat_pos3), rad_2_deg(lon_pos3))
+ point_4 = (rad_2_deg(lat_pos4), rad_2_deg(lon_pos4))
+ point_5 = (rad_2_deg(lat_pos5), rad_2_deg(lon_pos5))
+
+ return [point_1, point_2, point_3, point_4, point_5, point_1]
+
+
+
+
+[docs]
+def plot_specific_traffic_situation(
+ traffic_situations: List[Situation],
+ situation_number: int,
+):
+ """
+ Plot a specific situation in map.
+
+ Params:
+ traffic_situations: Generated traffic situations
+ situation_number: The specific situation to be plotted
+ """
+
+ num_situations = len(traffic_situations)
+ if situation_number > num_situations:
+ print(
+ f"Situation_number specified higher than number of situations available, plotting last situation: {num_situations}"
+ )
+ situation_number = num_situations
+
+ situation: Situation = traffic_situations[situation_number - 1]
+ assert situation.lat_lon_0 is not None
+ assert situation.own_ship is not None
+ assert situation.common_vector is not None
+
+ map_plot = Map(location=(situation.lat_lon_0[0], situation.lat_lon_0[1]), zoom_start=10)
+ map_plot = add_ship_to_map(
+ situation.own_ship,
+ situation.common_vector,
+ situation.lat_lon_0,
+ map_plot,
+ "black",
+ )
+
+ target_ships: Union[List[TargetShip], None] = situation.target_ship
+ assert target_ships is not None
+ for target_ship in target_ships:
+ map_plot = add_ship_to_map(
+ target_ship,
+ situation.common_vector,
+ situation.lat_lon_0,
+ map_plot,
+ "red",
+ )
+ map_plot.show_in_browser()
+
+
+
+
+[docs]
+def add_ship_to_map(
+ ship: Ship,
+ vector_time: float,
+ lat_lon_0: List[float],
+ map_plot: Optional[Map],
+ color: str = "black",
+) -> Map:
+ """
+ Add the ship to the map.
+
+ Params:
+ ship: Ship information
+ vector_time: Vector time [min]
+ lat_lon_0=Reference point, latitudinal [degree] and longitudinal [degree]
+ map_plot: Instance of Map. If not set, instance is set to None
+ color: Color of the ship. If not set, color is 'black'
+
+ Returns
+ -------
+ m: Updated instance of Map.
+ """
+ if map_plot is None:
+ map_plot = Map(location=(lat_lon_0[0], lat_lon_0[1]), zoom_start=10)
+
+ assert ship.start_pose is not None
+ vector_length = vector_time * knot_2_m_pr_min(ship.start_pose.speed)
+ _ = map_plot.add_child(
+ Polygon(
+ calculate_vector_arrow(
+ ship.start_pose.position, ship.start_pose.course, vector_length, lat_lon_0
+ ),
+ fill=True,
+ fill_opacity=1,
+ color=color,
+ )
+ )
+ _ = map_plot.add_child(
+ Polygon(
+ calculate_ship_outline(ship.start_pose.position, ship.start_pose.course, lat_lon_0),
+ fill=True,
+ fill_opacity=1,
+ color=color,
+ )
+ )
+ return map_plot
+
+
+
+
+[docs]
+def plot_traffic_situations(
+ traffic_situations: List[Situation],
+ col: int,
+ row: int,
+):
+ """
+ Plot the traffic situations in one more figures.
+
+ Params:
+ traffic_situations: Traffic situations to be plotted
+ col: Number of columns in each figure
+ row: Number of rows in each figure
+ """
+ max_columns = col
+ max_rows = row
+ num_subplots_pr_plot = max_columns * max_rows
+ small_size = 6
+ bigger_size = 10
+
+ plt.rc("axes", titlesize=small_size) # fontsize of the axes title
+ plt.rc("axes", labelsize=small_size) # fontsize of the x and y labels
+ plt.rc("xtick", labelsize=small_size) # fontsize of the tick labels
+ plt.rc("ytick", labelsize=small_size) # fontsize of the tick labels
+ plt.rc("figure", titlesize=bigger_size) # fontsize of the figure title
+
+ # The axes should have the same x/y limits, thus find max value for
+ # north/east position to be used for plotting
+ max_value: float = 0.0
+ for situation in traffic_situations:
+ assert situation.own_ship is not None
+ max_value = find_max_value_for_plot(situation.own_ship, max_value)
+ assert situation.target_ship is not None
+ for target_ship in situation.target_ship:
+ max_value = find_max_value_for_plot(target_ship, max_value)
+
+ plot_number: int = 1
+ _ = plt.figure(plot_number)
+ for i, situation in enumerate(traffic_situations):
+ if math.floor(i / num_subplots_pr_plot) + 1 > plot_number:
+ plot_number += 1
+ _ = plt.figure(plot_number)
+
+ axes: plt.Axes = plt.subplot(
+ max_rows,
+ max_columns,
+ int(1 + i - (plot_number - 1) * num_subplots_pr_plot),
+ xlabel="[nm]",
+ ylabel="[nm]",
+ )
+ _ = axes.set_title(situation.title)
+ assert situation.own_ship is not None
+ assert situation.common_vector is not None
+ axes = add_ship_to_plot(
+ situation.own_ship,
+ situation.common_vector,
+ axes,
+ "black",
+ )
+ assert situation.target_ship is not None
+ for target_ship in situation.target_ship:
+ axes = add_ship_to_plot(
+ target_ship,
+ situation.common_vector,
+ axes,
+ "red",
+ )
+ axes.set_aspect("equal")
+
+ _ = plt.xlim(-max_value, max_value)
+ _ = plt.ylim(-max_value, max_value)
+ _ = plt.subplots_adjust(wspace=0.4, hspace=0.4)
+
+ plt.show()
+
+
+
+
+[docs]
+def find_max_value_for_plot(
+ ship: Ship,
+ max_value: float,
+) -> float:
+ """
+ Find the maximum deviation from the Reference point in north and east direction.
+
+ Params:
+ ship: Ship information
+ max_value: maximum deviation in north, east direction
+
+ Returns
+ -------
+ max_value: updated maximum deviation in north, east direction
+ """
+ assert ship.start_pose is not None
+ max_value = np.max(
+ [
+ max_value,
+ np.abs(m2nm(ship.start_pose.position.north)),
+ np.abs(m2nm(ship.start_pose.position.east)),
+ ]
+ )
+ return max_value
+
+
+
+
+[docs]
+def add_ship_to_plot(
+ ship: Ship,
+ vector_time: float,
+ axes: Optional[plt.Axes],
+ color: str = "black",
+):
+ """
+ Add the ship to the plot.
+
+ Params:
+ ship: Ship information
+ vector_time: Vector time [min]
+ axes: Instance of figure axis. If not set, instance is set to None
+ color: Color of the ship. If not set, color is 'black'
+ """
+ if axes is None:
+ axes = plt.gca()
+ assert isinstance(axes, plt.Axes)
+
+ assert ship.start_pose is not None
+ pos_0_north = m2nm(ship.start_pose.position.north)
+ pos_0_east = m2nm(ship.start_pose.position.east)
+ course = ship.start_pose.course
+ speed = ship.start_pose.speed
+
+ vector_length = m2nm(vector_time * knot_2_m_pr_min(speed))
+
+ _ = axes.arrow(
+ pos_0_east,
+ pos_0_north,
+ vector_length * np.sin(deg_2_rad(course)),
+ vector_length * np.cos(deg_2_rad(course)),
+ edgecolor=color,
+ facecolor=color,
+ width=0.0001,
+ head_length=0.2,
+ head_width=0.2,
+ length_includes_head=True,
+ )
+ circle = Circle(
+ xy=(pos_0_east, pos_0_north),
+ radius=vector_time / 100.0, # type: ignore
+ color=color,
+ )
+ _ = axes.add_patch(circle)
+
+ return axes
+
+
+"""Functions to read the files needed to build one or more traffic situations."""
+
+import json
+import os
+from pathlib import Path
+from typing import List
+
+from trafficgen.types import EncounterSettings, Ship, Situation, TargetShip
+
+
+
+[docs]
+def read_situation_files(situation_folder: Path) -> List[Situation]:
+ """
+ Read traffic situation files.
+
+ Params:
+ situation_folder: Path to the folder where situation files are found
+
+ Returns
+ -------
+ situations: List of desired traffic situations
+ """
+ situations: List[Situation] = []
+ for file_name in [file for file in os.listdir(situation_folder) if file.endswith(".json")]:
+ file_path = os.path.join(situation_folder, file_name)
+ with open(file_path, encoding="utf-8") as f:
+ data = json.load(f)
+ situation: Situation = Situation(**data)
+ situation.input_file_name = file_name
+ situations.append(situation)
+ return situations
+
+
+
+
+[docs]
+def read_own_ship_file(own_ship_file: Path) -> Ship:
+ """
+ Read own ship file.
+
+ Params:
+ own_ship_file: Path to the own_ship_file file
+
+ Returns
+ -------
+ own_ship information
+ """
+ with open(own_ship_file, encoding="utf-8") as f:
+ data = json.load(f)
+ ship: Ship = Ship(**data)
+ return ship
+
+
+
+
+[docs]
+def read_target_ship_files(target_ship_folder: Path) -> List[TargetShip]:
+ """
+ Read target ship files.
+
+ Params:
+ target_ship_folder: Path to the folder where target ships are found
+
+ Returns
+ -------
+ target_ships: List of different target ships
+ """
+ target_ships: List[TargetShip] = []
+ for file_name in [file for file in os.listdir(target_ship_folder) if file.endswith(".json")]:
+ file_path = os.path.join(target_ship_folder, file_name)
+ with open(file_path, encoding="utf-8") as f:
+ data = json.load(f)
+ target_ship: TargetShip = TargetShip(**data)
+ target_ships.append(target_ship)
+ return target_ships
+
+
+
+
+[docs]
+def read_encounter_settings_file(settings_file: Path) -> EncounterSettings:
+ """
+ Read encounter settings file.
+
+ Params:
+ settings_file: Path to the encounter setting file
+
+ Returns
+ -------
+ Encounter settings
+ """
+ with open(settings_file, encoding="utf-8") as f:
+ data = json.load(f)
+ encounter_settings: EncounterSettings = EncounterSettings(**data)
+ return encounter_settings
+
+
+"""Functions to generate traffic situations."""
+
+from pathlib import Path
+from typing import List, Union
+
+from trafficgen.types import Encounter, EncounterSettings, Ship, Situation, TargetShip
+
+from . import (
+ generate_encounter,
+ read_encounter_settings_file,
+ read_own_ship_file,
+ read_situation_files,
+ read_target_ship_files,
+ update_position_data_own_ship,
+)
+
+
+
+[docs]
+def generate_traffic_situations(
+ situation_folder: Path,
+ own_ship_file: Path,
+ target_ship_folder: Path,
+ settings_file: Path,
+) -> List[Situation]:
+ """
+ Generate a set of traffic situations using input files.
+ This is the main function for generating a set of traffic situations using input files
+ specifying number and type of encounter, type of target ships etc.
+
+ Params:
+ * situation_folder: Path to situation folder, files describing the desired situations
+ * target_ship_folder: Path to where different type of target ships is found
+ * settings_file: Path to settings file
+
+ Returns
+ -------
+ traffic_situations: List of generated traffic situations.
+ One situation may consist of one or more encounters.
+ """
+
+ desired_traffic_situations: List[Situation] = read_situation_files(situation_folder)
+ own_ship: Ship = read_own_ship_file(own_ship_file)
+ target_ships: List[TargetShip] = read_target_ship_files(target_ship_folder)
+ encounter_settings: EncounterSettings = read_encounter_settings_file(settings_file)
+ traffic_situations: List[Situation] = []
+
+ for desired_traffic_situation in desired_traffic_situations:
+ num_situations: int = desired_traffic_situation.num_situations or 1
+ assert desired_traffic_situation.common_vector is not None
+ assert desired_traffic_situation.own_ship is not None
+ assert desired_traffic_situation.encounter is not None
+
+ for _ in range(num_situations):
+ traffic_situation: Situation = Situation(
+ title=desired_traffic_situation.title,
+ input_file_name=desired_traffic_situation.input_file_name,
+ common_vector=desired_traffic_situation.common_vector,
+ lat_lon_0=encounter_settings.lat_lon_0,
+ )
+ assert traffic_situation.common_vector is not None
+ own_ship.start_pose = desired_traffic_situation.own_ship.start_pose
+ own_ship = update_position_data_own_ship(
+ own_ship,
+ encounter_settings.lat_lon_0,
+ traffic_situation.common_vector,
+ )
+ traffic_situation.own_ship = own_ship
+ traffic_situation.target_ship = []
+ for k in range(len(desired_traffic_situation.encounter)):
+ encounter: Encounter = desired_traffic_situation.encounter[k]
+ desired_encounter_type = encounter.desired_encounter_type
+ settings = encounter_settings
+ beta: Union[float, None] = encounter.beta
+ relative_speed: Union[float, None] = encounter.relative_speed
+ vector_time: Union[float, None] = encounter.vector_time
+ target_ship_id = k + 1
+ target_ship, encounter_found = generate_encounter(
+ desired_encounter_type,
+ own_ship.model_copy(deep=True),
+ target_ships,
+ target_ship_id,
+ beta,
+ relative_speed,
+ vector_time,
+ settings,
+ )
+ if encounter_found:
+ traffic_situation.target_ship.append(target_ship)
+
+ traffic_situations.append(traffic_situation)
+ return traffic_situations
+
+
+"""Domain specific data types used in trafficgen."""
+
+from enum import Enum
+from typing import List, Union
+
+from pydantic import BaseModel
+
+
+
+[docs]
+class Position(BaseModel):
+ """Data type for a ship's position with attributes north, east in [m]."""
+
+ north: float = 0.0
+ east: float = 0.0
+ latitude: float = 0.0
+ longitude: float = 0.0
+
+
+
+
+[docs]
+class Pose(BaseModel):
+ """Data type for a (ship) pose."""
+
+ speed: float = 0.0
+ course: float = 0.0
+ position: Position = Position()
+
+
+
+
+[docs]
+class ShipType(Enum):
+ """Enumeration of ship types."""
+
+ PASSENGER_RORO = "Passenger/Ro-Ro Cargo Ship"
+ GENERAL_CARGO = "General Cargo Ship"
+ FISHING = "Fishing"
+ MILITARY = "Military ops"
+
+
+
+
+[docs]
+class StaticShipData(BaseModel):
+ """Data type for static ship data."""
+
+ length: float
+ width: float
+ height: float
+ speed_max: float
+ mmsi: int
+ name: str
+ ship_type: ShipType
+
+
+
+
+[docs]
+class Ship(BaseModel):
+ """Data type for a ship."""
+
+ static: Union[StaticShipData, None] = None
+ start_pose: Union[Pose, None] = None
+ waypoints: Union[List[Position], None] = None
+
+
+
+
+[docs]
+class TargetShip(Ship):
+ """Data type for a target ship."""
+
+ id: Union[int, None] = None
+
+
+
+
+[docs]
+class EncounterType(Enum):
+ """Enumeration of encounter types."""
+
+ OVERTAKING_STAND_ON = "overtaking-stand-on"
+ OVERTAKING_GIVE_WAY = "overtaking-give-way"
+ HEAD_ON = "head-on"
+ CROSSING_GIVE_WAY = "crossing-give-way"
+ CROSSING_STAND_ON = "crossing-stand-on"
+ NO_RISK_COLLISION = "noRiskCollision"
+
+
+
+
+[docs]
+class Encounter(BaseModel):
+ """Data type for an encounter."""
+
+ desired_encounter_type: EncounterType
+ beta: Union[float, None] = None
+ relative_speed: Union[float, None] = None
+ vector_time: Union[float, None] = None
+
+
+
+
+[docs]
+class Situation(BaseModel):
+ """Data type for a traffic situation."""
+
+ title: str
+ input_file_name: Union[str, None] = None
+ common_vector: Union[float, None] = None
+ lat_lon_0: Union[List[float], None] = None
+ own_ship: Union[Ship, None] = None
+ num_situations: Union[int, None] = None
+ encounter: Union[List[Encounter], None] = None
+ target_ship: Union[List[TargetShip], None] = None
+
+
+
+
+[docs]
+class EncounterClassification(BaseModel):
+ """Data type for the encounter classification."""
+
+ theta13_criteria: float
+ theta14_criteria: float
+ theta15_criteria: float
+ theta15: List[float]
+
+
+
+
+[docs]
+class EncounterRelativeSpeed(BaseModel):
+ """Data type for relative speed between two ships in an encounter."""
+
+ overtaking_stand_on: List[float]
+ overtaking_give_way: List[float]
+ head_on: List[float]
+ crossing_give_way: List[float]
+ crossing_stand_on: List[float]
+
+
+
+
+[docs]
+class EncounterSettings(BaseModel):
+ """Data type for encounter settings."""
+
+ classification: EncounterClassification
+ relative_speed: EncounterRelativeSpeed
+ vector_range: List[float]
+ max_meeting_distance: float
+ evolve_time: float
+ lat_lon_0: List[float]
+
+
+"""Utility functions that are used by several other functions."""
+
+import numpy as np
+
+from trafficgen.types import Position
+
+
+
+[docs]
+def m_pr_min_2_knot(speed_in_m_pr_min: float) -> float:
+ """
+ Convert ship speed in meters pr minutes to knot.
+
+ Params:
+ speed_in_m_pr_min: Ship speed in meters pr second
+
+ Returns
+ -------
+ speed_in_knot: Ship speed given in knots
+ """
+
+ knot_2_m_pr_sec: float = 0.5144
+ return speed_in_m_pr_min / (knot_2_m_pr_sec * 60.0)
+
+
+
+
+[docs]
+def knot_2_m_pr_min(speed_in_knot: float) -> float:
+ """
+ Convert ship speed in knot to meters pr minutes.
+
+ Params:
+ speed_in_knot: Ship speed given in knots
+
+ Returns
+ -------
+ speed_in_m_pr_min: Ship speed in meters pr minutes
+ """
+
+ knot_2_m_pr_sec: float = 0.5144
+ return speed_in_knot * knot_2_m_pr_sec * 60.0
+
+
+
+
+[docs]
+def m2nm(length_in_m: float) -> float:
+ """
+ Convert length given in meters to length given in nautical miles.
+
+ Params:
+ length_in_m: Length given in meters
+
+ Returns
+ -------
+ length_in_nm: Length given in nautical miles
+ """
+
+ m_2_nm: float = 1.0 / 1852.0
+ return m_2_nm * length_in_m
+
+
+
+
+[docs]
+def nm_2_m(length_in_nm: float) -> float:
+ """
+ Convert length given in nautical miles to length given in meters.
+
+ Params:
+ length_in_nm: Length given in nautical miles
+
+ Returns
+ -------
+ length_in_m: Length given in meters
+ """
+
+ nm_2_m_factor: float = 1852.0
+ return length_in_nm * nm_2_m_factor
+
+
+
+
+[docs]
+def deg_2_rad(angle_in_degrees: float) -> float:
+ """
+ Convert angle given in degrees to angle give in radians.
+
+ Params:
+ angle_in_degrees: Angle given in degrees
+
+ Returns
+ -------
+ angle given in radians: Angle given in radians
+ """
+
+ return angle_in_degrees * np.pi / 180.0
+
+
+
+
+[docs]
+def rad_2_deg(angle_in_radians: float) -> float:
+ """
+ Convert angle given in radians to angle give in degrees.
+
+ Params:
+ angle_in_degrees: Angle given in degrees
+
+ Returns
+ -------
+ angle given in radians: Angle given in radians
+
+ """
+
+ return angle_in_radians * 180.0 / np.pi
+
+
+
+
+[docs]
+def convert_angle_minus_180_to_180_to_0_to_360(angle_180: float) -> float:
+ """
+ Convert an angle given in the region -180 to 180 degrees to an
+ angle given in the region 0 to 360 degrees.
+
+ Params:
+ angle_180: Angle given in the region -180 to 180 degrees
+
+ Returns
+ -------
+ angle_360: Angle given in the region 0 to 360 degrees
+
+ """
+
+ return angle_180 if angle_180 >= 0.0 else angle_180 + 360.0
+
+
+
+
+[docs]
+def convert_angle_0_to_360_to_minus_180_to_180(angle_360: float) -> float:
+ """
+ Convert an angle given in the region 0 to 360 degrees to an
+ angle given in the region -180 to 180 degrees.
+
+ Params:
+ angle_360: Angle given in the region 0 to 360 degrees
+
+ Returns
+ -------
+ angle_180: Angle given in the region -180 to 180 degrees
+
+ """
+
+ return angle_360 if (angle_360 >= 0.0) & (angle_360 <= 180.0) else angle_360 - 360.0
+
+
+
+
+[docs]
+def calculate_position_at_certain_time(
+ position: Position,
+ speed: float,
+ course: float,
+ delta_time: float,
+) -> Position:
+ """
+ Calculate the position of the ship at a given time based on initial position
+ and delta time, and constand speed and course.
+
+ Params:
+ position: Initial ship position [m]
+ speed: Ship speed [knot]
+ course: Ship course [deg]
+ delta_time: Delta time from now to the time new position is being calculated [minutes]
+
+ Returns
+ -------
+ position{north, east}: Dict, north and east position given in meters
+
+ """
+
+ north = position.north + knot_2_m_pr_min(speed) * delta_time * np.cos(deg_2_rad(course))
+ east = position.east + knot_2_m_pr_min(speed) * delta_time * np.sin(deg_2_rad(course))
+ position_future: Position = Position(
+ north=north,
+ east=east,
+ )
+ return position_future
+
+
+"""Functions to clean traffic situations data before writing it to a json file."""
+
+from pathlib import Path
+from typing import List
+
+from trafficgen.types import Situation
+
+
+
+[docs]
+def write_traffic_situations_to_json_file(situations: List[Situation], write_folder: Path):
+ """
+ Write traffic situations to json file.
+
+ Params:
+ traffic_situations: Traffic situations to be written to file
+ write_folder: Folder where the json files is to be written
+ """
+
+ Path(write_folder).mkdir(parents=True, exist_ok=True)
+ for i, situation in enumerate(situations):
+ file_number: int = i + 1
+ output_file_path: Path = write_folder / f"traffic_situation_{file_number:02d}.json"
+ data: str = situation.model_dump_json(
+ indent=4,
+ exclude_unset=True,
+ exclude_defaults=False,
+ exclude_none=True,
+ )
+ with open(output_file_path, "w", encoding="utf-8") as outfile:
+ _ = outfile.write(data)
+
+
' + + '' + + _("Hide Search Matches") + + "
" + ) + ); + }, + + /** + * helper function to hide the search marks again + */ + hideSearchWords: () => { + document + .querySelectorAll("#searchbox .highlight-link") + .forEach((el) => el.remove()); + document + .querySelectorAll("span.highlighted") + .forEach((el) => el.classList.remove("highlighted")); + localStorage.removeItem("sphinx_highlight_terms") + }, + + initEscapeListener: () => { + // only install a listener if it is really needed + if (!DOCUMENTATION_OPTIONS.ENABLE_SEARCH_SHORTCUTS) return; + + document.addEventListener("keydown", (event) => { + // bail for input elements + if (BLACKLISTED_KEY_CONTROL_ELEMENTS.has(document.activeElement.tagName)) return; + // bail with special keys + if (event.shiftKey || event.altKey || event.ctrlKey || event.metaKey) return; + if (DOCUMENTATION_OPTIONS.ENABLE_SEARCH_SHORTCUTS && (event.key === "Escape")) { + SphinxHighlight.hideSearchWords(); + event.preventDefault(); + } + }); + }, +}; + +_ready(() => { + /* Do not call highlightSearchWords() when we are on the search page. + * It will highlight words from the *previous* search query. + */ + if (typeof Search === "undefined") SphinxHighlight.highlightSearchWords(); + SphinxHighlight.initEscapeListener(); +}); diff --git a/branch/main/api/index.html b/branch/main/api/index.html new file mode 100644 index 0000000..29c05fd --- /dev/null +++ b/branch/main/api/index.html @@ -0,0 +1,146 @@ + + + + + + +trafficgen.check_land_crossing
Module with helper functions to determine if a generated path is crossing land.
+
|
+Find if path is crossing land. |
+
Find if path is crossing land.
+position_1: Ship position in (north, east) [m]. +speed: Ship speed [knots]. +course: Ship course [degree]. +lat_lon_0: Reference point, latitudinal [degree] and longitudinal [degree]. +time_interval: The time interval the vessel should travel without crossing land [minutes]
+is_on_land
+True if parts of the path crosses land.
+trafficgen.cli
CLI for trafficgen package.
+
|
+Entry point for console script as configured in pyproject.toml. |
+
|
+Console script for trafficgen. |
+
+ | + |
+ | + |
+ | + |
+ | + |
+ | + |
+ | + |
+ | + |
+ | + |
Entry point for console script as configured in pyproject.toml.
+Runs the command line interface and parses arguments and options entered on the console.
+Console script for trafficgen. +Example: n +trafficgen gen-situation -s ./data/example_situations_input +-o ./data/test_output_1.
+trafficgen.encounter
Functions to generate encounters consisting of one own ship and one to many target ships. +The generated encounters may be of type head-on, overtaking give-way and stand-on and +crossing give-way and stand-on.
+
|
+Generate an encounter. |
+
|
+Check encounter evolvement. The generated encounter should be the same type of |
+
+ | Calculate minimum vector length (target ship speed x vector). This will |
+
|
+Find start position of target ship using desired beta and vector length. |
+
+ | Randomly assign future position of target ship. If drawing a circle with radius |
+
|
+Determine the colreg type based on alpha, relative bearing between target ship and own |
+
|
+Calculate relative bearing between own ship and target ship, both seen from |
+
|
+Calculate ship course between two waypoints. |
+
|
+Assign random (uniform) vector time. |
+
|
+Assign random (uniform) speed to target ship depending on type of encounter. |
+
|
+Assign random (uniform) relative bearing beta between own ship |
+
+ | Update position data of the target ship to also include latitude and longitude |
+
|
+Update position data of the target ship to also include latitude and longitude |
+
|
+Randomly pick a target ship from a list of target ships. |
+
Generate an encounter.
+desired_encounter_type: Desired encounter to be generated
own_ship: Dict, information about own ship that will encounter a target ship
target_ships: List of target ships that may be used in an encounter
target_ship_id: ID which should be used on target ship
beta_default: User defined beta. If not set, this is None.
target ship. If not set, this is None.
+vector_time_default: User defined vector time. If not set, this is None.
settings: Encounter settings
target_ship (target ship information, such as initial position, speed and course)
encounter_found (True=encounter found, False=encounter not found)
Check encounter evolvement. The generated encounter should be the same type of +encounter (head-on, crossing, give-way) also some time before the encounter is started.
+own_ship: Own ship information such as initial position, speed and course
target_ship: Target ship information such as initial position, speed and course
desired_encounter_type: Desired type of encounter to be generated
settings: Encounter settings
* returns True if encounter ok, False if encounter not ok
+Calculate minimum vector length (target ship speed x vector). This will +ensure that ship speed is high enough to find proper situation.
+own_ship_position: Own ship initial position, speed and course
own_ship_course: Own ship initial course
target_ship_position_future: Target ship future position
desired_beta: Desired relative bearing between
Returns: min_vector_length: Minimum vector length (target ship speed x vector)
+Find start position of target ship using desired beta and vector length.
+own_ship_position: Own ship initial position, speed and course
own_ship_course: Own ship initial course
target_ship_position_future: Target ship future position
target_ship_vector_length: vector length (target ship speed x vector)
desired_beta: Desired bearing between own ship and target ship seen from own ship
desired_encounter_type: Desired type of encounter to be generated
settings: Encounter settings
* start_position_target_ship (Dict, initial position of target ship {north, east} [m])
* start_position_found (0=position not found, 1=position found)
Randomly assign future position of target ship. If drawing a circle with radius +max_meeting_distance around future position of own ship, future position of +target ship shall be somewhere inside this circle.
+future, {north, east}
+a given time in the future [nm]
+future_position_target_ship
+Future position of target ship {north, east} [m]
+Determine the colreg type based on alpha, relative bearing between target ship and own +ship seen from target ship, and beta, relative bearing between own ship and target ship +seen from own ship.
+alpha: relative bearing between target ship and own ship seen from target ship
beta: relative bearing between own ship and target ship seen from own ship
theta13_criteria: Tolerance for “coming up with” relative bearing
theta14_criteria: Tolerance for “reciprocal or nearly reciprocal courses”, +“when in any doubt… assume… [head-on]”
theta15_criteria: Crossing aspect limit, used for classifying a crossing encounter
encounter
+* encounter classification
+Calculate relative bearing between own ship and target ship, both seen from +own ship and seen from target ship.
+position_own_ship: Dict, own ship position {north, east} [m]
heading_own_ship: Own ship course [deg]
position_target_ship: Dict, own ship position {north, east} [m]
heading_target_ship: Target ship course [deg]
* beta (relative bearing between own ship and target ship seen from own ship [deg])
* alpha (relative bearing between target ship and own ship seen from target ship [deg])
Calculate ship course between two waypoints.
+waypoint_0: Dict, waypoint {north, east} [m]
waypoint_1: Dict, waypoint {north, east} [m]
course
+Ship course [deg]
+Assign random (uniform) vector time.
+vector_range: Minimum and maximum value for vector time
vector_time
+Vector time [min]
+Assign random (uniform) speed to target ship depending on type of encounter.
+encounter_type: Type of encounter
own_ship_speed: Own ship speed [knot]
min_target_ship_speed: Minimum target ship speed [knot]
relative_speed_setting: Relative speed setting dependent on encounter [-]
target_ship_speed
+Target ship speed [knot]
+Assign random (uniform) relative bearing beta between own ship +and target ship depending on type of encounter.
+encounter_type: Type of encounter
settings: Encounter settings
Relative bearing between own ship and target ship seen from own ship [deg]
+Update position data of the target ship to also include latitude and longitude +position of the target ship.
+target_ship: Target ship data
lat_lon_0: Reference point, latitudinal [degree] and longitudinal [degree]
ship
+Updated target ship data
+Update position data of the target ship to also include latitude and longitude +position of the target ship.
+ship: Own ship data
lat_lon_0: Reference point, latitudinal [degree] and longitudinal [degree]
delta_time: Delta time from now to the time new position is being calculated [minutes]
ship
+Updated own ship data
+Randomly pick a target ship from a list of target ships.
+target_ships: list of target ships
The target ship, info of type, size etc.
+trafficgen
Top-level package for Traffic Generator.
+
|
+Convert ship speed in knot to meters pr minutes. |
+
|
+Convert ship speed in meters pr minutes to knot. |
+
|
+Convert length given in meters to length given in nautical miles. |
+
|
+Convert length given in nautical miles to length given in meters. |
+
|
+Convert angle given in degrees to angle give in radians. |
+
|
+Convert angle given in radians to angle give in degrees. |
+
+ | Convert an angle given in the region -180 to 180 degrees to an |
+
+ | Convert an angle given in the region 0 to 360 degrees to an |
+
+ | Calculate the position of the ship at a given time based on initial position |
+
|
+Compute longitude lon (rad), latitude lat (rad) and height h (m) for the |
+
|
+Compute (north, east) for a flat Earth coordinate system from longitude |
+
|
+Return the "smallest signed angle" (SSA) or the smallest difference between two angles. |
+
|
+Find if path is crossing land. |
+
|
+Write traffic situations to json file. |
+
|
+Generate an encounter. |
+
|
+Check encounter evolvement. The generated encounter should be the same type of |
+
|
+Find start position of target ship using desired beta and vector length. |
+
+ | Randomly assign future position of target ship. If drawing a circle with radius |
+
|
+Determine the colreg type based on alpha, relative bearing between target ship and own |
+
|
+Calculate relative bearing between own ship and target ship, both seen from |
+
|
+Calculate ship course between two waypoints. |
+
|
+Assign random (uniform) vector time. |
+
|
+Assign random (uniform) speed to target ship depending on type of encounter. |
+
|
+Assign random (uniform) relative bearing beta between own ship |
+
+ | Update position data of the target ship to also include latitude and longitude |
+
|
+Update position data of the target ship to also include latitude and longitude |
+
|
+Randomly pick a target ship from a list of target ships. |
+
|
+Plot the traffic situations in one more figures. |
+
|
+Plot a specific situation in map. |
+
|
+Read traffic situation files. |
+
|
+Read own ship file. |
+
|
+Read target ship files. |
+
+ | Read encounter settings file. |
+
Convert ship speed in knot to meters pr minutes.
+speed_in_knot: Ship speed given in knots
+speed_in_m_pr_min
+Ship speed in meters pr minutes
+Convert ship speed in meters pr minutes to knot.
+speed_in_m_pr_min: Ship speed in meters pr second
+speed_in_knot
+Ship speed given in knots
+Convert length given in meters to length given in nautical miles.
+length_in_m: Length given in meters
+length_in_nm
+Length given in nautical miles
+Convert length given in nautical miles to length given in meters.
+length_in_nm: Length given in nautical miles
+length_in_m
+Length given in meters
+Convert angle given in degrees to angle give in radians.
+angle_in_degrees: Angle given in degrees
+angle given in radians
+Angle given in radians
+Convert angle given in radians to angle give in degrees.
+angle_in_degrees: Angle given in degrees
+angle given in radians
+Angle given in radians
+Convert an angle given in the region -180 to 180 degrees to an +angle given in the region 0 to 360 degrees.
+angle_180: Angle given in the region -180 to 180 degrees
+angle_360
+Angle given in the region 0 to 360 degrees
+Convert an angle given in the region 0 to 360 degrees to an +angle given in the region -180 to 180 degrees.
+angle_360: Angle given in the region 0 to 360 degrees
+angle_180
+Angle given in the region -180 to 180 degrees
+Calculate the position of the ship at a given time based on initial position +and delta time, and constand speed and course.
+position: Initial ship position [m] +speed: Ship speed [knot] +course: Ship course [deg] +delta_time: Delta time from now to the time new position is being calculated [minutes]
+position{north, east}
+Dict, north and east position given in meters
+Compute longitude lon (rad), latitude lat (rad) and height h (m) for the +NED coordinates (xn,yn,zn).
+Method taken from the MSS (Marine System Simulator) toolbox which is a Matlab/Simulink +library for marine systems.
+The method computes longitude lon (rad), latitude lat (rad) and height h (m) for the +NED coordinates (xn,yn,zn) using a flat Earth coordinate system defined by the WGS-84 +ellipsoid. The flat Earth coordinate origin is located at (lon_0, lat_0) with reference +height h_ref in meters above the surface of the ellipsoid. Both height and h_ref +are positive upwards, while zn is positive downwards (NED). +Author: Thor I. Fossen +Date: 20 July 2018 +Revisions: 2023-02-04 updates the formulas for latitude and longitude
+xn: Ship position, north [m] +yn: Ship position, east [m] +zn=0.0: Ship position, down [m] +lat_0, lon_0: Flat earth coordinate located at (lon_0, lat_0) +h_ref=0.0: Flat earth coordinate with reference h_ref in meters above the surface +of the ellipsoid
+lat (Latitude [rad])
lon (Longitude [rad])
h (Height [m])
Compute (north, east) for a flat Earth coordinate system from longitude +lon (rad) and latitude lat (rad).
+Method taken from the MSS (Marine System Simulator) toolbox which is a Matlab/Simulink +library for marine systems.
+The method computes (north, east) for a flat Earth coordinate system from longitude +lon (rad) and latitude lat (rad) of the WGS-84 elipsoid. The flat Earth coordinate +origin is located at (lon_0, lat_0). +Author: Thor I. Fossen +Date: 20 July 2018 +Revisions: 2023-02-04 updates the formulas for latitude and longitude
+lat: Ship position in latitude [rad] +lon: Ship position in longitude [rad] +h=0.0: Ship height in meters above the surface of the ellipsoid +lat_0, lon_0: Flat earth coordinate located at (lon_0, lat_0) +h_ref=0.0: Flat earth coordinate with reference h_ref in meters above +the surface of the ellipsoid
+x_n (Ship position, north [m])
y_n (Ship position, east [m])
z_n (Ship position, down [m])
Return the “smallest signed angle” (SSA) or the smallest difference between two angles.
+Method taken from the MSS (Marine System Simulator) toolbox which is a Matlab/Simulink +library for marine systems.
+Examples
+angle = ssa(angle) maps an angle in rad to the interval [-pi pi)
+Author: Thor I. Fossen +Date: 2018-09-21
+angle: angle given in radius
+smallest_angle
+“smallest signed angle” or the smallest difference between two angles
+Find if path is crossing land.
+position_1: Ship position in (north, east) [m]. +speed: Ship speed [knots]. +course: Ship course [degree]. +lat_lon_0: Reference point, latitudinal [degree] and longitudinal [degree]. +time_interval: The time interval the vessel should travel without crossing land [minutes]
+is_on_land
+True if parts of the path crosses land.
+Write traffic situations to json file.
+traffic_situations: Traffic situations to be written to file +write_folder: Folder where the json files is to be written
+Generate an encounter.
+desired_encounter_type: Desired encounter to be generated
own_ship: Dict, information about own ship that will encounter a target ship
target_ships: List of target ships that may be used in an encounter
target_ship_id: ID which should be used on target ship
beta_default: User defined beta. If not set, this is None.
target ship. If not set, this is None.
+vector_time_default: User defined vector time. If not set, this is None.
settings: Encounter settings
target_ship (target ship information, such as initial position, speed and course)
encounter_found (True=encounter found, False=encounter not found)
Check encounter evolvement. The generated encounter should be the same type of +encounter (head-on, crossing, give-way) also some time before the encounter is started.
+own_ship: Own ship information such as initial position, speed and course
target_ship: Target ship information such as initial position, speed and course
desired_encounter_type: Desired type of encounter to be generated
settings: Encounter settings
* returns True if encounter ok, False if encounter not ok
+Find start position of target ship using desired beta and vector length.
+own_ship_position: Own ship initial position, speed and course
own_ship_course: Own ship initial course
target_ship_position_future: Target ship future position
target_ship_vector_length: vector length (target ship speed x vector)
desired_beta: Desired bearing between own ship and target ship seen from own ship
desired_encounter_type: Desired type of encounter to be generated
settings: Encounter settings
* start_position_target_ship (Dict, initial position of target ship {north, east} [m])
* start_position_found (0=position not found, 1=position found)
Randomly assign future position of target ship. If drawing a circle with radius +max_meeting_distance around future position of own ship, future position of +target ship shall be somewhere inside this circle.
+future, {north, east}
+a given time in the future [nm]
+future_position_target_ship
+Future position of target ship {north, east} [m]
+Determine the colreg type based on alpha, relative bearing between target ship and own +ship seen from target ship, and beta, relative bearing between own ship and target ship +seen from own ship.
+alpha: relative bearing between target ship and own ship seen from target ship
beta: relative bearing between own ship and target ship seen from own ship
theta13_criteria: Tolerance for “coming up with” relative bearing
theta14_criteria: Tolerance for “reciprocal or nearly reciprocal courses”, +“when in any doubt… assume… [head-on]”
theta15_criteria: Crossing aspect limit, used for classifying a crossing encounter
encounter
+* encounter classification
+Calculate relative bearing between own ship and target ship, both seen from +own ship and seen from target ship.
+position_own_ship: Dict, own ship position {north, east} [m]
heading_own_ship: Own ship course [deg]
position_target_ship: Dict, own ship position {north, east} [m]
heading_target_ship: Target ship course [deg]
* beta (relative bearing between own ship and target ship seen from own ship [deg])
* alpha (relative bearing between target ship and own ship seen from target ship [deg])
Calculate ship course between two waypoints.
+waypoint_0: Dict, waypoint {north, east} [m]
waypoint_1: Dict, waypoint {north, east} [m]
course
+Ship course [deg]
+Assign random (uniform) vector time.
+vector_range: Minimum and maximum value for vector time
vector_time
+Vector time [min]
+Assign random (uniform) speed to target ship depending on type of encounter.
+encounter_type: Type of encounter
own_ship_speed: Own ship speed [knot]
min_target_ship_speed: Minimum target ship speed [knot]
relative_speed_setting: Relative speed setting dependent on encounter [-]
target_ship_speed
+Target ship speed [knot]
+Assign random (uniform) relative bearing beta between own ship +and target ship depending on type of encounter.
+encounter_type: Type of encounter
settings: Encounter settings
Relative bearing between own ship and target ship seen from own ship [deg]
+Update position data of the target ship to also include latitude and longitude +position of the target ship.
+target_ship: Target ship data
lat_lon_0: Reference point, latitudinal [degree] and longitudinal [degree]
ship
+Updated target ship data
+Update position data of the target ship to also include latitude and longitude +position of the target ship.
+ship: Own ship data
lat_lon_0: Reference point, latitudinal [degree] and longitudinal [degree]
delta_time: Delta time from now to the time new position is being calculated [minutes]
ship
+Updated own ship data
+Randomly pick a target ship from a list of target ships.
+target_ships: list of target ships
The target ship, info of type, size etc.
+Plot the traffic situations in one more figures.
+traffic_situations: Traffic situations to be plotted +col: Number of columns in each figure +row: Number of rows in each figure
+Plot a specific situation in map.
+traffic_situations: Generated traffic situations +situation_number: The specific situation to be plotted
+Read traffic situation files.
+situation_folder: Path to the folder where situation files are found
+situations
+List of desired traffic situations
+Read own ship file.
+own_ship_file: Path to the own_ship_file file
+own_ship information
+Read target ship files.
+target_ship_folder: Path to the folder where target ships are found
+target_ships
+List of different target ships
+Read encounter settings file.
+settings_file: Path to the encounter setting file
+Encounter settings
+trafficgen.marine_system_simulator
The Marine Systems Simulator (MSS) is a Matlab and Simulink library for marine systems.
+It includes models for ships, underwater vehicles, unmanned surface vehicles, and floating structures. +The library also contains guidance, navigation, and control (GNC) blocks for real-time simulation. +The algorithms are described in:
+T. I. Fossen (2021). Handbook of Marine Craft Hydrodynamics and Motion Control. 2nd. Edition, +Wiley. ISBN-13: 978-1119575054
+Parts of the library have been re-implemented in Python and are found below.
+
|
+Compute longitude lon (rad), latitude lat (rad) and height h (m) for the |
+
|
+Compute (north, east) for a flat Earth coordinate system from longitude |
+
|
+Return the "smallest signed angle" (SSA) or the smallest difference between two angles. |
+
Compute longitude lon (rad), latitude lat (rad) and height h (m) for the +NED coordinates (xn,yn,zn).
+Method taken from the MSS (Marine System Simulator) toolbox which is a Matlab/Simulink +library for marine systems.
+The method computes longitude lon (rad), latitude lat (rad) and height h (m) for the +NED coordinates (xn,yn,zn) using a flat Earth coordinate system defined by the WGS-84 +ellipsoid. The flat Earth coordinate origin is located at (lon_0, lat_0) with reference +height h_ref in meters above the surface of the ellipsoid. Both height and h_ref +are positive upwards, while zn is positive downwards (NED). +Author: Thor I. Fossen +Date: 20 July 2018 +Revisions: 2023-02-04 updates the formulas for latitude and longitude
+xn: Ship position, north [m] +yn: Ship position, east [m] +zn=0.0: Ship position, down [m] +lat_0, lon_0: Flat earth coordinate located at (lon_0, lat_0) +h_ref=0.0: Flat earth coordinate with reference h_ref in meters above the surface +of the ellipsoid
+lat (Latitude [rad])
lon (Longitude [rad])
h (Height [m])
Compute (north, east) for a flat Earth coordinate system from longitude +lon (rad) and latitude lat (rad).
+Method taken from the MSS (Marine System Simulator) toolbox which is a Matlab/Simulink +library for marine systems.
+The method computes (north, east) for a flat Earth coordinate system from longitude +lon (rad) and latitude lat (rad) of the WGS-84 elipsoid. The flat Earth coordinate +origin is located at (lon_0, lat_0). +Author: Thor I. Fossen +Date: 20 July 2018 +Revisions: 2023-02-04 updates the formulas for latitude and longitude
+lat: Ship position in latitude [rad] +lon: Ship position in longitude [rad] +h=0.0: Ship height in meters above the surface of the ellipsoid +lat_0, lon_0: Flat earth coordinate located at (lon_0, lat_0) +h_ref=0.0: Flat earth coordinate with reference h_ref in meters above +the surface of the ellipsoid
+x_n (Ship position, north [m])
y_n (Ship position, east [m])
z_n (Ship position, down [m])
Return the “smallest signed angle” (SSA) or the smallest difference between two angles.
+Method taken from the MSS (Marine System Simulator) toolbox which is a Matlab/Simulink +library for marine systems.
+Examples
+angle = ssa(angle) maps an angle in rad to the interval [-pi pi)
+Author: Thor I. Fossen +Date: 2018-09-21
+angle: angle given in radius
+smallest_angle
+“smallest signed angle” or the smallest difference between two angles
+trafficgen.plot_traffic_situation
Functions to prepare and plot traffic situations.
+
|
+Calculate the arrow with length vector pointing in the direction of ship course. |
+
|
+Calculate the outline of the ship pointing in the direction of ship course. |
+
|
+Plot a specific situation in map. |
+
|
+Add the ship to the map. |
+
|
+Plot the traffic situations in one more figures. |
+
|
+Find the maximum deviation from the Reference point in north and east direction. |
+
|
+Add the ship to the plot. |
+
Calculate the arrow with length vector pointing in the direction of ship course.
+position: {north}, {east} position of the ship [m] +direction: direction the arrow is pointing [deg] +vector_length: length of vector +lat_lon_0: Reference point, latitudinal [degree] and longitudinal [degree]
+arrow_points
+Polygon points to draw the arrow
+Calculate the outline of the ship pointing in the direction of ship course.
+position: {north}, {east} position of the ship [m] +course: course of the ship [deg] +lat_lon_0: Reference point, latitudinal [degree] and longitudinal [degree] +ship_length: Ship length. If not given, ship length is set to 100 +ship_width: Ship width. If not given, ship width is set to 15
+ship_outline_points
+Polygon points to draw the ship
+Plot a specific situation in map.
+traffic_situations: Generated traffic situations +situation_number: The specific situation to be plotted
+Add the ship to the map.
+ship: Ship information +vector_time: Vector time [min] +lat_lon_0=Reference point, latitudinal [degree] and longitudinal [degree] +map_plot: Instance of Map. If not set, instance is set to None +color: Color of the ship. If not set, color is ‘black’
+m
+Updated instance of Map.
+Plot the traffic situations in one more figures.
+traffic_situations: Traffic situations to be plotted +col: Number of columns in each figure +row: Number of rows in each figure
+Find the maximum deviation from the Reference point in north and east direction.
+ship: Ship information +max_value: maximum deviation in north, east direction
+max_value
+updated maximum deviation in north, east direction
+Add the ship to the plot.
+ship: Ship information +vector_time: Vector time [min] +axes: Instance of figure axis. If not set, instance is set to None +color: Color of the ship. If not set, color is ‘black’
+trafficgen.read_files
Functions to read the files needed to build one or more traffic situations.
+
|
+Read traffic situation files. |
+
|
+Read own ship file. |
+
|
+Read target ship files. |
+
+ | Read encounter settings file. |
+
Read traffic situation files.
+situation_folder: Path to the folder where situation files are found
+situations
+List of desired traffic situations
+Read own ship file.
+own_ship_file: Path to the own_ship_file file
+own_ship information
+Read target ship files.
+target_ship_folder: Path to the folder where target ships are found
+target_ships
+List of different target ships
+Read encounter settings file.
+settings_file: Path to the encounter setting file
+Encounter settings
+trafficgen.ship_traffic_generator
Functions to generate traffic situations.
++ | Generate a set of traffic situations using input files. |
+
Generate a set of traffic situations using input files. +This is the main function for generating a set of traffic situations using input files +specifying number and type of encounter, type of target ships etc.
+situation_folder: Path to situation folder, files describing the desired situations
target_ship_folder: Path to where different type of target ships is found
settings_file: Path to settings file
traffic_situations (List of generated traffic situations.)
One situation may consist of one or more encounters.
trafficgen.types
Domain specific data types used in trafficgen.
++ | Data type for a ship's position with attributes north, east in [m]. |
+
+ | Data type for a (ship) pose. |
+
+ | Enumeration of ship types. |
+
+ | Data type for static ship data. |
+
+ | Data type for a ship. |
+
+ | Data type for a target ship. |
+
+ | Enumeration of encounter types. |
+
+ | Data type for an encounter. |
+
+ | Data type for a traffic situation. |
+
+ | Data type for the encounter classification. |
+
+ | Data type for relative speed between two ships in an encounter. |
+
+ | Data type for encounter settings. |
+
Bases: pydantic.BaseModel
Data type for a ship’s position with attributes north, east in [m].
+Bases: pydantic.BaseModel
Data type for a (ship) pose.
+Bases: enum.Enum
Enumeration of ship types.
+Bases: pydantic.BaseModel
Data type for static ship data.
+Bases: pydantic.BaseModel
Data type for a ship.
+Bases: Ship
Data type for a target ship.
+Bases: enum.Enum
Enumeration of encounter types.
+Bases: pydantic.BaseModel
Data type for an encounter.
+Bases: pydantic.BaseModel
Data type for a traffic situation.
+Bases: pydantic.BaseModel
Data type for the encounter classification.
+Bases: pydantic.BaseModel
Data type for relative speed between two ships in an encounter.
+Bases: pydantic.BaseModel
Data type for encounter settings.
+trafficgen.utils
Utility functions that are used by several other functions.
+
|
+Convert ship speed in meters pr minutes to knot. |
+
|
+Convert ship speed in knot to meters pr minutes. |
+
|
+Convert length given in meters to length given in nautical miles. |
+
|
+Convert length given in nautical miles to length given in meters. |
+
|
+Convert angle given in degrees to angle give in radians. |
+
|
+Convert angle given in radians to angle give in degrees. |
+
+ | Convert an angle given in the region -180 to 180 degrees to an |
+
+ | Convert an angle given in the region 0 to 360 degrees to an |
+
+ | Calculate the position of the ship at a given time based on initial position |
+
Convert ship speed in meters pr minutes to knot.
+speed_in_m_pr_min: Ship speed in meters pr second
+speed_in_knot
+Ship speed given in knots
+Convert ship speed in knot to meters pr minutes.
+speed_in_knot: Ship speed given in knots
+speed_in_m_pr_min
+Ship speed in meters pr minutes
+Convert length given in meters to length given in nautical miles.
+length_in_m: Length given in meters
+length_in_nm
+Length given in nautical miles
+Convert length given in nautical miles to length given in meters.
+length_in_nm: Length given in nautical miles
+length_in_m
+Length given in meters
+Convert angle given in degrees to angle give in radians.
+angle_in_degrees: Angle given in degrees
+angle given in radians
+Angle given in radians
+Convert angle given in radians to angle give in degrees.
+angle_in_degrees: Angle given in degrees
+angle given in radians
+Angle given in radians
+Convert an angle given in the region -180 to 180 degrees to an +angle given in the region 0 to 360 degrees.
+angle_180: Angle given in the region -180 to 180 degrees
+angle_360
+Angle given in the region 0 to 360 degrees
+Convert an angle given in the region 0 to 360 degrees to an +angle given in the region -180 to 180 degrees.
+angle_360: Angle given in the region 0 to 360 degrees
+angle_180
+Angle given in the region -180 to 180 degrees
+Calculate the position of the ship at a given time based on initial position +and delta time, and constand speed and course.
+position: Initial ship position [m] +speed: Ship speed [knot] +course: Ship course [deg] +delta_time: Delta time from now to the time new position is being calculated [minutes]
+position{north, east}
+Dict, north and east position given in meters
+trafficgen.write_traffic_situation_to_file
Functions to clean traffic situations data before writing it to a json file.
+
|
+Write traffic situations to json file. |
+
Write traffic situations to json file.
+traffic_situations: Traffic situations to be written to file +write_folder: Folder where the json files is to be written
+Contributions are welcome, and they are greatly appreciated! Every little bit +helps, and credit will always be given.
+You can contribute in many ways:
+Report bugs at https://github.com/dnv-opensource/ship-traffic-generator/issues.
+If you are reporting a bug, please include:
+Your operating system name and version.
The version of Python (and Conda) that you are using.
Any additional details about your local setup that might be helpful in troubleshooting.
Detailed steps to reproduce the bug.
Look through the GitHub issues for bugs. Anything tagged with “bug” and “help +wanted” is open to whoever wants to implement it.
+Look through the GitHub issues for features. Anything tagged with “enhancement” +and “help wanted” is open to whoever wants to implement it.
+Traffic Generator could always use more documentation, whether as part of the +official Traffic Generator docs, in docstrings, or even on the web in blog posts, +articles, and such.
+The best way to send feedback is to file an issue at https://github.com/dnv-opensource/ship-traffic-generator/issues.
+If you are proposing a feature:
+Explain in detail how it would work.
Keep the scope as narrow as possible, to make it easier to implement.
Remember that this is a volunteer-driven project, and that contributions +are welcome :)
Ready to contribute? Here’s how to set up trafficgen for local development.
+Clone the trafficgen repo on GitHub.
Install your local copy into a pyenv or conda environment.
Create a branch for local development:
+$ git checkout -b name-of-your-bugfix-or-feature
+
Now you can make your changes locally.
+When you’re done making changes, check that your changes pass flake8 and the +tests, including testing other Python versions with tox:
+$ flake8 --config tox.ini ./src/trafficgen ./tests
+$ pytest ./tests
+$ tox
+
If you installed the package with poetry
+++$ poetry install –with dev,docs
+
flake8, pytest and tox should already be installed in your Python environment. +Note that the tox config assumes Python 3.10 and Python 3.11, you would have +to have them both available to tox for all tests to run. +If you only have one of these available tox will skip the non supported +environment (and in most cases that is OK). +If you are managing your Python enhancements with pyenv you will have to +install the necessary versions and then run pyenv rehash to make them +available to tox (or set multiple local envs with pyenv local py310 py311). +If you are using conda you will have to create a new environment with +the necessary Python version, install virtualenv in the environments +and then run conda activate <env-name> to make it available to tox (to run all +the environments in one go do conda activate inside activated environments).
+You can also run the python tests from VSCode via the “Testing” view, +“Configure Python Tests”, with pytest` and select the folder tests.
+Commit your changes and push your branch to the source repo:
+$ git add .
+$ git commit -m "Your detailed description of your changes."
+$ git push origin name-of-your-bugfix-or-feature
+
Submit a pull request through https://github.com/dnv-opensource/ship-traffic-generator/pulls.
Before you submit a pull request, check that it meets these guidelines:
+The pull request should include tests.
If the pull request adds functionality, the docs should be updated. Put +your new functionality into a function with a docstring, and add the +feature to the list in README.md.
The pull request should work for Python 3.10.
To run a subset of tests:
+$ pytest tests.test_trafficgen
+
A reminder for the maintainers on how to deploy. +Make sure all your changes are committed (including an entry in HISTORY.rst). +Then run:
+$ bump2version patch # possible: major / minor / patch
+$ git push
+$ git push --tags
+
+ |
+ | + |
+ |
+ | + |
+ | + |
+ | + |
+ | + |
+ | + |
+ | + |
|
+
+ | + |
+ | + |
+ | + |
+ | + |
+ | + |
|
+
|
+
+ | + |
+ | + |
+ | + |
The tool generates a structured set of encounters for verifying automatic collision and +grounding avoidance systems. Based on input parameters such as desired situation, relative speed, +relative bearing etc, the tool will generate a set of traffic situations. The traffic situations +may be written to files and/or inspected using plots.
+A paper
is written describing the background for
+the tool and how it works.
trafficgen
Example 1: Complete specified situation:
+{
+ "title": "HO",
+ "common_vector": 10.0,
+ "own_ship": {
+ "speed": 10.0,
+ "course": 0.0,
+ "position": {
+ "north": 0.0,
+ "east": 0.0
+ }
+ },
+ "encounter": [
+ {
+ "desired_encounter_type": "head-on",
+ "beta": 2.0,
+ "relative_speed": 1.2,
+ "vector_time": 15.0
+ }
+ ]
+}
+
The common_vector is given in minutes. For radar plotting (plotting vessel positions and relative motions), +the common_vector and vector_time are used together with ship speed to display where the ship will be in e.g. 10 minutes +(Common vector is the common time vector used on a radar plot, e.g 10, 15, 20 minutes. The length of the arrow in the plot +will then be the speed times this time vector). +Speed and course of the own ship, which is the ship to be tested, are given in knots and degrees, respectively. +The own ship position is given in meters from the reference points, which are defined in latitudinal [degree] and longitudinal [degree]. +The global reference point is defined in src/trafficgen/settings/encounter_settings.json.
+An encounter may be fully described as shown above, but the user may also deside to input less data, +as demonstrated in Example 2. Desired encounter type is mandatory, +while the beta, relative_speed and vector_time parameters are optional:
++++
+- +
desired_encounter_type is either head-on, overtaking-give-way, overtaking-stand-on, crossing-give-way, and crossing-stand-on.
- +
beta is the relative bearing between the own ship and the target ship as seen from the own shop, given in degrees.
- +
relative_speed is relative speed between the own ship and the target ship as seen from the own ship, such that a relative speed of 1.2 means that the target ship’s speed is 20% higher than the speed of the own ship.
An encounter is built using a maximum meeting distance [nm], see the paper linked in the introduction for more info. +At some time in the future, given by the vector_time, the target ship will be located somewhere inside a circle +with a radius given by max_meeting_distance and a center point given by the own ship position. This is not necessarily the +closest point of approach.
+The max_meeting_distance parameter is common for all encounters and is specified in src/trafficgen/settings/encounter_settings.json.
+Example 2: Minimum specified situation:
+{
+ "title": "HO",
+ "common_vector": 10.0,
+ "own_ship": {
+ "speed": 10.0,
+ "course": 0.0,
+ "position": {
+ "north": 0.0,
+ "east": 0.0
+ }
+ },
+ "encounter": [
+ {
+ "desired_encounter_type": "head-on"
+ }
+ ]
+}
+
You can also request the generation of several traffic situations of the same encounter type by specifying num_situations:
+Example 3: Generate multiple situations using num_situations:
+{
+ "title": "OT_GW",
+ "common_vector": 10.0,
+ "own_ship": {
+ "speed": 7.0,
+ "course": 0.0,
+ "position": {
+ "north": 0.0,
+ "east": 0.0
+ }
+ },
+ "num_situations": 5,
+ "encounter": [
+ {
+ "desired_encounter_type": "overtaking-give-way"
+ }
+ ]
+}
+
To install Traffic Generator, run this command in your terminal:
+$ pip install trafficgen
+
This is the preferred method to install Traffic Generator, as it will always install the most recent stable release.
+If you don’t have pip installed, this Python installation guide can guide +you through the process.
+The sources for Traffic Generator can be downloaded from the https://github.com/dnv-opensource/ship-traffic-generator.
+You can either clone the public repository:
+$ git clone https://github.com/dnv-opensource/ship-traffic-generator
+
Once you have a copy of the source, you can install it with:
+$ python setup.py install
+
assign_beta()
assign_future_position_to_target_ship()
assign_speed_to_target_ship()
assign_vector_time()
calculate_position_at_certain_time()
calculate_relative_bearing()
calculate_ship_course()
check_encounter_evolvement()
convert_angle_0_to_360_to_minus_180_to_180()
convert_angle_minus_180_to_180_to_0_to_360()
decide_target_ship()
deg_2_rad()
determine_colreg()
find_start_position_target_ship()
flat2llh()
generate_encounter()
generate_traffic_situations()
knot_2_m_pr_min()
llh2flat()
m2nm()
m_pr_min_2_knot()
nm_2_m()
path_crosses_land()
plot_specific_traffic_situation()
plot_traffic_situations()
rad_2_deg()
read_encounter_settings_file()
read_own_ship_file()
read_situation_files()
read_target_ship_files()
ssa()
update_position_data_own_ship()
update_position_data_target_ship()
write_traffic_situations_to_json_file()
assign_beta()
assign_future_position_to_target_ship()
assign_speed_to_target_ship()
assign_vector_time()
calculate_min_vector_length_target_ship()
calculate_relative_bearing()
calculate_ship_course()
check_encounter_evolvement()
decide_target_ship()
determine_colreg()
find_start_position_target_ship()
generate_encounter()
update_position_data_own_ship()
update_position_data_target_ship()
flat2llh()
llh2flat()
ssa()
+ t | ||
+ |
+ trafficgen | + |
+ |
+ trafficgen.check_land_crossing | + |
+ |
+ trafficgen.cli | + |
+ |
+ trafficgen.encounter | + |
+ |
+ trafficgen.marine_system_simulator | + |
+ |
+ trafficgen.plot_traffic_situation | + |
+ |
+ trafficgen.read_files | + |
+ |
+ trafficgen.ship_traffic_generator | + |
+ |
+ trafficgen.types | + |
+ |
+ trafficgen.utils | + |
+ |
+ trafficgen.write_traffic_situation_to_file | + |
trafficgen.check_land_crossing
", "trafficgen.cli
", "trafficgen.encounter
", "trafficgen
", "trafficgen.marine_system_simulator
", "trafficgen.plot_traffic_situation
", "trafficgen.read_files
", "trafficgen.ship_traffic_generator
", "trafficgen.types
", "trafficgen.utils
", "trafficgen.write_traffic_situation_to_file
", "Authors", "Contributing", "History", "Welcome to Traffic Generator\u2019s documentation!", "Input files", "Installation", "trafficgen", "trafficgen package", "trafficgen.check_land_crossing module", "trafficgen.cli module", "trafficgen.encounter module", "trafficgen.marine_system_simulator module", "trafficgen.plot_traffic_situation module", "trafficgen.read_files module", "trafficgen.ship_traffic_generator module", "trafficgen.types module", "trafficgen.utils module", "trafficgen.write_traffic_situation_to_file module", "Usage"], "terms": {"thi": [0, 3, 4, 8, 13, 16, 17, 19, 22, 26, 27, 30], "page": [0, 15], "contain": [0, 5, 23], "auto": 0, "gener": [0, 1, 3, 4, 6, 8, 9, 13, 16, 17, 19, 20, 22, 24, 26, 27], "document": 0, "1": [0, 3, 4, 15, 16, 19, 22, 27, 30], "trafficgen": [0, 13, 15, 16, 17, 30], "check_land_cross": [0, 4, 18, 19], "cli": [0, 4, 18, 19], "encount": [0, 4, 7, 8, 9, 15, 16, 18, 19, 25, 26, 27, 30], "marine_system_simul": [0, 4, 18, 19], "plot_traffic_situ": [0, 4, 18, 19], "read_fil": [0, 4, 18, 19], "ship_traffic_gener": [0, 4, 18, 19], "type": [0, 1, 3, 4, 5, 6, 7, 8, 10, 11, 15, 16, 18, 19, 20, 22, 23, 24, 25, 26, 28], "util": [0, 4, 18, 19], "write_traffic_situation_to_fil": [0, 4, 18, 19], "creat": [0, 13], "sphinx": 0, "autoapi": 0, "helper": [1, 20], "determin": [1, 3, 4, 19, 20, 22], "path": [1, 2, 4, 7, 8, 11, 19, 20, 25, 26, 29, 30], "i": [1, 3, 4, 5, 6, 8, 10, 11, 13, 15, 16, 17, 19, 20, 22, 23, 24, 26, 28, 29, 30], "cross": [1, 3, 4, 9, 16, 19, 20, 22, 27, 30], "land": [1, 4, 19, 20], "path_crosses_land": [1, 4, 18, 19, 20], "position_1": [1, 4, 19, 20], "posit": [1, 3, 4, 5, 6, 9, 10, 16, 18, 19, 20, 22, 23, 24, 27, 28], "speed": [1, 3, 4, 9, 10, 15, 16, 19, 20, 22, 27, 28], "float": [1, 3, 4, 5, 6, 9, 10, 19, 20, 22, 23, 24, 27, 28], "cours": [1, 3, 4, 6, 9, 10, 16, 19, 20, 22, 24, 27, 28], "lat_lon_0": [1, 3, 4, 6, 9, 19, 20, 22, 24, 27], "list": [1, 3, 4, 6, 7, 8, 9, 11, 13, 19, 20, 22, 24, 25, 26, 27, 29], "time_interv": [1, 4, 19, 20], "50": [1, 4, 19, 20], "0": [1, 3, 4, 5, 6, 9, 10, 15, 16, 19, 20, 22, 23, 24, 27, 28], "bool": [1, 3, 4, 19, 20, 22], "sourc": [1, 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 19, 20, 22, 23, 24, 25, 26, 27, 28, 29], "find": [1, 3, 4, 6, 19, 20, 22, 24], "param": [1, 3, 4, 5, 6, 7, 8, 10, 11, 19, 20, 22, 23, 24, 25, 26, 28, 29], "ship": [1, 3, 4, 5, 6, 7, 8, 9, 10, 13, 16, 17, 18, 19, 20, 22, 23, 24, 25, 26, 27, 28, 30], "north": [1, 3, 4, 5, 6, 9, 10, 16, 19, 20, 22, 23, 24, 27, 28], "east": [1, 3, 4, 5, 6, 9, 10, 16, 19, 20, 22, 23, 24, 27, 28], "m": [1, 3, 4, 5, 6, 9, 10, 13, 19, 20, 22, 23, 24, 27, 28], "knot": [1, 3, 4, 10, 16, 19, 20, 22, 28], "degre": [1, 3, 4, 6, 10, 16, 19, 20, 22, 24, 28], "refer": [1, 3, 4, 5, 6, 15, 16, 19, 20, 22, 23, 24], "point": [1, 2, 3, 4, 6, 16, 19, 20, 22, 24], "latitudin": [1, 3, 4, 6, 16, 19, 20, 22, 24], "longitudin": [1, 3, 4, 6, 16, 19, 20, 22, 24], "The": [1, 3, 4, 5, 6, 13, 15, 16, 17, 19, 20, 22, 23, 24, 30], "time": [1, 3, 4, 5, 6, 10, 16, 19, 20, 22, 23, 24, 28], "interv": [1, 4, 5, 19, 20, 23], "vessel": [1, 4, 16, 19, 20], "should": [1, 3, 4, 13, 19, 20, 22, 27], "travel": [1, 4, 19, 20], "without": [1, 4, 19, 20, 30], "minut": [1, 3, 4, 10, 16, 19, 20, 22, 28], "return": [1, 3, 4, 5, 6, 7, 8, 10, 19, 20, 22, 23, 24, 25, 26, 28], "is_on_land": [1, 4, 19, 20], "true": [1, 3, 4, 19, 20, 22, 27], "part": [1, 4, 5, 13, 19, 20, 23], "packag": [2, 13, 18, 21], "logger": 2, "_": 2, "default_data_path": 2, "pathlib": [2, 4, 7, 8, 11], "situation_fold": [2, 4, 7, 8, 19, 25, 26], "own_ship_fil": [2, 4, 7, 8, 19, 25, 26], "target_ship_fold": [2, 4, 7, 8, 19, 25, 26], "settings_fil": [2, 4, 7, 8, 19, 25, 26], "output_fold": 2, "main": [2, 8, 19, 26], "arg": [2, 9], "none": [2, 3, 4, 6, 9, 19, 22, 24, 27, 30], "entri": [2, 13], "consol": 2, "script": 2, "configur": [2, 13, 27, 30], "pyproject": 2, "toml": 2, "run": [2, 13, 17], "command": [2, 17, 30], "line": [2, 30], "interfac": 2, "pars": 2, "argument": 2, "option": [2, 16, 30], "enter": 2, "gen_situ": 2, "situat": [2, 3, 4, 6, 7, 8, 9, 11, 15, 16, 18, 19, 22, 24, 25, 26, 27, 29], "own_ship": [2, 3, 4, 7, 9, 16, 19, 22, 25, 27], "target": [2, 3, 4, 7, 8, 9, 16, 19, 22, 25, 26, 27, 30], "set": [2, 3, 4, 6, 7, 8, 9, 13, 15, 16, 19, 22, 24, 25, 26, 27, 30], "visual": [2, 30], "col": [2, 4, 6, 19, 24, 30], "row": [2, 4, 6, 19, 24, 30], "visualize_situ": 2, "output": [2, 30], "exampl": [2, 4, 5, 16, 19, 23, 30], "n": 2, "gen": [2, 30], "": [2, 9, 13, 16, 27, 30], "data": [2, 3, 4, 9, 11, 16, 19, 22, 27, 29, 30], "example_situations_input": [2, 30], "o": [2, 30], "test_output_1": [2, 30], "consist": [3, 8, 19, 22, 26], "one": [3, 4, 6, 7, 8, 13, 19, 22, 24, 25, 26, 30], "own": [3, 4, 7, 16, 19, 22, 25], "mani": [3, 13, 22], "mai": [3, 4, 8, 15, 16, 19, 22, 26, 30], "head": [3, 4, 9, 16, 19, 22, 27, 30], "overtak": [3, 4, 9, 16, 19, 22, 27, 30], "give": [3, 4, 9, 10, 16, 19, 22, 27, 28, 30], "wai": [3, 4, 9, 13, 16, 19, 22, 27, 30], "stand": [3, 9, 16, 22, 27, 30], "generate_encount": [3, 4, 18, 19, 22], "desired_encounter_typ": [3, 4, 9, 16, 19, 22, 27], "encountertyp": [3, 4, 9, 18, 19, 22, 27], "target_ship": [3, 4, 7, 9, 19, 22, 25, 27, 30], "targetship": [3, 4, 7, 9, 18, 19, 22, 25, 27], "target_ship_id": [3, 4, 19, 22], "int": [3, 4, 6, 9, 19, 22, 24, 27], "beta_default": [3, 4, 19, 22], "relative_speed_default": [3, 4, 19, 22], "vector_time_default": [3, 4, 19, 22], "encounterset": [3, 4, 7, 9, 18, 19, 22, 25, 27], "tupl": [3, 4, 5, 6, 19, 22, 23, 24], "an": [3, 4, 5, 9, 10, 13, 16, 19, 22, 23, 27, 28, 30], "desir": [3, 4, 7, 8, 15, 16, 19, 22, 25, 26, 30], "dict": [3, 4, 10, 19, 22, 27, 28], "inform": [3, 4, 6, 7, 19, 22, 24, 25], "about": [3, 4, 13, 19, 22, 27], "us": [3, 4, 5, 8, 9, 10, 13, 15, 16, 19, 22, 23, 26, 27, 28, 30], "id": [3, 4, 9, 19, 22, 27], "which": [3, 4, 5, 16, 19, 22, 23, 30], "user": [3, 4, 16, 19, 22], "defin": [3, 4, 5, 16, 19, 22, 23, 27], "beta": [3, 4, 9, 16, 19, 22, 27], "If": [3, 4, 6, 13, 17, 19, 22, 24], "rel": [3, 4, 9, 15, 16, 19, 22, 27], "between": [3, 4, 5, 9, 16, 19, 22, 23, 27], "vector": [3, 4, 6, 16, 19, 22, 24], "initi": [3, 4, 10, 19, 22, 28], "encounter_found": [3, 4, 19, 22], "found": [3, 4, 5, 7, 8, 19, 22, 23, 25, 26, 30], "fals": [3, 4, 19, 22, 27], "check_encounter_evolv": [3, 4, 18, 19, 22], "own_ship_position_futur": [3, 4, 19, 22], "target_ship_position_futur": [3, 4, 19, 22], "check": [3, 4, 13, 19, 22], "evolv": [3, 4, 19, 22], "same": [3, 4, 16, 19, 22], "also": [3, 4, 5, 13, 16, 19, 22, 23], "some": [3, 4, 16, 19, 22], "befor": [3, 4, 11, 13, 19, 22, 29], "start": [3, 4, 15, 19, 22, 27], "ok": [3, 4, 13, 19, 22], "calculate_min_vector_length_target_ship": [3, 18, 19, 22], "own_ship_posit": [3, 4, 19, 22], "own_ship_cours": [3, 4, 19, 22], "desired_beta": [3, 4, 19, 22], "calcul": [3, 4, 6, 10, 19, 22, 24, 28], "minimum": [3, 4, 16, 19, 22], "length": [3, 4, 6, 9, 10, 16, 19, 22, 24, 27, 28], "x": [3, 4, 19, 22], "ensur": [3, 22], "high": [3, 22], "enough": [3, 22], "proper": [3, 22], "futur": [3, 4, 16, 19, 22], "bear": [3, 4, 15, 16, 19, 22], "min_vector_length": [3, 22], "find_start_position_target_ship": [3, 4, 18, 19, 22], "target_ship_vector_length": [3, 4, 19, 22], "seen": [3, 4, 16, 19, 22], "from": [3, 4, 5, 6, 10, 13, 15, 16, 19, 22, 23, 24, 27, 28], "start_position_target_ship": [3, 4, 19, 22], "start_position_found": [3, 4, 19, 22], "assign_future_position_to_target_ship": [3, 4, 18, 19, 22], "max_meeting_dist": [3, 4, 9, 16, 19, 22, 27], "randomli": [3, 4, 19, 22], "assign": [3, 4, 19, 22], "draw": [3, 4, 6, 19, 22, 24], "circl": [3, 4, 16, 19, 22], "radiu": [3, 4, 5, 16, 19, 22, 23], "around": [3, 4, 19, 22], "shall": [3, 4, 19, 22], "somewher": [3, 4, 16, 19, 22], "insid": [3, 4, 13, 16, 19, 22], "given": [3, 4, 5, 6, 10, 13, 16, 19, 22, 23, 24, 28], "maximum": [3, 4, 6, 16, 19, 22, 24], "distanc": [3, 4, 16, 19, 22], "nm": [3, 4, 16, 19, 22], "future_position_target_ship": [3, 4, 19, 22], "determine_colreg": [3, 4, 18, 19, 22], "alpha": [3, 4, 19, 22], "theta13_criteria": [3, 4, 9, 19, 22, 27], "theta14_criteria": [3, 4, 9, 19, 22, 27], "theta15_criteria": [3, 4, 9, 19, 22, 27], "theta15": [3, 4, 9, 19, 22, 27], "colreg": [3, 4, 19, 22], "base": [3, 4, 9, 10, 15, 19, 22, 27, 28], "toler": [3, 4, 19, 22], "come": [3, 4, 19, 22], "up": [3, 4, 13, 19, 22, 30], "reciproc": [3, 4, 19, 22], "nearli": [3, 4, 19, 22], "when": [3, 4, 13, 19, 22, 30], "ani": [3, 4, 9, 13, 19, 22], "doubt": [3, 4, 19, 22], "assum": [3, 4, 13, 19, 22], "aspect": [3, 4, 19, 22], "limit": [3, 4, 19, 22], "classifi": [3, 4, 19, 22], "22": [3, 4, 19, 22], "5": [3, 4, 16, 19, 22], "deg": [3, 4, 6, 10, 19, 22, 24, 28], "aft": [3, 4, 19, 22], "beam": [3, 4, 19, 22], "classif": [3, 4, 9, 19, 22, 27], "calculate_relative_bear": [3, 4, 18, 19, 22], "position_own_ship": [3, 4, 19, 22], "heading_own_ship": [3, 4, 19, 22], "position_target_ship": [3, 4, 19, 22], "heading_target_ship": [3, 4, 19, 22], "both": [3, 4, 5, 13, 19, 22, 23], "calculate_ship_cours": [3, 4, 18, 19, 22], "waypoint_0": [3, 4, 19, 22], "waypoint_1": [3, 4, 19, 22], "two": [3, 4, 5, 9, 19, 22, 23, 27], "waypoint": [3, 4, 9, 19, 22, 27], "assign_vector_tim": [3, 4, 18, 19, 22], "vector_time_rang": [3, 4, 19, 22], "random": [3, 4, 19, 22], "uniform": [3, 4, 19, 22], "vector_rang": [3, 4, 9, 19, 22, 27], "valu": [3, 4, 19, 22, 27, 30], "vector_tim": [3, 4, 6, 9, 16, 19, 22, 24, 27], "min": [3, 4, 6, 19, 22, 24], "assign_speed_to_target_ship": [3, 4, 18, 19, 22], "encounter_typ": [3, 4, 19, 22], "own_ship_spe": [3, 4, 19, 22], "min_target_ship_spe": [3, 4, 19, 22], "relative_speed_set": [3, 4, 19, 22], "encounterrelativespe": [3, 4, 9, 18, 19, 22, 27], "depend": [3, 4, 19, 22], "target_ship_spe": [3, 4, 19, 22], "assign_beta": [3, 4, 18, 19, 22], "update_position_data_target_ship": [3, 4, 18, 19, 22], "updat": [3, 4, 5, 6, 13, 19, 22, 23, 24], "includ": [3, 4, 5, 13, 19, 22, 23], "latitud": [3, 4, 5, 9, 19, 22, 23, 27], "longitud": [3, 4, 5, 9, 19, 22, 23, 27], "update_position_data_own_ship": [3, 4, 18, 19, 22], "delta_tim": [3, 4, 10, 19, 22, 28], "delta": [3, 4, 10, 19, 22, 28], "now": [3, 4, 10, 13, 19, 22, 28], "new": [3, 4, 10, 13, 19, 22, 28], "being": [3, 4, 10, 19, 22, 28], "decide_target_ship": [3, 4, 18, 19, 22], "pick": [3, 4, 19, 22], "info": [3, 4, 16, 19, 22], "size": [3, 4, 19, 22], "etc": [3, 4, 8, 15, 19, 22, 26], "top": [4, 19], "level": [4, 19], "traffic": [4, 6, 7, 8, 9, 11, 13, 16, 17, 19, 24, 25, 26, 27, 29], "knot_2_m_pr_min": [4, 10, 18, 19, 28], "speed_in_knot": [4, 10, 19, 28], "convert": [4, 10, 19, 28], "meter": [4, 5, 10, 16, 19, 23, 28], "pr": [4, 10, 19, 28], "speed_in_m_pr_min": [4, 10, 19, 28], "m_pr_min_2_knot": [4, 10, 18, 19, 28], "second": [4, 10, 19, 28], "m2nm": [4, 10, 18, 19, 28], "length_in_m": [4, 10, 19, 28], "nautic": [4, 10, 19, 28], "mile": [4, 10, 19, 28], "length_in_nm": [4, 10, 19, 28], "nm_2_m": [4, 10, 18, 19, 28], "deg_2_rad": [4, 10, 18, 19, 28], "angle_in_degre": [4, 10, 19, 28], "angl": [4, 5, 10, 19, 23, 28], "radian": [4, 10, 19, 28], "rad_2_deg": [4, 10, 18, 19, 28], "angle_in_radian": [4, 10, 19, 28], "convert_angle_minus_180_to_180_to_0_to_360": [4, 10, 18, 19, 28], "angle_180": [4, 10, 19, 28], "region": [4, 10, 19, 28], "180": [4, 10, 19, 28], "360": [4, 10, 19, 28], "angle_360": [4, 10, 19, 28], "convert_angle_0_to_360_to_minus_180_to_180": [4, 10, 18, 19, 28], "calculate_position_at_certain_tim": [4, 10, 18, 19, 28], "constand": [4, 10, 19, 28], "flat2llh": [4, 5, 18, 19, 23], "x_n": [4, 5, 19, 23], "y_n": [4, 5, 19, 23], "lat_0": [4, 5, 19, 23], "lon_0": [4, 5, 19, 23], "z_n": [4, 5, 19, 23], "height_ref": [4, 5, 19, 23], "comput": [4, 5, 19, 23], "lon": [4, 5, 19, 23], "rad": [4, 5, 19, 23], "lat": [4, 5, 19, 23], "height": [4, 5, 9, 19, 23, 27], "h": [4, 5, 19, 23], "ned": [4, 5, 19, 23], "coordin": [4, 5, 19, 23], "xn": [4, 5, 19, 23], "yn": [4, 5, 19, 23], "zn": [4, 5, 19, 23], "method": [4, 5, 17, 19, 23], "taken": [4, 5, 19, 23], "mss": [4, 5, 19, 23], "marin": [4, 5, 19, 23], "system": [4, 5, 13, 15, 19, 23], "simul": [4, 5, 19, 23], "toolbox": [4, 5, 19, 23], "matlab": [4, 5, 19, 23], "simulink": [4, 5, 19, 23], "librari": [4, 5, 19, 23], "flat": [4, 5, 19, 23], "earth": [4, 5, 19, 23], "wg": [4, 5, 19, 23], "84": [4, 5, 19, 23], "ellipsoid": [4, 5, 19, 23], "origin": [4, 5, 13, 19, 23], "locat": [4, 5, 16, 19, 23], "h_ref": [4, 5, 19, 23], "abov": [4, 5, 16, 19, 23], "surfac": [4, 5, 19, 23], "ar": [4, 5, 7, 10, 13, 16, 19, 23, 25, 28, 30], "upward": [4, 5, 19, 23], "while": [4, 5, 16, 19, 23], "downward": [4, 5, 19, 23], "author": [4, 5, 15, 19, 23], "thor": [4, 5, 19, 23], "fossen": [4, 5, 19, 23], "date": [4, 5, 19, 23], "20": [4, 5, 16, 19, 23], "juli": [4, 5, 19, 23], "2018": [4, 5, 19, 23], "revis": [4, 5, 19, 23], "2023": [4, 5, 15, 19, 23], "02": [4, 5, 19, 23], "04": [4, 5, 19, 23], "formula": [4, 5, 19, 23], "down": [4, 5, 19, 23], "llh2flat": [4, 5, 18, 19, 23], "elipsoid": [4, 5, 19, 23], "ssa": [4, 5, 18, 19, 23], "smallest": [4, 5, 19, 23], "sign": [4, 5, 19, 23], "differ": [4, 5, 7, 8, 19, 23, 25, 26, 30], "map": [4, 5, 6, 19, 23, 24, 27], "pi": [4, 5, 19, 23], "09": [4, 5, 19, 23], "21": [4, 5, 19, 23], "smallest_angl": [4, 5, 19, 23], "write_traffic_situations_to_json_fil": [4, 11, 18, 19, 29], "write_fold": [4, 11, 19, 29], "write": [4, 11, 19, 29, 30], "json": [4, 11, 16, 19, 29, 30], "file": [4, 7, 8, 11, 13, 15, 19, 25, 26, 29, 30], "traffic_situ": [4, 6, 8, 11, 19, 24, 26, 29], "written": [4, 11, 15, 19, 29], "folder": [4, 7, 8, 11, 13, 19, 25, 26, 29, 30], "where": [4, 7, 8, 11, 16, 19, 25, 26, 29, 30], "plot": [4, 6, 15, 16, 19, 24], "more": [4, 6, 7, 8, 13, 16, 19, 24, 25, 26, 30], "figur": [4, 6, 19, 24, 30], "number": [4, 6, 8, 19, 24, 26, 30], "column": [4, 6, 19, 24, 30], "each": [4, 6, 19, 24], "plot_specific_traffic_situ": [4, 6, 18, 19, 24], "situation_numb": [4, 6, 19, 24], "specif": [4, 6, 9, 19, 24, 27, 30], "read_situation_fil": [4, 7, 18, 19, 25], "read": [4, 7, 19, 25], "read_own_ship_fil": [4, 7, 18, 19, 25], "read_target_ship_fil": [4, 7, 18, 19, 25], "read_encounter_settings_fil": [4, 7, 18, 19, 25], "It": [5, 23], "model": [5, 23, 27], "underwat": [5, 23], "vehicl": [5, 23], "unman": [5, 23], "structur": [5, 15, 23], "guidanc": [5, 23], "navig": [5, 23], "control": [5, 23], "gnc": [5, 23], "block": [5, 23], "real": [5, 23], "algorithm": [5, 23], "describ": [5, 8, 15, 16, 19, 23, 26], "t": [5, 17, 23, 30], "2021": [5, 23], "handbook": [5, 23], "craft": [5, 23], "hydrodynam": [5, 23], "motion": [5, 16, 23], "2nd": [5, 23], "edit": [5, 23], "wilei": [5, 23], "isbn": [5, 23], "13": [5, 23], "978": [5, 23], "1119575054": [5, 23], "have": [5, 13, 17, 23], "been": [5, 23], "re": [5, 13, 23], "implement": [5, 23], "python": [5, 13, 17, 23], "below": [5, 23], "prepar": [6, 24], "calculate_vector_arrow": [6, 18, 19, 24], "direct": [6, 24], "vector_length": [6, 24], "arrow": [6, 16, 24], "arrow_point": [6, 24], "polygon": [6, 24], "calculate_ship_outlin": [6, 18, 19, 24], "ship_length": [6, 24], "100": [6, 24], "ship_width": [6, 24], "15": [6, 16, 24], "outlin": [6, 24], "width": [6, 9, 19, 24, 27], "ship_outline_point": [6, 24], "add_ship_to_map": [6, 18, 19, 24], "map_plot": [6, 24], "folium": 6, "color": [6, 24], "str": [6, 9, 24, 27], "black": [6, 24], "add": [6, 13, 24], "instanc": [6, 24], "find_max_value_for_plot": [6, 18, 19, 24], "max_valu": [6, 24], "deviat": [6, 24], "add_ship_to_plot": [6, 18, 19, 24], "ax": [6, 24], "matplotlib": 6, "pyplot": 6, "axi": [6, 24], "need": [7, 25, 30], "build": [7, 25], "generate_traffic_situ": [8, 18, 19, 26], "input": [8, 15, 19, 26, 30], "specifi": [8, 16, 19, 26, 30], "One": [8, 19, 26], "domain": [9, 27], "pydant": [9, 27], "basemodel": [9, 27], "attribut": [9, 27], "pose": [9, 18, 19, 27], "shiptyp": [9, 18, 19, 27], "kwd": 9, "enum": [9, 27], "enumer": [9, 27], "passenger_roro": [9, 19, 27], "passeng": [9, 27], "ro": [9, 27], "cargo": [9, 27], "general_cargo": [9, 19, 27], "fish": [9, 19, 27], "militari": [9, 19, 27], "op": [9, 27], "staticshipdata": [9, 18, 19, 27], "static": [9, 19, 27], "speed_max": [9, 19, 27], "mmsi": [9, 19, 27], "name": [9, 13, 19, 27], "ship_typ": [9, 19, 27], "start_pos": [9, 19, 27], "overtaking_stand_on": [9, 19, 27], "overtaking_give_wai": [9, 19, 27], "head_on": [9, 19, 27], "crossing_give_wai": [9, 19, 27], "crossing_stand_on": [9, 19, 27], "no_risk_collis": [9, 19, 27], "noriskcollis": [9, 27], "relative_spe": [9, 16, 19, 27], "titl": [9, 16, 19, 27], "input_file_nam": [9, 19, 27], "common_vector": [9, 16, 19, 27], "num_situ": [9, 16, 19, 27], "encounterclassif": [9, 18, 19, 27], "evolve_tim": [9, 19, 27], "sever": [10, 16, 28], "other": [10, 13, 28], "clean": [11, 29], "tom": 12, "arn": 12, "pedersen": 12, "dnv": [12, 13, 17], "com": [12, 13, 17], "grund": 12, "l\u00f8voll": 12, "stephani": 12, "kemna": 12, "welcom": 13, "thei": 13, "greatli": 13, "appreci": 13, "everi": 13, "littl": 13, "bit": 13, "help": [13, 30], "credit": 13, "alwai": [13, 17], "you": [13, 16, 17, 30], "can": [13, 16, 17, 30], "http": [13, 17], "github": [13, 17], "opensourc": [13, 17], "issu": 13, "pleas": 13, "your": [13, 17], "oper": 13, "version": 13, "conda": 13, "addit": 13, "detail": 13, "local": 13, "setup": [13, 17], "might": 13, "troubleshoot": 13, "step": 13, "reproduc": 13, "look": 13, "through": [13, 17], "anyth": 13, "tag": 13, "want": 13, "open": [13, 30], "whoever": 13, "enhanc": 13, "could": 13, "whether": 13, "offici": 13, "doc": 13, "docstr": 13, "even": 13, "web": 13, "blog": 13, "post": 13, "articl": 13, "best": 13, "send": 13, "propos": 13, "explain": 13, "how": [13, 15], "would": 13, "work": [13, 15], "keep": 13, "scope": 13, "narrow": 13, "possibl": 13, "make": 13, "easier": 13, "rememb": 13, "volunt": 13, "driven": 13, "project": [13, 30], "readi": 13, "here": 13, "develop": 13, "clone": [13, 17], "repo": 13, "instal": [13, 15], "copi": [13, 17], "pyenv": 13, "environ": 13, "branch": 13, "git": [13, 17], "checkout": 13, "b": 13, "bugfix": 13, "chang": 13, "done": 13, "pass": 13, "flake8": 13, "test": [13, 16], "tox": 13, "config": [13, 27], "ini": 13, "src": [13, 16], "pytest": 13, "poetri": 13, "dev": 13, "alreadi": 13, "note": [13, 30], "3": [13, 16, 30], "10": [13, 16, 30], "11": [13, 15], "them": 13, "avail": 13, "all": [13, 16], "onli": 13, "skip": 13, "non": 13, "support": 13, "most": [13, 17], "case": 13, "manag": 13, "necessari": 13, "rehash": 13, "multipl": [13, 16], "env": 13, "py310": 13, "py311": 13, "virtualenv": 13, "activ": 13, "go": 13, "do": 13, "vscode": 13, "via": 13, "view": 13, "select": 13, "commit": 13, "push": 13, "descript": 13, "meet": [13, 16], "function": [13, 19, 20, 22, 24, 25, 26, 28, 29], "put": 13, "readm": 13, "md": 13, "To": [13, 17, 30], "subset": 13, "test_trafficgen": 13, "A": [13, 15, 30], "remind": 13, "maintain": 13, "sure": 13, "histori": [13, 15], "rst": 13, "Then": 13, "bump2vers": 13, "patch": 13, "major": 13, "minor": 13, "first": 14, "releas": [14, 15], "pypi": 14, "tool": [15, 30], "verifi": 15, "automat": 15, "collis": 15, "ground": 15, "avoid": 15, "paramet": [15, 16], "inspect": 15, "paper": [15, 16], "background": 15, "stabl": 15, "usag": 15, "baselin": 15, "contribut": 15, "get": 15, "pull": 15, "request": [15, 16], "guidelin": 15, "tip": 15, "deploi": 15, "primari": 15, "tester": 15, "08": 15, "api": 15, "index": 15, "modul": [15, 18, 19], "search": 15, "complet": 16, "ho": 16, "2": [16, 30], "For": 16, "radar": [16, 30], "togeth": 16, "displai": [16, 30], "e": [16, 30], "g": [16, 30], "common": 16, "respect": [16, 30], "global": 16, "encounter_set": [16, 30], "fulli": 16, "shown": 16, "desid": 16, "less": 16, "demonstr": 16, "mandatori": 16, "either": [16, 17], "shop": 16, "mean": 16, "higher": 16, "than": 16, "built": 16, "see": 16, "link": 16, "introduct": 16, "At": 16, "center": 16, "necessarili": 16, "closest": 16, "approach": 16, "ot_gw": 16, "7": 16, "termin": 17, "pip": 17, "prefer": 17, "recent": 17, "don": 17, "guid": 17, "process": 17, "download": 17, "public": 17, "repositori": 17, "onc": 17, "py": 17, "submodul": 18, "model_config": [19, 27], "model_field": [19, 27], "class": 27, "classvar": 27, "configdict": 27, "dictionari": 27, "conform": 27, "fieldinfo": 27, "annot": 27, "union": 27, "nonetyp": 27, "requir": 27, "metadata": 27, "field": 27, "replac": 27, "__fields__": 27, "v1": 27, "qualnam": 27, "boundari": 27, "default": [27, 30], "import": 30, "take": 30, "baseline_situations_input": 30, "c": 30, "integ": 30, "6": 30, "show": 30, "messag": 30, "exit": 30, "cover": 30, "combin": 30, "total": 30, "55": 30, "pop": 30, "window": 30, "colum": 30, "per": 30, "browser": 30, "tab": 30, "openstreetmap": 30, "overlai": 30, "within": 30, "rang": 30, "12": 30}, "objects": {"": [[19, 0, 0, "-", "trafficgen"]], "trafficgen": [[19, 1, 1, "", "assign_beta"], [19, 1, 1, "", "assign_future_position_to_target_ship"], [19, 1, 1, "", "assign_speed_to_target_ship"], [19, 1, 1, "", "assign_vector_time"], [19, 1, 1, "", "calculate_position_at_certain_time"], [19, 1, 1, "", "calculate_relative_bearing"], [19, 1, 1, "", "calculate_ship_course"], [19, 1, 1, "", "check_encounter_evolvement"], [20, 0, 0, "-", "check_land_crossing"], [21, 0, 0, "-", "cli"], [19, 1, 1, "", "convert_angle_0_to_360_to_minus_180_to_180"], [19, 1, 1, "", "convert_angle_minus_180_to_180_to_0_to_360"], [19, 1, 1, "", "decide_target_ship"], [19, 1, 1, "", "deg_2_rad"], [19, 1, 1, "", "determine_colreg"], [22, 0, 0, "-", "encounter"], [19, 1, 1, "", "find_start_position_target_ship"], [19, 1, 1, "", "flat2llh"], [19, 1, 1, "", "generate_encounter"], [19, 1, 1, "", "generate_traffic_situations"], [19, 1, 1, "", "knot_2_m_pr_min"], [19, 1, 1, "", "llh2flat"], [19, 1, 1, "", "m2nm"], [19, 1, 1, "", "m_pr_min_2_knot"], [23, 0, 0, "-", "marine_system_simulator"], [19, 1, 1, "", "nm_2_m"], [19, 1, 1, "", "path_crosses_land"], [19, 1, 1, "", "plot_specific_traffic_situation"], [24, 0, 0, "-", "plot_traffic_situation"], [19, 1, 1, "", "plot_traffic_situations"], [19, 1, 1, "", "rad_2_deg"], [19, 1, 1, "", "read_encounter_settings_file"], [25, 0, 0, "-", "read_files"], [19, 1, 1, "", "read_own_ship_file"], [19, 1, 1, "", "read_situation_files"], [19, 1, 1, "", "read_target_ship_files"], [26, 0, 0, "-", "ship_traffic_generator"], [19, 1, 1, "", "ssa"], [27, 0, 0, "-", "types"], [19, 1, 1, "", "update_position_data_own_ship"], [19, 1, 1, "", "update_position_data_target_ship"], [28, 0, 0, "-", "utils"], [29, 0, 0, "-", "write_traffic_situation_to_file"], [19, 1, 1, "", "write_traffic_situations_to_json_file"]], "trafficgen.check_land_crossing": [[20, 1, 1, "", "path_crosses_land"]], "trafficgen.cli": [[2, 2, 1, "", "_"], [2, 2, 1, "", "default_data_path"], [2, 1, 1, "", "gen_situation"], [2, 2, 1, "", "logger"], [2, 1, 1, "", "main"], [2, 2, 1, "", "output_folder"], [2, 2, 1, "", "own_ship_file"], [2, 2, 1, "", "settings_file"], [2, 2, 1, "", "situation_folder"], [2, 2, 1, "", "target_ship_folder"]], "trafficgen.encounter": [[22, 1, 1, "", "assign_beta"], [22, 1, 1, "", "assign_future_position_to_target_ship"], [22, 1, 1, "", "assign_speed_to_target_ship"], [22, 1, 1, "", "assign_vector_time"], [22, 1, 1, "", "calculate_min_vector_length_target_ship"], [22, 1, 1, "", "calculate_relative_bearing"], [22, 1, 1, "", "calculate_ship_course"], [22, 1, 1, "", "check_encounter_evolvement"], [22, 1, 1, "", "decide_target_ship"], [22, 1, 1, "", "determine_colreg"], [22, 1, 1, "", "find_start_position_target_ship"], [22, 1, 1, "", "generate_encounter"], [22, 1, 1, "", "update_position_data_own_ship"], [22, 1, 1, "", "update_position_data_target_ship"]], "trafficgen.marine_system_simulator": [[23, 1, 1, "", "flat2llh"], [23, 1, 1, "", "llh2flat"], [23, 1, 1, "", "ssa"]], "trafficgen.plot_traffic_situation": [[24, 1, 1, "", "add_ship_to_map"], [24, 1, 1, "", "add_ship_to_plot"], [24, 1, 1, "", "calculate_ship_outline"], [24, 1, 1, "", "calculate_vector_arrow"], [24, 1, 1, "", "find_max_value_for_plot"], [24, 1, 1, "", "plot_specific_traffic_situation"], [24, 1, 1, "", "plot_traffic_situations"]], "trafficgen.read_files": [[25, 1, 1, "", "read_encounter_settings_file"], [25, 1, 1, "", "read_own_ship_file"], [25, 1, 1, "", "read_situation_files"], [25, 1, 1, "", "read_target_ship_files"]], "trafficgen.ship_traffic_generator": [[26, 1, 1, "", "generate_traffic_situations"]], "trafficgen.types": [[27, 3, 1, "", "Encounter"], [27, 3, 1, "", "EncounterClassification"], [27, 3, 1, "", "EncounterRelativeSpeed"], [27, 3, 1, "", "EncounterSettings"], [27, 3, 1, "", "EncounterType"], [27, 3, 1, "", "Pose"], [27, 3, 1, "", "Position"], [27, 3, 1, "", "Ship"], [27, 3, 1, "", "ShipType"], [27, 3, 1, "", "Situation"], [27, 3, 1, "", "StaticShipData"], [27, 3, 1, "", "TargetShip"]], "trafficgen.types.Encounter": [[27, 4, 1, "", "beta"], [27, 4, 1, "", "desired_encounter_type"], [27, 4, 1, "", "model_config"], [27, 4, 1, "", "model_fields"], [27, 4, 1, "", "relative_speed"], [27, 4, 1, "", "vector_time"]], "trafficgen.types.EncounterClassification": [[27, 4, 1, "", "model_config"], [27, 4, 1, "", "model_fields"], [27, 4, 1, "", "theta13_criteria"], [27, 4, 1, "", "theta14_criteria"], [27, 4, 1, "", "theta15"], [27, 4, 1, "", "theta15_criteria"]], "trafficgen.types.EncounterRelativeSpeed": [[27, 4, 1, "", "crossing_give_way"], [27, 4, 1, "", "crossing_stand_on"], [27, 4, 1, "", "head_on"], [27, 4, 1, "", "model_config"], [27, 4, 1, "", "model_fields"], [27, 4, 1, "", "overtaking_give_way"], [27, 4, 1, "", "overtaking_stand_on"]], "trafficgen.types.EncounterSettings": [[27, 4, 1, "", "classification"], [27, 4, 1, "", "evolve_time"], [27, 4, 1, "", "lat_lon_0"], [27, 4, 1, "", "max_meeting_distance"], [27, 4, 1, "", "model_config"], [27, 4, 1, "", "model_fields"], [27, 4, 1, "", "relative_speed"], [27, 4, 1, "", "vector_range"]], "trafficgen.types.EncounterType": [[27, 4, 1, "", "CROSSING_GIVE_WAY"], [27, 4, 1, "", "CROSSING_STAND_ON"], [27, 4, 1, "", "HEAD_ON"], [27, 4, 1, "", "NO_RISK_COLLISION"], [27, 4, 1, "", "OVERTAKING_GIVE_WAY"], [27, 4, 1, "", "OVERTAKING_STAND_ON"]], "trafficgen.types.Pose": [[27, 4, 1, "", "course"], [27, 4, 1, "", "model_config"], [27, 4, 1, "", "model_fields"], [27, 4, 1, "", "position"], [27, 4, 1, "", "speed"]], "trafficgen.types.Position": [[27, 4, 1, "", "east"], [27, 4, 1, "", "latitude"], [27, 4, 1, "", "longitude"], [27, 4, 1, "", "model_config"], [27, 4, 1, "", "model_fields"], [27, 4, 1, "", "north"]], "trafficgen.types.Ship": [[27, 4, 1, "", "model_config"], [27, 4, 1, "", "model_fields"], [27, 4, 1, "", "start_pose"], [27, 4, 1, "", "static"], [27, 4, 1, "", "waypoints"]], "trafficgen.types.ShipType": [[27, 4, 1, "", "FISHING"], [27, 4, 1, "", "GENERAL_CARGO"], [27, 4, 1, "", "MILITARY"], [27, 4, 1, "", "PASSENGER_RORO"]], "trafficgen.types.Situation": [[27, 4, 1, "", "common_vector"], [27, 4, 1, "", "encounter"], [27, 4, 1, "", "input_file_name"], [27, 4, 1, "", "lat_lon_0"], [27, 4, 1, "", "model_config"], [27, 4, 1, "", "model_fields"], [27, 4, 1, "", "num_situations"], [27, 4, 1, "", "own_ship"], [27, 4, 1, "", "target_ship"], [27, 4, 1, "", "title"]], "trafficgen.types.StaticShipData": [[27, 4, 1, "", "height"], [27, 4, 1, "", "length"], [27, 4, 1, "", "mmsi"], [27, 4, 1, "", "model_config"], [27, 4, 1, "", "model_fields"], [27, 4, 1, "", "name"], [27, 4, 1, "", "ship_type"], [27, 4, 1, "", "speed_max"], [27, 4, 1, "", "width"]], "trafficgen.types.TargetShip": [[27, 4, 1, "", "id"], [27, 4, 1, "", "model_config"], [27, 4, 1, "", "model_fields"]], "trafficgen.utils": [[28, 1, 1, "", "calculate_position_at_certain_time"], [28, 1, 1, "", "convert_angle_0_to_360_to_minus_180_to_180"], [28, 1, 1, "", "convert_angle_minus_180_to_180_to_0_to_360"], [28, 1, 1, "", "deg_2_rad"], [28, 1, 1, "", "knot_2_m_pr_min"], [28, 1, 1, "", "m2nm"], [28, 1, 1, "", "m_pr_min_2_knot"], [28, 1, 1, "", "nm_2_m"], [28, 1, 1, "", "rad_2_deg"]], "trafficgen.write_traffic_situation_to_file": [[29, 1, 1, "", "write_traffic_situations_to_json_file"]]}, "objtypes": {"0": "py:module", "1": "py:function", "2": "py:data", "3": "py:class", "4": "py:attribute"}, "objnames": {"0": ["py", "module", "Python module"], "1": ["py", "function", "Python function"], "2": ["py", "data", "Python data"], "3": ["py", "class", "Python class"], "4": ["py", "attribute", "Python attribute"]}, "titleterms": {"api": 0, "refer": 0, "trafficgen": [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29], "check_land_cross": [1, 20], "modul": [1, 2, 3, 5, 6, 7, 8, 9, 10, 11, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29], "content": [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 15], "function": [1, 2, 3, 4, 5, 6, 7, 8, 10, 11], "cli": [2, 21], "attribut": 2, "encount": [3, 22], "submodul": [4, 19], "packag": [4, 19], "marine_system_simul": [5, 23], "plot_traffic_situ": [6, 24], "read_fil": [7, 25], "ship_traffic_gener": [8, 26], "type": [9, 13, 27], "class": 9, "util": [10, 28], "write_traffic_situation_to_fil": [11, 29], "author": 12, "primari": 12, "tester": 12, "contribut": 13, "report": 13, "bug": 13, "fix": 13, "implement": 13, "featur": 13, "write": 13, "document": [13, 15], "submit": 13, "feedback": 13, "get": 13, "start": 13, "pull": 13, "request": 13, "guidelin": 13, "tip": 13, "deploi": 13, "histori": 14, "0": 14, "1": 14, "2023": 14, "11": 14, "08": 14, "welcom": 15, "traffic": [15, 30], "gener": [15, 30], "": 15, "indic": 15, "tabl": 15, "input": 16, "file": 16, "instal": 17, "stabl": 17, "releas": 17, "from": 17, "sourc": 17, "usag": 30, "situat": 30, "baselin": 30, "plot": 30, "all": 30, "individu": 30, "map": 30, "background": 30}, "envversion": {"sphinx.domains.c": 3, "sphinx.domains.changeset": 1, "sphinx.domains.citation": 1, "sphinx.domains.cpp": 9, "sphinx.domains.index": 1, "sphinx.domains.javascript": 3, "sphinx.domains.math": 2, "sphinx.domains.python": 4, "sphinx.domains.rst": 2, "sphinx.domains.std": 2, "sphinx.ext.viewcode": 1, "sphinx": 60}, "alltitles": {"API Reference": [[0, "api-reference"]], "trafficgen.check_land_crossing": [[1, "module-trafficgen.check_land_crossing"]], "Module Contents": [[1, "module-contents"], [2, "module-contents"], [3, "module-contents"], [5, "module-contents"], [6, "module-contents"], [7, "module-contents"], [8, "module-contents"], [9, "module-contents"], [10, "module-contents"], [11, "module-contents"]], "Functions": [[1, "functions"], [2, "functions"], [3, "functions"], [4, "functions"], [5, "functions"], [6, "functions"], [7, "functions"], [8, "functions"], [10, "functions"], [11, "functions"]], "trafficgen.cli": [[2, "module-trafficgen.cli"]], "Attributes": [[2, "attributes"]], "trafficgen.encounter": [[3, "module-trafficgen.encounter"]], "trafficgen": [[4, "module-trafficgen"], [18, "trafficgen"]], "Submodules": [[4, "submodules"], [19, "submodules"]], "Package Contents": [[4, "package-contents"]], "trafficgen.marine_system_simulator": [[5, "module-trafficgen.marine_system_simulator"]], "trafficgen.plot_traffic_situation": [[6, "module-trafficgen.plot_traffic_situation"]], "trafficgen.read_files": [[7, "module-trafficgen.read_files"]], "trafficgen.ship_traffic_generator": [[8, "module-trafficgen.ship_traffic_generator"]], "trafficgen.types": [[9, "module-trafficgen.types"]], "Classes": [[9, "classes"]], "trafficgen.utils": [[10, "module-trafficgen.utils"]], "trafficgen.write_traffic_situation_to_file": [[11, "module-trafficgen.write_traffic_situation_to_file"]], "Authors": [[12, "authors"]], "Primary author": [[12, "primary-author"]], "Testers": [[12, "testers"]], "Contributing": [[13, "contributing"]], "Types of Contributions": [[13, "types-of-contributions"]], "Report Bugs": [[13, "report-bugs"]], "Fix Bugs": [[13, "fix-bugs"]], "Implement Features": [[13, "implement-features"]], "Write Documentation": [[13, "write-documentation"]], "Submit Feedback": [[13, "submit-feedback"]], "Get Started!": [[13, "get-started"]], "Pull Request Guidelines": [[13, "pull-request-guidelines"]], "Tips": [[13, "tips"]], "Deploying": [[13, "deploying"]], "History": [[14, "history"]], "0.1.0 (2023-11-08)": [[14, "id1"]], "Welcome to Traffic Generator\u2019s documentation!": [[15, "welcome-to-traffic-generator-s-documentation"]], "Contents:": [[15, null]], "Indices and tables": [[15, "indices-and-tables"]], "Input files": [[16, "input-files"]], "Installation": [[17, "installation"]], "Stable release": [[17, "stable-release"]], "From sources": [[17, "from-sources"]], "trafficgen package": [[19, "module-trafficgen"]], "trafficgen.check_land_crossing module": [[20, "module-trafficgen.check_land_crossing"]], "trafficgen.cli module": [[21, "module-trafficgen.cli"]], "trafficgen.encounter module": [[22, "module-trafficgen.encounter"]], "trafficgen.marine_system_simulator module": [[23, "module-trafficgen.marine_system_simulator"]], "trafficgen.plot_traffic_situation module": [[24, "module-trafficgen.plot_traffic_situation"]], "trafficgen.read_files module": [[25, "module-trafficgen.read_files"]], "trafficgen.ship_traffic_generator module": [[26, "module-trafficgen.ship_traffic_generator"]], "trafficgen.types module": [[27, "module-trafficgen.types"]], "trafficgen.utils module": [[28, "module-trafficgen.utils"]], "trafficgen.write_traffic_situation_to_file module": [[29, "module-trafficgen.write_traffic_situation_to_file"]], "Usage": [[30, "usage"]], "Situations": [[30, "situations"]], "Baseline situations": [[30, "baseline-situations"]], "Plotting": [[30, "plotting"]], "Plotting all generated traffic situations": [[30, "plotting-all-generated-traffic-situations"]], "Individual plots with map background": [[30, "individual-plots-with-map-background"]]}, "indexentries": {"module": [[1, "module-trafficgen.check_land_crossing"], [2, "module-trafficgen.cli"], [3, "module-trafficgen.encounter"], [4, "module-trafficgen"], [5, "module-trafficgen.marine_system_simulator"], [6, "module-trafficgen.plot_traffic_situation"], [7, "module-trafficgen.read_files"], [8, "module-trafficgen.ship_traffic_generator"], [9, "module-trafficgen.types"], [10, "module-trafficgen.utils"], [11, "module-trafficgen.write_traffic_situation_to_file"], [19, "module-trafficgen"], [20, "module-trafficgen.check_land_crossing"], [21, "module-trafficgen.cli"], [22, "module-trafficgen.encounter"], [23, "module-trafficgen.marine_system_simulator"], [24, "module-trafficgen.plot_traffic_situation"], [25, "module-trafficgen.read_files"], [26, "module-trafficgen.ship_traffic_generator"], [27, "module-trafficgen.types"], [28, "module-trafficgen.utils"], [29, "module-trafficgen.write_traffic_situation_to_file"]], "path_crosses_land() (in module trafficgen.check_land_crossing)": [[1, "trafficgen.check_land_crossing.path_crosses_land"], [20, "trafficgen.check_land_crossing.path_crosses_land"]], "trafficgen.check_land_crossing": [[1, "module-trafficgen.check_land_crossing"], [20, "module-trafficgen.check_land_crossing"]], "_ (in module trafficgen.cli)": [[2, "trafficgen.cli._"]], "default_data_path (in module trafficgen.cli)": [[2, "trafficgen.cli.default_data_path"]], "gen_situation() (in module trafficgen.cli)": [[2, "trafficgen.cli.gen_situation"]], "logger (in module trafficgen.cli)": [[2, "trafficgen.cli.logger"]], "main() (in module trafficgen.cli)": [[2, "trafficgen.cli.main"]], "output_folder (in module trafficgen.cli)": [[2, "trafficgen.cli.output_folder"]], "own_ship_file (in module trafficgen.cli)": [[2, "trafficgen.cli.own_ship_file"]], "settings_file (in module trafficgen.cli)": [[2, "trafficgen.cli.settings_file"]], "situation_folder (in module trafficgen.cli)": [[2, "trafficgen.cli.situation_folder"]], "target_ship_folder (in module trafficgen.cli)": [[2, "trafficgen.cli.target_ship_folder"]], "trafficgen.cli": [[2, "module-trafficgen.cli"], [21, "module-trafficgen.cli"]], "assign_beta() (in module trafficgen.encounter)": [[3, "trafficgen.encounter.assign_beta"], [22, "trafficgen.encounter.assign_beta"]], "assign_future_position_to_target_ship() (in module trafficgen.encounter)": [[3, "trafficgen.encounter.assign_future_position_to_target_ship"], [22, "trafficgen.encounter.assign_future_position_to_target_ship"]], "assign_speed_to_target_ship() (in module trafficgen.encounter)": [[3, "trafficgen.encounter.assign_speed_to_target_ship"], [22, "trafficgen.encounter.assign_speed_to_target_ship"]], "assign_vector_time() (in module trafficgen.encounter)": [[3, "trafficgen.encounter.assign_vector_time"], [22, "trafficgen.encounter.assign_vector_time"]], "calculate_min_vector_length_target_ship() (in module trafficgen.encounter)": [[3, "trafficgen.encounter.calculate_min_vector_length_target_ship"], [22, "trafficgen.encounter.calculate_min_vector_length_target_ship"]], "calculate_relative_bearing() (in module trafficgen.encounter)": [[3, "trafficgen.encounter.calculate_relative_bearing"], [22, "trafficgen.encounter.calculate_relative_bearing"]], "calculate_ship_course() (in module trafficgen.encounter)": [[3, "trafficgen.encounter.calculate_ship_course"], [22, "trafficgen.encounter.calculate_ship_course"]], "check_encounter_evolvement() (in module trafficgen.encounter)": [[3, "trafficgen.encounter.check_encounter_evolvement"], [22, "trafficgen.encounter.check_encounter_evolvement"]], "decide_target_ship() (in module trafficgen.encounter)": [[3, "trafficgen.encounter.decide_target_ship"], [22, "trafficgen.encounter.decide_target_ship"]], "determine_colreg() (in module trafficgen.encounter)": [[3, "trafficgen.encounter.determine_colreg"], [22, "trafficgen.encounter.determine_colreg"]], "find_start_position_target_ship() (in module trafficgen.encounter)": [[3, "trafficgen.encounter.find_start_position_target_ship"], [22, "trafficgen.encounter.find_start_position_target_ship"]], "generate_encounter() (in module trafficgen.encounter)": [[3, "trafficgen.encounter.generate_encounter"], [22, "trafficgen.encounter.generate_encounter"]], "trafficgen.encounter": [[3, "module-trafficgen.encounter"], [22, "module-trafficgen.encounter"]], "update_position_data_own_ship() (in module trafficgen.encounter)": [[3, "trafficgen.encounter.update_position_data_own_ship"], [22, "trafficgen.encounter.update_position_data_own_ship"]], "update_position_data_target_ship() (in module trafficgen.encounter)": [[3, "trafficgen.encounter.update_position_data_target_ship"], [22, "trafficgen.encounter.update_position_data_target_ship"]], "assign_beta() (in module trafficgen)": [[4, "trafficgen.assign_beta"], [19, "trafficgen.assign_beta"]], "assign_future_position_to_target_ship() (in module trafficgen)": [[4, "trafficgen.assign_future_position_to_target_ship"], [19, "trafficgen.assign_future_position_to_target_ship"]], "assign_speed_to_target_ship() (in module trafficgen)": [[4, "trafficgen.assign_speed_to_target_ship"], [19, "trafficgen.assign_speed_to_target_ship"]], "assign_vector_time() (in module trafficgen)": [[4, "trafficgen.assign_vector_time"], [19, "trafficgen.assign_vector_time"]], "calculate_position_at_certain_time() (in module trafficgen)": [[4, "trafficgen.calculate_position_at_certain_time"], [19, "trafficgen.calculate_position_at_certain_time"]], "calculate_relative_bearing() (in module trafficgen)": [[4, "trafficgen.calculate_relative_bearing"], [19, "trafficgen.calculate_relative_bearing"]], "calculate_ship_course() (in module trafficgen)": [[4, "trafficgen.calculate_ship_course"], [19, "trafficgen.calculate_ship_course"]], "check_encounter_evolvement() (in module trafficgen)": [[4, "trafficgen.check_encounter_evolvement"], [19, "trafficgen.check_encounter_evolvement"]], "convert_angle_0_to_360_to_minus_180_to_180() (in module trafficgen)": [[4, "trafficgen.convert_angle_0_to_360_to_minus_180_to_180"], [19, "trafficgen.convert_angle_0_to_360_to_minus_180_to_180"]], "convert_angle_minus_180_to_180_to_0_to_360() (in module trafficgen)": [[4, "trafficgen.convert_angle_minus_180_to_180_to_0_to_360"], [19, "trafficgen.convert_angle_minus_180_to_180_to_0_to_360"]], "decide_target_ship() (in module trafficgen)": [[4, "trafficgen.decide_target_ship"], [19, "trafficgen.decide_target_ship"]], "deg_2_rad() (in module trafficgen)": [[4, "trafficgen.deg_2_rad"], [19, "trafficgen.deg_2_rad"]], "determine_colreg() (in module trafficgen)": [[4, "trafficgen.determine_colreg"], [19, "trafficgen.determine_colreg"]], "find_start_position_target_ship() (in module trafficgen)": [[4, "trafficgen.find_start_position_target_ship"], [19, "trafficgen.find_start_position_target_ship"]], "flat2llh() (in module trafficgen)": [[4, "trafficgen.flat2llh"], [19, "trafficgen.flat2llh"]], "generate_encounter() (in module trafficgen)": [[4, "trafficgen.generate_encounter"], [19, "trafficgen.generate_encounter"]], "knot_2_m_pr_min() (in module trafficgen)": [[4, "trafficgen.knot_2_m_pr_min"], [19, "trafficgen.knot_2_m_pr_min"]], "llh2flat() (in module trafficgen)": [[4, "trafficgen.llh2flat"], [19, "trafficgen.llh2flat"]], "m2nm() (in module trafficgen)": [[4, "trafficgen.m2nm"], [19, "trafficgen.m2nm"]], "m_pr_min_2_knot() (in module trafficgen)": [[4, "trafficgen.m_pr_min_2_knot"], [19, "trafficgen.m_pr_min_2_knot"]], "nm_2_m() (in module trafficgen)": [[4, "trafficgen.nm_2_m"], [19, "trafficgen.nm_2_m"]], "path_crosses_land() (in module trafficgen)": [[4, "trafficgen.path_crosses_land"], [19, "trafficgen.path_crosses_land"]], "plot_specific_traffic_situation() (in module trafficgen)": [[4, "trafficgen.plot_specific_traffic_situation"], [19, "trafficgen.plot_specific_traffic_situation"]], "plot_traffic_situations() (in module trafficgen)": [[4, "trafficgen.plot_traffic_situations"], [19, "trafficgen.plot_traffic_situations"]], "rad_2_deg() (in module trafficgen)": [[4, "trafficgen.rad_2_deg"], [19, "trafficgen.rad_2_deg"]], "read_encounter_settings_file() (in module trafficgen)": [[4, "trafficgen.read_encounter_settings_file"], [19, "trafficgen.read_encounter_settings_file"]], "read_own_ship_file() (in module trafficgen)": [[4, "trafficgen.read_own_ship_file"], [19, "trafficgen.read_own_ship_file"]], "read_situation_files() (in module trafficgen)": [[4, "trafficgen.read_situation_files"], [19, "trafficgen.read_situation_files"]], "read_target_ship_files() (in module trafficgen)": [[4, "trafficgen.read_target_ship_files"], [19, "trafficgen.read_target_ship_files"]], "ssa() (in module trafficgen)": [[4, "trafficgen.ssa"], [19, "trafficgen.ssa"]], "trafficgen": [[4, "module-trafficgen"], [19, "module-trafficgen"]], "update_position_data_own_ship() (in module trafficgen)": [[4, "trafficgen.update_position_data_own_ship"], [19, "trafficgen.update_position_data_own_ship"]], "update_position_data_target_ship() (in module trafficgen)": [[4, "trafficgen.update_position_data_target_ship"], [19, "trafficgen.update_position_data_target_ship"]], "write_traffic_situations_to_json_file() (in module trafficgen)": [[4, "trafficgen.write_traffic_situations_to_json_file"], [19, "trafficgen.write_traffic_situations_to_json_file"]], "flat2llh() (in module trafficgen.marine_system_simulator)": [[5, "trafficgen.marine_system_simulator.flat2llh"], [23, "trafficgen.marine_system_simulator.flat2llh"]], "llh2flat() (in module trafficgen.marine_system_simulator)": [[5, "trafficgen.marine_system_simulator.llh2flat"], [23, "trafficgen.marine_system_simulator.llh2flat"]], "ssa() (in module trafficgen.marine_system_simulator)": [[5, "trafficgen.marine_system_simulator.ssa"], [23, "trafficgen.marine_system_simulator.ssa"]], "trafficgen.marine_system_simulator": [[5, "module-trafficgen.marine_system_simulator"], [23, "module-trafficgen.marine_system_simulator"]], "add_ship_to_map() (in module trafficgen.plot_traffic_situation)": [[6, "trafficgen.plot_traffic_situation.add_ship_to_map"], [24, "trafficgen.plot_traffic_situation.add_ship_to_map"]], "add_ship_to_plot() (in module trafficgen.plot_traffic_situation)": [[6, "trafficgen.plot_traffic_situation.add_ship_to_plot"], [24, "trafficgen.plot_traffic_situation.add_ship_to_plot"]], "calculate_ship_outline() (in module trafficgen.plot_traffic_situation)": [[6, "trafficgen.plot_traffic_situation.calculate_ship_outline"], [24, "trafficgen.plot_traffic_situation.calculate_ship_outline"]], "calculate_vector_arrow() (in module trafficgen.plot_traffic_situation)": [[6, "trafficgen.plot_traffic_situation.calculate_vector_arrow"], [24, "trafficgen.plot_traffic_situation.calculate_vector_arrow"]], "find_max_value_for_plot() (in module trafficgen.plot_traffic_situation)": [[6, "trafficgen.plot_traffic_situation.find_max_value_for_plot"], [24, "trafficgen.plot_traffic_situation.find_max_value_for_plot"]], "plot_specific_traffic_situation() (in module trafficgen.plot_traffic_situation)": [[6, "trafficgen.plot_traffic_situation.plot_specific_traffic_situation"], [24, "trafficgen.plot_traffic_situation.plot_specific_traffic_situation"]], "plot_traffic_situations() (in module trafficgen.plot_traffic_situation)": [[6, "trafficgen.plot_traffic_situation.plot_traffic_situations"], [24, "trafficgen.plot_traffic_situation.plot_traffic_situations"]], "trafficgen.plot_traffic_situation": [[6, "module-trafficgen.plot_traffic_situation"], [24, "module-trafficgen.plot_traffic_situation"]], "read_encounter_settings_file() (in module trafficgen.read_files)": [[7, "trafficgen.read_files.read_encounter_settings_file"], [25, "trafficgen.read_files.read_encounter_settings_file"]], "read_own_ship_file() (in module trafficgen.read_files)": [[7, "trafficgen.read_files.read_own_ship_file"], [25, "trafficgen.read_files.read_own_ship_file"]], "read_situation_files() (in module trafficgen.read_files)": [[7, "trafficgen.read_files.read_situation_files"], [25, "trafficgen.read_files.read_situation_files"]], "read_target_ship_files() (in module trafficgen.read_files)": [[7, "trafficgen.read_files.read_target_ship_files"], [25, "trafficgen.read_files.read_target_ship_files"]], "trafficgen.read_files": [[7, "module-trafficgen.read_files"], [25, "module-trafficgen.read_files"]], "generate_traffic_situations() (in module trafficgen.ship_traffic_generator)": [[8, "trafficgen.ship_traffic_generator.generate_traffic_situations"], [26, "trafficgen.ship_traffic_generator.generate_traffic_situations"]], "trafficgen.ship_traffic_generator": [[8, "module-trafficgen.ship_traffic_generator"], [26, "module-trafficgen.ship_traffic_generator"]], "crossing_give_way (trafficgen.types.encountertype attribute)": [[9, "trafficgen.types.EncounterType.CROSSING_GIVE_WAY"], [27, "trafficgen.types.EncounterType.CROSSING_GIVE_WAY"]], "crossing_stand_on (trafficgen.types.encountertype attribute)": [[9, "trafficgen.types.EncounterType.CROSSING_STAND_ON"], [27, "trafficgen.types.EncounterType.CROSSING_STAND_ON"]], "encounter (class in trafficgen.types)": [[9, "trafficgen.types.Encounter"], [27, "trafficgen.types.Encounter"]], "encounterclassification (class in trafficgen.types)": [[9, "trafficgen.types.EncounterClassification"], [27, "trafficgen.types.EncounterClassification"]], "encounterrelativespeed (class in trafficgen.types)": [[9, "trafficgen.types.EncounterRelativeSpeed"], [27, "trafficgen.types.EncounterRelativeSpeed"]], "encountersettings (class in trafficgen.types)": [[9, "trafficgen.types.EncounterSettings"], [27, "trafficgen.types.EncounterSettings"]], "encountertype (class in trafficgen.types)": [[9, "trafficgen.types.EncounterType"], [27, "trafficgen.types.EncounterType"]], "fishing (trafficgen.types.shiptype attribute)": [[9, "trafficgen.types.ShipType.FISHING"], [27, "trafficgen.types.ShipType.FISHING"]], "general_cargo (trafficgen.types.shiptype attribute)": [[9, "trafficgen.types.ShipType.GENERAL_CARGO"], [27, "trafficgen.types.ShipType.GENERAL_CARGO"]], "head_on (trafficgen.types.encountertype attribute)": [[9, "trafficgen.types.EncounterType.HEAD_ON"], [27, "trafficgen.types.EncounterType.HEAD_ON"]], "military (trafficgen.types.shiptype attribute)": [[9, "trafficgen.types.ShipType.MILITARY"], [27, "trafficgen.types.ShipType.MILITARY"]], "no_risk_collision (trafficgen.types.encountertype attribute)": [[9, "trafficgen.types.EncounterType.NO_RISK_COLLISION"], [27, "trafficgen.types.EncounterType.NO_RISK_COLLISION"]], "overtaking_give_way (trafficgen.types.encountertype attribute)": [[9, "trafficgen.types.EncounterType.OVERTAKING_GIVE_WAY"], [27, "trafficgen.types.EncounterType.OVERTAKING_GIVE_WAY"]], "overtaking_stand_on (trafficgen.types.encountertype attribute)": [[9, "trafficgen.types.EncounterType.OVERTAKING_STAND_ON"], [27, "trafficgen.types.EncounterType.OVERTAKING_STAND_ON"]], "passenger_roro (trafficgen.types.shiptype attribute)": [[9, "trafficgen.types.ShipType.PASSENGER_RORO"], [27, "trafficgen.types.ShipType.PASSENGER_RORO"]], "pose (class in trafficgen.types)": [[9, "trafficgen.types.Pose"], [27, "trafficgen.types.Pose"]], "position (class in trafficgen.types)": [[9, "trafficgen.types.Position"], [27, "trafficgen.types.Position"]], "ship (class in trafficgen.types)": [[9, "trafficgen.types.Ship"], [27, "trafficgen.types.Ship"]], "shiptype (class in trafficgen.types)": [[9, "trafficgen.types.ShipType"], [27, "trafficgen.types.ShipType"]], "situation (class in trafficgen.types)": [[9, "trafficgen.types.Situation"], [27, "trafficgen.types.Situation"]], "staticshipdata (class in trafficgen.types)": [[9, "trafficgen.types.StaticShipData"], [27, "trafficgen.types.StaticShipData"]], "targetship (class in trafficgen.types)": [[9, "trafficgen.types.TargetShip"], [27, "trafficgen.types.TargetShip"]], "beta (trafficgen.types.encounter attribute)": [[9, "trafficgen.types.Encounter.beta"], [27, "trafficgen.types.Encounter.beta"]], "classification (trafficgen.types.encountersettings attribute)": [[9, "trafficgen.types.EncounterSettings.classification"], [27, "trafficgen.types.EncounterSettings.classification"]], "common_vector (trafficgen.types.situation attribute)": [[9, "trafficgen.types.Situation.common_vector"], [27, "trafficgen.types.Situation.common_vector"]], "course (trafficgen.types.pose attribute)": [[9, "trafficgen.types.Pose.course"], [27, "trafficgen.types.Pose.course"]], "crossing_give_way (trafficgen.types.encounterrelativespeed attribute)": [[9, "trafficgen.types.EncounterRelativeSpeed.crossing_give_way"], [27, "trafficgen.types.EncounterRelativeSpeed.crossing_give_way"]], "crossing_stand_on (trafficgen.types.encounterrelativespeed attribute)": [[9, "trafficgen.types.EncounterRelativeSpeed.crossing_stand_on"], [27, "trafficgen.types.EncounterRelativeSpeed.crossing_stand_on"]], "desired_encounter_type (trafficgen.types.encounter attribute)": [[9, "trafficgen.types.Encounter.desired_encounter_type"], [27, "trafficgen.types.Encounter.desired_encounter_type"]], "east (trafficgen.types.position attribute)": [[9, "trafficgen.types.Position.east"], [27, "trafficgen.types.Position.east"]], "encounter (trafficgen.types.situation attribute)": [[9, "trafficgen.types.Situation.encounter"], [27, "trafficgen.types.Situation.encounter"]], "evolve_time (trafficgen.types.encountersettings attribute)": [[9, "trafficgen.types.EncounterSettings.evolve_time"], [27, "trafficgen.types.EncounterSettings.evolve_time"]], "head_on (trafficgen.types.encounterrelativespeed attribute)": [[9, "trafficgen.types.EncounterRelativeSpeed.head_on"], [27, "trafficgen.types.EncounterRelativeSpeed.head_on"]], "height (trafficgen.types.staticshipdata attribute)": [[9, "trafficgen.types.StaticShipData.height"], [27, "trafficgen.types.StaticShipData.height"]], "id (trafficgen.types.targetship attribute)": [[9, "trafficgen.types.TargetShip.id"], [27, "trafficgen.types.TargetShip.id"]], "input_file_name (trafficgen.types.situation attribute)": [[9, "trafficgen.types.Situation.input_file_name"], [27, "trafficgen.types.Situation.input_file_name"]], "lat_lon_0 (trafficgen.types.encountersettings attribute)": [[9, "trafficgen.types.EncounterSettings.lat_lon_0"], [27, "trafficgen.types.EncounterSettings.lat_lon_0"]], "lat_lon_0 (trafficgen.types.situation attribute)": [[9, "trafficgen.types.Situation.lat_lon_0"], [27, "trafficgen.types.Situation.lat_lon_0"]], "latitude (trafficgen.types.position attribute)": [[9, "trafficgen.types.Position.latitude"], [27, "trafficgen.types.Position.latitude"]], "length (trafficgen.types.staticshipdata attribute)": [[9, "trafficgen.types.StaticShipData.length"], [27, "trafficgen.types.StaticShipData.length"]], "longitude (trafficgen.types.position attribute)": [[9, "trafficgen.types.Position.longitude"], [27, "trafficgen.types.Position.longitude"]], "max_meeting_distance (trafficgen.types.encountersettings attribute)": [[9, "trafficgen.types.EncounterSettings.max_meeting_distance"], [27, "trafficgen.types.EncounterSettings.max_meeting_distance"]], "mmsi (trafficgen.types.staticshipdata attribute)": [[9, "trafficgen.types.StaticShipData.mmsi"], [27, "trafficgen.types.StaticShipData.mmsi"]], "name (trafficgen.types.staticshipdata attribute)": [[9, "trafficgen.types.StaticShipData.name"], [27, "trafficgen.types.StaticShipData.name"]], "north (trafficgen.types.position attribute)": [[9, "trafficgen.types.Position.north"], [27, "trafficgen.types.Position.north"]], "num_situations (trafficgen.types.situation attribute)": [[9, "trafficgen.types.Situation.num_situations"], [27, "trafficgen.types.Situation.num_situations"]], "overtaking_give_way (trafficgen.types.encounterrelativespeed attribute)": [[9, "trafficgen.types.EncounterRelativeSpeed.overtaking_give_way"], [27, "trafficgen.types.EncounterRelativeSpeed.overtaking_give_way"]], "overtaking_stand_on (trafficgen.types.encounterrelativespeed attribute)": [[9, "trafficgen.types.EncounterRelativeSpeed.overtaking_stand_on"], [27, "trafficgen.types.EncounterRelativeSpeed.overtaking_stand_on"]], "own_ship (trafficgen.types.situation attribute)": [[9, "trafficgen.types.Situation.own_ship"], [27, "trafficgen.types.Situation.own_ship"]], "position (trafficgen.types.pose attribute)": [[9, "trafficgen.types.Pose.position"], [27, "trafficgen.types.Pose.position"]], "relative_speed (trafficgen.types.encounter attribute)": [[9, "trafficgen.types.Encounter.relative_speed"], [27, "trafficgen.types.Encounter.relative_speed"]], "relative_speed (trafficgen.types.encountersettings attribute)": [[9, "trafficgen.types.EncounterSettings.relative_speed"], [27, "trafficgen.types.EncounterSettings.relative_speed"]], "ship_type (trafficgen.types.staticshipdata attribute)": [[9, "trafficgen.types.StaticShipData.ship_type"], [27, "trafficgen.types.StaticShipData.ship_type"]], "speed (trafficgen.types.pose attribute)": [[9, "trafficgen.types.Pose.speed"], [27, "trafficgen.types.Pose.speed"]], "speed_max (trafficgen.types.staticshipdata attribute)": [[9, "trafficgen.types.StaticShipData.speed_max"], [27, "trafficgen.types.StaticShipData.speed_max"]], "start_pose (trafficgen.types.ship attribute)": [[9, "trafficgen.types.Ship.start_pose"], [27, "trafficgen.types.Ship.start_pose"]], "static (trafficgen.types.ship attribute)": [[9, "trafficgen.types.Ship.static"], [27, "trafficgen.types.Ship.static"]], "target_ship (trafficgen.types.situation attribute)": [[9, "trafficgen.types.Situation.target_ship"], [27, "trafficgen.types.Situation.target_ship"]], "theta13_criteria (trafficgen.types.encounterclassification attribute)": [[9, "trafficgen.types.EncounterClassification.theta13_criteria"], [27, "trafficgen.types.EncounterClassification.theta13_criteria"]], "theta14_criteria (trafficgen.types.encounterclassification attribute)": [[9, "trafficgen.types.EncounterClassification.theta14_criteria"], [27, "trafficgen.types.EncounterClassification.theta14_criteria"]], "theta15 (trafficgen.types.encounterclassification attribute)": [[9, "trafficgen.types.EncounterClassification.theta15"], [27, "trafficgen.types.EncounterClassification.theta15"]], "theta15_criteria (trafficgen.types.encounterclassification attribute)": [[9, "trafficgen.types.EncounterClassification.theta15_criteria"], [27, "trafficgen.types.EncounterClassification.theta15_criteria"]], "title (trafficgen.types.situation attribute)": [[9, "trafficgen.types.Situation.title"], [27, "trafficgen.types.Situation.title"]], "trafficgen.types": [[9, "module-trafficgen.types"], [27, "module-trafficgen.types"]], "vector_range (trafficgen.types.encountersettings attribute)": [[9, "trafficgen.types.EncounterSettings.vector_range"], [27, "trafficgen.types.EncounterSettings.vector_range"]], "vector_time (trafficgen.types.encounter attribute)": [[9, "trafficgen.types.Encounter.vector_time"], [27, "trafficgen.types.Encounter.vector_time"]], "waypoints (trafficgen.types.ship attribute)": [[9, "trafficgen.types.Ship.waypoints"], [27, "trafficgen.types.Ship.waypoints"]], "width (trafficgen.types.staticshipdata attribute)": [[9, "trafficgen.types.StaticShipData.width"], [27, "trafficgen.types.StaticShipData.width"]], "calculate_position_at_certain_time() (in module trafficgen.utils)": [[10, "trafficgen.utils.calculate_position_at_certain_time"], [28, "trafficgen.utils.calculate_position_at_certain_time"]], "convert_angle_0_to_360_to_minus_180_to_180() (in module trafficgen.utils)": [[10, "trafficgen.utils.convert_angle_0_to_360_to_minus_180_to_180"], [28, "trafficgen.utils.convert_angle_0_to_360_to_minus_180_to_180"]], "convert_angle_minus_180_to_180_to_0_to_360() (in module trafficgen.utils)": [[10, "trafficgen.utils.convert_angle_minus_180_to_180_to_0_to_360"], [28, "trafficgen.utils.convert_angle_minus_180_to_180_to_0_to_360"]], "deg_2_rad() (in module trafficgen.utils)": [[10, "trafficgen.utils.deg_2_rad"], [28, "trafficgen.utils.deg_2_rad"]], "knot_2_m_pr_min() (in module trafficgen.utils)": [[10, "trafficgen.utils.knot_2_m_pr_min"], [28, "trafficgen.utils.knot_2_m_pr_min"]], "m2nm() (in module trafficgen.utils)": [[10, "trafficgen.utils.m2nm"], [28, "trafficgen.utils.m2nm"]], "m_pr_min_2_knot() (in module trafficgen.utils)": [[10, "trafficgen.utils.m_pr_min_2_knot"], [28, "trafficgen.utils.m_pr_min_2_knot"]], "nm_2_m() (in module trafficgen.utils)": [[10, "trafficgen.utils.nm_2_m"], [28, "trafficgen.utils.nm_2_m"]], "rad_2_deg() (in module trafficgen.utils)": [[10, "trafficgen.utils.rad_2_deg"], [28, "trafficgen.utils.rad_2_deg"]], "trafficgen.utils": [[10, "module-trafficgen.utils"], [28, "module-trafficgen.utils"]], "trafficgen.write_traffic_situation_to_file": [[11, "module-trafficgen.write_traffic_situation_to_file"], [29, "module-trafficgen.write_traffic_situation_to_file"]], "write_traffic_situations_to_json_file() (in module trafficgen.write_traffic_situation_to_file)": [[11, "trafficgen.write_traffic_situation_to_file.write_traffic_situations_to_json_file"], [29, "trafficgen.write_traffic_situation_to_file.write_traffic_situations_to_json_file"]], "generate_traffic_situations() (in module trafficgen)": [[19, "trafficgen.generate_traffic_situations"]], "model_config (trafficgen.types.encounter attribute)": [[27, "trafficgen.types.Encounter.model_config"]], "model_config (trafficgen.types.encounterclassification attribute)": [[27, "trafficgen.types.EncounterClassification.model_config"]], "model_config (trafficgen.types.encounterrelativespeed attribute)": [[27, "trafficgen.types.EncounterRelativeSpeed.model_config"]], "model_config (trafficgen.types.encountersettings attribute)": [[27, "trafficgen.types.EncounterSettings.model_config"]], "model_config (trafficgen.types.pose attribute)": [[27, "trafficgen.types.Pose.model_config"]], "model_config (trafficgen.types.position attribute)": [[27, "trafficgen.types.Position.model_config"]], "model_config (trafficgen.types.ship attribute)": [[27, "trafficgen.types.Ship.model_config"]], "model_config (trafficgen.types.situation attribute)": [[27, "trafficgen.types.Situation.model_config"]], "model_config (trafficgen.types.staticshipdata attribute)": [[27, "trafficgen.types.StaticShipData.model_config"]], "model_config (trafficgen.types.targetship attribute)": [[27, "trafficgen.types.TargetShip.model_config"]], "model_fields (trafficgen.types.encounter attribute)": [[27, "trafficgen.types.Encounter.model_fields"]], "model_fields (trafficgen.types.encounterclassification attribute)": [[27, "trafficgen.types.EncounterClassification.model_fields"]], "model_fields (trafficgen.types.encounterrelativespeed attribute)": [[27, "trafficgen.types.EncounterRelativeSpeed.model_fields"]], "model_fields (trafficgen.types.encountersettings attribute)": [[27, "trafficgen.types.EncounterSettings.model_fields"]], "model_fields (trafficgen.types.pose attribute)": [[27, "trafficgen.types.Pose.model_fields"]], "model_fields (trafficgen.types.position attribute)": [[27, "trafficgen.types.Position.model_fields"]], "model_fields (trafficgen.types.ship attribute)": [[27, "trafficgen.types.Ship.model_fields"]], "model_fields (trafficgen.types.situation attribute)": [[27, "trafficgen.types.Situation.model_fields"]], "model_fields (trafficgen.types.staticshipdata attribute)": [[27, "trafficgen.types.StaticShipData.model_fields"]], "model_fields (trafficgen.types.targetship attribute)": [[27, "trafficgen.types.TargetShip.model_fields"]]}})
\ No newline at end of file
diff --git a/branch/main/trafficgen.check_land_crossing.html b/branch/main/trafficgen.check_land_crossing.html
new file mode 100644
index 0000000..7b74d88
--- /dev/null
+++ b/branch/main/trafficgen.check_land_crossing.html
@@ -0,0 +1,137 @@
+
+
+
+
+
+
+ Module with helper functions to determine if a generated path is crossing land.
+Find if path is crossing land.
+position_1: Ship position in (north, east) [m]. +speed: Ship speed [knots]. +course: Ship course [degree]. +lat_lon_0: Reference point, latitudinal [degree] and longitudinal [degree]. +time_interval: The time interval the vessel should travel without crossing land [minutes]
+is_on_land
+True if parts of the path crosses land.
+CLI for trafficgen package.
+Functions to generate encounters consisting of one own ship and one to many target ships. +The generated encounters may be of type head-on, overtaking give-way and stand-on and +crossing give-way and stand-on.
+Assign random (uniform) relative bearing beta between own ship +and target ship depending on type of encounter.
+encounter_type: Type of encounter
settings: Encounter settings
Relative bearing between own ship and target ship seen from own ship [deg]
+Randomly assign future position of target ship. If drawing a circle with radius +max_meeting_distance around future position of own ship, future position of +target ship shall be somewhere inside this circle.
+future, {north, east}
+a given time in the future [nm]
+future_position_target_ship
+Future position of target ship {north, east} [m]
+Assign random (uniform) speed to target ship depending on type of encounter.
+encounter_type: Type of encounter
own_ship_speed: Own ship speed [knot]
min_target_ship_speed: Minimum target ship speed [knot]
relative_speed_setting: Relative speed setting dependent on encounter [-]
target_ship_speed
+Target ship speed [knot]
+Assign random (uniform) vector time.
+vector_range: Minimum and maximum value for vector time
vector_time
+Vector time [min]
+Calculate minimum vector length (target ship speed x vector). This will +ensure that ship speed is high enough to find proper situation.
+own_ship_position: Own ship initial position, speed and course
own_ship_course: Own ship initial course
target_ship_position_future: Target ship future position
desired_beta: Desired relative bearing between
Returns: min_vector_length: Minimum vector length (target ship speed x vector)
+Calculate relative bearing between own ship and target ship, both seen from +own ship and seen from target ship.
+position_own_ship: Dict, own ship position {north, east} [m]
heading_own_ship: Own ship course [deg]
position_target_ship: Dict, own ship position {north, east} [m]
heading_target_ship: Target ship course [deg]
* beta (relative bearing between own ship and target ship seen from own ship [deg])
* alpha (relative bearing between target ship and own ship seen from target ship [deg])
Calculate ship course between two waypoints.
+waypoint_0: Dict, waypoint {north, east} [m]
waypoint_1: Dict, waypoint {north, east} [m]
course
+Ship course [deg]
+Check encounter evolvement. The generated encounter should be the same type of +encounter (head-on, crossing, give-way) also some time before the encounter is started.
+own_ship: Own ship information such as initial position, speed and course
target_ship: Target ship information such as initial position, speed and course
desired_encounter_type: Desired type of encounter to be generated
settings: Encounter settings
* returns True if encounter ok, False if encounter not ok
+Randomly pick a target ship from a list of target ships.
+target_ships: list of target ships
The target ship, info of type, size etc.
+Determine the colreg type based on alpha, relative bearing between target ship and own +ship seen from target ship, and beta, relative bearing between own ship and target ship +seen from own ship.
+alpha: relative bearing between target ship and own ship seen from target ship
beta: relative bearing between own ship and target ship seen from own ship
theta13_criteria: Tolerance for “coming up with” relative bearing
theta14_criteria: Tolerance for “reciprocal or nearly reciprocal courses”, +“when in any doubt… assume… [head-on]”
theta15_criteria: Crossing aspect limit, used for classifying a crossing encounter
encounter
+* encounter classification
+Find start position of target ship using desired beta and vector length.
+own_ship_position: Own ship initial position, speed and course
own_ship_course: Own ship initial course
target_ship_position_future: Target ship future position
target_ship_vector_length: vector length (target ship speed x vector)
desired_beta: Desired bearing between own ship and target ship seen from own ship
desired_encounter_type: Desired type of encounter to be generated
settings: Encounter settings
* start_position_target_ship (Dict, initial position of target ship {north, east} [m])
* start_position_found (0=position not found, 1=position found)
Generate an encounter.
+desired_encounter_type: Desired encounter to be generated
own_ship: Dict, information about own ship that will encounter a target ship
target_ships: List of target ships that may be used in an encounter
target_ship_id: ID which should be used on target ship
beta_default: User defined beta. If not set, this is None.
target ship. If not set, this is None.
+vector_time_default: User defined vector time. If not set, this is None.
settings: Encounter settings
target_ship (target ship information, such as initial position, speed and course)
encounter_found (True=encounter found, False=encounter not found)
Update position data of the target ship to also include latitude and longitude +position of the target ship.
+ship: Own ship data
lat_lon_0: Reference point, latitudinal [degree] and longitudinal [degree]
delta_time: Delta time from now to the time new position is being calculated [minutes]
ship
+Updated own ship data
+Update position data of the target ship to also include latitude and longitude +position of the target ship.
+target_ship: Target ship data
lat_lon_0: Reference point, latitudinal [degree] and longitudinal [degree]
ship
+Updated target ship data
+Top-level package for Traffic Generator.
+Assign random (uniform) relative bearing beta between own ship +and target ship depending on type of encounter.
+encounter_type: Type of encounter
settings: Encounter settings
Relative bearing between own ship and target ship seen from own ship [deg]
+Randomly assign future position of target ship. If drawing a circle with radius +max_meeting_distance around future position of own ship, future position of +target ship shall be somewhere inside this circle.
+future, {north, east}
+a given time in the future [nm]
+future_position_target_ship
+Future position of target ship {north, east} [m]
+Assign random (uniform) speed to target ship depending on type of encounter.
+encounter_type: Type of encounter
own_ship_speed: Own ship speed [knot]
min_target_ship_speed: Minimum target ship speed [knot]
relative_speed_setting: Relative speed setting dependent on encounter [-]
target_ship_speed
+Target ship speed [knot]
+Assign random (uniform) vector time.
+vector_range: Minimum and maximum value for vector time
vector_time
+Vector time [min]
+Calculate the position of the ship at a given time based on initial position +and delta time, and constand speed and course.
+position: Initial ship position [m] +speed: Ship speed [knot] +course: Ship course [deg] +delta_time: Delta time from now to the time new position is being calculated [minutes]
+position{north, east}
+Dict, north and east position given in meters
+Calculate relative bearing between own ship and target ship, both seen from +own ship and seen from target ship.
+position_own_ship: Dict, own ship position {north, east} [m]
heading_own_ship: Own ship course [deg]
position_target_ship: Dict, own ship position {north, east} [m]
heading_target_ship: Target ship course [deg]
* beta (relative bearing between own ship and target ship seen from own ship [deg])
* alpha (relative bearing between target ship and own ship seen from target ship [deg])
Calculate ship course between two waypoints.
+waypoint_0: Dict, waypoint {north, east} [m]
waypoint_1: Dict, waypoint {north, east} [m]
course
+Ship course [deg]
+Check encounter evolvement. The generated encounter should be the same type of +encounter (head-on, crossing, give-way) also some time before the encounter is started.
+own_ship: Own ship information such as initial position, speed and course
target_ship: Target ship information such as initial position, speed and course
desired_encounter_type: Desired type of encounter to be generated
settings: Encounter settings
* returns True if encounter ok, False if encounter not ok
+Convert an angle given in the region 0 to 360 degrees to an +angle given in the region -180 to 180 degrees.
+angle_360: Angle given in the region 0 to 360 degrees
+angle_180
+Angle given in the region -180 to 180 degrees
+Convert an angle given in the region -180 to 180 degrees to an +angle given in the region 0 to 360 degrees.
+angle_180: Angle given in the region -180 to 180 degrees
+angle_360
+Angle given in the region 0 to 360 degrees
+Randomly pick a target ship from a list of target ships.
+target_ships: list of target ships
The target ship, info of type, size etc.
+Convert angle given in degrees to angle give in radians.
+angle_in_degrees: Angle given in degrees
+angle given in radians
+Angle given in radians
+Determine the colreg type based on alpha, relative bearing between target ship and own +ship seen from target ship, and beta, relative bearing between own ship and target ship +seen from own ship.
+alpha: relative bearing between target ship and own ship seen from target ship
beta: relative bearing between own ship and target ship seen from own ship
theta13_criteria: Tolerance for “coming up with” relative bearing
theta14_criteria: Tolerance for “reciprocal or nearly reciprocal courses”, +“when in any doubt… assume… [head-on]”
theta15_criteria: Crossing aspect limit, used for classifying a crossing encounter
encounter
+* encounter classification
+Find start position of target ship using desired beta and vector length.
+own_ship_position: Own ship initial position, speed and course
own_ship_course: Own ship initial course
target_ship_position_future: Target ship future position
target_ship_vector_length: vector length (target ship speed x vector)
desired_beta: Desired bearing between own ship and target ship seen from own ship
desired_encounter_type: Desired type of encounter to be generated
settings: Encounter settings
* start_position_target_ship (Dict, initial position of target ship {north, east} [m])
* start_position_found (0=position not found, 1=position found)
Compute longitude lon (rad), latitude lat (rad) and height h (m) for the +NED coordinates (xn,yn,zn).
+Method taken from the MSS (Marine System Simulator) toolbox which is a Matlab/Simulink +library for marine systems.
+The method computes longitude lon (rad), latitude lat (rad) and height h (m) for the +NED coordinates (xn,yn,zn) using a flat Earth coordinate system defined by the WGS-84 +ellipsoid. The flat Earth coordinate origin is located at (lon_0, lat_0) with reference +height h_ref in meters above the surface of the ellipsoid. Both height and h_ref +are positive upwards, while zn is positive downwards (NED). +Author: Thor I. Fossen +Date: 20 July 2018 +Revisions: 2023-02-04 updates the formulas for latitude and longitude
+xn: Ship position, north [m] +yn: Ship position, east [m] +zn=0.0: Ship position, down [m] +lat_0, lon_0: Flat earth coordinate located at (lon_0, lat_0) +h_ref=0.0: Flat earth coordinate with reference h_ref in meters above the surface +of the ellipsoid
+lat (Latitude [rad])
lon (Longitude [rad])
h (Height [m])
Generate an encounter.
+desired_encounter_type: Desired encounter to be generated
own_ship: Dict, information about own ship that will encounter a target ship
target_ships: List of target ships that may be used in an encounter
target_ship_id: ID which should be used on target ship
beta_default: User defined beta. If not set, this is None.
target ship. If not set, this is None.
+vector_time_default: User defined vector time. If not set, this is None.
settings: Encounter settings
target_ship (target ship information, such as initial position, speed and course)
encounter_found (True=encounter found, False=encounter not found)
Generate a set of traffic situations using input files. +This is the main function for generating a set of traffic situations using input files +specifying number and type of encounter, type of target ships etc.
+situation_folder: Path to situation folder, files describing the desired situations
target_ship_folder: Path to where different type of target ships is found
settings_file: Path to settings file
traffic_situations (List of generated traffic situations.)
One situation may consist of one or more encounters.
Convert ship speed in knot to meters pr minutes.
+speed_in_knot: Ship speed given in knots
+speed_in_m_pr_min
+Ship speed in meters pr minutes
+Compute (north, east) for a flat Earth coordinate system from longitude +lon (rad) and latitude lat (rad).
+Method taken from the MSS (Marine System Simulator) toolbox which is a Matlab/Simulink +library for marine systems.
+The method computes (north, east) for a flat Earth coordinate system from longitude +lon (rad) and latitude lat (rad) of the WGS-84 elipsoid. The flat Earth coordinate +origin is located at (lon_0, lat_0). +Author: Thor I. Fossen +Date: 20 July 2018 +Revisions: 2023-02-04 updates the formulas for latitude and longitude
+lat: Ship position in latitude [rad] +lon: Ship position in longitude [rad] +h=0.0: Ship height in meters above the surface of the ellipsoid +lat_0, lon_0: Flat earth coordinate located at (lon_0, lat_0) +h_ref=0.0: Flat earth coordinate with reference h_ref in meters above +the surface of the ellipsoid
+x_n (Ship position, north [m])
y_n (Ship position, east [m])
z_n (Ship position, down [m])
Convert length given in meters to length given in nautical miles.
+length_in_m: Length given in meters
+length_in_nm
+Length given in nautical miles
+Convert ship speed in meters pr minutes to knot.
+speed_in_m_pr_min: Ship speed in meters pr second
+speed_in_knot
+Ship speed given in knots
+Convert length given in nautical miles to length given in meters.
+length_in_nm: Length given in nautical miles
+length_in_m
+Length given in meters
+Find if path is crossing land.
+position_1: Ship position in (north, east) [m]. +speed: Ship speed [knots]. +course: Ship course [degree]. +lat_lon_0: Reference point, latitudinal [degree] and longitudinal [degree]. +time_interval: The time interval the vessel should travel without crossing land [minutes]
+is_on_land
+True if parts of the path crosses land.
+Plot a specific situation in map.
+traffic_situations: Generated traffic situations +situation_number: The specific situation to be plotted
+Plot the traffic situations in one more figures.
+traffic_situations: Traffic situations to be plotted +col: Number of columns in each figure +row: Number of rows in each figure
+Convert angle given in radians to angle give in degrees.
+angle_in_degrees: Angle given in degrees
+angle given in radians
+Angle given in radians
+Read encounter settings file.
+settings_file: Path to the encounter setting file
+Encounter settings
+Read own ship file.
+own_ship_file: Path to the own_ship_file file
+own_ship information
+Read traffic situation files.
+situation_folder: Path to the folder where situation files are found
+situations
+List of desired traffic situations
+Read target ship files.
+target_ship_folder: Path to the folder where target ships are found
+target_ships
+List of different target ships
+Return the “smallest signed angle” (SSA) or the smallest difference between two angles.
+Method taken from the MSS (Marine System Simulator) toolbox which is a Matlab/Simulink +library for marine systems.
+Examples
+angle = ssa(angle) maps an angle in rad to the interval [-pi pi)
+Author: Thor I. Fossen +Date: 2018-09-21
+angle: angle given in radius
+smallest_angle
+“smallest signed angle” or the smallest difference between two angles
+Update position data of the target ship to also include latitude and longitude +position of the target ship.
+ship: Own ship data
lat_lon_0: Reference point, latitudinal [degree] and longitudinal [degree]
delta_time: Delta time from now to the time new position is being calculated [minutes]
ship
+Updated own ship data
+Update position data of the target ship to also include latitude and longitude +position of the target ship.
+target_ship: Target ship data
lat_lon_0: Reference point, latitudinal [degree] and longitudinal [degree]
ship
+Updated target ship data
+Write traffic situations to json file.
+traffic_situations: Traffic situations to be written to file +write_folder: Folder where the json files is to be written
+assign_beta()
assign_future_position_to_target_ship()
assign_speed_to_target_ship()
assign_vector_time()
calculate_min_vector_length_target_ship()
calculate_relative_bearing()
calculate_ship_course()
check_encounter_evolvement()
decide_target_ship()
determine_colreg()
find_start_position_target_ship()
generate_encounter()
update_position_data_own_ship()
update_position_data_target_ship()
flat2llh()
llh2flat()
ssa()
Encounter
+EncounterClassification
+EncounterRelativeSpeed
+EncounterSettings
+EncounterType
+Pose
+Position
+Ship
+ShipType
+Situation
+StaticShipData
+TargetShip
+The Marine Systems Simulator (MSS) is a Matlab and Simulink library for marine systems.
+It includes models for ships, underwater vehicles, unmanned surface vehicles, and floating structures. +The library also contains guidance, navigation, and control (GNC) blocks for real-time simulation. +The algorithms are described in:
+T. I. Fossen (2021). Handbook of Marine Craft Hydrodynamics and Motion Control. 2nd. Edition, +Wiley. ISBN-13: 978-1119575054
+Parts of the library have been re-implemented in Python and are found below.
+Compute longitude lon (rad), latitude lat (rad) and height h (m) for the +NED coordinates (xn,yn,zn).
+Method taken from the MSS (Marine System Simulator) toolbox which is a Matlab/Simulink +library for marine systems.
+The method computes longitude lon (rad), latitude lat (rad) and height h (m) for the +NED coordinates (xn,yn,zn) using a flat Earth coordinate system defined by the WGS-84 +ellipsoid. The flat Earth coordinate origin is located at (lon_0, lat_0) with reference +height h_ref in meters above the surface of the ellipsoid. Both height and h_ref +are positive upwards, while zn is positive downwards (NED). +Author: Thor I. Fossen +Date: 20 July 2018 +Revisions: 2023-02-04 updates the formulas for latitude and longitude
+xn: Ship position, north [m] +yn: Ship position, east [m] +zn=0.0: Ship position, down [m] +lat_0, lon_0: Flat earth coordinate located at (lon_0, lat_0) +h_ref=0.0: Flat earth coordinate with reference h_ref in meters above the surface +of the ellipsoid
+lat (Latitude [rad])
lon (Longitude [rad])
h (Height [m])
Compute (north, east) for a flat Earth coordinate system from longitude +lon (rad) and latitude lat (rad).
+Method taken from the MSS (Marine System Simulator) toolbox which is a Matlab/Simulink +library for marine systems.
+The method computes (north, east) for a flat Earth coordinate system from longitude +lon (rad) and latitude lat (rad) of the WGS-84 elipsoid. The flat Earth coordinate +origin is located at (lon_0, lat_0). +Author: Thor I. Fossen +Date: 20 July 2018 +Revisions: 2023-02-04 updates the formulas for latitude and longitude
+lat: Ship position in latitude [rad] +lon: Ship position in longitude [rad] +h=0.0: Ship height in meters above the surface of the ellipsoid +lat_0, lon_0: Flat earth coordinate located at (lon_0, lat_0) +h_ref=0.0: Flat earth coordinate with reference h_ref in meters above +the surface of the ellipsoid
+x_n (Ship position, north [m])
y_n (Ship position, east [m])
z_n (Ship position, down [m])
Return the “smallest signed angle” (SSA) or the smallest difference between two angles.
+Method taken from the MSS (Marine System Simulator) toolbox which is a Matlab/Simulink +library for marine systems.
+Examples
+angle = ssa(angle) maps an angle in rad to the interval [-pi pi)
+Author: Thor I. Fossen +Date: 2018-09-21
+angle: angle given in radius
+smallest_angle
+“smallest signed angle” or the smallest difference between two angles
+Functions to prepare and plot traffic situations.
+Add the ship to the map.
+ship: Ship information +vector_time: Vector time [min] +lat_lon_0=Reference point, latitudinal [degree] and longitudinal [degree] +map_plot: Instance of Map. If not set, instance is set to None +color: Color of the ship. If not set, color is ‘black’
+m
+Updated instance of Map.
+Add the ship to the plot.
+ship: Ship information +vector_time: Vector time [min] +axes: Instance of figure axis. If not set, instance is set to None +color: Color of the ship. If not set, color is ‘black’
+Calculate the outline of the ship pointing in the direction of ship course.
+position: {north}, {east} position of the ship [m] +course: course of the ship [deg] +lat_lon_0: Reference point, latitudinal [degree] and longitudinal [degree] +ship_length: Ship length. If not given, ship length is set to 100 +ship_width: Ship width. If not given, ship width is set to 15
+ship_outline_points
+Polygon points to draw the ship
+Calculate the arrow with length vector pointing in the direction of ship course.
+position: {north}, {east} position of the ship [m] +direction: direction the arrow is pointing [deg] +vector_length: length of vector +lat_lon_0: Reference point, latitudinal [degree] and longitudinal [degree]
+arrow_points
+Polygon points to draw the arrow
+Find the maximum deviation from the Reference point in north and east direction.
+ship: Ship information +max_value: maximum deviation in north, east direction
+max_value
+updated maximum deviation in north, east direction
+Plot a specific situation in map.
+traffic_situations: Generated traffic situations +situation_number: The specific situation to be plotted
+Plot the traffic situations in one more figures.
+traffic_situations: Traffic situations to be plotted +col: Number of columns in each figure +row: Number of rows in each figure
+Functions to read the files needed to build one or more traffic situations.
+Read encounter settings file.
+settings_file: Path to the encounter setting file
+Encounter settings
+Read own ship file.
+own_ship_file: Path to the own_ship_file file
+own_ship information
+Read traffic situation files.
+situation_folder: Path to the folder where situation files are found
+situations
+List of desired traffic situations
+Read target ship files.
+target_ship_folder: Path to the folder where target ships are found
+target_ships
+List of different target ships
+Functions to generate traffic situations.
+Generate a set of traffic situations using input files. +This is the main function for generating a set of traffic situations using input files +specifying number and type of encounter, type of target ships etc.
+situation_folder: Path to situation folder, files describing the desired situations
target_ship_folder: Path to where different type of target ships is found
settings_file: Path to settings file
traffic_situations (List of generated traffic situations.)
One situation may consist of one or more encounters.
Domain specific data types used in trafficgen.
+Bases: BaseModel
Data type for an encounter.
+Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
+Metadata about the fields defined on the model, +mapping of field names to [FieldInfo][pydantic.fields.FieldInfo].
+This replaces Model.__fields__ from Pydantic V1.
+Bases: BaseModel
Data type for the encounter classification.
+Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
+Metadata about the fields defined on the model, +mapping of field names to [FieldInfo][pydantic.fields.FieldInfo].
+This replaces Model.__fields__ from Pydantic V1.
+Bases: BaseModel
Data type for relative speed between two ships in an encounter.
+Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
+Metadata about the fields defined on the model, +mapping of field names to [FieldInfo][pydantic.fields.FieldInfo].
+This replaces Model.__fields__ from Pydantic V1.
+Bases: BaseModel
Data type for encounter settings.
+Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
+Metadata about the fields defined on the model, +mapping of field names to [FieldInfo][pydantic.fields.FieldInfo].
+This replaces Model.__fields__ from Pydantic V1.
+Bases: Enum
Enumeration of encounter types.
+Bases: BaseModel
Data type for a (ship) pose.
+Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
+Metadata about the fields defined on the model, +mapping of field names to [FieldInfo][pydantic.fields.FieldInfo].
+This replaces Model.__fields__ from Pydantic V1.
+Bases: BaseModel
Data type for a ship’s position with attributes north, east in [m].
+Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
+Metadata about the fields defined on the model, +mapping of field names to [FieldInfo][pydantic.fields.FieldInfo].
+This replaces Model.__fields__ from Pydantic V1.
+Bases: BaseModel
Data type for a ship.
+Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
+Metadata about the fields defined on the model, +mapping of field names to [FieldInfo][pydantic.fields.FieldInfo].
+This replaces Model.__fields__ from Pydantic V1.
+Bases: Enum
Enumeration of ship types.
+Bases: BaseModel
Data type for a traffic situation.
+Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
+Metadata about the fields defined on the model, +mapping of field names to [FieldInfo][pydantic.fields.FieldInfo].
+This replaces Model.__fields__ from Pydantic V1.
+Bases: BaseModel
Data type for static ship data.
+Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
+Metadata about the fields defined on the model, +mapping of field names to [FieldInfo][pydantic.fields.FieldInfo].
+This replaces Model.__fields__ from Pydantic V1.
+Bases: Ship
Data type for a target ship.
+Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
+Metadata about the fields defined on the model, +mapping of field names to [FieldInfo][pydantic.fields.FieldInfo].
+This replaces Model.__fields__ from Pydantic V1.
+Utility functions that are used by several other functions.
+Calculate the position of the ship at a given time based on initial position +and delta time, and constand speed and course.
+position: Initial ship position [m] +speed: Ship speed [knot] +course: Ship course [deg] +delta_time: Delta time from now to the time new position is being calculated [minutes]
+position{north, east}
+Dict, north and east position given in meters
+Convert an angle given in the region 0 to 360 degrees to an +angle given in the region -180 to 180 degrees.
+angle_360: Angle given in the region 0 to 360 degrees
+angle_180
+Angle given in the region -180 to 180 degrees
+Convert an angle given in the region -180 to 180 degrees to an +angle given in the region 0 to 360 degrees.
+angle_180: Angle given in the region -180 to 180 degrees
+angle_360
+Angle given in the region 0 to 360 degrees
+Convert angle given in degrees to angle give in radians.
+angle_in_degrees: Angle given in degrees
+angle given in radians
+Angle given in radians
+Convert ship speed in knot to meters pr minutes.
+speed_in_knot: Ship speed given in knots
+speed_in_m_pr_min
+Ship speed in meters pr minutes
+Convert length given in meters to length given in nautical miles.
+length_in_m: Length given in meters
+length_in_nm
+Length given in nautical miles
+Convert ship speed in meters pr minutes to knot.
+speed_in_m_pr_min: Ship speed in meters pr second
+speed_in_knot
+Ship speed given in knots
+Functions to clean traffic situations data before writing it to a json file.
+Write traffic situations to json file.
+traffic_situations: Traffic situations to be written to file +write_folder: Folder where the json files is to be written
+To use Traffic Generator in a project:
+import trafficgen
+
To use Traffic Generator as a command line tool for generating traffic situations, write:
+trafficgen gen-situation
+
The command line tool takes different input options:
+-s, --situations PATH Folders with situations (default=./baseline_situations_input/)
+-t, --targets PATH Folder with target configurations (default=./target_ships/)
+-c, --settings PATH Path to settings file (default=./settings/encounter_settings.json)
+--visualize Plot visualization
+--col INTEGER Number of columns for plot, may be used with visualize (default=10)
+--row INTEGER Number of rows for plot, may be used with visualize (default=6)
+--visualize-situation INTEGER Plot individual traffic situation, specify INTEGER value
+-o, --output PATH Output folder (default=None)
+--help Show this message and exit.
+
Example:
+trafficgen gen-situation -s ./data/example_situations_input -o ./data/test_output_1
+
When generating situations without specifying where the desired situations (--situation
) are found, the
+default path, which is default=./baseline_situations_input/
, will be used.
The baseline situations are a set of generic traffic situations covering head-on, overtaking stand-on/give-way
+and crossing stand-on/give-way encounters. To cover the combination of encounters for 1, 2 and 3 target ships,
+there are in total 55 baseline situations. The input files for generating these situations are found in
+./baseline_situations_input/
All the generated situations are displayed if using --visualize
. This will pop up one or more plot windows,
+which show all the traffic situations. The number of colums and rows for the plots (per figure) can be specified by
+using --col
and --row
, respectively.
A specific encounter is visualized by using --visualize-situation INTEGER
, e.g.:
trafficgen gen-situation -s ./data/example_situations_input -o ./data/test_output_1 --visualize-situation 2
+
This will open a browser window/tab with an OpenStreetMap background and the traffic situation +radar plot as an overlay. +Note that the integer needs to be within the range of the number of generated situations, +for example 1 - 12 if you generated 12 situations.
+