Skip to content

Add a per-model execution-enable property#1481

Open
Zaretto wants to merge 3 commits into
JSBSim-Team:masterfrom
Zaretto:feature/model-enabled-property
Open

Add a per-model execution-enable property#1481
Zaretto wants to merge 3 commits into
JSBSim-Team:masterfrom
Zaretto:feature/model-enabled-property

Conversation

@Zaretto

@Zaretto Zaretto commented Jun 23, 2026

Copy link
Copy Markdown
Contributor

Implements per-model enable proposed by @bcoconni in #1390.

The suggested solution (#1390 (comment)):

  • add a property to each model, managed by FGModel
  • when false, FGModel::Run() returns true and the model is skipped
  • name it simulation/models/{Name}/enabled

This branch:

  • adds simulation/models//enabled for every scheduled model, default true
  • checks it in FGModel::Run() via the existing "skip this frame" return that every model already honours
  • binds one property per model in FGFDMExec, in eModels order

Behaviour is unchanged unless a model is explicitly disabled. A disabled model's body does not run, but its last state and property bindings are preserved, so an external system can take over that model in place, for example an external propagator owning FGPropagate.

Two notes:

  • the names are fixed in eModels order rather than read from FGModel::Name, because some models rename themselves when their config loads. That is the only deviation from the {Name} form in the original suggestion.
  • a static_assert keeps the name table in step with the eModels enum

@codecov

codecov Bot commented Jun 23, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 86.36364% with 3 lines in your changes missing coverage. Please review.
✅ Project coverage is 25.03%. Comparing base (0b99c70) to head (2112cf8).
⚠️ Report is 7 commits behind head on master.

Files with missing lines Patch % Lines
src/input_output/FGInputType.cpp 0.00% 2 Missing ⚠️
src/input_output/FGOutputType.cpp 0.00% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##           master    #1481      +/-   ##
==========================================
- Coverage   25.10%   25.03%   -0.08%     
==========================================
  Files         171      171              
  Lines       18843    18827      -16     
==========================================
- Hits         4731     4713      -18     
- Misses      14112    14114       +2     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Zaretto added a commit to Zaretto/jsbsim that referenced this pull request Jun 23, 2026
Adds Setadot, Setbdot, SetNx, SetNy and SetNz to FGAuxiliary so a host that owns the state integration can inject the alpha/beta rates and body-axis load factors that Auxiliary would otherwise derive from the propagation it is no longer running.

The host-owned domain is propagation together with ground reactions. The two are tightly coupled through the 6DoF integration and are externalised as one unit, so when a host takes them over these are among the few derived quantities Auxiliary cannot recompute and must be supplied.

Together with the per-model enable property (JSBSim-Team#1481), this is the main JSBSim-core change needed to host the engine inside an externally hosted simulation such as DCS World. The rest reuses existing mechanisms: atmosphere override, FGWinds, and the existing velocity setters. A large capability for a small, additive surface. It follows the state-propagation review that Agostino De Marco raised in JSBSim-Team#1390 and JSBSim-Team#1391.
Zaretto added a commit to Zaretto/jsbsim that referenced this pull request Jun 23, 2026
Adds Setadot, Setbdot, SetNx, SetNy and SetNz to FGAuxiliary so a host that owns the state integration can inject the alpha/beta rates and body-axis load factors that Auxiliary would otherwise derive from the propagation it is no longer running.

The host-owned domain is propagation together with ground reactions. The two are tightly coupled through the 6DoF integration and are externalised as one unit, so when a host takes them over these are among the few derived quantities Auxiliary cannot recompute and must be supplied.

Together with the per-model enable property (JSBSim-Team#1481), this is the main JSBSim-core change needed to host the engine inside an externally hosted simulation such as DCS World. The rest reuses existing mechanisms: atmosphere override, FGWinds, and the existing velocity setters. A large capability for a small, additive surface. It follows the state-propagation review that Agostino De Marco raised in JSBSim-Team#1390 and JSBSim-Team#1391.
Each scheduled model gains a simulation/models/<name>/enabled property (default true), bound by FGFDMExec using a stable canonical name per eModels. When the property is set false, FGModel::Run() skips the model's body while its last state and property bindings are preserved. This is a property-tree mechanism by which an external system can replace a model, for example an external propagator owning FGPropagate, or a host physics engine owning ground reactions, without removing it from the schedule.

Behaviour is unchanged unless a model is explicitly disabled. The canonical names are deliberately independent of FGModel::Name, since some models rename themselves when their config is loaded. A static_assert keeps the name table in step with the eModels enum.
@Zaretto Zaretto force-pushed the feature/model-enabled-property branch from a0aa665 to 1399a6b Compare June 23, 2026 12:33
@seanmcleod70

Copy link
Copy Markdown
Contributor

I took a look at #1390 to refresh my memory of some of the earlier discussions and came across my comment at the time towards the end of the thread, see - #1390 (comment)

Which it doesn't look like it was answered at the time, so my questions still stand.

@bcoconni

bcoconni commented Jun 30, 2026

Copy link
Copy Markdown
Member

I agree with you @seanmcleod70 and in addition to that, I am not too happy with the implementation. I am really struggling about why the enable/disable feature should imply modifying the FGFDMExec class and not be totally delegated to the classes that inherit from FGModel ? 🤔

[...] some models rename themselves when their config loads. That is the only deviation from the {Name} form in the original suggestion.

This does not look like a reason to me for centralizing the feature in FGFDMExec.

@Zaretto

Zaretto commented Jul 6, 2026

Copy link
Copy Markdown
Contributor Author

Taking the general question about this and #1482 - I agree that a single MR is better.

#1390 ... doesn't look like it was answered at the time, so my questions still stand.

@seanmcleod70 the points you raised in #1390 about Auxiliary are the reason why my approach changed because you were right that replacing Auxiliary with a handful of setters only appeared to be working.

So this change together with #1482 are what I've ended up with because the better design is actually to run most of the models except the one that absolutely must be replaced which in this case is Propagate.

I did all of the models because that is what I understood that @bcoconni wanted even though all that actually is needed for this case is to be able to disable the Propagate model

There is a good argument for disabling ground reactions completely but that isn't necessary for my work because keeping the gear retracted achieves the same, albeit with a small performance hit.

@bcoconni asked a good question about centralizing the feature and original reason was to follow the way that exec is already managing allocating all of the models. In hindsight this isn't really adding much and instead I'd change the FGModel constructor to accept an optional enableName parameter that when present would call BindModelEnabled(enableName);

@bcoconni

bcoconni commented Jul 6, 2026

Copy link
Copy Markdown
Member

I did all of the models because that is what I understood that @bcoconni wanted even though all that actually is needed for this case is to be able to disable the Propagate model

My point was that if we want to be able to disable any model then IMHO the best option is to add a property to FGModel. Now if your PR only targets FGPropagate then maybe modifying the FGModel class is not the way to proceed and you should only focus your changes on FGPropagate?

I mean we may target a change with a reduced scope for a start and then after having cumulated some experience over the usage of that feature, we may be able to extend the concept to all instances of FGModel?

@seanmcleod70 the points you raised in #1390 about Auxiliary are the reason why my approach changed because you were right that replacing Auxiliary with a handful of setters only appeared to be working.

I do not follow your point here. @seanmcleod70 made some good points about the extent of the setters that would have to be added but also about the properties that would no longer be updated. How your PR is addressing that particular issue?

Because FGPropagate manages a lot of properties:

PropertyManager->Tie("velocities/h-dot-fps", this, &FGPropagate::Gethdot);
PropertyManager->Tie("velocities/v-north-fps", this, eNorth, &FGPropagate::GetVel);
PropertyManager->Tie("velocities/v-east-fps", this, eEast, &FGPropagate::GetVel);
PropertyManager->Tie("velocities/v-down-fps", this, eDown, &FGPropagate::GetVel);
PropertyManager->Tie("velocities/u-fps", this, eU, &FGPropagate::GetUVW);
PropertyManager->Tie("velocities/v-fps", this, eV, &FGPropagate::GetUVW);
PropertyManager->Tie("velocities/w-fps", this, eW, &FGPropagate::GetUVW);
PropertyManager->Tie("velocities/p-rad_sec", this, eP, &FGPropagate::GetPQR);
PropertyManager->Tie("velocities/q-rad_sec", this, eQ, &FGPropagate::GetPQR);
PropertyManager->Tie("velocities/r-rad_sec", this, eR, &FGPropagate::GetPQR);
PropertyManager->Tie("velocities/pi-rad_sec", this, eP, &FGPropagate::GetPQRi);
PropertyManager->Tie("velocities/qi-rad_sec", this, eQ, &FGPropagate::GetPQRi);
PropertyManager->Tie("velocities/ri-rad_sec", this, eR, &FGPropagate::GetPQRi);
PropertyManager->Tie("velocities/eci-x-fps", this, eX, &FGPropagate::GetInertialVelocity);
PropertyManager->Tie("velocities/eci-y-fps", this, eY, &FGPropagate::GetInertialVelocity);
PropertyManager->Tie("velocities/eci-z-fps", this, eZ, &FGPropagate::GetInertialVelocity);
PropertyManager->Tie("velocities/ecef-x-fps", this, eX, &FGPropagate::GetECEFVelocity);
PropertyManager->Tie("velocities/ecef-y-fps", this, eY, &FGPropagate::GetECEFVelocity);
PropertyManager->Tie("velocities/ecef-z-fps", this, eZ, &FGPropagate::GetECEFVelocity);
PropertyManager->Tie("velocities/eci-velocity-mag-fps", this, &FGPropagate::GetInertialVelocityMagnitude);
PropertyManager->Tie("velocities/ned-velocity-mag-fps", this, &FGPropagate::GetNEDVelocityMagnitude);
PropertyManager->Tie("position/h-sl-ft", this, &FGPropagate::GetAltitudeASL,
&FGPropagate::SetAltitudeASL);
PropertyManager->Tie("position/h-sl-meters", this, &FGPropagate::GetAltitudeASLmeters,
&FGPropagate::SetAltitudeASLmeters);
PropertyManager->Tie("position/lat-gc-rad", this, &FGPropagate::GetLatitude,
&FGPropagate::SetLatitude);
PropertyManager->Tie("position/long-gc-rad", this, &FGPropagate::GetLongitude,
&FGPropagate::SetLongitude);
PropertyManager->Tie("position/lat-gc-deg", this, &FGPropagate::GetLatitudeDeg,
&FGPropagate::SetLatitudeDeg);
PropertyManager->Tie("position/long-gc-deg", this, &FGPropagate::GetLongitudeDeg,
&FGPropagate::SetLongitudeDeg);
PropertyManager->Tie("position/lat-geod-rad", this, &FGPropagate::GetGeodLatitudeRad);
PropertyManager->Tie("position/lat-geod-deg", this, &FGPropagate::GetGeodLatitudeDeg);
PropertyManager->Tie("position/geod-alt-ft", this, &FGPropagate::GetGeodeticAltitude);
PropertyManager->Tie("position/h-agl-ft", this, &FGPropagate::GetDistanceAGL,
&FGPropagate::SetDistanceAGL);
PropertyManager->Tie("position/geod-alt-km", this, &FGPropagate::GetGeodeticAltitudeKm);
PropertyManager->Tie("position/h-agl-km", this, &FGPropagate::GetDistanceAGLKm,
&FGPropagate::SetDistanceAGLKm);
PropertyManager->Tie("position/radius-to-vehicle-ft", this, &FGPropagate::GetRadius);
PropertyManager->Tie("position/terrain-elevation-asl-ft", this, &FGPropagate::GetTerrainElevation,
&FGPropagate::SetTerrainElevation);
PropertyManager->Tie("position/eci-x-ft", this, eX, &FGPropagate::GetInertialPosition);
PropertyManager->Tie("position/eci-y-ft", this, eY, &FGPropagate::GetInertialPosition);
PropertyManager->Tie("position/eci-z-ft", this, eZ, &FGPropagate::GetInertialPosition);
PropertyManager->Tie("position/ecef-x-ft", this, eX, &FGPropagate::GetLocation);
PropertyManager->Tie("position/ecef-y-ft", this, eY, &FGPropagate::GetLocation);
PropertyManager->Tie("position/ecef-z-ft", this, eZ, &FGPropagate::GetLocation);
PropertyManager->Tie("position/epa-rad", this, &FGPropagate::GetEarthPositionAngle);
PropertyManager->Tie("metrics/terrain-radius", this, &FGPropagate::GetLocalTerrainRadius);
PropertyManager->Tie("attitude/phi-rad", this, ePhi, &FGPropagate::GetEuler);
PropertyManager->Tie("attitude/theta-rad", this, eTht, &FGPropagate::GetEuler);
PropertyManager->Tie("attitude/psi-rad", this, ePsi, &FGPropagate::GetEuler);
PropertyManager->Tie("attitude/phi-deg", this, ePhi, &FGPropagate::GetEulerDeg);
PropertyManager->Tie("attitude/theta-deg", this, eTht, &FGPropagate::GetEulerDeg);
PropertyManager->Tie("attitude/psi-deg", this, ePsi, &FGPropagate::GetEulerDeg);
PropertyManager->Tie("attitude/roll-rad", this, ePhi, &FGPropagate::GetEuler);
PropertyManager->Tie("attitude/pitch-rad", this, eTht, &FGPropagate::GetEuler);
PropertyManager->Tie("attitude/heading-true-rad", this, ePsi, &FGPropagate::GetEuler);
PropertyManager->Tie("orbital/specific-angular-momentum-ft2_sec", &h);
PropertyManager->Tie("orbital/inclination-deg", &Inclination);
PropertyManager->Tie("orbital/right-ascension-deg", &RightAscension);
PropertyManager->Tie("orbital/eccentricity", &Eccentricity);
PropertyManager->Tie("orbital/argument-of-perigee-deg", &PerigeeArgument);
PropertyManager->Tie("orbital/true-anomaly-deg", &TrueAnomaly);
PropertyManager->Tie("orbital/apoapsis-radius-ft", &ApoapsisRadius);
PropertyManager->Tie("orbital/periapsis-radius-ft", &PeriapsisRadius);
PropertyManager->Tie("orbital/period-sec", &OrbitalPeriod);
PropertyManager->Tie("simulation/integrator/rate/rotational", (int*)&integrator_rotational_rate);
PropertyManager->Tie("simulation/integrator/rate/translational", (int*)&integrator_translational_rate);
PropertyManager->Tie("simulation/integrator/position/rotational", (int*)&integrator_rotational_position);
PropertyManager->Tie("simulation/integrator/position/translational", (int*)&integrator_translational_position);
PropertyManager->Tie<FGPropagate, int>("simulation/write-state-file", this,
nullptr, &FGPropagate::WriteStateFile);

Move the enable-name binding out of FGFDMExec entirely: the FGModel constructor takes an optional stable canonical name and binds simulation/models/<name>/enabled itself, and each model passes its own name at construction. This removes the central name array, the static_assert that guarded it, and the binding loop; FGFDMExec no longer references the feature. BindModelEnabled becomes a protected helper.

Response to review on JSBSim-Team#1481 (bcoconni): the feature now lives wholly in the FGModel hierarchy.
@Zaretto

Zaretto commented Jul 8, 2026

Copy link
Copy Markdown
Contributor Author

See the update on #1482 - basically I don't need this code change any more.

However being able to disable modules is something that may still have some value; certainly being able to freeze (disable) systems it's something that is a standard feature for the systems on the level D simulators as it permits isolation of issues and there are times when I could see that it might be useful.

One specific example is a project I worked on last year where run time performance was critical so there was a JSBSim patch script as part of the CI to to remove ground reactions, external reactions and some other systems (I can't remember the exact list).

Before I close this and delete the branch I'd like to have the discussion about if there is any need for this code.

Zaretto added a commit to Zaretto/acEFM that referenced this pull request Jul 10, 2026
Integration is suppressed by setting the Propagate integrators all to eNone at init. We then inject the state from set_current_state_body_axis which will no longer be overwritten by Propagate.

This removes the need to disable modules (JSBSim-Team/jsbsim#1481). GroundReactions now runs but we keep it effectively disabled by never extending the gear and by having no contact points.

EarthPositionAngle is forced to zero every frame because the DCS World's world is static and does not rotate and not doing this would probably cause longitude to drift west.

In set_current_state_body_axis the attitude is now set before the body velocity. SetUVW converts body velocity to inertial using the transforms in force and then Propagate::Run's CalculateUVW inverts that using the transforms. Setting the attitude first makes both directions use the same frame.

Because this now looks like finished, validated code I have taken the leap to strip all the commented-out FlightGear interface code carried in JSBSim_interface since the port.
Zaretto added a commit to Zaretto/acEFM that referenced this pull request Jul 11, 2026
Integration is suppressed by setting the Propagate integrators all to eNone at init. We then inject the state from set_current_state_body_axis which will no longer be overwritten by Propagate.

This removes the need for new setters (JSBSim-Team/jsbsim#1482) and the need to disable modules (JSBSim-Team/jsbsim#1481) and also . GroundReactions now runs but we keep it effectively disabled by never extending the gear and by having no contact points. There is still an argument for keeping the ability to disable modules but we will wait and see what the JSBSim-Team decides.

EarthPositionAngle is forced to zero every frame because the DCS World's world is static and does not rotate and not doing this would probably cause longitude to drift west.

In set_current_state_body_axis the attitude is now set before the body velocity. SetUVW converts body velocity to inertial using the transforms in force and then Propagate::Run's CalculateUVW inverts that using the transforms. Setting the attitude first makes both directions use the same frame.

Because this now looks like finished, validated code I have taken the leap to strip all the commented-out FlightGear interface code carried in JSBSim_interface since the port.

@bcoconni bcoconni left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the code in the constructor of FGModel could be simpler using a tied property instead of managing explicitly an SGPropertyNode instance with all the if's that that drains.

Also I don't see much point in using 2 different names, one for the enable property and another one for the Name member? I would merge them into a single one. And the model classes would still be able to rename themselves without affecting the name of the enabled property.

Finally, I am not a huge fan of Uncle Bob's clean code principle about using a myriad of small trivial functions. So I'd rather not have the new method BindModelEnabled, especially since, when using a tied property, its code is 2 lines long.

Comment thread src/models/FGModel.cpp Outdated
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/

FGModel::FGModel(FGFDMExec* fdmex)
FGModel::FGModel(FGFDMExec* fdmex, const std::string& enableName)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
FGModel::FGModel(FGFDMExec* fdmex, const std::string& enableName)
FGModel::FGModel(FGFDMExec* fdmex, const std::string& name)
: Name(name)

I would take opportunity of passing a name to the constructor to initialize the member Name. That would save setting Name in each inherited class.

Comment thread src/models/FGModel.cpp Outdated
Comment on lines +71 to +72
if (!enableName.empty()) BindModelEnabled(enableName);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure why a separate method is needed for this trivial task? The constructor of FGModel is a dozen lines long, the content of BindModelEnabled could be copied inside the constructor and its code would still be much shorter than any screen height.

Comment thread src/models/FGModel.cpp Outdated
Comment on lines +95 to +99
const string path = "simulation/models/" + name + "/enabled";
const bool existed = PropertyManager->HasNode(path);
ModelEnabled = PropertyManager->GetNode(path, true);
// Default to enabled; a freshly created node would otherwise read false.
if (!existed && ModelEnabled) ModelEnabled->setBoolValue(true);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
const string path = "simulation/models/" + name + "/enabled";
const bool existed = PropertyManager->HasNode(path);
ModelEnabled = PropertyManager->GetNode(path, true);
// Default to enabled; a freshly created node would otherwise read false.
if (!existed && ModelEnabled) ModelEnabled->setBoolValue(true);
const string path = "simulation/models/" + Name + "/enabled";
Property->Tie(path, &enabled);

Tying the property to a member bool enabled makes the code much shorter and saves the trouble of all the ifs you have used to guard the code from potential errors.

This code should be moved directly inside the constructor.

Comment thread src/models/FGModel.cpp Outdated
// entirely: its Run() body does not execute, but its last state and property
// bindings are preserved so an external system can replace it, for example
// external propagation or host-owned ground reactions.
if (ModelEnabled && !ModelEnabled->getBoolValue()) return true;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
if (ModelEnabled && !ModelEnabled->getBoolValue()) return true;
if (!enabled) return true;

Using a tied property makes the test much simpler and more legible.

Comment thread src/models/FGModel.h
Comment on lines +51 to +52
class SGPropertyNode;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
class SGPropertyNode;

You don't need that when using tied properties.

Comment thread src/models/FGModel.h Outdated
Comment on lines +75 to +80
/** Constructor.
@param enableName optional stable canonical name for this model. When
non-empty it binds simulation/models/<enableName>/enabled
(default true); setting that property false skips this
model's Run(). Empty means the model has no enable flag. */
explicit FGModel(FGFDMExec*, const std::string& enableName = "");

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
/** Constructor.
@param enableName optional stable canonical name for this model. When
non-empty it binds simulation/models/<enableName>/enabled
(default true); setting that property false skips this
model's Run(). Empty means the model has no enable flag. */
explicit FGModel(FGFDMExec*, const std::string& enableName = "");
/** Constructor.
@param name optional stable canonical name for this model. When
non-empty it binds simulation/models/<enableName>/enabled
(default true); setting that property false skips this
model's Run(). Empty means the model has no enable flag. */
FGModel(FGFDMExec*, const std::string& name);
  • You no longer need the explicit qualifier for a constructor with more than one argument.
  • I would rather use name for the name argument since the point is to use that value to populate the member Name in the process.
  • I would not provide a default value to name, thus forcing all classes inheriting from FGModel to pick a name.

Comment thread src/models/FGModel.h Outdated
protected:
unsigned int exe_ctr;
unsigned int rate;
SGPropertyNode* ModelEnabled = nullptr;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
SGPropertyNode* ModelEnabled = nullptr;
bool enable = true;

Using a tied property allows to define the default value here and saves using a lot of ifs to check for the existence of the pointer and property.

Comment thread src/models/FGModel.h Outdated
Comment on lines +113 to +120
/** Bind this model's execution-enable flag to
simulation/models/<name>/enabled (default true), where name is the stable
canonical name passed to the constructor. When that property is set false,
Run() is skipped while the model's last state and property bindings are
preserved, the property-tree mechanism by which an external system can
replace a model, for example external propagation owning FGPropagate or a
host physics engine owning FGGroundReactions. */
void BindModelEnabled(const std::string& name);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This method is no longer needed but the docs should be kept and moved in the class documentation (lines 57-63)

Comment thread src/models/FGOutput.cpp Outdated
Comment on lines 58 to 60
FGOutput::FGOutput(FGFDMExec* fdmex) : FGModel(fdmex, "output")
{
Name = "FGOutput";

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
FGOutput::FGOutput(FGFDMExec* fdmex) : FGModel(fdmex, "output")
{
Name = "FGOutput";
FGOutput::FGOutput(FGFDMExec* fdmex) : FGModel(fdmex, "FGOutput")
{

Since the FGModel constructor populates Name itself, you no longer need to initialize it in the FGOutput constructor.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And the same should be applied to the other model classes FGAcceleration, FGAerodynamics, etc.

@bcoconni

bcoconni commented Jul 12, 2026

Copy link
Copy Markdown
Member

Just for the record, I have just came across this old feature request on Sourceforge #86 Turn off models individually from @jonsberndt and dating back to October 10, 2011.

Your PR will allow to close an almost 15-year-old request @Zaretto 😆

…d require Name in the constructor

Bind simulation/models/<Name>/enabled by tying it to a bool member constructed from the model name in the constructor when the model name isn't empty.

FGInput, FGInputType, FGOutput and FGOutputType already had an enabled property so remove that and use the new one from the base class.
@Zaretto

Zaretto commented Jul 13, 2026

Copy link
Copy Markdown
Contributor Author

Thanks @bcoconni for the guidance, and it makes it a lot nicer. All applied and pushed ready for your input.

One thing I'd like your guidance on and maybe @seanmcleod70 was my change to use FGInertial instead of the current name "Earth" mainly because "Earth" just seemed wrong whereas simulation/models/FGInertial/enabled looked right.

@agodemar

Copy link
Copy Markdown
Contributor

@Zaretto @bcoconni @seanmcleod70 this is a great outcome!
Can someone remind me how this new feature relates to this Discussion: Review & revise the state propagation procedure (FGPropagate / FGFDMExec) #1391 ?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants