Skip to content

Commit a0aa665

Browse files
committed
Add a per-model execution-enable property
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.
1 parent d89e357 commit a0aa665

3 files changed

Lines changed: 48 additions & 0 deletions

File tree

src/FGFDMExec.cpp

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,23 @@ FGFDMExec::FGFDMExec(FGPropertyManager* root, std::shared_ptr<unsigned int> fdmc
162162
instance->Tie("simulation/trim-completed", &trim_completed);
163163
instance->Tie("forces/hold-down", this, &FGFDMExec::GetHoldDown, &FGFDMExec::SetHoldDown);
164164

165+
// Per-model execution-enable property: simulation/models/<name>/enabled
166+
// (default true). Setting one false skips that model's Run() while preserving
167+
// its state. This is the property-tree mechanism by which an external system
168+
// can replace a model, for example external propagation or host-owned ground
169+
// reactions. Names use the stable canonical eModels order, independent of
170+
// FGModel::Name.
171+
static const char* const modelEnableNames[] = {
172+
"propagate", "input", "inertial", "atmosphere", "winds", "systems",
173+
"massbalance", "auxiliary", "propulsion", "aerodynamics", "groundreactions",
174+
"externalreactions", "buoyantforces", "aircraft", "accelerations", "output"
175+
};
176+
static_assert(sizeof(modelEnableNames)/sizeof(*modelEnableNames) == eNumStandardModels,
177+
"modelEnableNames must stay in step with eModels");
178+
for (unsigned int i = 0; i < Models.size(); ++i)
179+
if (Models[i])
180+
Models[i]->BindModelEnabled(modelEnableNames[i]);
181+
165182
Constructing = false;
166183
}
167184

src/models/FGModel.cpp

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ INCLUDES
4242
#include "FGFDMExec.h"
4343
#include "input_output/FGModelLoader.h"
4444
#include "input_output/FGLog.h"
45+
#include "input_output/FGPropertyManager.h"
4546

4647
using namespace std;
4748

@@ -87,10 +88,27 @@ bool FGModel::InitModel(void)
8788

8889
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8990

91+
void FGModel::BindModelEnabled(const std::string& name)
92+
{
93+
const string path = "simulation/models/" + name + "/enabled";
94+
const bool existed = PropertyManager->HasNode(path);
95+
ModelEnabled = PropertyManager->GetNode(path, true);
96+
// Default to enabled; a freshly created node would otherwise read false.
97+
if (!existed && ModelEnabled) ModelEnabled->setBoolValue(true);
98+
}
99+
100+
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
101+
90102
bool FGModel::Run(bool Holding)
91103
{
92104
FGModel::Debug(2);
93105

106+
// A model whose simulation/models/<name>/enabled property is false is skipped
107+
// entirely: its Run() body does not execute, but its last state and property
108+
// bindings are preserved so an external system can replace it, for example
109+
// external propagation or host-owned ground reactions.
110+
if (ModelEnabled && !ModelEnabled->getBoolValue()) return true;
111+
94112
if (rate == 1) return false; // Fast exit if nothing to do
95113

96114
if (exe_ctr >= rate) exe_ctr = 0;

src/models/FGModel.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,8 @@ INCLUDES
4848
FORWARD DECLARATIONS
4949
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
5050

51+
class SGPropertyNode;
52+
5153
namespace JSBSim {
5254

5355
class FGFDMExec;
@@ -93,6 +95,16 @@ class JSBSIM_API FGModel : public FGModelFunctions
9395
unsigned int GetRate(void) const { return rate; }
9496
FGFDMExec* GetExec(void) const { return FDMExec; }
9597

98+
/** Bind this model's execution-enable flag to the property
99+
simulation/models/<name>/enabled (default true), using the stable
100+
canonical name supplied by FGFDMExec. When that property is set false,
101+
Run() is skipped while the model's last state and property bindings are
102+
preserved. This is the property-tree mechanism by which an external system
103+
can replace a model, for example external propagation owning FGPropagate,
104+
or a host physics engine owning FGGroundReactions. Behaviour is unchanged
105+
unless the property is explicitly set false. */
106+
void BindModelEnabled(const std::string& name);
107+
96108
void SetPropertyManager(std::shared_ptr<FGPropertyManager> fgpm) { PropertyManager=fgpm;}
97109
virtual SGPath FindFullPathName(const SGPath& path) const;
98110
const std::string& GetName(void) const { return Name; }
@@ -101,6 +113,7 @@ class JSBSIM_API FGModel : public FGModelFunctions
101113
protected:
102114
unsigned int exe_ctr;
103115
unsigned int rate;
116+
SGPropertyNode* ModelEnabled = nullptr;
104117
std::string Name;
105118

106119
/** Uploads this model in memory.

0 commit comments

Comments
 (0)