63
64
#include "models/FGInput.h"
64
65
#include "models/FGOutput.h"
65
66
#include "initialization/FGInitialCondition.h"
67
#include "initialization/FGSimplexTrim.h"
68
#include "initialization/FGLinearization.h"
66
69
#include "input_output/FGPropertyManager.h"
67
70
#include "input_output/FGScript.h"
71
#include "input_output/FGXMLFileRead.h"
72
#include "input_output/FGXMLElement.h"
69
74
using namespace std;
73
static const char *IdSrc = "$Id: FGFDMExec.cpp,v 1.133 2012/04/14 18:10:43 bcoconni Exp $";
78
static const char *IdSrc = "$Id: FGFDMExec.cpp,v 1.150 2013/11/24 11:40:55 bcoconni Exp $";
74
79
static const char *IdHdr = ID_FDMEXEC;
76
81
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
148
153
Constructing = true;
149
154
typedef int (FGFDMExec::*iPMF)(void) const;
155
typedef double (FGFDMExec::*dPMF)(void) const;
150
156
// typedef unsigned int (FGFDMExec::*uiPMF)(void) const;
151
157
// instance->Tie("simulation/do_trim_analysis", this, (iPMF)0, &FGFDMExec::DoTrimAnalysis, false);
152
158
instance->Tie("simulation/do_simple_trim", this, (iPMF)0, &FGFDMExec::DoTrim, false);
159
instance->Tie("simulation/do_simplex_trim", this, (iPMF)0, &FGFDMExec::DoSimplexTrim);
160
instance->Tie("simulation/do_linearization", this, (iPMF)0, &FGFDMExec::DoLinearization);
153
161
instance->Tie("simulation/reset", this, (iPMF)0, &FGFDMExec::ResetToInitialConditions, false);
154
162
instance->Tie("simulation/randomseed", this, (iPMF)0, &FGFDMExec::SRand, false);
155
163
instance->Tie("simulation/terminate", (int *)&Terminate);
156
164
instance->Tie("simulation/sim-time-sec", this, &FGFDMExec::GetSimTime);
165
instance->Tie("simulation/dt", this, &FGFDMExec::GetDeltaT);
157
166
instance->Tie("simulation/jsbsim-debug", this, &FGFDMExec::GetDebugLevel, &FGFDMExec::SetDebugLevel);
158
167
instance->Tie("simulation/frame", (int *)&Frame, false);
169
// simplex trim properties
170
instanceRoot->SetDouble("trim/solver/rtol",0.0001);
171
instanceRoot->SetDouble("trim/solver/speed",2);
172
instanceRoot->SetDouble("trim/solver/abstol",0.001);
173
instanceRoot->SetDouble("trim/solver/iterMax",2000);
174
instanceRoot->SetInt("trim/solver/debugLevel",0);
175
instanceRoot->SetDouble("trim/solver/random",0);
176
instanceRoot->SetBool("trim/solver/showSimplex",false);
177
instanceRoot->SetBool("trim/solver/showConvergence",false);
178
instanceRoot->SetBool("trim/solver/pause",false);
179
instanceRoot->SetBool("trim/solver/variablePropPitch",false);
181
instanceRoot->SetDouble("trim/solver/throttleGuess",0.50);
182
instanceRoot->SetDouble("trim/solver/throttleMin",0.0);
183
instanceRoot->SetDouble("trim/solver/throttleMax",1.0);
184
instanceRoot->SetDouble("trim/solver/throttleStep",0.1);
186
instanceRoot->SetDouble("trim/solver/aileronGuess",0);
187
instanceRoot->SetDouble("trim/solver/aileronMin",-1.00);
188
instanceRoot->SetDouble("trim/solver/aileronMax",1.00);
189
instanceRoot->SetDouble("trim/solver/aileronStep",0.1);
191
instanceRoot->SetDouble("trim/solver/rudderGuess",0);
192
instanceRoot->SetDouble("trim/solver/rudderMin",-1.00);
193
instanceRoot->SetDouble("trim/solver/rudderMax",1.00);
194
instanceRoot->SetDouble("trim/solver/rudderStep",0.1);
196
instanceRoot->SetDouble("trim/solver/elevatorGuess",-0.1);
197
instanceRoot->SetDouble("trim/solver/elevatorMin",-1.0);
198
instanceRoot->SetDouble("trim/solver/elevatorMax",1.0);
199
instanceRoot->SetDouble("trim/solver/elevatorStep",0.1);
201
instanceRoot->SetDouble("trim/solver/alphaGuess",0.05);
202
instanceRoot->SetDouble("trim/solver/alphaMin",-0.1);
203
instanceRoot->SetDouble("trim/solver/alphaMax",.18);
204
instanceRoot->SetDouble("trim/solver/alphaStep",0.05);
206
instanceRoot->SetDouble("trim/solver/betaGuess",0);
207
instanceRoot->SetDouble("trim/solver/betaMin",-0.1);
208
instanceRoot->SetDouble("trim/solver/betaMax",0.1);
209
instanceRoot->SetDouble("trim/solver/betaStep",0.0001);
160
211
Constructing = false;
213
266
Models[eSystems] = new FGFCS(this);
214
267
Models[ePropulsion] = new FGPropulsion(this);
215
268
Models[eAerodynamics] = new FGAerodynamics (this);
217
GetGroundCallback()->SetSeaLevelRadius(((FGInertial*)Models[eInertial])->GetRefRadius());
219
269
Models[eGroundReactions] = new FGGroundReactions(this);
220
270
Models[eExternalReactions] = new FGExternalReactions(this);
221
271
Models[eBuoyantForces] = new FGBuoyantForces(this);
222
272
Models[eMassBalance] = new FGMassBalance(this);
223
273
Models[eAircraft] = new FGAircraft(this);
224
274
Models[eAccelerations] = new FGAccelerations(this);
275
Models[eOutput] = new FGOutput(this);
226
277
// Assign the Model shortcuts for internal executive use only.
227
278
Propagate = (FGPropagate*)Models[ePropagate];
591
632
if (Constructing) return;
593
vector <FGModel*>::iterator it;
594
for (it = Models.begin(); it != Models.end(); ++it) (*it)->InitModel();
634
for (unsigned int i = 0; i < Models.size(); i++) {
635
// The Output model will be initialized during the RunIC() execution
636
if (i == eOutput) continue;
639
Models[i]->InitModel();
597
644
if (Script) Script->ResetEvents();
600
647
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
602
bool FGFDMExec::SetOutputFileName(const string& fname)
604
if (Outputs.size() > 0) Outputs[0]->SetOutputFileName(fname);
609
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
611
string FGFDMExec::GetOutputFileName(void)
613
if (Outputs.size() > 0) return Outputs[0]->GetOutputFileName();
614
else return string("");
617
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
619
649
vector <string> FGFDMExec::EnumerateFDMs(void)
621
651
vector <string> FDMList;
830
861
// Process the output element[s]. This element is OPTIONAL, and there may be more than one.
832
typedef double (FGOutput::*iOPMF)(void) const;
833
typedef int (FGFDMExec::*iOPV)(void) const;
834
862
element = document->FindElement("output");
835
863
while (element) {
836
if (debug_lvl > 0) cout << endl << " Output data set: " << idx << " ";
837
FGOutput* Output = new FGOutput(this);
838
result = Output->Load(element);
864
string output_file_name = aircraftCfgFileName;
866
if (!element->GetAttributeValue("file").empty()) {
867
output_file_name = RootDir + element->GetAttributeValue("file");
868
result = ((FGOutput*)Models[eOutput])->SetDirectivesFile(output_file_name);
871
result = ((FGOutput*)Models[eOutput])->Load(element);
840
cerr << endl << "Aircraft output element has problems in file " << aircraftCfgFileName << endl;
874
cerr << endl << "Aircraft output element has problems in file " << output_file_name << endl;
846
Outputs.push_back(Output);
847
string outputProp = CreateIndexedPropertyName("simulation/output",idx);
848
instance->Tie(outputProp+"/log_rate_hz", Output, (iOPMF)0, &FGOutput::SetRate, false);
851
877
element = document->FindNextElement("output");
854
instance->Tie("simulation/force-output", this, (iOPV)0, &FGFDMExec::ForceOutput, false);
856
880
// Lastly, process the child element. This element is OPTIONAL - and NOT YET SUPPORTED.
857
881
element = document->FindElement("child");
915
943
int node_idx = 0;
917
945
for (int i=0; i<pcs->node->nChildren(); i++) {
918
947
pcsNew->base_string = pcs->base_string + "/" + pcs->node->getChild(i)->getName();
919
948
node_idx = pcs->node->getChild(i)->getIndex();
920
949
if (node_idx != 0) {
921
950
pcsNew->base_string = CreateIndexedPropertyName(pcsNew->base_string, node_idx);
923
952
if (pcs->node->getChild(i)->nChildren() == 0) {
924
if (pcsNew->base_string.substr(0,11) == string("/fdm/jsbsim")) {
953
if (pcsNew->base_string.substr(0,12) == string("/fdm/jsbsim/")) {
925
954
pcsNew->base_string = pcsNew->base_string.erase(0,12);
927
PropertyCatalog.push_back(pcsNew->base_string);
956
if (pcs->node->getChild(i)->getAttribute(SGPropertyNode::READ)) access="R";
957
if (pcs->node->getChild(i)->getAttribute(SGPropertyNode::WRITE)) access+="W";
958
PropertyCatalog.push_back(pcsNew->base_string+" ("+access+")");
929
pcsNew->node = (FGPropertyManager*)pcs->node->getChild(i);
960
pcsNew->node = (FGPropertyNode*)pcs->node->getChild(i);
930
961
BuildPropertyCatalog(pcsNew);
1152
1165
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1154
void FGFDMExec::ForceOutput(int idx)
1156
if (idx >= (int)0 && idx < (int)Outputs.size()) Outputs[idx]->Print();
1159
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1161
bool FGFDMExec::SetOutputDirectives(const string& fname)
1165
FGOutput* Output = new FGOutput(this);
1166
Output->SetDirectivesFile(RootDir + fname);
1167
result = Output->Load(0);
1170
Output->InitModel();
1172
Output->Run(holding);
1173
Outputs.push_back(Output);
1174
typedef double (FGOutput::*iOPMF)(void) const;
1175
string outputProp = CreateIndexedPropertyName("simulation/output",Outputs.size()-1);
1176
instance->Tie(outputProp+"/log_rate_hz", Output, (iOPMF)0, &FGOutput::SetRate, false);
1184
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1186
1167
void FGFDMExec::DoTrim(int mode)
1188
1169
double saved_time;
1203
1184
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1186
void FGFDMExec::DoSimplexTrim(int mode)
1189
if (Constructing) return;
1190
if (mode < 0 || mode > JSBSim::tNone) {
1191
cerr << endl << "Illegal trimming mode!" << endl << endl;
1194
saved_time = sim_time;
1195
FGSimplexTrim trim(this, (JSBSim::TrimMode)mode);
1196
sim_time = saved_time;
1197
Setsim_time(saved_time);
1198
std::cout << "dT: " << dT << std::endl;
1201
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1203
void FGFDMExec::DoLinearization(int mode)
1206
if (Constructing) return;
1207
saved_time = sim_time;
1208
FGLinearization lin(this,mode);
1209
sim_time = saved_time;
1210
Setsim_time(saved_time);
1213
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1205
1215
void FGFDMExec::SRand(int sr)