mirror of
https://github.com/dcs-retribution/dcs-retribution.git
synced 2025-11-10 15:41:24 +00:00
Differentiate total time and travel time.
There's an ugly special case in flight simulation to handle hold points because we don't differentiate between the total time between two waypoints (which can include delays from actions like holding) and travel time. Split those up and remove the special case.
This commit is contained in:
parent
5ca344e87b
commit
75498fe061
@ -231,8 +231,23 @@ class FlightPlan(ABC, Generic[LayoutT]):
|
|||||||
)
|
)
|
||||||
|
|
||||||
for previous_waypoint, waypoint in self.edges(until=destination):
|
for previous_waypoint, waypoint in self.edges(until=destination):
|
||||||
total += self.travel_time_between_waypoints(previous_waypoint, waypoint)
|
total += self.total_time_between_waypoints(previous_waypoint, waypoint)
|
||||||
return total
|
# Trim microseconds. Our simulation tick rate is 1 second, so anything that
|
||||||
|
# takes 100.1 or 100.9 seconds will take 100 seconds. DCS doesn't handle
|
||||||
|
# sub-second resolution for tasks anyway, nor are they interesting from a
|
||||||
|
# mission planning perspective, so there's little value to keeping them in the
|
||||||
|
# model.
|
||||||
|
return timedelta(seconds=math.floor(total.total_seconds()))
|
||||||
|
|
||||||
|
def total_time_between_waypoints(
|
||||||
|
self, a: FlightWaypoint, b: FlightWaypoint
|
||||||
|
) -> timedelta:
|
||||||
|
"""Returns the total time spent between a and b.
|
||||||
|
|
||||||
|
The total time between waypoints differs from the travel time in that it may
|
||||||
|
include additional time for actions such as loitering.
|
||||||
|
"""
|
||||||
|
return self.travel_time_between_waypoints(a, b)
|
||||||
|
|
||||||
def travel_time_between_waypoints(
|
def travel_time_between_waypoints(
|
||||||
self, a: FlightWaypoint, b: FlightWaypoint
|
self, a: FlightWaypoint, b: FlightWaypoint
|
||||||
|
|||||||
@ -14,7 +14,6 @@ from game.utils import Speed, meters, nautical_miles, feet
|
|||||||
from .flightplan import FlightPlan
|
from .flightplan import FlightPlan
|
||||||
from .formation import FormationFlightPlan, FormationLayout
|
from .formation import FormationFlightPlan, FormationLayout
|
||||||
from .ibuilder import IBuilder
|
from .ibuilder import IBuilder
|
||||||
from .planningerror import PlanningError
|
|
||||||
from .waypointbuilder import StrikeTarget, WaypointBuilder
|
from .waypointbuilder import StrikeTarget, WaypointBuilder
|
||||||
from .. import FlightType
|
from .. import FlightType
|
||||||
from ..flightwaypoint import FlightWaypoint
|
from ..flightwaypoint import FlightWaypoint
|
||||||
@ -56,42 +55,19 @@ class FormationAttackFlightPlan(FormationFlightPlan, ABC):
|
|||||||
"RADIO",
|
"RADIO",
|
||||||
)
|
)
|
||||||
|
|
||||||
@property
|
|
||||||
def travel_time_to_target(self) -> timedelta:
|
|
||||||
"""The estimated time between the first waypoint and the target."""
|
|
||||||
destination = self.tot_waypoint
|
|
||||||
total = timedelta()
|
|
||||||
for previous_waypoint, waypoint in self.edges():
|
|
||||||
if waypoint == self.tot_waypoint:
|
|
||||||
# For anything strike-like the TOT waypoint is the *flight's*
|
|
||||||
# mission target, but to synchronize with the rest of the
|
|
||||||
# package we need to use the travel time to the same position as
|
|
||||||
# the others.
|
|
||||||
total += self.travel_time_between_waypoints(
|
|
||||||
previous_waypoint, self.target_area_waypoint
|
|
||||||
)
|
|
||||||
break
|
|
||||||
total += self.travel_time_between_waypoints(previous_waypoint, waypoint)
|
|
||||||
else:
|
|
||||||
raise PlanningError(
|
|
||||||
f"Did not find destination waypoint {destination} in "
|
|
||||||
f"waypoints for {self.flight}"
|
|
||||||
)
|
|
||||||
return total
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def join_time(self) -> timedelta:
|
def join_time(self) -> timedelta:
|
||||||
travel_time = self.travel_time_between_waypoints(
|
travel_time = self.total_time_between_waypoints(
|
||||||
self.layout.join, self.layout.ingress
|
self.layout.join, self.layout.ingress
|
||||||
)
|
)
|
||||||
return self.ingress_time - travel_time
|
return self.ingress_time - travel_time
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def split_time(self) -> timedelta:
|
def split_time(self) -> timedelta:
|
||||||
travel_time_ingress = self.travel_time_between_waypoints(
|
travel_time_ingress = self.total_time_between_waypoints(
|
||||||
self.layout.ingress, self.target_area_waypoint
|
self.layout.ingress, self.target_area_waypoint
|
||||||
)
|
)
|
||||||
travel_time_egress = self.travel_time_between_waypoints(
|
travel_time_egress = self.total_time_between_waypoints(
|
||||||
self.target_area_waypoint, self.layout.split
|
self.target_area_waypoint, self.layout.split
|
||||||
)
|
)
|
||||||
minutes_at_target = 0.75 * len(self.layout.targets)
|
minutes_at_target = 0.75 * len(self.layout.targets)
|
||||||
@ -106,7 +82,7 @@ class FormationAttackFlightPlan(FormationFlightPlan, ABC):
|
|||||||
@property
|
@property
|
||||||
def ingress_time(self) -> timedelta:
|
def ingress_time(self) -> timedelta:
|
||||||
tot = self.tot
|
tot = self.tot
|
||||||
travel_time = self.travel_time_between_waypoints(
|
travel_time = self.total_time_between_waypoints(
|
||||||
self.layout.ingress, self.target_area_waypoint
|
self.layout.ingress, self.target_area_waypoint
|
||||||
)
|
)
|
||||||
return tot - travel_time
|
return tot - travel_time
|
||||||
|
|||||||
@ -33,10 +33,10 @@ class LoiterFlightPlan(StandardFlightPlan[Any], ABC):
|
|||||||
return self.push_time + self.tot_offset
|
return self.push_time + self.tot_offset
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def travel_time_between_waypoints(
|
def total_time_between_waypoints(
|
||||||
self, a: FlightWaypoint, b: FlightWaypoint
|
self, a: FlightWaypoint, b: FlightWaypoint
|
||||||
) -> timedelta:
|
) -> timedelta:
|
||||||
travel_time = super().travel_time_between_waypoints(a, b)
|
travel_time = super().total_time_between_waypoints(a, b)
|
||||||
if a != self.layout.hold:
|
if a != self.layout.hold:
|
||||||
return travel_time
|
return travel_time
|
||||||
return travel_time + self.hold_duration
|
return travel_time + self.hold_duration
|
||||||
|
|||||||
@ -59,10 +59,10 @@ class PackageRefuelingFlightPlan(RefuelingFlightPlan):
|
|||||||
"REFUEL", FlightWaypointType.REFUEL, refuel, altitude
|
"REFUEL", FlightWaypointType.REFUEL, refuel, altitude
|
||||||
)
|
)
|
||||||
|
|
||||||
delay_target_to_split: timedelta = self.travel_time_between_waypoints(
|
delay_target_to_split: timedelta = self.total_time_between_waypoints(
|
||||||
self.target_area_waypoint(), split_waypoint
|
self.target_area_waypoint(), split_waypoint
|
||||||
)
|
)
|
||||||
delay_split_to_refuel: timedelta = self.travel_time_between_waypoints(
|
delay_split_to_refuel: timedelta = self.total_time_between_waypoints(
|
||||||
split_waypoint, refuel_waypoint
|
split_waypoint, refuel_waypoint
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@ -56,7 +56,7 @@ class SweepFlightPlan(LoiterFlightPlan):
|
|||||||
|
|
||||||
@property
|
@property
|
||||||
def sweep_start_time(self) -> timedelta:
|
def sweep_start_time(self) -> timedelta:
|
||||||
travel_time = self.travel_time_between_waypoints(
|
travel_time = self.total_time_between_waypoints(
|
||||||
self.layout.sweep_start, self.layout.sweep_end
|
self.layout.sweep_start, self.layout.sweep_end
|
||||||
)
|
)
|
||||||
return self.sweep_end_time - travel_time
|
return self.sweep_end_time - travel_time
|
||||||
|
|||||||
@ -51,17 +51,9 @@ class InFlight(FlightState, ABC):
|
|||||||
return index <= self.waypoint_index
|
return index <= self.waypoint_index
|
||||||
|
|
||||||
def travel_time_between_waypoints(self) -> timedelta:
|
def travel_time_between_waypoints(self) -> timedelta:
|
||||||
travel_time = self.flight.flight_plan.travel_time_between_waypoints(
|
return self.flight.flight_plan.travel_time_between_waypoints(
|
||||||
self.current_waypoint, self.next_waypoint
|
self.current_waypoint, self.next_waypoint
|
||||||
)
|
)
|
||||||
if self.current_waypoint.waypoint_type is FlightWaypointType.LOITER:
|
|
||||||
# Loiter time is already built into travel_time_between_waypoints. If we're
|
|
||||||
# at a loiter point but still a regular InFlight (Loiter overrides this
|
|
||||||
# method) that means we're traveling from the loiter point but no longer
|
|
||||||
# loitering.
|
|
||||||
assert self.flight.flight_plan.is_loiter(self.flight.flight_plan)
|
|
||||||
travel_time -= self.flight.flight_plan.hold_duration
|
|
||||||
return travel_time
|
|
||||||
|
|
||||||
@abstractmethod
|
@abstractmethod
|
||||||
def estimate_position(self) -> Point:
|
def estimate_position(self) -> Point:
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user