mirror of
https://github.com/dcs-liberation/dcs_liberation.git
synced 2025-11-10 14:22:26 +00:00
Add types for distance and speed.
Not converting all at once so I can prove the concept. After that we'll want to cover all the cases where an int distance or speed is a part of the save game (I've done one of them here with `Flight.alt`) so further cleanups don't break save compat. https://github.com/Khopa/dcs_liberation/issues/558
This commit is contained in:
parent
44bc2d769b
commit
113947b9f0
@ -1,7 +1,7 @@
|
||||
from dataclasses import dataclass
|
||||
from datetime import timedelta
|
||||
|
||||
from game.utils import nm_to_meter, feet_to_meter
|
||||
from game.utils import Distance, feet, nm_to_meter, feet_to_meter
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
@ -15,13 +15,13 @@ class Doctrine:
|
||||
strike_max_range: int
|
||||
sead_max_range: int
|
||||
|
||||
rendezvous_altitude: int
|
||||
rendezvous_altitude: Distance
|
||||
hold_distance: int
|
||||
push_distance: int
|
||||
join_distance: int
|
||||
split_distance: int
|
||||
ingress_egress_distance: int
|
||||
ingress_altitude: int
|
||||
ingress_altitude: Distance
|
||||
egress_altitude: int
|
||||
|
||||
min_patrol_altitude: int
|
||||
@ -47,13 +47,13 @@ MODERN_DOCTRINE = Doctrine(
|
||||
antiship=True,
|
||||
strike_max_range=1500000,
|
||||
sead_max_range=1500000,
|
||||
rendezvous_altitude=feet_to_meter(25000),
|
||||
rendezvous_altitude=feet(25000),
|
||||
hold_distance=nm_to_meter(15),
|
||||
push_distance=nm_to_meter(20),
|
||||
join_distance=nm_to_meter(20),
|
||||
split_distance=nm_to_meter(20),
|
||||
ingress_egress_distance=nm_to_meter(45),
|
||||
ingress_altitude=feet_to_meter(20000),
|
||||
ingress_altitude=feet(20000),
|
||||
egress_altitude=feet_to_meter(20000),
|
||||
min_patrol_altitude=feet_to_meter(15000),
|
||||
max_patrol_altitude=feet_to_meter(33000),
|
||||
@ -75,13 +75,13 @@ COLDWAR_DOCTRINE = Doctrine(
|
||||
antiship=True,
|
||||
strike_max_range=1500000,
|
||||
sead_max_range=1500000,
|
||||
rendezvous_altitude=feet_to_meter(22000),
|
||||
rendezvous_altitude=feet(22000),
|
||||
hold_distance=nm_to_meter(10),
|
||||
push_distance=nm_to_meter(10),
|
||||
join_distance=nm_to_meter(10),
|
||||
split_distance=nm_to_meter(10),
|
||||
ingress_egress_distance=nm_to_meter(30),
|
||||
ingress_altitude=feet_to_meter(18000),
|
||||
ingress_altitude=feet(18000),
|
||||
egress_altitude=feet_to_meter(18000),
|
||||
min_patrol_altitude=feet_to_meter(10000),
|
||||
max_patrol_altitude=feet_to_meter(24000),
|
||||
@ -107,9 +107,9 @@ WWII_DOCTRINE = Doctrine(
|
||||
push_distance=nm_to_meter(5),
|
||||
join_distance=nm_to_meter(5),
|
||||
split_distance=nm_to_meter(5),
|
||||
rendezvous_altitude=feet_to_meter(10000),
|
||||
rendezvous_altitude=feet(10000),
|
||||
ingress_egress_distance=nm_to_meter(7),
|
||||
ingress_altitude=feet_to_meter(8000),
|
||||
ingress_altitude=feet(8000),
|
||||
egress_altitude=feet_to_meter(8000),
|
||||
min_patrol_altitude=feet_to_meter(4000),
|
||||
max_patrol_altitude=feet_to_meter(15000),
|
||||
|
||||
239
game/utils.py
239
game/utils.py
@ -1,65 +1,18 @@
|
||||
def meter_to_feet(value_in_meter: float) -> int:
|
||||
"""Converts meters to feets
|
||||
from __future__ import annotations
|
||||
|
||||
:arg value_in_meter Value in meters
|
||||
"""
|
||||
return int(3.28084 * value_in_meter)
|
||||
import math
|
||||
from dataclasses import dataclass
|
||||
from typing import Union
|
||||
|
||||
METERS_TO_FEET = 3.28084
|
||||
FEET_TO_METERS = 1 / METERS_TO_FEET
|
||||
NM_TO_METERS = 1852
|
||||
METERS_TO_NM = 1 / NM_TO_METERS
|
||||
|
||||
def feet_to_meter(value_in_feet: float) -> int:
|
||||
"""Converts feets to meters
|
||||
|
||||
:arg value_in_feet Value in feets
|
||||
"""
|
||||
return int(value_in_feet / 3.28084)
|
||||
|
||||
|
||||
def meter_to_nm(value_in_meter: float) -> int:
|
||||
"""Converts meters to nautic miles
|
||||
|
||||
:arg value_in_meter Value in meters
|
||||
"""
|
||||
return int(value_in_meter / 1852)
|
||||
|
||||
|
||||
def nm_to_meter(value_in_nm: float) -> int:
|
||||
"""Converts nautic miles to meters
|
||||
|
||||
:arg value_in_nm Value in nautic miles
|
||||
"""
|
||||
return int(value_in_nm * 1852)
|
||||
|
||||
|
||||
def knots_to_kph(value_in_knots: float) -> int:
|
||||
"""Converts Knots to Kilometer Per Hour
|
||||
|
||||
:arg value_in_knots Knots
|
||||
"""
|
||||
return int(value_in_knots * 1.852)
|
||||
|
||||
|
||||
def mps_to_knots(value_in_mps: float) -> int:
|
||||
"""Converts Meters Per Second To Knots
|
||||
|
||||
:arg value_in_mps Meters Per Second
|
||||
"""
|
||||
return int(value_in_mps * 1.943)
|
||||
|
||||
|
||||
def mps_to_kph(speed: float) -> int:
|
||||
"""Converts meters per second to kilometers per hour.
|
||||
|
||||
:arg speed Speed in m/s.
|
||||
"""
|
||||
return int(speed * 3.6)
|
||||
|
||||
|
||||
def kph_to_mps(speed: float) -> int:
|
||||
"""Converts kilometers per hour to meters per second.
|
||||
|
||||
:arg speed Speed in KPH.
|
||||
"""
|
||||
return int(speed / 3.6)
|
||||
KNOTS_TO_KPH = 1.852
|
||||
KPH_TO_KNOTS = 1 / KNOTS_TO_KPH
|
||||
MS_TO_KPH = 3.6
|
||||
KPH_TO_MS = 1 / MS_TO_KPH
|
||||
|
||||
|
||||
def heading_sum(h, a) -> int:
|
||||
@ -71,5 +24,171 @@ def heading_sum(h, a) -> int:
|
||||
else:
|
||||
return h
|
||||
|
||||
|
||||
def opposite_heading(h):
|
||||
return heading_sum(h, 180)
|
||||
return heading_sum(h, 180)
|
||||
|
||||
|
||||
def meter_to_feet(value: float) -> int:
|
||||
return int(meters(value).feet)
|
||||
|
||||
|
||||
def feet_to_meter(value: float) -> int:
|
||||
return int(feet(value).meters)
|
||||
|
||||
|
||||
def meter_to_nm(value: float) -> int:
|
||||
return int(meters(value).nautical_miles)
|
||||
|
||||
|
||||
def nm_to_meter(value: float) -> int:
|
||||
return int(nautical_miles(value).meters)
|
||||
|
||||
|
||||
def knots_to_kph(value: float) -> int:
|
||||
return int(knots(value).kph)
|
||||
|
||||
|
||||
def kph_to_mps(value: float) -> int:
|
||||
return int(kph(value).meters_per_second)
|
||||
|
||||
|
||||
def mps_to_kph(value: float) -> int:
|
||||
return int(mps(value).kph)
|
||||
|
||||
|
||||
def mps_to_knots(value: float) -> int:
|
||||
return int(mps(value).knots)
|
||||
|
||||
|
||||
@dataclass(frozen=True, order=True)
|
||||
class Distance:
|
||||
distance_in_meters: float
|
||||
|
||||
@property
|
||||
def feet(self) -> float:
|
||||
return self.distance_in_meters * METERS_TO_FEET
|
||||
|
||||
@property
|
||||
def meters(self) -> float:
|
||||
return self.distance_in_meters
|
||||
|
||||
@property
|
||||
def nautical_miles(self) -> float:
|
||||
return self.distance_in_meters * METERS_TO_NM
|
||||
|
||||
@classmethod
|
||||
def from_feet(cls, value: float) -> Distance:
|
||||
return cls(value * FEET_TO_METERS)
|
||||
|
||||
@classmethod
|
||||
def from_meters(cls, value: float) -> Distance:
|
||||
return cls(value)
|
||||
|
||||
@classmethod
|
||||
def from_nautical_miles(cls, value: float) -> Distance:
|
||||
return cls(value * NM_TO_METERS)
|
||||
|
||||
def __mul__(self, other: Union[float, int]) -> Distance:
|
||||
return Distance(self.meters * other)
|
||||
|
||||
def __truediv__(self, other: Union[float, int]) -> Distance:
|
||||
return Distance(self.meters / other)
|
||||
|
||||
def __floordiv__(self, other: Union[float, int]) -> Distance:
|
||||
return Distance(self.meters // other)
|
||||
|
||||
|
||||
def feet(value: float) -> Distance:
|
||||
return Distance.from_feet(value)
|
||||
|
||||
|
||||
def meters(value: float) -> Distance:
|
||||
return Distance.from_meters(value)
|
||||
|
||||
|
||||
def nautical_miles(value: float) -> Distance:
|
||||
return Distance.from_nautical_miles(value)
|
||||
|
||||
|
||||
@dataclass(frozen=True, order=True)
|
||||
class Speed:
|
||||
speed_in_kph: float
|
||||
|
||||
@property
|
||||
def knots(self) -> float:
|
||||
return self.speed_in_kph * KPH_TO_KNOTS
|
||||
|
||||
@property
|
||||
def kph(self) -> float:
|
||||
return self.speed_in_kph
|
||||
|
||||
@property
|
||||
def meters_per_second(self) -> float:
|
||||
return self.speed_in_kph * KPH_TO_MS
|
||||
|
||||
def mach(self, altitude: Distance = meters(0)) -> float:
|
||||
c_sound = mach(1, altitude)
|
||||
return self.speed_in_kph / c_sound.kph
|
||||
|
||||
@classmethod
|
||||
def from_knots(cls, value: float) -> Speed:
|
||||
return cls(value * KNOTS_TO_KPH)
|
||||
|
||||
@classmethod
|
||||
def from_kph(cls, value: float) -> Speed:
|
||||
return cls(value)
|
||||
|
||||
@classmethod
|
||||
def from_meters_per_second(cls, value: float) -> Speed:
|
||||
return cls(value * MS_TO_KPH)
|
||||
|
||||
@classmethod
|
||||
def from_mach(cls, value: float, altitude: Distance) -> Speed:
|
||||
# https://www.grc.nasa.gov/WWW/K-12/airplane/atmos.html
|
||||
if altitude <= feet(36152):
|
||||
temperature_f = 59 - 0.00356 * altitude.feet
|
||||
else:
|
||||
# There's another formula for altitudes over 82k feet, but we better
|
||||
# not be planning waypoints that high...
|
||||
temperature_f = -70
|
||||
|
||||
temperature_k = (temperature_f + 459.67) * (5 / 9)
|
||||
|
||||
# https://www.engineeringtoolbox.com/specific-heat-ratio-d_602.html
|
||||
# Dependent on temperature, but varies very little (+/-0.001)
|
||||
# between -40F and 180F.
|
||||
heat_capacity_ratio = 1.4
|
||||
|
||||
# https://www.grc.nasa.gov/WWW/K-12/airplane/sound.html
|
||||
gas_constant = 286 # m^2/s^2/K
|
||||
c_sound = math.sqrt(heat_capacity_ratio * gas_constant * temperature_k)
|
||||
return mps(c_sound) * value
|
||||
|
||||
def __mul__(self, other: Union[float, int]) -> Speed:
|
||||
return Speed(self.kph * other)
|
||||
|
||||
def __truediv__(self, other: Union[float, int]) -> Speed:
|
||||
return Speed(self.kph / other)
|
||||
|
||||
def __floordiv__(self, other: Union[float, int]) -> Speed:
|
||||
return Speed(self.kph // other)
|
||||
|
||||
|
||||
def knots(value: float) -> Speed:
|
||||
return Speed.from_knots(value)
|
||||
|
||||
|
||||
def kph(value: float) -> Speed:
|
||||
return Speed.from_kph(value)
|
||||
|
||||
|
||||
def mps(value: float) -> Speed:
|
||||
return Speed.from_meters_per_second(value)
|
||||
|
||||
|
||||
def mach(value: float, altitude: Distance) -> Speed:
|
||||
return Speed.from_mach(value, altitude)
|
||||
|
||||
|
||||
SPEED_OF_SOUND_AT_SEA_LEVEL = knots(661.5)
|
||||
|
||||
@ -85,7 +85,7 @@ from game.theater.controlpoint import (
|
||||
)
|
||||
from game.theater.theatergroundobject import TheaterGroundObject
|
||||
from game.unitmap import UnitMap
|
||||
from game.utils import knots_to_kph, nm_to_meter
|
||||
from game.utils import Distance, Speed, knots_to_kph, kph, meters, nm_to_meter
|
||||
from gen.airsupportgen import AirSupport
|
||||
from gen.ato import AirTaskingOrder, Package
|
||||
from gen.callsigns import create_group_callsign_from_unit
|
||||
@ -110,12 +110,12 @@ from .naming import namegen
|
||||
if TYPE_CHECKING:
|
||||
from game import Game
|
||||
|
||||
WARM_START_HELI_AIRSPEED = 120
|
||||
WARM_START_HELI_ALT = 500
|
||||
WARM_START_ALTITUDE = 3000
|
||||
WARM_START_AIRSPEED = 550
|
||||
WARM_START_HELI_AIRSPEED = kph(120)
|
||||
WARM_START_HELI_ALT = meters(500)
|
||||
WARM_START_ALTITUDE = meters(3000)
|
||||
WARM_START_AIRSPEED = kph(550)
|
||||
|
||||
RTB_ALTITUDE = 800
|
||||
RTB_ALTITUDE = meters(800)
|
||||
RTB_DISTANCE = 5000
|
||||
HELI_ALT = 500
|
||||
|
||||
@ -867,7 +867,9 @@ class AircraftConflictGenerator:
|
||||
start_type=self._start_type(start_type),
|
||||
group_size=count)
|
||||
|
||||
def _add_radio_waypoint(self, group: FlyingGroup, position, altitude: int, airspeed: int = 600):
|
||||
def _add_radio_waypoint(self, group: FlyingGroup, position,
|
||||
altitude: Distance,
|
||||
airspeed: int = 600) -> MovingPoint:
|
||||
point = group.add_waypoint(position, altitude, airspeed)
|
||||
point.alt_type = "RADIO"
|
||||
return point
|
||||
@ -884,7 +886,8 @@ class AircraftConflictGenerator:
|
||||
tod_location = position.point_from_heading(heading, RTB_DISTANCE)
|
||||
self._add_radio_waypoint(group, tod_location, last_waypoint.alt)
|
||||
|
||||
destination_waypoint = self._add_radio_waypoint(group, position, RTB_ALTITUDE)
|
||||
destination_waypoint = self._add_radio_waypoint(group, position,
|
||||
RTB_ALTITUDE)
|
||||
if isinstance(at, Airport):
|
||||
group.land_at(at)
|
||||
return destination_waypoint
|
||||
@ -1380,7 +1383,8 @@ class PydcsWaypointBuilder:
|
||||
|
||||
def build(self) -> MovingPoint:
|
||||
waypoint = self.group.add_waypoint(
|
||||
Point(self.waypoint.x, self.waypoint.y), self.waypoint.alt,
|
||||
Point(self.waypoint.x, self.waypoint.y),
|
||||
self.waypoint.alt.meters,
|
||||
name=self.mission.string(self.waypoint.name))
|
||||
|
||||
if self.waypoint.flyover:
|
||||
|
||||
@ -10,6 +10,7 @@ from dcs.unittype import FlyingType
|
||||
|
||||
from game import db
|
||||
from game.theater.controlpoint import ControlPoint, MissionTarget
|
||||
from game.utils import Distance, meters
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from gen.ato import Package
|
||||
@ -67,7 +68,7 @@ class FlightWaypointType(Enum):
|
||||
class FlightWaypoint:
|
||||
|
||||
def __init__(self, waypoint_type: FlightWaypointType, x: float, y: float,
|
||||
alt: int = 0) -> None:
|
||||
alt: Distance = meters(0)) -> None:
|
||||
"""Creates a flight waypoint.
|
||||
|
||||
Args:
|
||||
|
||||
@ -28,7 +28,7 @@ from game.theater import (
|
||||
TheaterGroundObject,
|
||||
)
|
||||
from game.theater.theatergroundobject import EwrGroundObject
|
||||
from game.utils import nm_to_meter, meter_to_nm
|
||||
from game.utils import Distance, meters, nm_to_meter, meter_to_nm
|
||||
from .closestairfields import ObjectiveDistanceCache
|
||||
from .flight import Flight, FlightType, FlightWaypoint, FlightWaypointType
|
||||
from .traveltime import GroundSpeed, TravelTime
|
||||
@ -537,7 +537,8 @@ class StrikeFlightPlan(FormationFlightPlan):
|
||||
def target_area_waypoint(self) -> FlightWaypoint:
|
||||
return FlightWaypoint(FlightWaypointType.TARGET_GROUP_LOC,
|
||||
self.package.target.position.x,
|
||||
self.package.target.position.y, 0)
|
||||
self.package.target.position.y,
|
||||
meters(0))
|
||||
|
||||
@property
|
||||
def travel_time_to_target(self) -> timedelta:
|
||||
@ -863,10 +864,10 @@ class FlightPlanBuilder:
|
||||
raise InvalidObjectiveLocation(flight.flight_type, location)
|
||||
|
||||
start, end = self.racetrack_for_objective(location)
|
||||
patrol_alt = random.randint(
|
||||
patrol_alt = meters(random.randint(
|
||||
self.doctrine.min_patrol_altitude,
|
||||
self.doctrine.max_patrol_altitude
|
||||
)
|
||||
))
|
||||
|
||||
builder = WaypointBuilder(self.game.conditions, flight, self.doctrine)
|
||||
start, end = builder.race_track(start, end, patrol_alt)
|
||||
@ -983,8 +984,8 @@ class FlightPlanBuilder:
|
||||
"""
|
||||
location = self.package.target
|
||||
|
||||
patrol_alt = random.randint(self.doctrine.min_patrol_altitude,
|
||||
self.doctrine.max_patrol_altitude)
|
||||
patrol_alt = meters(random.randint(self.doctrine.min_patrol_altitude,
|
||||
self.doctrine.max_patrol_altitude))
|
||||
|
||||
# Create points
|
||||
builder = WaypointBuilder(self.game.conditions, flight, self.doctrine)
|
||||
|
||||
@ -8,7 +8,13 @@ from typing import Optional, TYPE_CHECKING
|
||||
from dcs.mapping import Point
|
||||
from dcs.unittype import FlyingType
|
||||
|
||||
from game.utils import meter_to_nm
|
||||
from game.utils import (
|
||||
Distance,
|
||||
SPEED_OF_SOUND_AT_SEA_LEVEL,
|
||||
Speed,
|
||||
kph, mach, meter_to_nm,
|
||||
meters,
|
||||
)
|
||||
from gen.flights.flight import Flight
|
||||
|
||||
if TYPE_CHECKING:
|
||||
@ -18,7 +24,7 @@ if TYPE_CHECKING:
|
||||
class GroundSpeed:
|
||||
|
||||
@classmethod
|
||||
def for_flight(cls, flight: Flight, altitude: int) -> int:
|
||||
def for_flight(cls, flight: Flight, altitude: Distance) -> int:
|
||||
if not issubclass(flight.unit_type, FlyingType):
|
||||
raise TypeError("Flight has non-flying unit")
|
||||
|
||||
@ -27,56 +33,20 @@ class GroundSpeed:
|
||||
# on fuel, but mission speed will be fast enough to keep the flight
|
||||
# safer.
|
||||
|
||||
c_sound_sea_level = 661.5
|
||||
|
||||
# DCS's max speed is in kph at 0 MSL. Convert to knots.
|
||||
max_speed = flight.unit_type.max_speed * 0.539957
|
||||
if max_speed > c_sound_sea_level:
|
||||
# DCS's max speed is in kph at 0 MSL.
|
||||
max_speed = kph(flight.unit_type.max_speed)
|
||||
if max_speed > SPEED_OF_SOUND_AT_SEA_LEVEL:
|
||||
# Aircraft is supersonic. Limit to mach 0.8 to conserve fuel and
|
||||
# account for heavily loaded jets.
|
||||
return int(cls.from_mach(0.8, altitude))
|
||||
return int(mach(0.8, altitude).knots)
|
||||
|
||||
# For subsonic aircraft, assume the aircraft can reasonably perform at
|
||||
# 80% of its maximum, and that it can maintain the same mach at altitude
|
||||
# as it can at sea level. This probably isn't great assumption, but
|
||||
# might. be sufficient given the wiggle room. We can come up with
|
||||
# another heuristic if needed.
|
||||
mach = max_speed * 0.8 / c_sound_sea_level
|
||||
return int(cls.from_mach(mach, altitude)) # knots
|
||||
|
||||
@staticmethod
|
||||
def from_mach(mach: float, altitude_m: int) -> float:
|
||||
"""Returns the ground speed in knots for the given mach and altitude.
|
||||
|
||||
Args:
|
||||
mach: The mach number to convert to ground speed.
|
||||
altitude_m: The altitude in meters.
|
||||
|
||||
Returns:
|
||||
The ground speed corresponding to the given altitude and mach number
|
||||
in knots.
|
||||
"""
|
||||
# https://www.grc.nasa.gov/WWW/K-12/airplane/atmos.html
|
||||
altitude_ft = altitude_m * 3.28084
|
||||
if altitude_ft <= 36152:
|
||||
temperature_f = 59 - 0.00356 * altitude_ft
|
||||
else:
|
||||
# There's another formula for altitudes over 82k feet, but we better
|
||||
# not be planning waypoints that high...
|
||||
temperature_f = -70
|
||||
|
||||
temperature_k = (temperature_f + 459.67) * (5 / 9)
|
||||
|
||||
# https://www.engineeringtoolbox.com/specific-heat-ratio-d_602.html
|
||||
# Dependent on temperature, but varies very little (+/-0.001)
|
||||
# between -40F and 180F.
|
||||
heat_capacity_ratio = 1.4
|
||||
|
||||
# https://www.grc.nasa.gov/WWW/K-12/airplane/sound.html
|
||||
gas_constant = 286 # m^2/s^2/K
|
||||
c_sound = math.sqrt(heat_capacity_ratio * gas_constant * temperature_k)
|
||||
# c_sound is in m/s, convert to knots.
|
||||
return (c_sound * 1.944) * mach
|
||||
cruise_mach = max_speed.mach() * 0.8
|
||||
return int(mach(cruise_mach, altitude).knots)
|
||||
|
||||
|
||||
class TravelTime:
|
||||
|
||||
@ -14,6 +14,7 @@ from game.theater import (
|
||||
OffMapSpawn,
|
||||
TheaterGroundObject,
|
||||
)
|
||||
from game.utils import Distance, meters
|
||||
from game.weather import Conditions
|
||||
from .flight import Flight, FlightWaypoint, FlightWaypointType
|
||||
|
||||
@ -53,7 +54,9 @@ class WaypointBuilder:
|
||||
FlightWaypointType.NAV,
|
||||
position.x,
|
||||
position.y,
|
||||
500 if self.is_helo else self.doctrine.rendezvous_altitude
|
||||
meters(
|
||||
500
|
||||
) if self.is_helo else self.doctrine.rendezvous_altitude
|
||||
)
|
||||
waypoint.name = "NAV"
|
||||
waypoint.alt_type = "BARO"
|
||||
@ -64,7 +67,7 @@ class WaypointBuilder:
|
||||
FlightWaypointType.TAKEOFF,
|
||||
position.x,
|
||||
position.y,
|
||||
0
|
||||
meters(0)
|
||||
)
|
||||
waypoint.name = "TAKEOFF"
|
||||
waypoint.alt_type = "RADIO"
|
||||
@ -84,7 +87,9 @@ class WaypointBuilder:
|
||||
FlightWaypointType.NAV,
|
||||
position.x,
|
||||
position.y,
|
||||
500 if self.is_helo else self.doctrine.rendezvous_altitude
|
||||
meters(
|
||||
500
|
||||
) if self.is_helo else self.doctrine.rendezvous_altitude
|
||||
)
|
||||
waypoint.name = "NAV"
|
||||
waypoint.alt_type = "BARO"
|
||||
@ -95,7 +100,7 @@ class WaypointBuilder:
|
||||
FlightWaypointType.LANDING_POINT,
|
||||
position.x,
|
||||
position.y,
|
||||
0
|
||||
meters(0)
|
||||
)
|
||||
waypoint.name = "LANDING"
|
||||
waypoint.alt_type = "RADIO"
|
||||
@ -116,12 +121,12 @@ class WaypointBuilder:
|
||||
position = divert.position
|
||||
if isinstance(divert, OffMapSpawn):
|
||||
if self.is_helo:
|
||||
altitude = 500
|
||||
altitude = meters(500)
|
||||
else:
|
||||
altitude = self.doctrine.rendezvous_altitude
|
||||
altitude_type = "BARO"
|
||||
else:
|
||||
altitude = 0
|
||||
altitude = meters(0)
|
||||
altitude_type = "RADIO"
|
||||
|
||||
waypoint = FlightWaypoint(
|
||||
@ -142,7 +147,9 @@ class WaypointBuilder:
|
||||
FlightWaypointType.LOITER,
|
||||
position.x,
|
||||
position.y,
|
||||
500 if self.is_helo else self.doctrine.rendezvous_altitude
|
||||
meters(
|
||||
500
|
||||
) if self.is_helo else self.doctrine.rendezvous_altitude
|
||||
)
|
||||
waypoint.pretty_name = "Hold"
|
||||
waypoint.description = "Wait until push time"
|
||||
@ -154,7 +161,9 @@ class WaypointBuilder:
|
||||
FlightWaypointType.JOIN,
|
||||
position.x,
|
||||
position.y,
|
||||
500 if self.is_helo else self.doctrine.ingress_altitude
|
||||
meters(
|
||||
500
|
||||
) if self.is_helo else self.doctrine.ingress_altitude
|
||||
)
|
||||
waypoint.pretty_name = "Join"
|
||||
waypoint.description = "Rendezvous with package"
|
||||
@ -166,7 +175,9 @@ class WaypointBuilder:
|
||||
FlightWaypointType.SPLIT,
|
||||
position.x,
|
||||
position.y,
|
||||
500 if self.is_helo else self.doctrine.ingress_altitude
|
||||
meters(
|
||||
500
|
||||
) if self.is_helo else self.doctrine.ingress_altitude
|
||||
)
|
||||
waypoint.pretty_name = "Split"
|
||||
waypoint.description = "Depart from package"
|
||||
@ -179,7 +190,9 @@ class WaypointBuilder:
|
||||
ingress_type,
|
||||
position.x,
|
||||
position.y,
|
||||
500 if self.is_helo else self.doctrine.ingress_altitude
|
||||
meters(
|
||||
500
|
||||
) if self.is_helo else self.doctrine.ingress_altitude
|
||||
)
|
||||
waypoint.pretty_name = "INGRESS on " + objective.name
|
||||
waypoint.description = "INGRESS on " + objective.name
|
||||
@ -193,7 +206,9 @@ class WaypointBuilder:
|
||||
FlightWaypointType.EGRESS,
|
||||
position.x,
|
||||
position.y,
|
||||
500 if self.is_helo else self.doctrine.ingress_altitude
|
||||
meters(
|
||||
500
|
||||
) if self.is_helo else self.doctrine.ingress_altitude
|
||||
)
|
||||
waypoint.pretty_name = "EGRESS from " + target.name
|
||||
waypoint.description = "EGRESS from " + target.name
|
||||
@ -218,7 +233,7 @@ class WaypointBuilder:
|
||||
FlightWaypointType.TARGET_POINT,
|
||||
target.target.position.x,
|
||||
target.target.position.y,
|
||||
0
|
||||
meters(0)
|
||||
)
|
||||
waypoint.description = description
|
||||
waypoint.pretty_name = description
|
||||
@ -249,7 +264,7 @@ class WaypointBuilder:
|
||||
FlightWaypointType.TARGET_GROUP_LOC,
|
||||
location.position.x,
|
||||
location.position.y,
|
||||
0
|
||||
meters(0)
|
||||
)
|
||||
waypoint.description = name
|
||||
waypoint.pretty_name = name
|
||||
@ -274,7 +289,7 @@ class WaypointBuilder:
|
||||
FlightWaypointType.CAS,
|
||||
position.x,
|
||||
position.y,
|
||||
500 if self.is_helo else 1000
|
||||
meters(500) if self.is_helo else meters(1000)
|
||||
)
|
||||
waypoint.alt_type = "RADIO"
|
||||
waypoint.description = "Provide CAS"
|
||||
@ -283,12 +298,12 @@ class WaypointBuilder:
|
||||
return waypoint
|
||||
|
||||
@staticmethod
|
||||
def race_track_start(position: Point, altitude: int) -> FlightWaypoint:
|
||||
def race_track_start(position: Point, altitude: Distance) -> FlightWaypoint:
|
||||
"""Creates a racetrack start waypoint.
|
||||
|
||||
Args:
|
||||
position: Position of the waypoint.
|
||||
altitude: Altitude of the racetrack in meters.
|
||||
altitude: Altitude of the racetrack.
|
||||
"""
|
||||
waypoint = FlightWaypoint(
|
||||
FlightWaypointType.PATROL_TRACK,
|
||||
@ -302,12 +317,12 @@ class WaypointBuilder:
|
||||
return waypoint
|
||||
|
||||
@staticmethod
|
||||
def race_track_end(position: Point, altitude: int) -> FlightWaypoint:
|
||||
def race_track_end(position: Point, altitude: Distance) -> FlightWaypoint:
|
||||
"""Creates a racetrack end waypoint.
|
||||
|
||||
Args:
|
||||
position: Position of the waypoint.
|
||||
altitude: Altitude of the racetrack in meters.
|
||||
altitude: Altitude of the racetrack.
|
||||
"""
|
||||
waypoint = FlightWaypoint(
|
||||
FlightWaypointType.PATROL,
|
||||
@ -321,7 +336,7 @@ class WaypointBuilder:
|
||||
return waypoint
|
||||
|
||||
def race_track(self, start: Point, end: Point,
|
||||
altitude: int) -> Tuple[FlightWaypoint, FlightWaypoint]:
|
||||
altitude: Distance) -> Tuple[FlightWaypoint, FlightWaypoint]:
|
||||
"""Creates two waypoint for a racetrack orbit.
|
||||
|
||||
Args:
|
||||
@ -333,7 +348,7 @@ class WaypointBuilder:
|
||||
self.race_track_end(end, altitude))
|
||||
|
||||
@staticmethod
|
||||
def sweep_start(position: Point, altitude: int) -> FlightWaypoint:
|
||||
def sweep_start(position: Point, altitude: Distance) -> FlightWaypoint:
|
||||
"""Creates a sweep start waypoint.
|
||||
|
||||
Args:
|
||||
@ -352,7 +367,7 @@ class WaypointBuilder:
|
||||
return waypoint
|
||||
|
||||
@staticmethod
|
||||
def sweep_end(position: Point, altitude: int) -> FlightWaypoint:
|
||||
def sweep_end(position: Point, altitude: Distance) -> FlightWaypoint:
|
||||
"""Creates a sweep end waypoint.
|
||||
|
||||
Args:
|
||||
@ -371,7 +386,7 @@ class WaypointBuilder:
|
||||
return waypoint
|
||||
|
||||
def sweep(self, start: Point, end: Point,
|
||||
altitude: int) -> Tuple[FlightWaypoint, FlightWaypoint]:
|
||||
altitude: Distance) -> Tuple[FlightWaypoint, FlightWaypoint]:
|
||||
"""Creates two waypoint for a racetrack orbit.
|
||||
|
||||
Args:
|
||||
@ -404,7 +419,9 @@ class WaypointBuilder:
|
||||
FlightWaypointType.TARGET_GROUP_LOC,
|
||||
target.position.x,
|
||||
target.position.y,
|
||||
500 if self.is_helo else self.doctrine.ingress_altitude
|
||||
meters(
|
||||
500
|
||||
) if self.is_helo else self.doctrine.ingress_altitude
|
||||
)
|
||||
waypoint.name = "TARGET"
|
||||
waypoint.description = "Escort the package"
|
||||
|
||||
@ -153,7 +153,7 @@ class FlightPlanBuilder:
|
||||
self.rows.append([
|
||||
str(waypoint.number),
|
||||
waypoint.waypoint.pretty_name,
|
||||
str(int(units.meters_to_feet(waypoint.waypoint.alt))),
|
||||
str(int(waypoint.waypoint.alt.feet)),
|
||||
self._waypoint_distance(waypoint.waypoint),
|
||||
self._ground_speed(waypoint.waypoint),
|
||||
self._format_time(waypoint.waypoint.tot),
|
||||
|
||||
@ -441,7 +441,7 @@ class QLiberationMap(QGraphicsView):
|
||||
waypoint: FlightWaypoint, position: Tuple[int, int],
|
||||
flight_plan: FlightPlan) -> None:
|
||||
|
||||
altitude = meter_to_feet(waypoint.alt)
|
||||
altitude = int(waypoint.alt.feet)
|
||||
altitude_type = "AGL" if waypoint.alt_type == "RADIO" else "MSL"
|
||||
|
||||
prefix = "TOT"
|
||||
|
||||
@ -12,7 +12,7 @@ class QFlightWaypointInfoBox(QGroupBox):
|
||||
self.flight_wpt = FlightWaypoint(0,0,0)
|
||||
self.x_position_label = QLabel(str(self.flight_wpt.x))
|
||||
self.y_position_label = QLabel(str(self.flight_wpt.y))
|
||||
self.alt_label = QLabel(str(self.flight_wpt.alt))
|
||||
self.alt_label = QLabel(str(int(self.flight_wpt.alt.feet)))
|
||||
self.name_label = QLabel(str(self.flight_wpt.name))
|
||||
self.desc_label = QLabel(str(self.flight_wpt.description))
|
||||
self.init_ui()
|
||||
@ -60,7 +60,7 @@ class QFlightWaypointInfoBox(QGroupBox):
|
||||
self.flight_wpt = FlightWaypoint(0,0,0)
|
||||
self.x_position_label.setText(str(self.flight_wpt.x))
|
||||
self.y_position_label.setText(str(self.flight_wpt.y))
|
||||
self.alt_label.setText(str(self.flight_wpt.alt))
|
||||
self.alt_label.setText(str(int(self.flight_wpt.alt.feet)))
|
||||
self.name_label.setText(str(self.flight_wpt.name))
|
||||
self.desc_label.setText(str(self.flight_wpt.description))
|
||||
self.setTitle(self.flight_wpt.name)
|
||||
|
||||
@ -49,7 +49,7 @@ class QFlightWaypointList(QTableView):
|
||||
|
||||
self.model.setItem(row, 0, QWaypointItem(waypoint, row))
|
||||
|
||||
altitude = meter_to_feet(waypoint.alt)
|
||||
altitude = int(waypoint.alt.feet)
|
||||
altitude_type = "AGL" if waypoint.alt_type == "RADIO" else "MSL"
|
||||
altitude_item = QStandardItem(f"{altitude} ft {altitude_type}")
|
||||
altitude_item.setEditable(False)
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user