 |
JSBSim Flight Dynamics Model
1.1.11 (13 Feb 2022)
An Open Source Flight Dynamics and Control Software Library in C++
|
43 #include "input_output/FGModelLoader.h"
45 #include "models/flight_control/FGFilter.h"
46 #include "models/flight_control/FGDeadBand.h"
47 #include "models/flight_control/FGGain.h"
48 #include "models/flight_control/FGPID.h"
49 #include "models/flight_control/FGSwitch.h"
50 #include "models/flight_control/FGSummer.h"
51 #include "models/flight_control/FGKinemat.h"
52 #include "models/flight_control/FGFCSFunction.h"
53 #include "models/flight_control/FGActuator.h"
54 #include "models/flight_control/FGAccelerometer.h"
55 #include "models/flight_control/FGMagnetometer.h"
56 #include "models/flight_control/FGGyro.h"
57 #include "models/flight_control/FGWaypoint.h"
58 #include "models/flight_control/FGAngles.h"
59 #include "models/flight_control/FGDistributor.h"
60 #include "models/flight_control/FGLinearActuator.h"
62 #include "FGFCSChannel.h"
79 DaCmd = DeCmd = DrCmd = DfCmd = DsbCmd = DspCmd = 0;
80 PTrimCmd = YTrimCmd = RTrimCmd = 0.0;
81 GearCmd = GearPos = 1;
82 BrakePos.resize(FGLGear::bgNumBrakeGroups);
83 TailhookPos = WingFoldPos = 0.0;
86 for (i=0;i<NForms;i++) {
87 DePos[i] = DaLPos[i] = DaRPos[i] = DrPos[i] = 0.0;
88 DfPos[i] = DsbPos[i] = DspPos[i] = 0.0;
102 PropAdvanceCmd.clear();
104 PropFeatherCmd.clear();
109 for (i=0;i<SystemChannels.size();i++)
delete SystemChannels[i];
110 SystemChannels.clear();
117 bool FGFCS::InitModel(
void)
119 if (!FGModel::InitModel())
return false;
123 for (i=0; i<ThrottlePos.size(); i++) ThrottlePos[i] = 0.0;
124 for (i=0; i<MixturePos.size(); i++) MixturePos[i] = 0.0;
125 for (i=0; i<ThrottleCmd.size(); i++) ThrottleCmd[i] = 0.0;
126 for (i=0; i<MixtureCmd.size(); i++) MixtureCmd[i] = 0.0;
127 for (i=0; i<PropAdvance.size(); i++) PropAdvance[i] = 0.0;
128 for (i=0; i<PropFeather.size(); i++) PropFeather[i] = 0.0;
130 DaCmd = DeCmd = DrCmd = DfCmd = DsbCmd = DspCmd = 0;
131 PTrimCmd = YTrimCmd = RTrimCmd = 0.0;
132 TailhookPos = WingFoldPos = 0.0;
134 for (i=0;i<NForms;i++) {
135 DePos[i] = DaLPos[i] = DaRPos[i] = DrPos[i] = 0.0;
136 DfPos[i] = DsbPos[i] = DspPos[i] = 0.0;
140 for (
unsigned int i=0; i<SystemChannels.size(); i++) SystemChannels[i]->Reset();
158 if (Holding)
return false;
162 for (i=0; i<ThrottlePos.size(); i++) ThrottlePos[i] = ThrottleCmd[i];
163 for (i=0; i<MixturePos.size(); i++) MixturePos[i] = MixtureCmd[i];
164 for (i=0; i<PropAdvance.size(); i++) PropAdvance[i] = PropAdvanceCmd[i];
165 for (i=0; i<PropFeather.size(); i++) PropFeather[i] = PropFeatherCmd[i];
168 for (i=0; i<SystemChannels.size(); i++) {
169 if (debug_lvl & 4) cout <<
" Executing System Channel: " << SystemChannels[i]->GetName() << endl;
170 ChannelRate = SystemChannels[i]->GetRate();
171 SystemChannels[i]->Execute();
187 DaLPos[ofDeg] = pos*radtodeg;
190 DaLPos[ofRad] = pos*degtorad;
194 DaLPos[ofNorm] = pos;
196 DaLPos[ofMag] = fabs(DaLPos[ofRad]);
206 DaRPos[ofDeg] = pos*radtodeg;
209 DaRPos[ofRad] = pos*degtorad;
213 DaRPos[ofNorm] = pos;
215 DaRPos[ofMag] = fabs(DaRPos[ofRad]);
225 DePos[ofDeg] = pos*radtodeg;
228 DePos[ofRad] = pos*degtorad;
234 DePos[ofMag] = fabs(DePos[ofRad]);
244 DrPos[ofDeg] = pos*radtodeg;
247 DrPos[ofRad] = pos*degtorad;
253 DrPos[ofMag] = fabs(DrPos[ofRad]);
263 DfPos[ofDeg] = pos*radtodeg;
266 DfPos[ofRad] = pos*degtorad;
272 DfPos[ofMag] = fabs(DfPos[ofRad]);
282 DsbPos[ofDeg] = pos*radtodeg;
285 DsbPos[ofRad] = pos*degtorad;
289 DsbPos[ofNorm] = pos;
291 DsbPos[ofMag] = fabs(DsbPos[ofRad]);
301 DspPos[ofDeg] = pos*radtodeg;
304 DspPos[ofRad] = pos*degtorad;
308 DspPos[ofNorm] = pos;
310 DspPos[ofMag] = fabs(DspPos[ofRad]);
317 if (engineNum < (
int)ThrottlePos.size()) {
319 for (
unsigned int ctr=0; ctr<ThrottleCmd.size(); ctr++)
320 ThrottleCmd[ctr] = setting;
322 ThrottleCmd[engineNum] = setting;
325 cerr <<
"Throttle " << engineNum <<
" does not exist! " << ThrottleCmd.size()
326 <<
" engines exist, but attempted throttle command is for engine "
327 << engineNum << endl;
335 if (engineNum < (
int)ThrottlePos.size()) {
337 for (
unsigned int ctr=0; ctr<ThrottlePos.size(); ctr++)
338 ThrottlePos[ctr] = setting;
340 ThrottlePos[engineNum] = setting;
343 cerr <<
"Throttle " << engineNum <<
" does not exist! " << ThrottlePos.size()
344 <<
" engines exist, but attempted throttle position setting is for engine "
345 << engineNum << endl;
351 double FGFCS::GetThrottleCmd(
int engineNum)
const
353 if (engineNum < (
int)ThrottlePos.size()) {
355 cerr <<
"Cannot get throttle value for ALL engines" << endl;
357 return ThrottleCmd[engineNum];
360 cerr <<
"Throttle " << engineNum <<
" does not exist! " << ThrottleCmd.size()
361 <<
" engines exist, but throttle setting for engine " << engineNum
362 <<
" is selected" << endl;
369 double FGFCS::GetThrottlePos(
int engineNum)
const
371 if (engineNum < (
int)ThrottlePos.size()) {
373 cerr <<
"Cannot get throttle value for ALL engines" << endl;
375 return ThrottlePos[engineNum];
378 cerr <<
"Throttle " << engineNum <<
" does not exist! " << ThrottlePos.size()
379 <<
" engines exist, but attempted throttle position setting is for engine "
380 << engineNum << endl;
389 if (engineNum < (
int)ThrottlePos.size()) {
391 for (
unsigned int ctr=0; ctr<MixtureCmd.size(); ctr++)
392 MixtureCmd[ctr] = setting;
394 MixtureCmd[engineNum] = setting;
403 if (engineNum < (
int)ThrottlePos.size()) {
405 for (
unsigned int ctr=0; ctr<MixtureCmd.size(); ctr++)
406 MixturePos[ctr] = MixtureCmd[ctr];
408 MixturePos[engineNum] = setting;
417 if (engineNum < (
int)ThrottlePos.size()) {
419 for (
unsigned int ctr=0; ctr<PropAdvanceCmd.size(); ctr++)
420 PropAdvanceCmd[ctr] = setting;
422 PropAdvanceCmd[engineNum] = setting;
431 if (engineNum < (
int)ThrottlePos.size()) {
433 for (
unsigned int ctr=0; ctr<PropAdvanceCmd.size(); ctr++)
434 PropAdvance[ctr] = PropAdvanceCmd[ctr];
436 PropAdvance[engineNum] = setting;
445 if (engineNum < (
int)ThrottlePos.size()) {
447 for (
unsigned int ctr=0; ctr<PropFeatherCmd.size(); ctr++)
448 PropFeatherCmd[ctr] = setting;
450 PropFeatherCmd[engineNum] = setting;
459 if (engineNum < (
int)ThrottlePos.size()) {
461 for (
unsigned int ctr=0; ctr<PropFeatherCmd.size(); ctr++)
462 PropFeather[ctr] = PropFeatherCmd[ctr];
464 PropFeather[engineNum] = setting;
473 if (document->
GetName() ==
"autopilot") {
474 Name =
"Autopilot: ";
475 systype = stAutoPilot;
476 }
else if (document->
GetName() ==
"flight_control") {
479 }
else if (document->
GetName() ==
"system") {
494 while (channel_element) {
506 if (sOnOffProperty.length() > 0) {
507 FGPropertyNode* OnOffPropertyNode = PropertyManager->GetNode(sOnOffProperty);
508 if (OnOffPropertyNode == 0) {
510 <<
"The On/Off property, " << sOnOffProperty <<
" specified for channel "
512 <<
"understood. The simulation will abort" <<
reset << endl;
513 throw(
"Bad system definition");
515 newChannel =
new FGFCSChannel(
this, sChannelName, ChannelRate,
518 newChannel =
new FGFCSChannel(
this, sChannelName, ChannelRate);
520 SystemChannels.push_back(newChannel);
527 while (component_element) {
529 if ((component_element->
GetName() ==
string(
"lag_filter")) ||
530 (component_element->
GetName() ==
string(
"lead_lag_filter")) ||
531 (component_element->
GetName() ==
string(
"washout_filter")) ||
532 (component_element->
GetName() ==
string(
"second_order_filter")) )
534 newChannel->
Add(
new FGFilter(
this, component_element));
535 }
else if ((component_element->
GetName() ==
string(
"pure_gain")) ||
536 (component_element->
GetName() ==
string(
"scheduled_gain")) ||
537 (component_element->
GetName() ==
string(
"aerosurface_scale")))
539 newChannel->
Add(
new FGGain(
this, component_element));
540 }
else if (component_element->
GetName() ==
string(
"summer")) {
541 newChannel->
Add(
new FGSummer(
this, component_element));
542 }
else if (component_element->
GetName() ==
string(
"deadband")) {
544 }
else if (component_element->
GetName() ==
string(
"switch")) {
545 newChannel->
Add(
new FGSwitch(
this, component_element));
546 }
else if (component_element->
GetName() ==
string(
"kinematic")) {
547 newChannel->
Add(
new FGKinemat(
this, component_element));
548 }
else if (component_element->
GetName() ==
string(
"fcs_function")) {
550 }
else if (component_element->
GetName() ==
string(
"pid")) {
551 newChannel->
Add(
new FGPID(
this, component_element));
552 }
else if (component_element->
GetName() ==
string(
"integrator")) {
556 cerr << component_element->
ReadFrom();
558 +
" does not provide the parameter <c1>");
560 c1_el->ChangeName(
"ki");
563 newChannel->
Add(
new FGPID(
this, component_element));
564 }
else if (component_element->
GetName() ==
string(
"actuator")) {
566 }
else if (component_element->
GetName() ==
string(
"sensor")) {
567 newChannel->
Add(
new FGSensor(
this, component_element));
568 }
else if (component_element->
GetName() ==
string(
"accelerometer")) {
570 }
else if (component_element->
GetName() ==
string(
"magnetometer")) {
572 }
else if (component_element->
GetName() ==
string(
"gyro")) {
573 newChannel->
Add(
new FGGyro(
this, component_element));
574 }
else if ((component_element->
GetName() ==
string(
"waypoint_heading")) ||
575 (component_element->
GetName() ==
string(
"waypoint_distance")))
578 }
else if (component_element->
GetName() ==
string(
"angle")) {
579 newChannel->
Add(
new FGAngles(
this, component_element));
580 }
else if (component_element->
GetName() ==
string(
"distributor")) {
582 }
else if (component_element->
GetName() ==
string(
"linear_actuator")) {
585 cerr <<
"Unknown FCS component: " << component_element->
GetName() << endl;
589 cerr <<
reset << endl;
597 PostLoad(document, FDMExec);
611 SGPath FGFCS::FindFullPathName(
const SGPath& path)
const
613 SGPath name = FGModel::FindFullPathName(path);
614 if (systype != stSystem || !name.isNull())
return name;
617 if (!name.isNull())
return name;
626 string CompStrings =
"";
627 bool firstime =
true;
630 for (
unsigned int i=0; i<SystemChannels.size(); i++)
632 for (
unsigned int c=0; c<SystemChannels[i]->GetNumComponents(); c++)
634 if (firstime) firstime =
false;
635 else CompStrings += delimiter;
637 CompStrings += SystemChannels[i]->GetComponent(c)->GetName();
649 std::ostringstream buf;
651 bool firstime =
true;
654 for (
unsigned int i=0; i<SystemChannels.size(); i++)
656 for (
unsigned int c=0; c<SystemChannels[i]->GetNumComponents(); c++)
658 if (firstime) firstime =
false;
659 else buf << delimiter;
661 buf << setprecision(9) << SystemChannels[i]->GetComponent(c)->GetOutput();
671 void FGFCS::AddThrottle(
void)
673 ThrottleCmd.push_back(0.0);
674 ThrottlePos.push_back(0.0);
675 MixtureCmd.push_back(0.0);
676 MixturePos.push_back(0.0);
677 PropAdvanceCmd.push_back(0.0);
678 PropAdvance.push_back(0.0);
679 PropFeatherCmd.push_back(
false);
680 PropFeather.push_back(
false);
682 unsigned int num = (
unsigned int)ThrottleCmd.size()-1;
688 double FGFCS::GetDt(
void)
const
695 void FGFCS::bind(
void)
749 PropertyManager->
Tie(
"simulation/channel-dt",
this, &FGFCS::GetChannelDeltaT);
756 void FGFCS::bindThrottle(
unsigned int num)
760 tmp = CreateIndexedPropertyName(
"fcs/throttle-cmd-norm", num);
761 PropertyManager->
Tie( tmp.c_str(),
this, num, &FGFCS::GetThrottleCmd,
763 tmp = CreateIndexedPropertyName(
"fcs/throttle-pos-norm", num);
764 PropertyManager->
Tie( tmp.c_str(),
this, num, &FGFCS::GetThrottlePos,
766 tmp = CreateIndexedPropertyName(
"fcs/mixture-cmd-norm", num);
767 PropertyManager->
Tie( tmp.c_str(),
this, num, &FGFCS::GetMixtureCmd,
769 tmp = CreateIndexedPropertyName(
"fcs/mixture-pos-norm", num);
770 PropertyManager->
Tie( tmp.c_str(),
this, num, &FGFCS::GetMixturePos,
772 tmp = CreateIndexedPropertyName(
"fcs/advance-cmd-norm", num);
775 tmp = CreateIndexedPropertyName(
"fcs/advance-pos-norm", num);
776 PropertyManager->
Tie( tmp.c_str(),
this, num, &FGFCS::GetPropAdvance,
778 tmp = CreateIndexedPropertyName(
"fcs/feather-cmd-norm", num);
781 tmp = CreateIndexedPropertyName(
"fcs/feather-pos-norm", num);
782 PropertyManager->
Tie( tmp.c_str(),
this, num, &FGFCS::GetPropFeather,
805 void FGFCS::Debug(
int from)
807 if (debug_lvl <= 0)
return;
811 cout << endl <<
" " << Name << endl;
814 if (debug_lvl & 2 ) {
815 if (from == 0) cout <<
"Instantiated: FGFCS" << endl;
816 if (from == 1) cout <<
"Destroyed: FGFCS" << endl;
818 if (debug_lvl & 4 ) {
820 if (debug_lvl & 8 ) {
822 if (debug_lvl & 16) {
824 if (debug_lvl & 64) {
void SetDaRPos(int form, double pos)
Sets the right aileron position.
void SetDspPos(int form, double pos)
Sets the spoiler position.
Encapsulates the JSBSim simulation executive.
const SGPath & GetSystemsPath(void)
Retrieves the systems path.
double GetCBrake(void) const
Gets the center brake.
double GetGearPos(void) const
Gets the gear position (0 up, 1 down), defaults to down.
void SetPropAdvance(int engine, double cmd)
Sets the actual prop pitch setting for the specified engine.
double GetDsbCmd(void) const
Gets the speedbrake command.
void SetFeatherCmd(int engine, bool cmd)
Sets the propeller feather command for the specified engine.
void SetThrottlePos(int engine, double cmd)
Sets the actual throttle setting for the specified engine.
void SetDfPos(int form, double pos)
Sets the flaps position.
bool Upload(Element *el, bool preLoad)
Uploads this model in memory.
Encapsulates a kinematic (mechanical) component for the flight control system.
Base class for all scheduled JSBSim models.
double GetPitchTrimCmd(void) const
Gets the pitch trim command.
bool HasAttribute(const std::string &key)
Determines if an element has the supplied attribute.
std::string GetAttributeValue(const std::string &key)
Retrieves an attribute.
Encapsulates a Gyro component for the flight control system.
double GetDeCmd(void) const
Gets the elevator command.
~FGFCS() override
Destructor.
Encapsulates a PID control component for the flight control system.
Element * FindElement(const std::string &el="")
Searches for a specified element.
void SetDeCmd(double cmd)
Sets the elevator command.
void SetRBrake(double cmd)
Sets the right brake group.
Provides a way to determine the smallest included angle.
double GetYawTrimCmd(void) const
Gets the rudder trim command.
bool GetFeatherCmd(int engine) const
Gets the prop feather command.
double GetDfPos(int form=ofRad) const
Gets the flaps position.
void SetMixturePos(int engine, double cmd)
Sets the actual mixture setting for the specified engine.
double GetDfCmd(void) const
Gets the flaps command.
void SetThrottleCmd(int engine, double cmd)
Sets the throttle command for the specified engine.
double GetTailhookPos(void) const
Gets the tailhook position (0 up, 1 down)
void SetDrPos(int form, double pos)
Sets the rudder position.
double GetDaCmd(void) const
Gets the aileron command.
void SetPropFeather(int engine, bool cmd)
Sets the actual prop feather setting for the specified engine.
Models a deadband object.
Class wrapper for property handling.
double GetPropAdvanceCmd(int engine) const
Gets the prop pitch command.
std::string GetComponentStrings(const std::string &delimiter) const
Retrieves all component names for inclusion in output stream.
void SetDspCmd(double cmd)
Sets the spoilers command.
void SetDfCmd(double cmd)
Sets the flaps command.
double GetWingFoldPos(void) const
Gets the wing fold position (0 unfolded, 1 folded)
bool Run(bool Holding) override
Runs the Flight Controls model; called by the Executive Can pass in a value indicating if the executi...
Encapsulates a Accelerometer component for the flight control system.
void SetDaCmd(double cmd)
Sets the aileron command.
Models a Waypoint object.
Models a FCSFunction object.
Encapsulates a Sensor component for the flight control system.
double GetDePos(int form=ofRad) const
Gets the elevator position.
static char fgred[6]
red text
double GetLBrake(void) const
Gets the left brake.
void SetGearCmd(double gearcmd)
Set the gear extend/retract command, defaults to down.
void SetDaLPos(int form, double pos)
Sets the left aileron position.
void Add(FGFCSComponent *comp)
Adds a component to a channel.
Encapsulates a gain component for the flight control system.
static char reset[5]
resets text properties
void SetDsbCmd(double cmd)
Sets the speedbrake command.
double GetDspPos(int form=ofRad) const
Gets the spoiler position.
void SetWingFoldPos(double foldpos)
Set the wing fold position.
Models a flight control system summing component.
double GetDeltaT(void) const
Returns the simulation delta T.
double GetDspCmd(void) const
Gets the spoiler command.
void SetPitchTrimCmd(double cmd)
Sets the pitch trim command.
Encapsulates a filter for the flight control system.
double GetAttributeValueAsNumber(const std::string &key)
Retrieves an attribute value as a double precision real number.
std::string GetComponentValues(const std::string &delimiter) const
Retrieves all component outputs for inclusion in output stream.
virtual bool Run(bool Holding)
Runs the model; called by the Executive.
const std::string & GetName(void) const
Retrieves the element name.
double GetDsbPos(int form=ofRad) const
Gets the speedbrake position.
Models a flight control system summing component.
void SetYawTrimCmd(double cmd)
Sets the rudder trim command.
double GetDrCmd(void) const
Gets the rudder command.
double GetRBrake(void) const
Gets the right brake.
double GetRollTrimCmd(void) const
Gets the aileron trim command.
BrakeGroup
Brake grouping enumerators.
void SetLBrake(double cmd)
Sets the left brake group.
double GetDaRPos(int form=ofRad) const
Gets the right aileron position.
static char normint[6]
normal intensity text
void SetMixtureCmd(int engine, double cmd)
Sets the mixture command for the specified engine.
void SetPropAdvanceCmd(int engine, double cmd)
Sets the propeller pitch command for the specified engine.
void SetDsbPos(int form, double pos)
Sets the speedbrake position.
void SetTailhookPos(double hookpos)
Set the tailhook position.
std::string ReadFrom(void) const
Return a string that contains a description of the location where the current XML element was read fr...
bool Load(Element *el) override
Loads the Flight Control System.
static char highint[5]
highlights text
void SetDrCmd(double cmd)
Sets the rudder command.
Element * FindNextElement(const std::string &el="")
Searches for the next element as specified.
void SetCBrake(double cmd)
Sets the center brake group.
Element * GetNextElement(void)
Returns a pointer to the next element in the list.
Element * GetElement(unsigned int el=0)
Returns a pointer to the element requested by index.
Encapsulates a switch for the flight control system.
double GetGearCmd(void) const
Get the gear extend/retract command.
double GetBrake(FGLGear::BrakeGroup bg)
Gets the brake for a specified group.
const SGPath & GetFullAircraftPath(void)
Retrieves the full aircraft path name.
double GetDaLPos(int form=ofRad) const
Gets the left aileron position.
Encapsulates an Actuator component for the flight control system.
static char fgblue[6]
blue text
Encapsulates a magnetometer component for the flight control system.
void SetRollTrimCmd(double cmd)
Sets the aileron trim command.
void Tie(const std::string &name, T *pointer)
Tie a property to an external variable.
Encapsulates a distributor for the flight control system.
double GetDrPos(int form=ofRad) const
Gets the rudder position.
void SetDePos(int form, double pos)
Sets the elevator position.
void SetGearPos(double gearpos)
Set the gear extend/retract position, defaults to down.
void AddAttribute(const std::string &name, const std::string &value)
Stores an attribute belonging to this element.