def compute_next_flight_point(self, flight_points: List[FlightPoint], time_step: float) -> FlightPoint: """ Computes time, altitude, speed, mass and ground distance of next flight point. :param flight_points: previous flight points :param time_step: time step for computing next point :return: the computed next flight point """ start = flight_points[0] previous = flight_points[-1] next_point = FlightPoint() next_point.mass = previous.mass - self.propulsion.get_consumed_mass( previous, time_step) next_point.time = previous.time + time_step next_point.ground_distance = ( previous.ground_distance + previous.true_airspeed * time_step * np.cos(previous.slope_angle)) self._compute_next_altitude(next_point, previous) if self.target.true_airspeed == self.CONSTANT_VALUE: next_point.true_airspeed = previous.true_airspeed elif self.target.equivalent_airspeed == self.CONSTANT_VALUE: next_point.equivalent_airspeed = start.equivalent_airspeed elif self.target.mach == self.CONSTANT_VALUE: next_point.mach = start.mach else: next_point.true_airspeed = previous.true_airspeed + time_step * previous.acceleration # The naming is not done in complete_flight_point for not naming the start point next_point.name = self.name return next_point
def compute(self, inputs: Vector, outputs: Vector, start_flight_point: FlightPoint) -> pd.DataFrame: """ To be used during compute() of an OpenMDAO component. Builds the mission from input file, and computes it. `outputs` vector is filled with duration, burned fuel and covered ground distance for each part of the flight. :param inputs: the input vector of the OpenMDAO component :param outputs: the output vector of the OpenMDAO component :param start_flight_point: the starting flight point just after takeoff :return: a pandas DataFrame where columns names match fields of :class:`~fastoad.model_base.flight_point.FlightPoint` """ mission = self.build(inputs, self.mission_name) def _compute_vars(name_root, start: FlightPoint, end: FlightPoint): """Computes duration, burned fuel and covered distance.""" if name_root + ":duration" in outputs: outputs[name_root + ":duration"] = end.time - start.time if name_root + ":fuel" in outputs: outputs[name_root + ":fuel"] = start.mass - end.mass if name_root + ":distance" in outputs: outputs[ name_root + ":distance"] = end.ground_distance - start.ground_distance if not start_flight_point.name: start_flight_point.name = mission.flight_sequence[0].name current_flight_point = start_flight_point flight_points = mission.compute_from(start_flight_point) for part in mission.flight_sequence: var_name_root = "data:mission:%s" % part.name part_end = FlightPoint.create( flight_points.loc[flight_points.name.str.startswith( part.name)].iloc[-1]) _compute_vars(var_name_root, current_flight_point, part_end) if isinstance(part, FlightSequence): # In case of a route, outputs are computed for each phase in the route phase_start = current_flight_point for phase in part.flight_sequence: phase_points = flight_points.loc[flight_points.name == phase.name] if len(phase_points) > 0: phase_end = FlightPoint.create(phase_points.iloc[-1]) var_name_root = "data:mission:%s" % phase.name _compute_vars(var_name_root, phase_start, phase_end) phase_start = phase_end current_flight_point = part_end # Outputs for the whole mission var_name_root = "data:mission:%s" % mission.name _compute_vars(var_name_root, start_flight_point, current_flight_point) return flight_points