#include "FGPosition.h"
#include "FGAuxiliary.h"
#include "FGOutput.h"
+#include "FGPropertyManager.h"
#include "filtersjb/FGFilter.h"
#include "filtersjb/FGDeadBand.h"
static const char *IdSrc = "$Id$";
static const char *IdHdr = ID_FCS;
+#if defined(WIN32) && !defined(__CYGWIN__)
+#define snprintf _snprintf
+#endif
+
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
CLASS IMPLEMENTATION
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
FGFCS::FGFCS(FGFDMExec* fdmex) : FGModel(fdmex)
{
+ int i;
Name = "FGFCS";
DaCmd = DeCmd = DrCmd = DfCmd = DsbCmd = DspCmd = 0.0;
PTrimCmd = YTrimCmd = RTrimCmd = 0.0;
- DaPos = DePos = DrPos = DfPos = DsbPos = DspPos = 0.0;
GearCmd = GearPos = 1; // default to gear down
LeftBrake = RightBrake = CenterBrake = 0.0;
-
+ DoNormalize=true;
+
+ bind();
+ for (i=0;i<=NForms;i++) {
+ DePos[i] = DaLPos[i] = DaRPos[i] = DrPos[i] = 0.0;
+ DfPos[i] = DsbPos[i] = DspPos[i] = 0.0;
+ }
+
+ for (i=0;i<NNorm;i++) { ToNormalize[i]=-1;}
Debug(0);
}
PropAdvance.clear();
unsigned int i;
+
+ unbind();
for (i=0;i<Components.size();i++) delete Components[i];
Debug(1);
for (i=0; i<MixturePos.size(); i++) MixturePos[i] = MixtureCmd[i];
for (i=0; i<PropAdvance.size(); i++) PropAdvance[i] = PropAdvanceCmd[i];
for (i=0; i<Components.size(); i++) Components[i]->Run();
+ if (DoNormalize) Normalize();
} else {
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-double FGFCS::GetThrottleCmd(int engineNum)
+double FGFCS::GetThrottleCmd(int engineNum) const
{
if (engineNum < (int)ThrottlePos.size()) {
if (engineNum < 0) {
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-double FGFCS::GetThrottlePos(int engineNum)
+double FGFCS::GetThrottlePos(int engineNum) const
{
if (engineNum < (int)ThrottlePos.size()) {
if (engineNum < 0) {
bool FGFCS::Load(FGConfigFile* AC_cfg)
{
string token;
-
+ unsigned i;
+
Name = Name + ":" + AC_cfg->GetValue("NAME");
if (debug_lvl > 0) cout << " Control System Name: " << Name << endl;
+ if ( AC_cfg->GetValue("NORMALIZE") == "FALSE") {
+ DoNormalize=false;
+ cout << " Automatic Control Surface Normalization Disabled" << endl;
+ }
AC_cfg->GetNextConfigLine();
while ((token = AC_cfg->GetValue()) != string("/FLIGHT_CONTROL")) {
if (token == "COMPONENT") {
token = AC_cfg->GetValue("TYPE");
- if (debug_lvl > 0) cout << " Loading Component \""
+ if (debug_lvl > 0) cout << endl << " Loading Component \""
<< AC_cfg->GetValue("NAME")
<< "\" of type: " << token << endl;
if ((token == "LAG_FILTER") ||
AC_cfg->GetNextConfigLine();
}
}
+ //collect information for normalizing control surfaces
+ string nodeName;
+ for (i=0;i<Components.size();i++) {
+
+ if ( (Components[i]->GetType() == "AEROSURFACE_SCALE"
+ || Components[i]->GetType() == "KINEMAT")
+ && Components[i]->GetOutputNode() ) {
+ nodeName= Components[i]->GetOutputNode()->GetName();
+ if ( nodeName == "elevator-pos-rad" ) {
+ ToNormalize[iDe]=i;
+ } else if ( nodeName == "left-aileron-pos-rad"
+ || nodeName == "aileron-pos-rad" ) {
+ ToNormalize[iDaL]=i;
+ } else if ( nodeName == "right-aileron-pos-rad" ) {
+ ToNormalize[iDaR]=i;
+ } else if ( nodeName == "rudder-pos-rad" ) {
+ ToNormalize[iDr]=i;
+ } else if ( nodeName == "speedbrake-pos-rad" ) {
+ ToNormalize[iDsb]=i;
+ } else if ( nodeName == "spoiler-pos-rad" ) {
+ ToNormalize[iDsp]=i;
+ } else if ( nodeName == "flap-pos-deg" ) {
+ ToNormalize[iDf]=i;
+ }
+ }
+ }
+
+ bindModel();
+
return true;
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-double FGFCS::GetComponentOutput(eParam idx) {
+double FGFCS::GetComponentOutput(int idx) {
return Components[idx]->GetOutput();
}
PropAdvance.push_back(0.0);
}
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+void FGFCS::Normalize(void) {
+
+ //not all of these are guaranteed to be defined for every model
+ //those that are have an index >=0 in the ToNormalize array
+ //ToNormalize is filled in Load()
+
+ if ( ToNormalize[iDe] > -1 ) {
+ DePos[ofNorm] = Components[ToNormalize[iDe]]->GetOutputPct();
+ }
+
+ if ( ToNormalize[iDaL] > -1 ) {
+ DaLPos[ofNorm] = Components[ToNormalize[iDaL]]->GetOutputPct();
+ }
+
+ if ( ToNormalize[iDaR] > -1 ) {
+ DaRPos[ofNorm] = Components[ToNormalize[iDaR]]->GetOutputPct();
+ }
+
+ if ( ToNormalize[iDr] > -1 ) {
+ DrPos[ofNorm] = Components[ToNormalize[iDr]]->GetOutputPct();
+ }
+
+ if ( ToNormalize[iDsb] > -1 ) {
+ DsbPos[ofNorm] = Components[ToNormalize[iDsb]]->GetOutputPct();
+ }
+
+ if ( ToNormalize[iDsp] > -1 ) {
+ DspPos[ofNorm] = Components[ToNormalize[iDsp]]->GetOutputPct();
+ }
+
+ if ( ToNormalize[iDf] > -1 ) {
+ DfPos[ofNorm] = Components[ToNormalize[iDf]]->GetOutputPct();
+ }
+
+ DePos[ofMag] = fabs(DePos[ofRad]);
+ DaLPos[ofMag] = fabs(DaLPos[ofRad]);
+ DaRPos[ofMag] = fabs(DaRPos[ofRad]);
+ DrPos[ofMag] = fabs(DrPos[ofRad]);
+ DsbPos[ofMag] = fabs(DsbPos[ofRad]);
+ DspPos[ofMag] = fabs(DspPos[ofRad]);
+ DfPos[ofMag] = fabs(DfPos[ofRad]);
+
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+void FGFCS::bind(void)
+{
+ PropertyManager->Tie("fcs/aileron-cmd-norm", this,
+ &FGFCS::GetDaCmd,
+ &FGFCS::SetDaCmd,
+ true);
+ PropertyManager->Tie("fcs/elevator-cmd-norm", this,
+ &FGFCS::GetDeCmd,
+ &FGFCS::SetDeCmd,
+ true);
+ PropertyManager->Tie("fcs/rudder-cmd-norm", this,
+ &FGFCS::GetDrCmd,
+ &FGFCS::SetDrCmd,
+ true);
+ PropertyManager->Tie("fcs/flap-cmd-norm", this,
+ &FGFCS::GetDfCmd,
+ &FGFCS::SetDfCmd,
+ true);
+ PropertyManager->Tie("fcs/speedbrake-cmd-norm", this,
+ &FGFCS::GetDsbCmd,
+ &FGFCS::SetDsbCmd,
+ true);
+ PropertyManager->Tie("fcs/spoiler-cmd-norm", this,
+ &FGFCS::GetDspCmd,
+ &FGFCS::SetDspCmd,
+ true);
+ PropertyManager->Tie("fcs/pitch-trim-cmd-norm", this,
+ &FGFCS::GetPitchTrimCmd,
+ &FGFCS::SetPitchTrimCmd,
+ true);
+ PropertyManager->Tie("fcs/roll-trim-cmd-norm", this,
+ &FGFCS::GetYawTrimCmd,
+ &FGFCS::SetYawTrimCmd,
+ true);
+ PropertyManager->Tie("fcs/yaw-trim-cmd-norm", this,
+ &FGFCS::GetRollTrimCmd,
+ &FGFCS::SetRollTrimCmd,
+ true);
+ PropertyManager->Tie("gear/gear-cmd-norm", this,
+ &FGFCS::GetGearCmd,
+ &FGFCS::SetGearCmd,
+ true);
+
+ PropertyManager->Tie("fcs/left-aileron-pos-rad", this,ofRad,
+ &FGFCS::GetDaLPos,
+ &FGFCS::SetDaLPos,
+ true);
+ PropertyManager->Tie("fcs/left-aileron-pos-norm", this,ofNorm,
+ &FGFCS::GetDaLPos,
+ &FGFCS::SetDaLPos,
+ true);
+ PropertyManager->Tie("fcs/mag-left-aileron-pos-rad", this,ofMag,
+ &FGFCS::GetDaLPos,
+ &FGFCS::SetDaLPos,
+ true);
+
+ PropertyManager->Tie("fcs/right-aileron-pos-rad", this,ofRad,
+ &FGFCS::GetDaRPos,
+ &FGFCS::SetDaRPos,
+ true);
+ PropertyManager->Tie("fcs/right-aileron-pos-norm", this,ofNorm,
+ &FGFCS::GetDaRPos,
+ &FGFCS::SetDaRPos,
+ true);
+ PropertyManager->Tie("fcs/mag-right-aileron-pos-rad", this,ofMag,
+ &FGFCS::GetDaRPos,
+ &FGFCS::SetDaRPos,
+ true);
+
+ PropertyManager->Tie("fcs/elevator-pos-rad", this, ofRad,
+ &FGFCS::GetDePos,
+ &FGFCS::SetDePos,
+ true );
+ PropertyManager->Tie("fcs/elevator-pos-norm", this,ofNorm,
+ &FGFCS::GetDePos,
+ &FGFCS::SetDePos,
+ true );
+ PropertyManager->Tie("fcs/mag-elevator-pos-rad", this,ofMag,
+ &FGFCS::GetDePos,
+ &FGFCS::SetDePos,
+ true );
+
+ PropertyManager->Tie("fcs/rudder-pos-rad", this,ofRad,
+ &FGFCS::GetDrPos,
+ &FGFCS::SetDrPos,
+ true);
+ PropertyManager->Tie("fcs/rudder-pos-norm", this,ofNorm,
+ &FGFCS::GetDrPos,
+ &FGFCS::SetDrPos,
+ true);
+ PropertyManager->Tie("fcs/mag-rudder-pos-rad", this,ofMag,
+ &FGFCS::GetDrPos,
+ &FGFCS::SetDrPos,
+ true);
+
+ PropertyManager->Tie("fcs/flap-pos-deg", this,ofRad,
+ &FGFCS::GetDfPos,
+ &FGFCS::SetDfPos,
+ true);
+ PropertyManager->Tie("fcs/flap-pos-norm", this,ofNorm,
+ &FGFCS::GetDfPos,
+ &FGFCS::SetDfPos,
+ true);
+
+ PropertyManager->Tie("fcs/speedbrake-pos-rad", this,ofRad,
+ &FGFCS::GetDsbPos,
+ &FGFCS::SetDsbPos,
+ true);
+ PropertyManager->Tie("fcs/speedbrake-pos-norm", this,ofNorm,
+ &FGFCS::GetDsbPos,
+ &FGFCS::SetDsbPos,
+ true);
+ PropertyManager->Tie("fcs/mag-speedbrake-pos-rad", this,ofMag,
+ &FGFCS::GetDsbPos,
+ &FGFCS::SetDsbPos,
+ true);
+
+ PropertyManager->Tie("fcs/spoiler-pos-rad", this,ofRad,
+ &FGFCS::GetDspPos,
+ &FGFCS::SetDspPos,
+ true);
+ PropertyManager->Tie("fcs/spoiler-pos-norm", this,ofNorm,
+ &FGFCS::GetDspPos,
+ &FGFCS::SetDspPos,
+ true);
+ PropertyManager->Tie("fcs/mag-spoiler-pos-rad", this,ofMag,
+ &FGFCS::GetDspPos,
+ &FGFCS::SetDspPos,
+ true);
+
+ PropertyManager->Tie("gear/gear-pos-norm", this,
+ &FGFCS::GetGearPos,
+ &FGFCS::SetGearPos,
+ true);
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+void FGFCS::bindModel(void)
+{
+ unsigned i;
+ char tmp[80];
+
+ for (i=0; i<ThrottleCmd.size(); i++) {
+ snprintf(tmp,80,"fcs/throttle-cmd-norm[%u]",i);
+ PropertyManager->Tie( tmp,this,i,
+ &FGFCS::GetThrottleCmd,
+ &FGFCS::SetThrottleCmd,
+ true );
+ snprintf(tmp,80,"fcs/throttle-pos-norm[%u]",i);
+ PropertyManager->Tie( tmp,this,i,
+ &FGFCS::GetThrottlePos,
+ &FGFCS::SetThrottlePos,
+ true );
+ if ( MixtureCmd.size() > i ) {
+ snprintf(tmp,80,"fcs/mixture-cmd-norm[%u]",i);
+ PropertyManager->Tie( tmp,this,i,
+ &FGFCS::GetMixtureCmd,
+ &FGFCS::SetMixtureCmd,
+ true );
+ snprintf(tmp,80,"fcs/mixture-pos-norm[%u]",i);
+ PropertyManager->Tie( tmp,this,i,
+ &FGFCS::GetMixturePos,
+ &FGFCS::SetMixturePos,
+ true );
+ }
+ if ( PropAdvanceCmd.size() > i ) {
+ snprintf(tmp,80,"fcs/advance-cmd-norm[%u]",i);
+ PropertyManager->Tie( tmp,this,i,
+ &FGFCS::GetPropAdvanceCmd,
+ &FGFCS::SetPropAdvanceCmd,
+ true );
+ snprintf(tmp,80,"fcs/advance-pos-norm[%u]",i);
+ PropertyManager->Tie( tmp,this,i,
+ &FGFCS::GetPropAdvance,
+ &FGFCS::SetPropAdvance,
+ true );
+ }
+ }
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+void FGFCS::unbind(void)
+{
+ PropertyManager->Untie("fcs/aileron-cmd-norm");
+ PropertyManager->Untie("fcs/elevator-cmd-norm");
+ PropertyManager->Untie("fcs/rudder-cmd-norm");
+ PropertyManager->Untie("fcs/flap-cmd-norm");
+ PropertyManager->Untie("fcs/speedbrake-cmd-norm");
+ PropertyManager->Untie("fcs/spoiler-cmd-norm");
+ PropertyManager->Untie("fcs/pitch-trim-cmd-norm");
+ PropertyManager->Untie("fcs/roll-trim-cmd-norm");
+ PropertyManager->Untie("fcs/yaw-trim-cmd-norm");
+ PropertyManager->Untie("gear/gear-cmd-norm");
+ PropertyManager->Untie("fcs/left-aileron-pos-rad");
+ PropertyManager->Untie("fcs/mag-left-aileron-pos-rad");
+ PropertyManager->Untie("fcs/left-aileron-pos-norm");
+ PropertyManager->Untie("fcs/right-aileron-pos-rad");
+ PropertyManager->Untie("fcs/mag-right-aileron-pos-rad");
+ PropertyManager->Untie("fcs/right-aileron-pos-norm");
+ PropertyManager->Untie("fcs/elevator-pos-rad");
+ PropertyManager->Untie("fcs/mag-elevator-pos-rad");
+ PropertyManager->Untie("fcs/elevator-pos-norm");
+ PropertyManager->Untie("fcs/rudder-pos-rad");
+ PropertyManager->Untie("fcs/mag-rudder-pos-rad");
+ PropertyManager->Untie("fcs/rudder-pos-norm");
+ PropertyManager->Untie("fcs/flap-pos-deg");
+ PropertyManager->Untie("fcs/flap-pos-norm");
+ PropertyManager->Untie("fcs/speedbrake-pos-rad");
+ PropertyManager->Untie("fcs/mag-speedbrake-pos-rad");
+ PropertyManager->Untie("fcs/speedbrake-pos-norm");
+ PropertyManager->Untie("fcs/spoiler-pos-rad");
+ PropertyManager->Untie("fcs/mag-spoiler-pos-rad");
+ PropertyManager->Untie("fcs/spoiler-pos-norm");
+ PropertyManager->Untie("gear/gear-pos-norm");
+}
+
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
// The bitmasked value choices are as follows:
// unset: In this case (the default) JSBSim would only print
}
if (debug_lvl & 16) { // Sanity checking
}
+ if (debug_lvl & 64) {
+ if (from == 0) { // Constructor
+ cout << IdSrc << endl;
+ cout << IdHdr << endl;
+ }
+ }
}
+