+ return 0.0;
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+string FGFCS::GetComponentStrings(void)
+{
+ unsigned int comp;
+ string CompStrings = "";
+ bool firstime = true;
+
+ for (comp = 0; comp < FCSComponents.size(); comp++) {
+ if (firstime) firstime = false;
+ else CompStrings += ", ";
+
+ CompStrings += FCSComponents[comp]->GetName();
+ }
+
+ for (comp = 0; comp < APComponents.size(); comp++)
+ {
+ CompStrings += ", ";
+ CompStrings += APComponents[comp]->GetName();
+ }
+
+ return CompStrings;
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+string FGFCS::GetComponentValues(void)
+{
+ unsigned int comp;
+ string CompValues = "";
+ char buffer[10];
+ bool firstime = true;
+
+ for (comp = 0; comp < FCSComponents.size(); comp++) {
+ if (firstime) firstime = false;
+ else CompValues += ", ";
+
+ sprintf(buffer, "%9.6f", FCSComponents[comp]->GetOutput());
+ CompValues += string(buffer);
+ }
+
+ for (comp = 0; comp < APComponents.size(); comp++) {
+ sprintf(buffer, ", %9.6f", APComponents[comp]->GetOutput());
+ CompValues += string(buffer);
+ }
+
+ return CompValues;
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+void FGFCS::AddThrottle(void)
+{
+ ThrottleCmd.push_back(0.0);
+ ThrottlePos.push_back(0.0);
+ MixtureCmd.push_back(0.0); // assume throttle and mixture are coupled
+ MixturePos.push_back(0.0);
+ PropAdvanceCmd.push_back(0.0); // assume throttle and prop pitch are coupled
+ 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] = FCSComponents[ToNormalize[iDe]]->GetOutputPct();
+ }
+
+ if ( ToNormalize[iDaL] > -1 ) {
+ DaLPos[ofNorm] = FCSComponents[ToNormalize[iDaL]]->GetOutputPct();
+ }
+
+ if ( ToNormalize[iDaR] > -1 ) {
+ DaRPos[ofNorm] = FCSComponents[ToNormalize[iDaR]]->GetOutputPct();
+ }
+
+ if ( ToNormalize[iDr] > -1 ) {
+ DrPos[ofNorm] = FCSComponents[ToNormalize[iDr]]->GetOutputPct();
+ }
+
+ if ( ToNormalize[iDsb] > -1 ) {
+ DsbPos[ofNorm] = FCSComponents[ToNormalize[iDsb]]->GetOutputPct();
+ }
+
+ if ( ToNormalize[iDsp] > -1 ) {
+ DspPos[ofNorm] = FCSComponents[ToNormalize[iDsp]]->GetOutputPct();
+ }
+
+ if ( ToNormalize[iDf] > -1 ) {
+ DfPos[ofNorm] = FCSComponents[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);
+
+ PropertyManager->Tie("ap/elevator_cmd", this,
+ &FGFCS::GetAPDeCmd,
+ &FGFCS::SetAPDeCmd,
+ true);
+
+ PropertyManager->Tie("ap/aileron_cmd", this,
+ &FGFCS::GetAPDaCmd,
+ &FGFCS::SetAPDaCmd,
+ true);
+
+ PropertyManager->Tie("ap/rudder_cmd", this,
+ &FGFCS::GetAPDrCmd,
+ &FGFCS::SetAPDrCmd,
+ true);
+
+ PropertyManager->Tie("ap/throttle_cmd", this,
+ &FGFCS::GetAPThrottleCmd,
+ &FGFCS::SetAPThrottleCmd,
+ true);
+
+ PropertyManager->Tie("ap/attitude_setpoint", this,
+ &FGFCS::GetAPAttitudeSetPt,
+ &FGFCS::SetAPAttitudeSetPt,
+ true);
+
+ PropertyManager->Tie("ap/altitude_setpoint", this,
+ &FGFCS::GetAPAltitudeSetPt,
+ &FGFCS::SetAPAltitudeSetPt,
+ true);
+
+ PropertyManager->Tie("ap/heading_setpoint", this,
+ &FGFCS::GetAPHeadingSetPt,
+ &FGFCS::SetAPHeadingSetPt,
+ true);
+
+ PropertyManager->Tie("ap/airspeed_setpoint", this,
+ &FGFCS::GetAPAirspeedSetPt,
+ &FGFCS::SetAPAirspeedSetPt,
+ true);
+
+ PropertyManager->Tie("ap/acquire_attitude", this,
+ &FGFCS::GetAPAcquireAttitude,
+ &FGFCS::SetAPAcquireAttitude,
+ true);
+
+ PropertyManager->Tie("ap/acquire_altitude", this,
+ &FGFCS::GetAPAcquireAltitude,
+ &FGFCS::SetAPAcquireAltitude,
+ true);
+
+ PropertyManager->Tie("ap/acquire_heading", this,
+ &FGFCS::GetAPAcquireHeading,
+ &FGFCS::SetAPAcquireHeading,
+ true);
+
+ PropertyManager->Tie("ap/acquire_airspeed", this,
+ &FGFCS::GetAPAcquireAirspeed,
+ &FGFCS::SetAPAcquireAirspeed,
+ true);
+
+ PropertyManager->Tie("ap/attitude_hold", this,
+ &FGFCS::GetAPAttitudeHold,
+ &FGFCS::SetAPAttitudeHold,
+ true);
+
+ PropertyManager->Tie("ap/altitude_hold", this,
+ &FGFCS::GetAPAltitudeHold,
+ &FGFCS::SetAPAltitudeHold,
+ true);
+
+ PropertyManager->Tie("ap/heading_hold", this,
+ &FGFCS::GetAPHeadingHold,
+ &FGFCS::SetAPHeadingHold,
+ true);
+
+ PropertyManager->Tie("ap/airspeed_hold", this,
+ &FGFCS::GetAPAirspeedHold,
+ &FGFCS::SetAPAirspeedHold,
+ true);
+
+ PropertyManager->Tie("ap/wingslevel_hold", this,
+ &FGFCS::GetAPWingsLevelHold,
+ &FGFCS::SetAPWingsLevelHold,
+ 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(FGPropertyManager *node)
+{
+ int N = node->nChildren();
+ for(int i=0;i<N;i++) {
+ if(node->getChild(i)->nChildren() ) {
+ unbind( (FGPropertyManager*)node->getChild(i) );
+ } else if( node->getChild(i)->isTied() ) {
+ node->getChild(i)->untie();
+ }
+ }