]> git.mxchange.org Git - flightgear.git/commitdiff
A set of additions related to allow the use of SID and STAR procedures.
authordurk <durk>
Sun, 8 Mar 2009 17:14:05 +0000 (17:14 +0000)
committerTim Moore <timoore@redhat.com>
Wed, 11 Mar 2009 22:14:34 +0000 (23:14 +0100)
The current code still has some rough edges, in particular memory still
needs to be deallocated where possible, and the actual use of the code
needs more testing. This code has been running without noticable problems,
so I think it's ready for some wider exposure. Detailed changes include:
- Finetuning of the SID/STAR data concept.
- Preloading of all SIDs, from one xml file.
- ATC determines which SID should be used and echoes this over the com1 or
  com2 radio.

12 files changed:
src/AIModel/AIFlightPlan.cxx
src/AIModel/AIFlightPlan.hxx
src/AIModel/AIFlightPlanCreate.cxx
src/ATC/trafficcontrol.cxx
src/Airports/Makefile.am
src/Airports/dynamics.cxx
src/Airports/dynamics.hxx
src/Airports/sidstar.cxx [new file with mode: 0644]
src/Airports/sidstar.hxx [new file with mode: 0644]
src/Airports/simple.cxx
src/Airports/xmlloader.cxx
src/Airports/xmlloader.hxx

index c901cbf5348f976648b663cd05fdca5c2227e84d..41c7966be01d95ed37bc52eaac9009a27a442724 100644 (file)
 
 using std::cerr;
 
+FGAIFlightPlan::FGAIFlightPlan() 
+{
+   sid = 0;
+}
 
 FGAIFlightPlan::FGAIFlightPlan(const string& filename)
 {
   int i;
+  sid = 0;
   start_time = 0;
   leg = 10;
   gateId = 0;
@@ -118,6 +123,7 @@ FGAIFlightPlan::FGAIFlightPlan(FGAIAircraft *ac,
                               const string& acType,
                               const string& airline)
 {
+  sid = 0;
   repeat = false;
   leg = 10;
   gateId=0;
index c3a0cff0f606356debb0529ffc8f6b990fa450c4..65e4c79073fa3e4b8c9e3baefcc1c468f4a54ae1 100644 (file)
@@ -58,7 +58,7 @@ public:
    string time;
 
   } waypoint;
-
+  FGAIFlightPlan();
   FGAIFlightPlan(const string& filename);
   FGAIFlightPlan(FGAIAircraft *,
                  const std::string& p,
@@ -113,8 +113,17 @@ public:
   void setRunway(string rwy) { activeRunway = rwy; };
   string getRunwayClassFromTrafficType(string fltType);
 
+  void addWaypoint(waypoint* wpt) { waypoints.push_back(wpt); };
+
+  void setName(string n) { name = n; };
+  string getName() { return name; };
+
+  void setSID(FGAIFlightPlan* fp) { sid = fp;};
+  FGAIFlightPlan* getSID() { return sid; };
+
 private:
   FGRunway* rwy;
+  FGAIFlightPlan *sid;
   typedef vector <waypoint*> wpt_vector_type;
   typedef wpt_vector_type::const_iterator wpt_vector_iterator;
 
@@ -131,6 +140,7 @@ private:
   string activeRunway;
   FGAirRoute airRoute;
   FGTaxiRoute *taxiRoute;
+  string name;
 
   void createPushBack(FGAIAircraft *, bool, FGAirport*, double, double, double, const string&, const string&, const string&);
   void createPushBackFallBack(FGAIAircraft *, bool, FGAirport*, double, double, double, const string&, const string&, const string&);
@@ -151,13 +161,15 @@ private:
   waypoint* createOnGround(FGAIAircraft *, const std::string& aName, const SGGeod& aPos, double aElev, double aSpeed);
   waypoint* createInAir(FGAIAircraft *, const std::string& aName, const SGGeod& aPos, double aElev, double aSpeed);
   waypoint* cloneWithPos(FGAIAircraft *, waypoint* aWpt, const std::string& aName, const SGGeod& aPos);
+  waypoint* clone(waypoint* aWpt);
     
 
   //void createCruiseFallback(bool, FGAirport*, FGAirport*, double, double, double, double);
  void evaluateRoutePart(double deplat, double deplon, double arrlat, double arrlon);
+ public:
+  wpt_vector_iterator getFirstWayPoint() { return waypoints.begin(); };
+  wpt_vector_iterator getLastWayPoint()  { return waypoints.end(); };
 
- bool loadSID(const string& filename);
- string expandICAODirs(const string in);
 };    
 
 #endif  // _FG_AIFLIGHTPLAN_HXX
index 8035ae2ce683cb16093ce745a6068ddaddfd1875..77032b3fac87aff29b8eb954dbd38e3df23621e2 100644 (file)
@@ -148,6 +148,27 @@ FGAIFlightPlan::cloneWithPos(FGAIAircraft *ac, waypoint* aWpt, const std::string
   return wpt;
 }
 
+FGAIFlightPlan::waypoint*
+FGAIFlightPlan::clone(waypoint* aWpt)
+{
+  waypoint* wpt  = new waypoint;
+  wpt->name      = aWpt->name;
+  wpt->longitude = aWpt->longitude;
+  wpt->latitude  = aWpt->latitude;
+
+  wpt->altitude  = aWpt->altitude;
+  wpt->speed     = aWpt->speed; 
+  wpt->crossat   = aWpt->crossat;
+  wpt->gear_down = aWpt->gear_down;
+  wpt->flaps_down= aWpt->flaps_down;
+  wpt->finished  = aWpt->finished;
+  wpt->on_ground = aWpt->on_ground;
+  wpt->routeIndex = 0;
+  
+  return wpt;
+}
+
+
 void FGAIFlightPlan::createDefaultTakeoffTaxi(FGAIAircraft *ac, FGAirport* aAirport, FGRunway* aRunway)
 {
   SGGeod runwayTakeoff = aRunway->pointOnCenterline(5.0);
@@ -415,25 +436,14 @@ void FGAIFlightPlan::createClimb(FGAIAircraft *ac, bool firstFlight, FGAirport *
     apt->getDynamics()->getActiveRunway(rwyClass, 1, activeRunway, heading);
     rwy = apt->getRunwayByIdent(activeRunway);
   }
-  if (fgGetBool("/sim/traffic-manager/use-custom-scenery-data") == true) {
-       string_list sc = globals->get_fg_scenery();
-       char buffer[64];
-       // NOTE: Currently for testing only. A slightly more elaborate naming convention
-       // needs to be dropped here.
-       snprintf(buffer, 64, "%s.SID-%s-01.xml", apt->getId().c_str(), activeRunway.c_str() );
-       string airportDir = expandICAODirs(apt->getId());
-       for (string_list_iterator i = sc.begin(); i != sc.end(); i++) {
-           SGPath aptpath( *i );
-           aptpath.append( "Airports" );
-           aptpath.append ( airportDir );
-           aptpath.append( string(buffer) );
-           if (aptpath.exists()) {
-               planLoaded = loadSID(aptpath.str());
-               //cerr << "Reading " << aptpath.str() << endl;
-           }
-        }
-  }
-  if (!planLoaded) {
+  if (sid) {
+    for (wpt_vector_iterator i = sid->getFirstWayPoint(); 
+         i != sid->getLastWayPoint(); 
+         i++) {
+            waypoints.push_back(clone(*(i)));
+            //cerr << " Cloning waypoint " << endl;
+    }
+  } else  {
       SGGeod climb1 = rwy->pointOnCenterline(10*SG_NM_TO_METER);
       wpt = createInAir(ac, "10000ft climb", climb1, speed, 10000);
       wpt->gear_down = true;
@@ -447,59 +457,6 @@ void FGAIFlightPlan::createClimb(FGAIAircraft *ac, bool firstFlight, FGAirport *
    }
 }
 
-bool FGAIFlightPlan::loadSID(const string& filename)
-{
-  SGPropertyNode root;
-  try {
-      readProperties(filename, &root);
-  } catch (const sg_exception &e) {
-      SG_LOG(SG_GENERAL, SG_ALERT,
-       "Error reading AI flight plan: " << filename);
-       // cout << path.str() << endl;
-     return false;
-  }
-
-  SGPropertyNode * node = root.getNode("flightplan");
-  for (int i = 0; i < node->nChildren(); i++) { 
-     //cout << "Reading waypoint " << i << endl;        
-     waypoint* wpt = new waypoint;
-     SGPropertyNode * wpt_node = node->getChild(i);
-     wpt->name      = wpt_node->getStringValue("name", "END");
-     wpt->latitude  = wpt_node->getDoubleValue("lat", 0);
-     wpt->longitude = wpt_node->getDoubleValue("lon", 0);
-     wpt->altitude  = wpt_node->getDoubleValue("alt", 0);
-     wpt->speed     = wpt_node->getDoubleValue("ktas", 0);
-     wpt->crossat   = wpt_node->getDoubleValue("crossat", -10000);
-     wpt->gear_down = wpt_node->getBoolValue("gear-down", false);
-     wpt->flaps_down= wpt_node->getBoolValue("flaps-down", false);
-     wpt->on_ground = wpt_node->getBoolValue("on-ground", false);
-     wpt->time_sec   = wpt_node->getDoubleValue("time-sec", 0);
-     wpt->time       = wpt_node->getStringValue("time", "");
-
-     if (wpt->name == "END") wpt->finished = true;
-     else wpt->finished = false;
-
-     waypoints.push_back( wpt );
-   }
-
-  //wpt_iterator = waypoints.begin();
-  //cout << waypoints.size() << " waypoints read." << endl;
-  return true;
-}
-
-// NOTE: This is just copied from Airports/readXML. 
-string FGAIFlightPlan::expandICAODirs(const string in){
-     //cerr << "Expanding " << in << endl;
-     if (in.size() == 4) {
-          char buffer[11];
-          snprintf(buffer, 11, "%c/%c/%c", in[0], in[1], in[2]);
-          //cerr << "result: " << buffer << endl;
-          return string(buffer);
-     } else {
-           return in;
-     }
-     //exit(1);
-}
 
 
 /*******************************************************************
index 3d3d8a3e05ff4462ba8d001eb4edac6e6f0a27ab..c8657ba1d0e910c678a3abac7c9481ad8607a812 100644 (file)
@@ -384,6 +384,8 @@ void FGATCController::transmit(FGTrafficRecord *rec, AtcMsgId msgId, AtcMsgDir m
     string activeRunway;
     string fltType;
     string rwyClass;
+    string SID;
+    FGAIFlightPlan *fp;
     switch (msgId) {
           case MSG_ANNOUNCE_ENGINE_START:
                text = sender + ". Ready to Start up";
@@ -406,19 +408,32 @@ void FGATCController::transmit(FGTrafficRecord *rec, AtcMsgId msgId, AtcMsgDir m
 
                rec->getAircraft()->getTrafficRef()->getDepartureAirport()->getDynamics()->getActiveRunway(rwyClass, 1, activeRunway, heading);
                rec->getAircraft()->GetFlightPlan()->setRunway(activeRunway);
+               fp = rec->getAircraft()->getTrafficRef()->getDepartureAirport()->getDynamics()->getSID(activeRunway, heading);
+               rec->getAircraft()->GetFlightPlan()->setSID(fp);
+               if (fp) {
+                   SID = fp->getName() + " departure";
+               } else {
+                   SID = "fly runway heading ";
+               }
                //snprintf(buffer, 7, "%3.2f", heading);
                text = receiver + ". Start-up approved. " + atisInformation + " correct, runway " + activeRunway
-                       + ", AAA departure, squawk BBBB. " +
+                       + ", " + SID + ", squawk BBBB. " +
                       "For push-back and taxi clearance call " + taxiFreqStr + ". " + sender + " control.";
                break;
           case MSG_DENY_ENGINE_START:
                text = receiver + ". Standby";
                break;
          case MSG_ACKNOWLEDGE_ENGINE_START:
+               fp = rec->getAircraft()->GetFlightPlan()->getSID();
+               if (fp) {
+                  SID = rec->getAircraft()->GetFlightPlan()->getSID()->getName() + " departure";
+               } else {
+                  SID = "fly runway heading ";
+               }
                taxiFreqStr = formatATCFrequency3_2(taxiFreq);
                activeRunway = rec->getAircraft()->GetFlightPlan()->getRunway();
                text = receiver + ". Start-up approved. " + atisInformation + " correct, runway " +
-                      activeRunway + ", AAA departure, squawk BBBB. " +
+                      activeRunway + ", " + SID + ", squawk BBBB. " +
                       "For push-back and taxi clearance call " + taxiFreqStr + ". " + sender;
                break;
            default:
index 71a49a139904ff5e376216367b1c1036a69baab9..e78463b4ba2b498328763422dc47044b0d7f1a53 100644 (file)
@@ -12,6 +12,7 @@ libAirports_a_SOURCES = \
        groundnetwork.cxx groundnetwork.hxx \
        dynamics.cxx dynamics.hxx \
        dynamicloader.cxx dynamicloader.hxx \
+       sidstar.cxx sidstar.hxx \
        runwayprefloader.cxx runwayprefloader.hxx \
        xmlloader.cxx xmlloader.hxx \
        runwaybase.cxx runwaybase.hxx
index 34a6dce8ad71d9ca8693ec477f22071168624ed6..fe8079075a0a6216a2d9bce5de31991350163ef3 100644 (file)
@@ -52,7 +52,7 @@ using std::random_shuffle;
 #include "dynamics.hxx"
 
 FGAirportDynamics::FGAirportDynamics(FGAirport* ap) :
-  _ap(ap), rwyPrefs(ap) {
+  _ap(ap), rwyPrefs(ap), SIDs(ap) {
   lastUpdate = 0;
 
   // For testing only. This needs to be refined when we move ATIS functionality over.
@@ -61,7 +61,8 @@ FGAirportDynamics::FGAirportDynamics(FGAirport* ap) :
 
 // Note that the ground network should also be copied
 FGAirportDynamics::FGAirportDynamics(const FGAirportDynamics& other) :
-  rwyPrefs(other.rwyPrefs)
+  rwyPrefs(other.rwyPrefs),
+  SIDs(other.SIDs)
 {
   for (FGParkingVecConstIterator ip= other.parkings.begin(); ip != other.parkings.end(); ip++)
     parkings.push_back(*(ip));
@@ -555,4 +556,9 @@ int FGAirportDynamics::getGroundFrequency(int leg) {
           groundFreq = freqGround[leg-2];
      }
     return groundFreq;
+}
+
+FGAIFlightPlan *FGAirportDynamics::getSID(string activeRunway, double heading)
+{
+   return SIDs.getBest(activeRunway, heading);
 }
\ No newline at end of file
index b2f1ba00168dd0b838a79b5ecc59354b7eba1026..56bef8225a54c57dc725fe57bffd25c2bf679078 100644 (file)
@@ -33,6 +33,7 @@
 #include "parking.hxx"
 #include "groundnetwork.hxx"
 #include "runwayprefs.hxx"
+#include "sidstar.hxx"
 
 //typedef vector<float> DoubleVec;
 //typedef vector<float>::iterator DoubleVecIterator;
@@ -47,6 +48,7 @@ private:
 
   FGParkingVec        parkings;
   FGRunwayPreference  rwyPrefs;
+  FGSidStar           SIDs;
   FGStartupController startupController;
   FGGroundNetwork     groundNetwork;
   FGTowerController   towerController;
@@ -104,6 +106,10 @@ public:
   //const string &getName() const { return _name;};
   // Returns degrees
 
+  // Departure / Arrival procedures
+  FGSidStar * getSIDs() { return &SIDs; };
+  FGAIFlightPlan * getSID(string activeRunway, double heading);
+
 
   // ATC related functions. 
   FGStartupController *getStartupController() { return &startupController; };
diff --git a/src/Airports/sidstar.cxx b/src/Airports/sidstar.cxx
new file mode 100644 (file)
index 0000000..cbeac9a
--- /dev/null
@@ -0,0 +1,116 @@
+// sidstar.cxx - Code to manage departure / arrival procedures
+// Written by Durk Talsma, started March 2009.
+//
+//
+// 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 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 details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+//
+// $Id$
+
+#include <iostream>
+#include <stdlib.h>
+
+#include <simgear/props/props.hxx>
+#include <simgear/props/props_io.hxx>
+
+
+
+#include <Airports/simple.hxx>
+
+
+#include "sidstar.hxx"
+
+using std::cerr;
+using std::endl;
+
+FGSidStar::FGSidStar(FGAirport *ap) {
+     id = ap->getId();
+     initialized = false;
+}
+
+
+FGSidStar::FGSidStar(const FGSidStar &other) {
+     cerr << "TODO" << endl;
+     exit(1);
+}
+
+void FGSidStar::load(SGPath filename) {
+  SGPropertyNode root;
+  string runway;
+  string name;
+  try {
+      readProperties(filename.str(), &root);
+  } catch (const sg_exception &e) {
+      SG_LOG(SG_GENERAL, SG_ALERT,
+       "Error reading AI flight plan: " << filename.str());
+       // cout << path.str() << endl;
+     return;
+  }
+
+  SGPropertyNode * node = root.getNode("SIDS");
+  FGAIFlightPlan *fp;
+  for (int i = 0; i < node->nChildren(); i++) { 
+     fp = new FGAIFlightPlan;
+     SGPropertyNode * fpl_node = node->getChild(i);
+     name   =  fpl_node->getStringValue("name", "END");
+     runway =  fpl_node->getStringValue("runway", "27");
+     //cerr << "Runway = " << runway << endl;
+     fp->setName(name);
+     SGPropertyNode * wpts_node = fpl_node->getNode("wpts");
+     for (int j = 0; j < wpts_node->nChildren(); j++) { 
+          FGAIFlightPlan::waypoint* wpt = new FGAIFlightPlan::waypoint;
+          SGPropertyNode * wpt_node = wpts_node->getChild(j);
+          //cerr << "Reading waypoint " << j << wpt_node->getStringValue("name", "END") << endl;
+          wpt->name      = wpt_node->getStringValue("name", "END");
+          wpt->latitude  = wpt_node->getDoubleValue("lat", 0);
+          wpt->longitude = wpt_node->getDoubleValue("lon", 0);
+          wpt->altitude  = wpt_node->getDoubleValue("alt", 0);
+          wpt->speed     = wpt_node->getDoubleValue("ktas", 0);
+          wpt->crossat   = wpt_node->getDoubleValue("crossat", -10000);
+          wpt->gear_down = wpt_node->getBoolValue("gear-down", false);
+          wpt->flaps_down= wpt_node->getBoolValue("flaps-down", false);
+          wpt->on_ground = wpt_node->getBoolValue("on-ground", false);
+          wpt->time_sec   = wpt_node->getDoubleValue("time-sec", 0);
+          wpt->time       = wpt_node->getStringValue("time", "");
+
+          if (wpt->name == "END") wpt->finished = true;
+          else wpt->finished = false;
+
+          // 
+          fp->addWaypoint( wpt );
+     }
+     data[runway].push_back(fp);
+     //cerr << "Runway = " << runway << endl;
+   }
+
+
+  //wpt_iterator = waypoints.begin();
+  //cout << waypoints.size() << " waypoints read." << endl;
+}
+
+
+FGAIFlightPlan *FGSidStar::getBest(string activeRunway, double heading)
+{
+    //cerr << "Getting best procedure for " << activeRunway << endl;
+    for (FlightPlanVecIterator i = data[activeRunway].begin(); i != data[activeRunway].end(); i++) {
+        //cerr << (*i)->getName() << endl;
+    }
+    int size = data[activeRunway].size();
+    //cerr << "size is " << size << endl;
+    if (size) {
+        return data[activeRunway][(rand() % size)];
+     } else {
+        return 0;
+    }
+}
\ No newline at end of file
diff --git a/src/Airports/sidstar.hxx b/src/Airports/sidstar.hxx
new file mode 100644 (file)
index 0000000..ef388e4
--- /dev/null
@@ -0,0 +1,67 @@
+// sidstar.hxx - a class to store and maintain data for SID and STAR
+// procedures. 
+// Written by Durk Talsma, started March 2009.
+//
+//
+// 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 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 details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+//
+// $Id$
+
+
+#ifndef _SIDSTAR_HXX_
+#define _SIDSTAR_HXX_
+
+#include <string>
+
+#include <simgear/misc/sg_path.hxx>
+
+#include <simgear/xml/easyxml.hxx>
+
+#include <ATC/trafficcontrol.hxx>
+#include <AIModel/AIFlightPlan.hxx>
+#include "parking.hxx"
+#include "groundnetwork.hxx"
+#include "runwayprefs.hxx"
+
+
+using std::string;
+
+class FGAirport;
+
+typedef vector<FGAIFlightPlan*>           FlightPlanVec;
+typedef vector<FGAIFlightPlan*>::iterator FlightPlanVecIterator;
+
+typedef std::map < std::string, FlightPlanVec > FlightPlanVecMap;
+
+
+class FGSidStar 
+{
+   private:
+      string id;
+      bool initialized;
+      FlightPlanVecMap data;
+
+   public:
+      FGSidStar(FGAirport *ap);
+      FGSidStar(const FGSidStar &other);
+
+      string getId() { return id; };
+      void load(SGPath path);
+      FGAIFlightPlan *getBest(string activeRunway, double heading);
+};
+
+
+
+#endif
\ No newline at end of file
index 02d7025b8c62c8c1ecd45270efed823d63ad7528..7da4fa1a85a15588d8641a4f8c363fc52ac63d4a 100644 (file)
@@ -92,6 +92,9 @@ FGAirportDynamics * FGAirport::getDynamics()
         FGRunwayPreference rwyPrefs(this);
         XMLLoader::load(&rwyPrefs);
         _dynamics->setRwyUse(rwyPrefs);
+
+        //FGSidStar SIDs(this);
+        XMLLoader::load(_dynamics->getSIDs());
    }
     return _dynamics;
 }
index e808eaf5c01b5fe1871d899d04086c57b28ec65d..7005ca52a72a6fa28b157bf0626d6652659d73d2 100644 (file)
@@ -118,3 +118,28 @@ void XMLLoader::load(FGRunwayPreference* p) {
     }
 }
 
+void XMLLoader::load(FGSidStar* p) {
+    //FGRunwayPreferenceXMLLoader visitor(p);
+    if (fgGetBool("/sim/traffic-manager/use-custom-scenery-data") == true) {
+       string_list sc = globals->get_fg_scenery();
+       char buffer[32];
+       snprintf(buffer, 32, "%s.SID.xml", p->getId().c_str() );
+       string airportDir = expandICAODirs(p->getId());
+       for (string_list_iterator i = sc.begin(); i != sc.end(); i++) {
+           SGPath sidpath( *i );
+           sidpath.append( "Airports" );
+           sidpath.append ( airportDir );
+           sidpath.append( string(buffer) );
+           if (sidpath.exists()) {
+               try {
+                   //readXML(rwypath.str(), visitor);
+                   //cerr << "Reading SID procedure : " << sidpath.str() << endl;
+                   p->load(sidpath);
+                } 
+                catch (const sg_exception &e) {
+                }
+                return;
+            }
+        }
+    }
+}
index 436e86994d0e1a31ef0f1ac741c07ccdb9806630..eb066495f09a2c6fc52d6c664248cd49c4e64345 100644 (file)
@@ -20,6 +20,7 @@
 
 class FGAirportDynamics;
 class FGRunwayPreference;
+class FGSidStar;
 
 
 
@@ -29,7 +30,8 @@ public:
   ~XMLLoader();
   static string expandICAODirs(const string in);
   static void load(FGRunwayPreference* p);
-  static void load(FGAirportDynamics* d);
+  static void load(FGAirportDynamics*  d);
+  static void load(FGSidStar*          s);
   
 };