Skip to content

Commit

Permalink
Merge pull request #484 from fast-aircraft-design/super-segment
Browse files Browse the repository at this point in the history
"Super" segment
  • Loading branch information
christophe-david committed Mar 23, 2023
2 parents b4788e7 + b824429 commit b50f395
Show file tree
Hide file tree
Showing 10 changed files with 297 additions and 50 deletions.
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# This file is part of FAST-OAD : A framework for rapid Overall Aircraft Design
# Copyright (C) 2022 ONERA & ISAE-SUPAERO
# Copyright (C) 2023 ONERA & ISAE-SUPAERO
# FAST is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
Expand Down Expand Up @@ -49,10 +49,6 @@ def compute_from_start_to_target(self, start, target) -> pd.DataFrame:
pass


TestSegment._attribute_units["vector_parameter_1"] = "kg"
TestSegment._attribute_units["vector_parameter_3"] = "m"


def test_with_custom_segment(cleanup, with_dummy_plugin_2):
input_file_path = pth.join(DATA_FOLDER_PATH, "test_with_custom_segment.xml")
ivc = DataFile(input_file_path).to_ivc()
Expand Down
3 changes: 1 addition & 2 deletions src/fastoad/models/performances/mission/segments/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,13 +24,12 @@
from . import (
altitude_change,
cruise,
end_of_takeoff,
ground_speed_change,
hold,
mass_input,
rotation,
speed_change,
start,
takeoff,
taxi,
transition,
)
48 changes: 25 additions & 23 deletions src/fastoad/models/performances/mission/segments/base.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
"""Base classes for simulating flight segments."""
# This file is part of FAST-OAD : A framework for rapid Overall Aircraft Design
# Copyright (C) 2022 ONERA & ISAE-SUPAERO
# Copyright (C) 2023 ONERA & ISAE-SUPAERO
# FAST is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
Expand All @@ -16,7 +16,7 @@
from abc import ABC, abstractmethod
from copy import deepcopy
from dataclasses import dataclass, field
from typing import Dict, List, Optional, Tuple, Type
from typing import List, Optional, Tuple, Type

import numpy as np
import pandas as pd
Expand Down Expand Up @@ -47,23 +47,23 @@ class SegmentDefinitions(Enum):
"""

@classmethod
def add_segment(cls, segment_name: str, segment_class: Type["AbstractFlightSegment"]):
def add_segment(cls, segment_name: str, segment_class: Type[IFlightPart]):
"""
Adds a segment definition.
:param segment_name: segment names (mission file keyword)
:param segment_class: segment implementation (derived of :class:`~FlightSegment`)
"""
if issubclass(segment_class, AbstractFlightSegment):
if issubclass(segment_class, IFlightPart):
extend_enum(cls, segment_name, segment_class)
else:
raise RuntimeWarning(
f'"{segment_name}" is ignored as segment name because its associated class '
"does not derive from FlightSegment."
"does not derive from IFlightPart."
)

@classmethod
def get_segment_class(cls, segment_name) -> Optional[Type["AbstractFlightSegment"]]:
def get_segment_class(cls, segment_name) -> Optional[Type["IFlightPart"]]:
"""
Provides the segment implementation for provided name.
Expand All @@ -83,12 +83,9 @@ def get_segment_class(cls, segment_name) -> Optional[Type["AbstractFlightSegment
raise FastUnknownMissionSegmentError(segment_name)


@dataclass
class AbstractFlightSegment(IFlightPart, ABC):
class RegisteredSegment(IFlightPart, ABC):
"""
Base class for flight path segment.
As a dataclass, attributes can be set at instantiation.
Base class for classes that can be associated with a keyword in mission definition file.
When subclassing this class, the attribute "mission_file_keyword" can be set,
so that the segment can be used in mission file definition with this keyword:
Expand All @@ -104,6 +101,20 @@ class AbstractFlightSegment(IFlightPart, ABC):
my_phase:
parts:
- segment: new_segment
"""

@classmethod
def __init_subclass__(cls, *, mission_file_keyword=""):
if mission_file_keyword:
SegmentDefinitions.add_segment(mission_file_keyword, cls)


@dataclass
class AbstractFlightSegment(RegisteredSegment, IFlightPart, ABC):
"""
Base class for flight path segment.
As a dataclass, attributes can be set at instantiation.
.. Important::
Expand Down Expand Up @@ -147,12 +158,8 @@ def compute_from_start_to_target(self, start, target) -> pd.DataFrame:
"""

@classmethod
def __init_subclass__(cls, *, mission_file_keyword="", attribute_units: Dict[str, str] = None):
if mission_file_keyword:
SegmentDefinitions.add_segment(mission_file_keyword, cls)
cls._attribute_units = cls._attribute_units.copy()
if attribute_units:
cls._attribute_units.update(attribute_units)
def __init_subclass__(cls, *, mission_file_keyword=""):
super().__init_subclass__(mission_file_keyword=mission_file_keyword)

# We want to have self.target as a property to ensure it gets always "scalarized".
# But properties and dataclasses do not mix very well. It would be possible to
Expand All @@ -173,11 +180,6 @@ def _set_target(self, value: FlightPoint):

cls.target = property(_get_target, _set_target)

@classmethod
def get_attribute_unit(cls, attribute_name: str) -> str:
"""Returns unit for specified attribute."""
return cls._attribute_units.get(attribute_name)

def compute_from(self, start: FlightPoint) -> pd.DataFrame:
"""
Computes the flight path segment from provided start point.
Expand Down Expand Up @@ -635,7 +637,7 @@ def get_distance_to_target(
@dataclass
class TakeOffSegment(AbstractManualThrustSegment, ABC):
"""
Class for computing takeoff segment
Class for computing takeoff segment.
"""

# Default time step for this dynamic segment
Expand Down
3 changes: 1 addition & 2 deletions src/fastoad/models/performances/mission/segments/cruise.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
"""Classes for simulating cruise segments."""
# This file is part of FAST-OAD : A framework for rapid Overall Aircraft Design
# Copyright (C) 2022 ONERA & ISAE-SUPAERO
# Copyright (C) 2023 ONERA & ISAE-SUPAERO
# FAST is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
Expand Down Expand Up @@ -196,7 +196,6 @@ def _climb_to_altitude_and_cruise(
class BreguetCruiseSegment(
CruiseSegment,
mission_file_keyword="breguet",
attribute_units=dict(climb_and_descent_distance="m"),
):
"""
Class for computing cruise flight segment at constant altitude using Breguet-Leduc formula.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
"""
Classes for simulating takeoff-related flight segments.
Be sure to import this package before interpreting a mission input file.
"""
# This file is part of FAST-OAD : A framework for rapid Overall Aircraft Design
# Copyright (C) 2023 ONERA & ISAE-SUPAERO
# FAST is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.

# pylint: disable=unused-import
# flake8: noqa

# With these imports, importing only the current package ensures to have all
# these segments available when interpreting a mission input file
from . import end_of_takeoff, rotation, takeoff
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
"""Classes for climb/descent segments."""
# This file is part of FAST-OAD : A framework for rapid Overall Aircraft Design
# Copyright (C) 2021 ONERA & ISAE-SUPAERO
# Copyright (C) 2023 ONERA & ISAE-SUPAERO
# FAST is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
Expand All @@ -20,14 +20,14 @@
from scipy.constants import g

from fastoad.model_base import FlightPoint
from .base import TakeOffSegment
from ..exceptions import FastFlightSegmentIncompleteFlightPoint
from fastoad.models.performances.mission.exceptions import FastFlightSegmentIncompleteFlightPoint
from fastoad.models.performances.mission.segments.base import TakeOffSegment

_LOGGER = logging.getLogger(__name__) # Logger for this module


@dataclass
class EndOfTakoffSegment(TakeOffSegment, mission_file_keyword="end_of_takeoff"):
class EndOfTakeoffSegment(TakeOffSegment, mission_file_keyword="end_of_takeoff"):
"""
Computes a flight path segment where altitude is modified with constant pitch angle.
As a result, the slope angle and angle of attack are changing through time.
Expand Down Expand Up @@ -87,7 +87,8 @@ def get_distance_to_target(
"No valid target definition for altitude change."
)

def compute_next_alpha(self, next_point: FlightPoint, previous_point: FlightPoint):
@staticmethod
def compute_next_alpha(next_point: FlightPoint, previous_point: FlightPoint):
"""
Computes angle of attack (alpha) based on gamma_dot, using constant pitch angle assumption
Expand All @@ -99,7 +100,8 @@ def compute_next_alpha(self, next_point: FlightPoint, previous_point: FlightPoin
# Constant pitch angle hypothesis
next_point.alpha = previous_point.alpha - time_step * previous_point.slope_angle_derivative

def compute_next_gamma(self, next_point: FlightPoint, previous_point: FlightPoint):
@staticmethod
def compute_next_gamma(next_point: FlightPoint, previous_point: FlightPoint):
"""
Computes slope angle (gamma) based on gamma_dot
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
"""Classes for acceleration/deceleration segments."""
# This file is part of FAST-OAD : A framework for rapid Overall Aircraft Design
# Copyright (C) 2021 ONERA & ISAE-SUPAERO
# Copyright (C) 2023 ONERA & ISAE-SUPAERO
# FAST is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
Expand All @@ -16,11 +16,11 @@
from dataclasses import dataclass
from typing import List

from numpy import pi, sin, cos
from numpy import cos, pi, sin
from scipy.constants import g

from fastoad.model_base import FlightPoint
from .base import GroundSegment
from fastoad.models.performances.mission.segments.base import GroundSegment

_LOGGER = logging.getLogger(__name__) # Logger for this module

Expand All @@ -31,7 +31,7 @@ class RotationSegment(GroundSegment, mission_file_keyword="rotation"):
Computes a flight path segment with constant rotation rate while on ground
and accelerating.
The target is the lift-off. A protection is included is the aicraft reaches
The target is the lift-off. A protection is included is the aircraft reaches
alpha_limit (tail-strike).
"""

Expand Down Expand Up @@ -77,7 +77,7 @@ def get_distance_to_target(
if alpha >= self.alpha_limit:
# Tail strick, issue warning and continue accelerating without rotation
self.rotation_rate = 0.0
_LOGGER.warning("TAIL STRICK during take-off, consider increasing VR.")
_LOGGER.warning("TAIL STRIKE during take-off, consider increasing VR.")

return lift - mass * g

Expand Down

0 comments on commit b50f395

Please sign in to comment.