Example #1
0
    def compute_from(self, start: FlightPoint) -> pd.DataFrame:
        self.complete_flight_point(
            start)  # needed to ensure all speed values are computed.

        if self.target.altitude:
            if isinstance(self.target.altitude, str):
                # Target altitude will be modified along the process, so we keep track
                # of the original order in target CL, that is not used otherwise.
                self.target.CL = self.target.altitude  # pylint: disable=invalid-name
                # let's put a numerical, negative value in self.target.altitude to
                # ensure there will be no problem in self._get_distance_to_target()
                self.target.altitude = -1000.0
                self.interrupt_if_getting_further_from_target = False
            else:
                # Target altitude is fixed, back to original settings (in case
                # this instance is used more than once)
                self.target.CL = None
                self.interrupt_if_getting_further_from_target = True

        atm = AtmosphereSI(start.altitude)
        if self.target.equivalent_airspeed == self.CONSTANT_VALUE:
            start.true_airspeed = atm.get_true_airspeed(
                start.equivalent_airspeed)
        elif self.target.mach == self.CONSTANT_VALUE:
            start.true_airspeed = start.mach * atm.speed_of_sound

        return super().compute_from(start)
Example #2
0
    def _get_distance_to_target(self,
                                flight_points: List[FlightPoint]) -> float:
        current = flight_points[-1]

        # Max flight level is first priority
        max_authorized_altitude = self.maximum_flight_level * 100.0 * foot
        if current.altitude >= max_authorized_altitude:
            return max_authorized_altitude - current.altitude

        if self.target.CL:
            # Optimal altitude is based on a target Mach number, though target speed
            # may be specified as TAS or EAS. If so, Mach number has to be computed
            # for target altitude and speed.

            # First, as target speed is expected to be set to self.CONSTANT_VALUE for one
            # parameter. Let's get the real value from start point.
            target_speed = copy(self.target)
            for speed_param in [
                    "true_airspeed", "equivalent_airspeed", "mach"
            ]:
                if isinstance(getattr(target_speed, speed_param), str):
                    setattr(target_speed, speed_param,
                            getattr(flight_points[0], speed_param))

            # Now, let's compute target Mach number
            atm = AtmosphereSI(max(self.target.altitude, current.altitude))
            if target_speed.equivalent_airspeed:
                target_speed.true_airspeed = atm.get_true_airspeed(
                    target_speed.equivalent_airspeed)
            if target_speed.true_airspeed:
                target_speed.mach = target_speed.true_airspeed / atm.speed_of_sound

            # Now we compute optimal altitude
            optimal_altitude = self._get_optimal_altitude(
                current.mass, target_speed.mach, current.altitude)
            if self.target.CL == self.OPTIMAL_ALTITUDE:
                self.target.altitude = optimal_altitude
            else:  # self.target.CL == self.OPTIMAL_FLIGHT_LEVEL:
                self.target.altitude = get_closest_flight_level(
                    optimal_altitude, up_direction=False)

        if self.target.altitude is not None:
            return self.target.altitude - current.altitude
        if self.target.true_airspeed and self.target.true_airspeed != self.CONSTANT_VALUE:
            return self.target.true_airspeed - current.true_airspeed
        if (self.target.equivalent_airspeed
                and self.target.equivalent_airspeed != self.CONSTANT_VALUE):
            return self.target.equivalent_airspeed - current.equivalent_airspeed
        if self.target.mach is not None and self.target.mach != self.CONSTANT_VALUE:
            return self.target.mach - current.mach

        raise FastFlightSegmentIncompleteFlightPoint(
            "No valid target definition for altitude change.")
Example #3
0
    def compute_from(self, start: FlightPoint) -> pd.DataFrame:
        start = FlightPoint(start)
        self.complete_flight_point(start)  # needed to ensure all speed values are computed.

        if self.target.altitude and self.target.altitude < 0.0:
            # Target altitude will be modified along the process, so we keep track
            # of the original order in target CL, that is not used otherwise.
            self.target.CL = self.target.altitude
            self.interrupt_if_getting_further_from_target = False

        atm = AtmosphereSI(start.altitude)
        if self.target.equivalent_airspeed == "constant":
            start.true_airspeed = atm.get_true_airspeed(start.equivalent_airspeed)
        elif self.target.mach == "constant":
            start.true_airspeed = start.mach * atm.speed_of_sound

        return super().compute_from(start)
Example #4
0
    def _get_distance_to_target(self, flight_points: List[FlightPoint]) -> bool:
        current = flight_points[-1]
        if self.target.CL:
            # Optimal altitude is based on a target Mach number, though target speed
            # may be specified as TAS or EAS. If so, Mach number has to be computed
            # for target altitude and speed.

            # First, as target speed is expected to be set to "constant" for one
            # parameter. Let's get the real value from start point.
            target_speed = FlightPoint(self.target)
            for speed_param in ["true_airspeed", "equivalent_airspeed", "mach"]:
                if isinstance(target_speed.get(speed_param), str):
                    target_speed[speed_param] = flight_points[0][speed_param]

            # Now, let's compute target Mach number
            atm = AtmosphereSI(max(self.target.altitude, current.altitude))
            if target_speed.equivalent_airspeed:
                target_speed.true_airspeed = atm.get_true_airspeed(target_speed.equivalent_airspeed)
            if target_speed.true_airspeed:
                target_speed.mach = target_speed.true_airspeed / atm.speed_of_sound

            # Mach number has to be capped by self.maximum_mach
            target_mach = min(target_speed.mach, self.maximum_mach)

            # Now we compute optimal altitude
            optimal_altitude = self._get_optimal_altitude(
                current.mass, target_mach, current.altitude
            )
            if self.target.CL == self.OPTIMAL_ALTITUDE:
                self.target.altitude = optimal_altitude
            else:  # self.target.CL == self.OPTIMAL_FLIGHT_LEVEL:
                flight_level = 1000 * foot
                self.target.altitude = flight_level * np.floor(optimal_altitude / flight_level)

        if self.target.altitude:
            return self.target.altitude - current.altitude
        elif self.target.true_airspeed:
            return self.target.true_airspeed - current.true_airspeed
        elif self.target.equivalent_airspeed:
            return self.target.equivalent_airspeed - current.equivalent_airspeed
        elif self.target.mach:
            return self.target.mach - current.mach
Example #5
0
    def _complete_speed_values(flight_point: FlightPoint):
        """
        Computes consistent values between TAS, EAS and Mach, assuming one of them is defined.
        """
        atm = AtmosphereSI(flight_point.altitude)

        if flight_point.true_airspeed is None:
            if flight_point.mach is not None:
                flight_point.true_airspeed = flight_point.mach * atm.speed_of_sound
            elif flight_point.equivalent_airspeed is not None:
                flight_point.true_airspeed = atm.get_true_airspeed(
                    flight_point.equivalent_airspeed)
            else:
                raise FastFlightSegmentIncompleteFlightPoint(
                    "Flight point should be defined for true_airspeed, "
                    "equivalent_airspeed, or mach.")
        if flight_point.mach is None:
            flight_point.mach = flight_point.true_airspeed / atm.speed_of_sound

        if flight_point.equivalent_airspeed is None:
            flight_point.equivalent_airspeed = atm.get_equivalent_airspeed(
                flight_point.true_airspeed)