]> git.mxchange.org Git - flightgear.git/blobdiff - src/FDM/JSBSim/initialization/FGInitialCondition.cpp
Merge branch 'jmt/units-fix' into maint
[flightgear.git] / src / FDM / JSBSim / initialization / FGInitialCondition.cpp
index 02262b092ecba16a3fc69237cd1cd58ad19e3e73..7eb3f7f6661b01346b66a01d38c083b415ac1d15 100644 (file)
@@ -7,20 +7,20 @@
  ------------- Copyright (C) 1999  Anthony K. Peden (apeden@earthlink.net) -------------
 
  This program is free software; you can redistribute it and/or modify it under
- the terms of the GNU General Public License as published by the Free Software
+ the terms of the GNU Lesser General Public License as published by the Free Software
  Foundation; either version 2 of the License, or (at your option) any later
  version.
 
  This program is distributed in the hope that it will be useful, but WITHOUT
  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
- FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
+ FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
  details.
 
- You should have received a copy of the GNU General Public License along with
+ You should have received a copy of the GNU Lesser General Public License along with
  this program; if not, write to the Free Software Foundation, Inc., 59 Temple
  Place - Suite 330, Boston, MA  02111-1307, USA.
 
- Further information about the GNU General Public License can also be found on
+ Further information about the GNU Lesser General Public License can also be found on
  the world wide web at http://www.gnu.org.
 
 
@@ -42,30 +42,22 @@ you have chosen your IC's wisely) even after setting it up with this class.
 INCLUDES
 *******************************************************************************/
 
-#ifdef FGFS
-#  include <simgear/compiler.h>
-#  ifdef SG_HAVE_STD_INCLUDES
-#    include <fstream>
-#  else
-#    include <fstream.h>
-#  endif
-#else
-#  if defined(sgi) && !defined(__GNUC__) && (_COMPILER_VERSION < 740)
-#    include <fstream.h>
-#  else
-#    include <fstream>
-#  endif
-#endif
-
 #include "FGInitialCondition.h"
-#include <FGFDMExec.h>
-#include <models/FGInertial.h>
-#include <models/FGAtmosphere.h>
-#include <models/FGAerodynamics.h>
-#include <models/FGPropagate.h>
-#include <input_output/FGPropertyManager.h>
-#include <models/FGPropulsion.h>
-#include <input_output/FGXMLParse.h>
+#include "FGFDMExec.h"
+#include "models/FGInertial.h"
+#include "models/FGAtmosphere.h"
+#include "models/FGAerodynamics.h"
+#include "models/FGPropagate.h"
+#include "input_output/FGPropertyManager.h"
+#include "input_output/FGXMLElement.h"
+#include "models/FGPropulsion.h"
+#include "input_output/FGXMLParse.h"
+#include "math/FGQuaternion.h"
+#include <iostream>
+#include <fstream>
+#include <cstdlib>
+
+using namespace std;
 
 namespace JSBSim {
 
@@ -74,13 +66,80 @@ static const char *IdHdr = ID_INITIALCONDITION;
 
 //******************************************************************************
 
-FGInitialCondition::FGInitialCondition(FGFDMExec *FDMExec)
+FGInitialCondition::FGInitialCondition(FGFDMExec *FDMExec) : fdmex(FDMExec)
+{
+  InitializeIC();
+
+  if(FDMExec != NULL ) {
+    fdmex->GetPropagate()->SetAltitudeASL(altitudeASL);
+    fdmex->GetAtmosphere()->Run();
+    PropertyManager=fdmex->GetPropertyManager();
+    Constructing = true;
+    bind();
+    Constructing = false;
+  } else {
+    cout << "FGInitialCondition: This class requires a pointer to a valid FGFDMExec object" << endl;
+  }
+
+  Debug(0);
+}
+
+//******************************************************************************
+
+FGInitialCondition::~FGInitialCondition()
+{
+  Debug(1);
+}
+
+//******************************************************************************
+
+void FGInitialCondition::ResetIC(double u0, double v0, double w0,
+                                 double p0, double q0, double r0,
+                                 double alpha0, double beta0,
+                                 double phi0, double theta0, double psi0,
+                                 double latRad0, double lonRad0, double altAGLFt0,
+                                 double gamma0)
+{
+  InitializeIC();
+
+  u = u0;  v = v0;  w = w0;
+  p = p0;  q = q0;  r = r0;
+  alpha = alpha0;  beta = beta0;
+  phi = phi0;  theta = theta0;  psi = psi0;
+  gamma = gamma0;
+
+  latitude = latRad0;
+  longitude = lonRad0;
+  SetAltitudeAGLFtIC(altAGLFt0);
+
+  cphi   = cos(phi);   sphi   = sin(phi);   // phi, rad
+  ctheta = cos(theta); stheta = sin(theta); // theta, rad
+  cpsi   = cos(psi);   spsi   = sin(psi);   // psi, rad
+
+  FGQuaternion Quat( phi, theta, psi );
+  Quat.Normalize();
+
+  const FGMatrix33& _Tl2b  = Quat.GetT();     // local to body frame
+  const FGMatrix33& _Tb2l  = Quat.GetTInv();  // body to local
+
+  FGColumnVector3 _vUVW_BODY(u,v,w);
+  FGColumnVector3 _vUVW_NED = _Tb2l * _vUVW_BODY;
+  FGColumnVector3 _vWIND_NED(wnorth,weast,wdown);
+//  FGColumnVector3 _vUVWAero = _Tl2b * ( _vUVW_NED + _vWIND_NED );
+
+  uw=_vWIND_NED(1); vw=_vWIND_NED(2); ww=_vWIND_NED(3);
+
+}
+
+//******************************************************************************
+
+void FGInitialCondition::InitializeIC(void)
 {
   vt=vc=ve=vg=0;
   mach=0;
   alpha=beta=gamma=0;
   theta=phi=psi=0;
-  altitude=hdot=0;
+  altitudeASL=hdot=0;
   latitude=longitude=0;
   u=v=w=0;
   p=q=r=0;
@@ -91,32 +150,48 @@ FGInitialCondition::FGInitialCondition(FGFDMExec *FDMExec)
   wdir=wmag=0;
   lastSpeedSet=setvt;
   lastWindSet=setwned;
-  sea_level_radius = FDMExec->GetInertial()->RefRadius();
-  radius_to_vehicle = FDMExec->GetInertial()->RefRadius();
-  terrain_altitude = 0;
+  radius_to_vehicle = sea_level_radius = fdmex->GetInertial()->GetRefRadius();
+  terrain_elevation = 0;
+
+  targetNlfIC = 1.0;
 
   salpha=sbeta=stheta=sphi=spsi=sgamma=0;
   calpha=cbeta=ctheta=cphi=cpsi=cgamma=1;
-
-  if(FDMExec != NULL ) {
-    fdmex=FDMExec;
-    fdmex->GetPropagate()->Seth(altitude);
-    fdmex->GetAtmosphere()->Run();
-    PropertyManager=fdmex->GetPropertyManager();
-    bind();
-  } else {
-    cout << "FGInitialCondition: This class requires a pointer to a valid FGFDMExec object" << endl;
-  }
-
-  Debug(0);
 }
 
 //******************************************************************************
 
-FGInitialCondition::~FGInitialCondition()
+void FGInitialCondition::WriteStateFile(int num)
 {
-  unbind();
-  Debug(1);
+  if (Constructing) return;
+
+  string filename = fdmex->GetFullAircraftPath();
+
+  if (filename.empty())
+    filename = "initfile.xml";
+  else
+    filename.append("/initfile.xml");
+  
+  ofstream outfile(filename.c_str());
+  FGPropagate* Propagate = fdmex->GetPropagate();
+  
+  if (outfile.is_open()) {
+    outfile << "<?xml version=\"1.0\"?>" << endl;
+    outfile << "<initialize name=\"reset00\">" << endl;
+    outfile << "  <ubody unit=\"FT/SEC\"> " << Propagate->GetUVW(eX) << " </ubody> " << endl;
+    outfile << "  <vbody unit=\"FT/SEC\"> " << Propagate->GetUVW(eY) << " </vbody> " << endl;
+    outfile << "  <wbody unit=\"FT/SEC\"> " << Propagate->GetUVW(eZ) << " </wbody> " << endl;
+    outfile << "  <phi unit=\"DEG\"> " << Propagate->GetEuler(ePhi) << " </phi>" << endl;
+    outfile << "  <theta unit=\"DEG\"> " << Propagate->GetEuler(eTht) << " </theta>" << endl;
+    outfile << "  <psi unit=\"DEG\"> " << Propagate->GetEuler(ePsi) << " </psi>" << endl;
+    outfile << "  <longitude unit=\"DEG\"> " << Propagate->GetLongitudeDeg() << " </longitude>" << endl;
+    outfile << "  <latitude unit=\"DEG\"> " << Propagate->GetLatitudeDeg() << " </latitude>" << endl;
+    outfile << "  <altitude unit=\"FT\"> " << Propagate->GetAltitudeASL() << " </altitude>" << endl;
+    outfile << "</initialize>" << endl;
+    outfile.close();
+  } else {
+    cerr << "Could not open and/or write the state to the initial conditions file: " << filename << endl;
+  }
 }
 
 //******************************************************************************
@@ -280,10 +355,69 @@ void FGInitialCondition::SetWBodyFpsIC(double tt) {
   lastSpeedSet=setuvw;
 }
 
+
+//******************************************************************************
+
+void FGInitialCondition::SetVNorthFpsIC(double tt) {
+  double ua,va,wa;
+  double vxz;
+  vnorth = tt;
+  calcUVWfromNED();
+  ua = u + uw; va = v + vw; wa = w + ww;
+  vt = sqrt( ua*ua + va*va + wa*wa );
+  alpha = beta = 0;
+  vxz = sqrt( u*u + w*w );
+  if( w != 0 ) alpha = atan2( w, u );
+  if( vxz != 0 ) beta = atan2( v, vxz );
+  mach=vt/fdmex->GetAtmosphere()->GetSoundSpeed();
+  vc=calcVcas(mach);
+  ve=vt*sqrt(fdmex->GetAtmosphere()->GetDensityRatio());
+  lastSpeedSet=setned;
+}
+
+//******************************************************************************
+
+void FGInitialCondition::SetVEastFpsIC(double tt) {
+  double ua,va,wa;
+  double vxz;
+  veast = tt;
+  calcUVWfromNED();
+  ua = u + uw; va = v + vw; wa = w + ww;
+  vt = sqrt( ua*ua + va*va + wa*wa );
+  alpha = beta = 0;
+  vxz = sqrt( u*u + w*w );
+  if( w != 0 ) alpha = atan2( w, u );
+  if( vxz != 0 ) beta = atan2( v, vxz );
+  mach=vt/fdmex->GetAtmosphere()->GetSoundSpeed();
+  vc=calcVcas(mach);
+  ve=vt*sqrt(fdmex->GetAtmosphere()->GetDensityRatio());
+  lastSpeedSet=setned;
+}
+
+//******************************************************************************
+
+void FGInitialCondition::SetVDownFpsIC(double tt) {
+  double ua,va,wa;
+  double vxz;
+  vdown = tt;
+  calcUVWfromNED();
+  ua = u + uw; va = v + vw; wa = w + ww;
+  vt = sqrt( ua*ua + va*va + wa*wa );
+  alpha = beta = 0;
+  vxz = sqrt( u*u + w*w );
+  if( w != 0 ) alpha = atan2( w, u );
+  if( vxz != 0 ) beta = atan2( v, vxz );
+  mach=vt/fdmex->GetAtmosphere()->GetSoundSpeed();
+  vc=calcVcas(mach);
+  ve=vt*sqrt(fdmex->GetAtmosphere()->GetDensityRatio());
+  SetClimbRateFpsIC(-1*vdown);
+  lastSpeedSet=setned;
+}
+
 //******************************************************************************
 
 double FGInitialCondition::GetUBodyFpsIC(void) const {
-    if(lastSpeedSet == setvg )
+    if (lastSpeedSet == setvg || lastSpeedSet == setned)
       return u;
     else
       return vt*calpha*cbeta - uw;
@@ -292,7 +426,7 @@ double FGInitialCondition::GetUBodyFpsIC(void) const {
 //******************************************************************************
 
 double FGInitialCondition::GetVBodyFpsIC(void) const {
-    if( lastSpeedSet == setvg )
+    if (lastSpeedSet == setvg || lastSpeedSet == setned)
       return v;
     else {
       return vt*sbeta - vw;
@@ -302,7 +436,7 @@ double FGInitialCondition::GetVBodyFpsIC(void) const {
 //******************************************************************************
 
 double FGInitialCondition::GetWBodyFpsIC(void) const {
-    if( lastSpeedSet == setvg )
+    if (lastSpeedSet == setvg || lastSpeedSet == setned)
       return w;
     else
       return vt*salpha*cbeta -ww;
@@ -409,9 +543,10 @@ void FGInitialCondition::calcWindUVW(void) {
 
 //******************************************************************************
 
-void FGInitialCondition::SetAltitudeFtIC(double tt) {
-  altitude=tt;
-  fdmex->GetPropagate()->Seth(altitude);
+void FGInitialCondition::SetAltitudeASLFtIC(double tt)
+{
+  altitudeASL=tt;
+  fdmex->GetPropagate()->SetAltitudeASL(altitudeASL);
   fdmex->GetAtmosphere()->Run();
   //lets try to make sure the user gets what they intended
 
@@ -438,25 +573,29 @@ void FGInitialCondition::SetAltitudeFtIC(double tt) {
 
 //******************************************************************************
 
-void FGInitialCondition::SetAltitudeAGLFtIC(double tt) {
-  SetAltitudeFtIC(terrain_altitude + tt);
+void FGInitialCondition::SetAltitudeAGLFtIC(double tt)
+{
+  SetAltitudeASLFtIC(terrain_elevation + tt);
 }
 
 //******************************************************************************
 
-void FGInitialCondition::SetSeaLevelRadiusFtIC(double tt) {
+void FGInitialCondition::SetSeaLevelRadiusFtIC(double tt)
+{
   sea_level_radius = tt;
 }
 
 //******************************************************************************
 
-void FGInitialCondition::SetTerrainAltitudeFtIC(double tt) {
-  terrain_altitude=tt;
+void FGInitialCondition::SetTerrainElevationFtIC(double tt)
+{
+  terrain_elevation=tt;
 }
 
 //******************************************************************************
 
-void FGInitialCondition::calcUVWfromNED(void) {
+void FGInitialCondition::calcUVWfromNED(void)
+{
   u=vnorth*ctheta*cpsi +
      veast*ctheta*spsi -
      vdown*stheta;
@@ -470,34 +609,6 @@ void FGInitialCondition::calcUVWfromNED(void) {
 
 //******************************************************************************
 
-void FGInitialCondition::SetVnorthFpsIC(double tt) {
-  vnorth=tt;
-  calcUVWfromNED();
-  vt=sqrt(u*u + v*v + w*w);
-  lastSpeedSet=setned;
-}
-
-//******************************************************************************
-
-void FGInitialCondition::SetVeastFpsIC(double tt) {
-  veast=tt;
-  calcUVWfromNED();
-  vt=sqrt(u*u + v*v + w*w);
-  lastSpeedSet=setned;
-}
-
-//******************************************************************************
-
-void FGInitialCondition::SetVdownFpsIC(double tt) {
-  vdown=tt;
-  calcUVWfromNED();
-  vt=sqrt(u*u + v*v + w*w);
-  SetClimbRateFpsIC(-1*vdown);
-  lastSpeedSet=setned;
-}
-
-//******************************************************************************
-
 bool FGInitialCondition::getMachFromVcas(double *Mach,double vcas) {
 
   bool result=false;
@@ -731,48 +842,68 @@ double FGInitialCondition::GetWindDirDegIC(void) const {
 
 bool FGInitialCondition::Load(string rstfile, bool useStoredPath)
 {
-  string resetDef, acpath;
-  ifstream initialization_file;
-  FGXMLParse initialization_file_parser;
-  Element *document, *el;
   int n;
 
   string sep = "/";
-# ifdef macintosh
-   string sep = ";";
-# endif
-
   if( useStoredPath ) {
-    acpath = fdmex->GetAircraftPath() + sep + fdmex->GetModelName();
-    resetDef = acpath + sep + rstfile + ".xml";
+    init_file_name = fdmex->GetFullAircraftPath() + sep + rstfile + ".xml";
   } else {
-    resetDef = rstfile;
+    init_file_name = rstfile;
   }
 
-  initialization_file.open(resetDef.c_str());
-  if ( !initialization_file.is_open()) {
-    cerr << "Could not open initialization file: " << resetDef << endl;
-    return false;
+  document = LoadXMLDocument(init_file_name);
+
+  // Make sure that the document is valid
+  if (!document) {
+    cerr << "File: " << init_file_name << " could not be read." << endl;
+    exit(-1);
   }
 
-  readXML(initialization_file, initialization_file_parser);
-  document = initialization_file_parser.GetDocument(); // document holds the
-                                                       // initialization description
   if (document->GetName() != string("initialize")) {
-    cerr << "File: " << resetDef << " is not a reset file" << endl;
+    cerr << "File: " << init_file_name << " is not a reset file." << endl;
     exit(-1);
   }
 
+  if (document->FindElement("latitude"))
+    SetLatitudeDegIC(document->FindElementValueAsNumberConvertTo("latitude", "DEG"));
+  if (document->FindElement("longitude"))
+    SetLongitudeDegIC(document->FindElementValueAsNumberConvertTo("longitude", "DEG"));
+  if (document->FindElement("elevation"))
+    SetTerrainElevationFtIC(document->FindElementValueAsNumberConvertTo("elevation", "FT"));
+
+  if (document->FindElement("altitude")) // This is feet above ground level
+    SetAltitudeAGLFtIC(document->FindElementValueAsNumberConvertTo("altitude", "FT"));
+  else if (document->FindElement("altitudeAGL")) // This is feet above ground level
+    SetAltitudeAGLFtIC(document->FindElementValueAsNumberConvertTo("altitudeAGL", "FT"));
+  else if (document->FindElement("altitudeMSL")) // This is feet above sea level
+    SetAltitudeASLFtIC(document->FindElementValueAsNumberConvertTo("altitudeMSL", "FT"));
+
   if (document->FindElement("ubody"))
     SetUBodyFpsIC(document->FindElementValueAsNumberConvertTo("ubody", "FT/SEC"));
   if (document->FindElement("vbody"))
     SetVBodyFpsIC(document->FindElementValueAsNumberConvertTo("vbody", "FT/SEC"));
   if (document->FindElement("wbody"))
     SetWBodyFpsIC(document->FindElementValueAsNumberConvertTo("wbody", "FT/SEC"));
-  if (document->FindElement("latitude"))
-    SetLatitudeDegIC(document->FindElementValueAsNumberConvertTo("latitude", "DEG"));
-  if (document->FindElement("longitude"))
-    SetLongitudeDegIC(document->FindElementValueAsNumberConvertTo("longitude", "DEG"));
+  if (document->FindElement("vnorth"))
+    SetVNorthFpsIC(document->FindElementValueAsNumberConvertTo("vnorth", "FT/SEC"));
+  if (document->FindElement("veast"))
+    SetVEastFpsIC(document->FindElementValueAsNumberConvertTo("veast", "FT/SEC"));
+  if (document->FindElement("vdown"))
+    SetVDownFpsIC(document->FindElementValueAsNumberConvertTo("vdown", "FT/SEC"));
+  if (document->FindElement("winddir"))
+    SetWindDirDegIC(document->FindElementValueAsNumberConvertTo("winddir", "DEG"));
+  if (document->FindElement("vwind"))
+    SetWindMagKtsIC(document->FindElementValueAsNumberConvertTo("vwind", "KTS"));
+  if (document->FindElement("hwind"))
+    SetHeadWindKtsIC(document->FindElementValueAsNumberConvertTo("hwind", "KTS"));
+  if (document->FindElement("xwind"))
+    SetCrossWindKtsIC(document->FindElementValueAsNumberConvertTo("xwind", "KTS"));
+  if (document->FindElement("vc"))
+    SetVcalibratedKtsIC(document->FindElementValueAsNumberConvertTo("vc", "KTS"));
+  if (document->FindElement("vt"))
+    SetVtrueKtsIC(document->FindElementValueAsNumberConvertTo("vt", "KTS"));
+  if (document->FindElement("mach"))
+    SetMachIC(document->FindElementValueAsNumber("mach"));
   if (document->FindElement("phi"))
     SetPhiDegIC(document->FindElementValueAsNumberConvertTo("phi", "DEG"));
   if (document->FindElement("theta"))
@@ -786,31 +917,21 @@ bool FGInitialCondition::Load(string rstfile, bool useStoredPath)
   if (document->FindElement("gamma"))
     SetFlightPathAngleDegIC(document->FindElementValueAsNumberConvertTo("gamma", "DEG"));
   if (document->FindElement("roc"))
-    SetClimbRateFpmIC(document->FindElementValueAsNumberConvertTo("roc", "FT/SEC"));
-  if (document->FindElement("altitude"))
-    SetAltitudeFtIC(document->FindElementValueAsNumberConvertTo("altitude", "FT"));
-  if (document->FindElement("winddir"))
-    SetWindDirDegIC(document->FindElementValueAsNumberConvertTo("winddir", "DEG"));
-  if (document->FindElement("vwind"))
-    SetWindMagKtsIC(document->FindElementValueAsNumberConvertTo("vwind", "FT/SEC"));
-  if (document->FindElement("hwind"))
-    SetHeadWindKtsIC(document->FindElementValueAsNumberConvertTo("hwind", "KTS"));
-  if (document->FindElement("xwind"))
-    SetCrossWindKtsIC(document->FindElementValueAsNumberConvertTo("xwind", "KTS"));
-  if (document->FindElement("vc"))
-    SetVcalibratedKtsIC(document->FindElementValueAsNumberConvertTo("vc", "FT/SEC"));
-  if (document->FindElement("mach"))
-    SetMachIC(document->FindElementValueAsNumber("mach"));
+    SetClimbRateFpsIC(document->FindElementValueAsNumberConvertTo("roc", "FT/SEC"));
   if (document->FindElement("vground"))
-    SetVgroundKtsIC(document->FindElementValueAsNumberConvertTo("vground", "FT/SEC"));
-  if (document->FindElement("running")) {
-    n = document->FindElementValueAsNumber("running");
-    if (n != 0) {
-      FGPropulsion* propulsion = fdmex->GetPropulsion();
-      for(int i=0; i<propulsion->GetNumEngines(); i++) {
-         propulsion->GetEngine(i)->SetRunning(true);
-      }
-    }
+    SetVgroundKtsIC(document->FindElementValueAsNumberConvertTo("vground", "KTS"));
+  if (document->FindElement("targetNlf"))
+  {
+    SetTargetNlfIC(document->FindElementValueAsNumber("targetNlf"));
+  }
+
+  // Check to see if any engines are specified to be initialized in a running state
+  FGPropulsion* propulsion = fdmex->GetPropulsion();
+  Element* running_elements = document->FindElement("running");
+  while (running_elements) {
+    n = int(running_elements->GetDataAsNumber());
+    propulsion->InitRunning(n);
+    running_elements = document->FindNextElement("running");
   }
 
   fdmex->RunIC();
@@ -876,8 +997,8 @@ void FGInitialCondition::bind(void){
                        &FGInitialCondition::SetLongitudeDegIC,
                        true);
   PropertyManager->Tie("ic/h-sl-ft", this,
-                       &FGInitialCondition::GetAltitudeFtIC,
-                       &FGInitialCondition::SetAltitudeFtIC,
+                       &FGInitialCondition::GetAltitudeASLFtIC,
+                       &FGInitialCondition::SetAltitudeASLFtIC,
                        true);
   PropertyManager->Tie("ic/h-agl-ft", this,
                        &FGInitialCondition::GetAltitudeAGLFtIC,
@@ -887,9 +1008,9 @@ void FGInitialCondition::bind(void){
                        &FGInitialCondition::GetSeaLevelRadiusFtIC,
                        &FGInitialCondition::SetSeaLevelRadiusFtIC,
                        true);
-  PropertyManager->Tie("ic/terrain-altitude-ft", this,
-                       &FGInitialCondition::GetTerrainAltitudeFtIC,
-                       &FGInitialCondition::SetTerrainAltitudeFtIC,
+  PropertyManager->Tie("ic/terrain-elevation-ft", this,
+                       &FGInitialCondition::GetTerrainElevationFtIC,
+                       &FGInitialCondition::SetTerrainElevationFtIC,
                        true);
   PropertyManager->Tie("ic/vg-fps", this,
                        &FGInitialCondition::GetVgroundFpsIC,
@@ -934,7 +1055,18 @@ void FGInitialCondition::bind(void){
                        &FGInitialCondition::GetWBodyFpsIC,
                        &FGInitialCondition::SetWBodyFpsIC,
                        true);
-
+  PropertyManager->Tie("ic/vn-fps", this,
+                       &FGInitialCondition::GetVNorthFpsIC,
+                       &FGInitialCondition::SetVNorthFpsIC,
+                       true);
+  PropertyManager->Tie("ic/ve-fps", this,
+                       &FGInitialCondition::GetVEastFpsIC,
+                       &FGInitialCondition::SetVEastFpsIC,
+                       true);
+  PropertyManager->Tie("ic/vd-fps", this,
+                       &FGInitialCondition::GetVDownFpsIC,
+                       &FGInitialCondition::SetVDownFpsIC,
+                       true);
   PropertyManager->Tie("ic/gamma-rad", this,
                        &FGInitialCondition::GetFlightPathAngleRadIC,
                        &FGInitialCondition::SetFlightPathAngleRadIC,
@@ -978,58 +1110,11 @@ void FGInitialCondition::bind(void){
                        &FGInitialCondition::SetRRadpsIC,
                        true);
 
-}
-
-//******************************************************************************
-
-void FGInitialCondition::unbind(void)
-{
-  PropertyManager->Untie("ic/vc-kts");
-  PropertyManager->Untie("ic/ve-kts");
-  PropertyManager->Untie("ic/vg-kts");
-  PropertyManager->Untie("ic/vt-kts");
-  PropertyManager->Untie("ic/mach");
-  PropertyManager->Untie("ic/roc-fpm");
-  PropertyManager->Untie("ic/gamma-deg");
-  PropertyManager->Untie("ic/alpha-deg");
-  PropertyManager->Untie("ic/beta-deg");
-  PropertyManager->Untie("ic/theta-deg");
-  PropertyManager->Untie("ic/phi-deg");
-  PropertyManager->Untie("ic/psi-true-deg");
-  PropertyManager->Untie("ic/lat-gc-deg");
-  PropertyManager->Untie("ic/long-gc-deg");
-  PropertyManager->Untie("ic/h-sl-ft");
-  PropertyManager->Untie("ic/h-agl-ft");
-  PropertyManager->Untie("ic/sea-level-radius-ft");
-  PropertyManager->Untie("ic/terrain-altitude-ft");
-  PropertyManager->Untie("ic/vg-fps");
-  PropertyManager->Untie("ic/vt-fps");
-  PropertyManager->Untie("ic/vw-bx-fps");
-  PropertyManager->Untie("ic/vw-by-fps");
-  PropertyManager->Untie("ic/vw-bz-fps");
-  PropertyManager->Untie("ic/vw-north-fps");
-  PropertyManager->Untie("ic/vw-east-fps");
-  PropertyManager->Untie("ic/vw-down-fps");
-  PropertyManager->Untie("ic/vw-mag-fps");
-  PropertyManager->Untie("ic/vw-dir-deg");
-
-  PropertyManager->Untie("ic/roc-fps");
-
-  PropertyManager->Untie("ic/u-fps");
-  PropertyManager->Untie("ic/v-fps");
-  PropertyManager->Untie("ic/w-fps");
-
-  PropertyManager->Untie("ic/gamma-rad");
-  PropertyManager->Untie("ic/alpha-rad");
-  PropertyManager->Untie("ic/theta-rad");
-  PropertyManager->Untie("ic/beta-rad");
-  PropertyManager->Untie("ic/phi-rad");
-  PropertyManager->Untie("ic/psi-true-rad");
-  PropertyManager->Untie("ic/lat-gc-rad");
-  PropertyManager->Untie("ic/long-gc-rad");
-  PropertyManager->Untie("ic/p-rad_sec");
-  PropertyManager->Untie("ic/q-rad_sec");
-  PropertyManager->Untie("ic/r-rad_sec");
+  typedef int (FGInitialCondition::*iPMF)(void) const;
+  PropertyManager->Tie("simulation/write-state-file",
+                       this,
+                       (iPMF)0,
+                       &FGInitialCondition::WriteStateFile);
 
 }