Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add keyword argument in AbstractManualThrustFlightPhase class #382

Open
vinx012 opened this issue Sep 16, 2021 · 6 comments
Open

Add keyword argument in AbstractManualThrustFlightPhase class #382

vinx012 opened this issue Sep 16, 2021 · 6 comments
Assignees
Labels
enhancement New feature or request

Comments

@vinx012
Copy link

vinx012 commented Sep 16, 2021

Hello,

I have an "electric_power_rate' variable that I want to pass to the engine class as it's done for the 'thrust_rate' variable. In order to do that, I had to create a new 'AbstractManualThrustFlightPhase' class to add the new variable. Is there a better way to do it which doesn't lead to this kind of redundancy?

N.b.: I am using the version 0.5.4b0

Thanks,
Vincenzo

@vinx012 vinx012 added the enhancement New feature or request label Sep 16, 2021
@christophe-david
Copy link
Contributor

Is there a better way to do it which doesn't lead to this kind of redundancy?

Not in the version you use, I'm afraid.

In current version (1.0.5), it would be possible to do something more efficient:
The idea in the current performance model is that missions are defined by YAML files. In these files, segments are the base building blocks, and each segment type is implemented as a Python class.

What is currently not advertised in the documentation, is that it is possible to build very easily custom segment types, by subclassing the class FlightSegment. As said in the example of the class documentation, you can create a class NewSegment that will be callable, as a segment type, in the mission file with the keyword new_segment.

Another thing to be known, is that the segment parameters that are available in the mission file are declared in the segment classes as dataclass fields.

Therefore, anywhere in the code you run, you may define a new class like this one:

from fastoad.models.performances.mission.segments.speed_change import SpeedChangeSegment

@dataclass
class SpeedChangeElectric(SpeedChangeSegment, mission_file_keyword="speed_change_electric"):
    electric_power_rate: float = 0.0  # do not forget the type hint, required by the data class syntax, 
                                      # and the default value that is needed "because of the inheritance" (short story)

With only these few lines, you get a usable segment type for the mission files, called speed_change_electric, that handles accelerations/decelerations, with all parameters of the original speed_change segment type, but with the added parameter electric_power_rate.

The drawback of this method (besides the fact that you are not using the needed version of FAST-OAD) is that you have to do
your specific segments (which is the intended purpose of the feature), though in this case, it would make sense to only add the parameter to the existing ones. Moreover, knowing that SpeedChangeSegment and AltitudeChangeSegment both inherit from ManualThrustSegment, it would be nice to simply add the parameter to ManualThrustSegment.
This looks very much like what we implemented for the FlightPoint class, so maybe we could apply the same logic.

@vinx012
Copy link
Author

vinx012 commented Sep 16, 2021

Hello Christophe,

Thanks for the answer. I haven't planned to upgrade to the latest version anytime soon, but thanks for the insights.

Regarding the segment classes, I am aware the simplest thing to do would be to add the decorator @AddKeyAttributes({"electric_power_rate": 0.}) the line before the class definition of 'ManualThrustSegment', however that would mean having to modify the original FAST-OAD files, whereas I try to keep the whole FAST-OAD directory unchanged. Therefore in order to avoid too many redundancies of classes I preferred to create a new 'SpeedChangeSegment' and 'AltitudeChangeSegment' as follows:

from fastoad.models.performances.mission.segments.altitude_change import AltitudeChangeSegment

@AddKeyAttributes({"power_rate_electric": 0.0})
class AltitudeChangeSegmentHybrid(AltitudeChangeSegment):
    """
    Computes a flight path segment where altitude is modified with constant speed 
    with a given thrust_rate and electric_power_rate
    
    """

    def _compute_propulsion(self, flight_point: FlightPoint):
        flight_point.thrust_rate = self.thrust_rate
        flight_point.power_rate_electric = self.power_rate_electric
        flight_point.thrust_is_regulated = False
        self.propulsion.compute_flight_points(flight_point)

@vinx012
Copy link
Author

vinx012 commented Sep 16, 2021

I have also tried to do something like this:

AddKeyAttribute("power_rate_electric",0.)(SEGMENT_KEYWORD_ARGUMENTS)

Howevr adding this line at the beginning of my standard_flight class give me the following error:
AttributeError: 'dict' object has no attribute 'power_rate_electric'

Why is that? I was expecting it to work exactly like for the flight_points class

@vinx012
Copy link
Author

vinx012 commented Sep 16, 2021

Why is that? I was expecting it to work exactly like for the flight_points class

I guess it is because "SEGMENT_KEYWORD_ARGUMENTS" is simple dictionary, whereas FlightPoint is a DynamicAttributeDict. Is that right?

@christophe-david
Copy link
Contributor

Thank you for these elements. I had completely forgotten about the DynamicAttributeDict 😅.

And actually, it allows you to avoid duplicating segment classes. You just have to run the line

AddKeyAttributes({"electric_power_rate": 0.0})(ManualThrustSegment)

and you get this attribute available in this class and its inheritors.
(and yes, it works only with the class that inherits from DynamicAttributeDict, and SEGMENT_KEYWORD_ARGUMENTS is not such class. Actually, it is not even a class! )

Nevertheless, since your original question is about 'AbstractManualThrustFlightPhase, that does not inherit from DynamicAttributeDict, you cannot apply this solution to it.

@christophe-david
Copy link
Contributor

Just realizing my last comment is probably irrelevant, because you have to manage your electric_power_rate parameter in the ManualThrustSegment class, hence you have to produce your own version of this class...

And though the architecture has changed, I think that problem still applies to version 1.x. We will have to check that out...

@christophe-david christophe-david self-assigned this Nov 2, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

2 participants