-
Notifications
You must be signed in to change notification settings - Fork 462
New issue
Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? # to your account
Do not store the result of FGFDMExec::GetAtmosphere()
.
#908
Do not store the result of FGFDMExec::GetAtmosphere()
.
#908
Conversation
Codecov Report
@@ Coverage Diff @@
## master #908 +/- ##
==========================================
+ Coverage 23.16% 23.18% +0.02%
==========================================
Files 167 167
Lines 19644 19657 +13
==========================================
+ Hits 4551 4558 +7
- Misses 15093 15099 +6
|
I planned to mention in the earlier pull request, just very busy with work at the moment, before @agodemar merged it in very quickly, that Line 247 in db830c6
|
The other general comment I was going to make, is that in general the switching of models like this is a bit messy. I had started taking a look at the initialisation order, what other models depend on each other before any XML files are loaded in etc. The one other somewhat similiar case I noticed was in terms of the ability to change some of the planet's constants. There is special code to handle that case, involving resetting and re-initiliasing other models again etc. In that particular case there isn't the added complication of property bindings. As I mentioned I'm quite busy work-wise, so haven't had enough time to go through it in detail and make useful comments/suggestions. Just that at first glance as I mentioned above, it seems somewhat messy. So half-wondering whether there isn't some other mechanism to process these sorts of requirements, i.e. planet constants, athmosphere model selection etc. earlier, i.e. before JSBSim currently starts reading XML files, so that we can initialise the Inertial (planet constants) model, atmosphere model etc. once up-front. Talking of which, where would the user typically specify the atmosphere model that they want to use for a simulation run? |
Sorry guys @bcoconni @seanmcleod for merging too quickly |
No problem, I was a bit slow 😉 |
That's a good point and fortunately I did not overlook it: https://github.com/bcoconni/jsbsim/blob/2bd695bdca57a0a5167eaf22c29cfcfa6eeb9fc8/src/FGFDMExec.cpp#L825
I agree that these PR (i.e. #902 and the current one) bring some complexity that we'd like to avoid. However the situation might not be as bad as it sounds. Below is an extract of the code I'm currently working on and that would be integrated in Element* atm_element = element->FindElement("atmosphere");
if (atm_element) {
if (atm_element->HasAttribute("model")) {
string model = atm_element->GetAttributeValue("model");
if (model == "MSIS") {
// Replace the existing atmosphere model
instance->Unbind(Models[eAtmosphere]);
Models[eAtmosphere] = std::make_shared<MSIS>(this);
Atmosphere = static_cast<FGAtmosphere*>(Models[eAtmosphere].get());
// Model initialization sequence
LoadInputs(eAtmosphere);
Atmosphere->InitModel();
Atmosphere->Load(element);
InitializeModels();
}
}
} There is indeed some boilerplate but it's not that bad.
I understand that you are referring to the following code: Lines 802 to 813 in db830c6
You are making a good point and I think that the bind/unbind problem has been overlooked for this particular case. This needs some investigation.
No problem. There is no rush.
Suggestions are welcome and I mean it. That is really the point of submitting code via a PR.
I'm currently considering adding an <planet name="Earth">
<atmosphere model="MSIS"/>
</planet> The |
@agodemar no problem on my side either 😉 |
After some further thoughts, the issue of binding/unbinding does not apply in this case as the instance of Lines 800 to 812 in 1e19876
To avoid the unbing/binding sequence I can imagine 3 options:
Option 1 -
|
FGAtmosphere::FGAtmosphere(FGFDMExec* fdmex) | |
: FGModel(fdmex), | |
StdDaySLsoundspeed(sqrt(SHRatio*Reng0*StdDaySLtemperature)) | |
{ | |
Name = "FGAtmosphere"; | |
bind(); | |
Debug(0); | |
} |
bind(); |
However the gain would be minimal as we would trade one line of code for another one:
Element* atm_element = element->FindElement("atmosphere");
if (atm_element) {
if (atm_element->HasAttribute("model")) {
string model = atm_element->GetAttributeValue("model");
if (model == "MSIS") {
// Replace the existing atmosphere model
- instance->Unbind(Models[eAtmosphere]);
Models[eAtmosphere] = std::make_shared<MSIS>(this);
Atmosphere = static_cast<FGAtmosphere*>(Models[eAtmosphere].get());
// Model initialization sequence
LoadInputs(eAtmosphere);
Atmosphere->InitModel();
Atmosphere->Load(element);
InitializeModels();
}
}
}
+ Atmosphere->bind();
In addition, this option would not prevent the need for the current PR as we would still delete the current instance of FGAtmosphere
and replace it by an instance of FGMSIS
. So we would still need to make sure that nowhere a pointer to the deleted instance has been stored.
This change would also make FGAtmosphere
one of a kind as it would be the only FGModel
inherited class that would delegate the call to its bind()
method to FGFDMExec
.
These are my 2 cents and hopefully these suggestions will feed the discussion 😃
Correct, I did look at how the update to the So my general question was whether these sorts of requests by the user, planet constants, atmospheric model to use etc. couldn't be read in earlier via some "system initialization" file (initial conditions 'like') so that the relevant models could be initialized once and before any of the other models that take dependencies on them. I wasn't that familiar of how the planet constants were specified by the user and how you planned for the user to specify the atmosphere model they wanted to use. So looking at the planet case it looks like it gets specified inside the FDM XML file right? Just seems a bit weird in the sense of it not really being a property of the aircraft model, rather something external. So if I want to run the 737 model using planet constants X and atmosphere model Y I need to add them to the 737's FDM? And then remove them/edit them for another run with a different set? Shouldn't these rather be specified external to the FDM, a bit like initial condition files? |
Correct.
Correct.
I hadn't thought about that and your suggestion is making sense. I guess we could add a method |
…#908) * Do not store the result of `FGFDMExec::GetAtmosphere()`. * Constification to clarify the intent.
This PR is a followup of the PR #902.
As was exposed in #902, we might need to modify the atmosphere model when
FGFDMExec::LoadModel()
is executed and that would result inModel[eAtmosphere]
being modified. As a result if a class stores the pointer returned byFGFDMExec::GetAtmosphere()
before the atmosphere model could be modified then this pointer could be invalidated.This sequence of events exists when the constructor of the class
FGInitialCondition
is called and stores a copy ofFGFDMExec::GetAtmosphere()
in its memberAtmosphere
:jsbsim/src/initialization/FGInitialCondition.cpp
Lines 62 to 67 in db830c6
And the constructor of
FGInitialCondition
is called from the constructor ofFGFDMExec
i.e. beforeFGFDMExec::LoadModel()
is executed:jsbsim/src/FGFDMExec.cpp
Line 267 in db830c6
This PR addresses this issue by removing the storage of a copy of the result of
FGFDMExec::GetAtmosphere()
. After the PR will be merged,FGInitialCondition
will callFGFDMExec::GetAtmosphere()
each time it needs to get data from the atmosphere model. AsFGInitialCondition
is only used during initialization, the performance impact (if any) is negligible.The classes
FGOutputType
,FGOutputTextFile
andFGOutputSocket
also store a copy ofFGFDMExec::GetAtmosphere()
but strictly speaking they are not concerned by this issue as they are created byFGOutput::Load()
after the atmosphere model would be modified:jsbsim/src/models/FGOutput.cpp
Lines 202 to 220 in db830c6
Indeed
FGOutput
is the lastFGModel
instance that parses the XML files:jsbsim/src/FGFDMExec.cpp
Lines 940 to 948 in db830c6
However this PR extends the requirement of not storing a copy of
FGFDMExec::GetAtmosphere()
to all classes because this fortunate call sequence might be (accidentally ?) broken in the future for the classesFGOutputType
,FGOutputTextFile
andFGOutputSocket
. In addition the performance impact is low as well for output classes as outputs are generally not requested at every time step and furthermore the call toFGFDMExec::GetAtmosphere()
will be inlined by compilers.