diff --git a/projects/VC90/FlightGear/FlightGear.vcproj b/projects/VC90/FlightGear/FlightGear.vcproj index 8d70c4028..98fde43d6 100644 --- a/projects/VC90/FlightGear/FlightGear.vcproj +++ b/projects/VC90/FlightGear/FlightGear.vcproj @@ -3437,6 +3437,14 @@ RelativePath="..\..\..\src\Environment\presets.hxx" > </File> + <File + RelativePath="..\..\..\src\Environment\gravity.cxx" + > + </File> + <File + RelativePath="..\..\..\src\Environment\gravity.hxx" + > + </File> </Filter> <Filter Name="Lib_Model" diff --git a/src/Autopilot/route_mgr.cxx b/src/Autopilot/route_mgr.cxx index 1b37fa256..044c624c8 100644 --- a/src/Autopilot/route_mgr.cxx +++ b/src/Autopilot/route_mgr.cxx @@ -40,6 +40,7 @@ #include <simgear/misc/strutils.hxx> #include <simgear/structure/exception.hxx> +#include <simgear/structure/commands.hxx> #include <simgear/misc/sgstream.hxx> #include <simgear/props/props_io.hxx> @@ -109,6 +110,151 @@ PropertyWatcher* createWatcher(T* obj, void (T::*m)()) return new MethodPropertyWatcher<T>(obj, m); } +static bool commandLoadFlightPlan(const SGPropertyNode* arg) +{ + FGRouteMgr* self = (FGRouteMgr*) globals->get_subsystem("route-manager"); + SGPath path(arg->getStringValue("path")); + return self->loadRoute(path); +} + +static bool commandSaveFlightPlan(const SGPropertyNode* arg) +{ + FGRouteMgr* self = (FGRouteMgr*) globals->get_subsystem("route-manager"); + SGPath path(arg->getStringValue("path")); + return self->saveRoute(path); +} + +static bool commandActivateFlightPlan(const SGPropertyNode* arg) +{ + FGRouteMgr* self = (FGRouteMgr*) globals->get_subsystem("route-manager"); + bool activate = arg->getBoolValue("activate", true); + if (activate) { + self->activate(); + } else { + + } + + return true; +} + +static bool commandClearFlightPlan(const SGPropertyNode*) +{ + FGRouteMgr* self = (FGRouteMgr*) globals->get_subsystem("route-manager"); + self->clearRoute(); + return true; +} + +static bool commandSetActiveWaypt(const SGPropertyNode* arg) +{ + FGRouteMgr* self = (FGRouteMgr*) globals->get_subsystem("route-manager"); + int index = arg->getIntValue("index"); + if ((index < 0) || (index >= self->numWaypts())) { + return false; + } + + self->jumpToIndex(index); + return true; +} + +static bool commandInsertWaypt(const SGPropertyNode* arg) +{ + FGRouteMgr* self = (FGRouteMgr*) globals->get_subsystem("route-manager"); + int index = arg->getIntValue("index"); + std::string ident(arg->getStringValue("id")); + int alt = arg->getIntValue("altitude-ft", -999); + int ias = arg->getIntValue("speed-knots", -999); + + WayptRef wp; +// lat/lon may be supplied to narrow down navaid search, or to specify +// a raw waypoint + SGGeod pos; + if (arg->hasChild("longitude-deg")) { + pos = SGGeod::fromDeg(arg->getDoubleValue("longitude-deg"), + arg->getDoubleValue("latitude-deg")); + } + + if (arg->hasChild("navaid")) { + FGPositionedRef p = FGPositioned::findClosestWithIdent(arg->getStringValue("navaid"), pos); + + if (arg->hasChild("navaid", 1)) { + // intersection of two radials + FGPositionedRef p2 = FGPositioned::findClosestWithIdent(arg->getStringValue("navaid[1]"), pos); + if (!p2) { + SG_LOG( SG_AUTOPILOT, SG_INFO, "Unable to find FGPositioned with ident:" << arg->getStringValue("navaid[1]")); + return false; + } + + double r1 = arg->getDoubleValue("radial"), + r2 = arg->getDoubleValue("radial[1]"); + + SGGeod intersection; + bool ok = SGGeodesy::radialIntersection(p->geod(), r1, p2->geod(), r2, intersection); + if (!ok) { + SG_LOG(SG_AUTOPILOT, SG_INFO, "no valid intersection for:" << p->ident() + << "," << p2->ident()); + return false; + } + + std::string name = p->ident() + "-" + p2->ident(); + wp = new BasicWaypt(intersection, name, NULL); + } else if (arg->hasChild("offset-nm") && arg->hasChild("radial")) { + // offset radial from navaid + double radial = arg->getDoubleValue("radial"); + double distanceNm = arg->getDoubleValue("offset-nm"); + //radial += magvar->getDoubleValue(); // convert to true bearing + wp = new OffsetNavaidWaypoint(p, NULL, radial, distanceNm); + } else { + wp = new NavaidWaypoint(p, NULL); + } + } else if (arg->hasChild("airport")) { + const FGAirport* apt = fgFindAirportID(arg->getStringValue("airport")); + if (!apt) { + SG_LOG(SG_AUTOPILOT, SG_INFO, "no such airport" << arg->getStringValue("airport")); + return false; + } + + if (arg->hasChild("runway")) { + if (!apt->hasRunwayWithIdent(arg->getStringValue("runway"))) { + SG_LOG(SG_AUTOPILOT, SG_INFO, "No runway: " << arg->getStringValue("runway") << " at " << apt->ident()); + return false; + } + + FGRunway* runway = apt->getRunwayByIdent(arg->getStringValue("runway")); + wp = new RunwayWaypt(runway, NULL); + } else { + wp = new NavaidWaypoint((FGAirport*) apt, NULL); + } + } else if (arg->hasChild("text")) { + wp = self->waypointFromString(arg->getStringValue("text")); + } else if (!(pos == SGGeod())) { + // just a raw lat/lon + wp = new BasicWaypt(pos, ident, NULL); + } else { + return false; // failed to build waypoint + } + + if (alt >= 0) { + wp->setAltitude(alt, flightgear::RESTRICT_AT); + } + + if (ias > 0) { + wp->setSpeed(ias, flightgear::RESTRICT_AT); + } + + self->insertWayptAtIndex(wp, index); + return true; +} + +static bool commandDeleteWaypt(const SGPropertyNode* arg) +{ + FGRouteMgr* self = (FGRouteMgr*) globals->get_subsystem("route-manager"); + int index = arg->getIntValue("index"); + self->removeWayptAtIndex(index); + return true; +} + +///////////////////////////////////////////////////////////////////////////// + FGRouteMgr::FGRouteMgr() : _currentIndex(0), input(fgGetNode( RM "input", true )), @@ -117,6 +263,14 @@ FGRouteMgr::FGRouteMgr() : listener = new InputListener(this); input->setStringValue(""); input->addChangeListener(listener); + + SGCommandMgr::instance()->addCommand("load-flightplan", commandLoadFlightPlan); + SGCommandMgr::instance()->addCommand("save-flightplan", commandSaveFlightPlan); + SGCommandMgr::instance()->addCommand("activate-flightplan", commandActivateFlightPlan); + SGCommandMgr::instance()->addCommand("clear-flightplan", commandClearFlightPlan); + SGCommandMgr::instance()->addCommand("set-active-waypt", commandSetActiveWaypt); + SGCommandMgr::instance()->addCommand("insert-waypt", commandInsertWaypt); + SGCommandMgr::instance()->addCommand("delete-waypt", commandDeleteWaypt); } @@ -227,7 +381,7 @@ void FGRouteMgr::postinit() SGPath path(_pathNode->getStringValue()); if (path.exists()) { SG_LOG(SG_AUTOPILOT, SG_INFO, "loading flight-plan from:" << path.str()); - loadRoute(); + loadRoute(path); } // this code only matters for the --wp option now - perhaps the option @@ -897,11 +1051,11 @@ void FGRouteMgr::InputListener::valueChanged(SGPropertyNode *prop) else if (!strcmp(s, "@ACTIVATE")) mgr->activate(); else if (!strcmp(s, "@LOAD")) { - mgr->loadRoute(); + SGPath path(mgr->_pathNode->getStringValue()); + mgr->loadRoute(path); } else if (!strcmp(s, "@SAVE")) { - mgr->saveRoute(); - } else if (!strcmp(s, "@POP")) { - SG_LOG(SG_AUTOPILOT, SG_WARN, "route-manager @POP command is deprecated"); + SGPath path(mgr->_pathNode->getStringValue()); + mgr->saveRoute(path); } else if (!strcmp(s, "@NEXT")) { mgr->jumpToIndex(mgr->_currentIndex + 1); } else if (!strcmp(s, "@PREVIOUS")) { @@ -1119,9 +1273,8 @@ Waypt* FGRouteMgr::wayptAtIndex(int index) const return _route[index]; } -void FGRouteMgr::saveRoute() +bool FGRouteMgr::saveRoute(const SGPath& path) { - SGPath path(_pathNode->getStringValue()); SG_LOG(SG_IO, SG_INFO, "Saving route to " << path.str()); try { SGPropertyNode_ptr d(new SGPropertyNode); @@ -1148,18 +1301,19 @@ void FGRouteMgr::saveRoute() wpt->saveAsNode(routeNode->getChild("wp", i, true)); } // of waypoint iteration writeProperties(path.str(), d, true /* write-all */); + return true; } catch (sg_exception& e) { SG_LOG(SG_IO, SG_WARN, "failed to save flight-plan:" << e.getMessage()); + return false; } } -void FGRouteMgr::loadRoute() +bool FGRouteMgr::loadRoute(const SGPath& path) { // deactivate route first active->setBoolValue(false); SGPropertyNode_ptr routeData(new SGPropertyNode); - SGPath path(_pathNode->getStringValue()); SG_LOG(SG_IO, SG_INFO, "going to read flight-plan from:" << path.str()); @@ -1167,8 +1321,7 @@ void FGRouteMgr::loadRoute() readProperties(path.str(), routeData); } catch (sg_exception& ) { // if XML parsing fails, the file might be simple textual list of waypoints - loadPlainTextRoute(path); - return; + return loadPlainTextRoute(path); } try { @@ -1180,9 +1333,11 @@ void FGRouteMgr::loadRoute() } else { throw sg_io_exception("unsupported XML route version"); } + return true; } catch (sg_exception& e) { SG_LOG(SG_IO, SG_WARN, "failed to load flight-plan (from '" << e.getOrigin() << "'):" << e.getMessage()); + return false; } } @@ -1299,11 +1454,11 @@ WayptRef FGRouteMgr::parseVersion1XMLWaypt(SGPropertyNode* aWP) return w; } -void FGRouteMgr::loadPlainTextRoute(const SGPath& path) +bool FGRouteMgr::loadPlainTextRoute(const SGPath& path) { sg_gzifstream in(path.str().c_str()); if (!in.is_open()) { - return; + return false; } try { @@ -1330,8 +1485,10 @@ void FGRouteMgr::loadPlainTextRoute(const SGPath& path) } // of line iteration _route = wpts; + return true; } catch (sg_exception& e) { SG_LOG(SG_IO, SG_WARN, "failed to load route from:" << path.str() << ":" << e.getMessage()); + return false; } } diff --git a/src/Autopilot/route_mgr.hxx b/src/Autopilot/route_mgr.hxx index 16b4adc4b..31336f96a 100644 --- a/src/Autopilot/route_mgr.hxx +++ b/src/Autopilot/route_mgr.hxx @@ -118,13 +118,22 @@ public: */ void jumpToIndex(int index); - void saveRoute(); - void loadRoute(); + bool saveRoute(const SGPath& p); + bool loadRoute(const SGPath& p); /** * Helper command to setup current airport/runway if necessary */ void initAtPosition(); + + /** + * Create a WayPoint from a string in the following format: + * - simple identifier + * - decimal-lon,decimal-lat + * - airport-id/runway-id + * - navaid/radial-deg/offset-nm + */ + flightgear::WayptRef waypointFromString(const std::string& target); private: flightgear::WayptVec _route; int _currentIndex; @@ -188,17 +197,7 @@ private: SGPropertyNode_ptr weightOnWheels; InputListener *listener; - SGPropertyNode_ptr mirror; - - /** - * Create a SGWayPoint from a string in the following format: - * - simple identifier - * - decimal-lon,decimal-lat - * - airport-id/runway-id - * - navaid/radial-deg/offset-nm - */ - flightgear::WayptRef waypointFromString(const std::string& target); - + SGPropertyNode_ptr mirror; void departureChanged(); void buildDeparture(flightgear::WayptRef enroute, flightgear::WayptVec& wps); @@ -229,7 +228,7 @@ private: bool checkFinished(); - void loadPlainTextRoute(const SGPath& path); + bool loadPlainTextRoute(const SGPath& path); void loadVersion1XMLRoute(SGPropertyNode_ptr routeData); void loadVersion2XMLRoute(SGPropertyNode_ptr routeData); diff --git a/src/Environment/CMakeLists.txt b/src/Environment/CMakeLists.txt index 69fa003ed..ada06638e 100644 --- a/src/Environment/CMakeLists.txt +++ b/src/Environment/CMakeLists.txt @@ -16,6 +16,7 @@ set(SOURCES ridge_lift.cxx terrainsampler.cxx presets.cxx + gravity.cxx ) flightgear_component(Environment "${SOURCES}") diff --git a/src/Environment/Makefile.am b/src/Environment/Makefile.am index c3b1b5fbf..876f4f797 100644 --- a/src/Environment/Makefile.am +++ b/src/Environment/Makefile.am @@ -17,6 +17,7 @@ libEnvironment_a_SOURCES = \ ridge_lift.cxx ridge_lift.hxx \ ephemeris.cxx ephemeris.hxx \ terrainsampler.cxx terrainsampler.cxx \ - presets.cxx presets.hxx + presets.cxx presets.hxx \ + gravity.cxx gravity.hxx INCLUDES = -I$(top_srcdir) -I$(top_srcdir)/src diff --git a/src/Environment/atmosphere.hxx b/src/Environment/atmosphere.hxx index 1ee4e1b6b..466cba270 100644 --- a/src/Environment/atmosphere.hxx +++ b/src/Environment/atmosphere.hxx @@ -31,8 +31,6 @@ #include <cmath> #include <utility> -using namespace std; - /** * Model the atmosphere in a way consistent with the laws * of physics. diff --git a/src/Environment/environment_mgr.cxx b/src/Environment/environment_mgr.cxx index 42023ea84..97c81b9b9 100644 --- a/src/Environment/environment_mgr.cxx +++ b/src/Environment/environment_mgr.cxx @@ -42,6 +42,7 @@ #include "ridge_lift.hxx" #include "terrainsampler.hxx" #include "Airports/simple.hxx" +#include "gravity.hxx" class SGSky; extern SGSky *thesky; @@ -50,7 +51,7 @@ FGEnvironmentMgr::FGEnvironmentMgr () : _environment(new FGEnvironment()), fgClouds(new FGClouds()), _cloudLayersDirty(true), - _altitudeNode(fgGetNode("/position/altitude-ft", true)), + _altitude_n(fgGetNode("/position/altitude-ft", true)), _longitude_n(fgGetNode( "/position/longitude-deg", true )), _latitude_n( fgGetNode( "/position/latitude-deg", true )), _positionTimeToLive(0.0) @@ -98,10 +99,11 @@ FGEnvironmentMgr::init () SGSubsystemGroup::init(); fgClouds->Init(); + // FIXME: is this really part of the environment_mgr? // Initialize the longitude, latitude and altitude to the initial position // of the aircraft so that the atmospheric properties (pressure, temperature // and density) can be initialized accordingly. - _altitudeNode->setDoubleValue(fgGetDouble("/sim/presets/altitude-ft")); + _altitude_n->setDoubleValue(fgGetDouble("/sim/presets/altitude-ft")); _longitude_n->setDoubleValue(fgGetDouble("/sim/presets/longitude-deg")); _latitude_n->setDoubleValue(fgGetDouble("/sim/presets/latitude-deg")); } @@ -201,7 +203,7 @@ FGEnvironmentMgr::update (double dt) { SGSubsystemGroup::update(dt); - _environment->set_elevation_ft( _altitudeNode->getDoubleValue() ); + _environment->set_elevation_ft( _altitude_n->getDoubleValue() ); simgear::Particles::setWindFrom( _environment->get_wind_from_heading_deg(), _environment->get_wind_speed_kt() ); @@ -210,6 +212,14 @@ FGEnvironmentMgr::update (double dt) fgClouds->set_update_event( fgClouds->get_update_event()+1 ); } + + fgSetDouble( "/environment/gravitational-acceleration-mps2", + Environment::Gravity::instance()->getGravity(SGGeod::fromDegFt( + _longitude_n->getDoubleValue(), + _latitude_n->getDoubleValue(), + _altitude_n->getDoubleValue() + ))); + _positionTimeToLive -= dt; if( _positionTimeToLive <= 0.0 ) { diff --git a/src/Environment/environment_mgr.hxx b/src/Environment/environment_mgr.hxx index 67d929ec8..18b1668bc 100644 --- a/src/Environment/environment_mgr.hxx +++ b/src/Environment/environment_mgr.hxx @@ -95,7 +95,7 @@ private: FGEnvironment * _environment; // always the same, for now FGClouds *fgClouds; bool _cloudLayersDirty; - SGPropertyNode_ptr _altitudeNode; + SGPropertyNode_ptr _altitude_n; SGPropertyNode_ptr _longitude_n; SGPropertyNode_ptr _latitude_n; double _positionTimeToLive; diff --git a/src/Environment/fgclouds.cxx b/src/Environment/fgclouds.cxx index d5d9fbbc0..6cc4d49ef 100644 --- a/src/Environment/fgclouds.cxx +++ b/src/Environment/fgclouds.cxx @@ -45,6 +45,9 @@ extern SGSky *thesky; +static bool do_delete_3Dcloud (const SGPropertyNode *arg); +static bool do_move_3Dcloud (const SGPropertyNode *arg); +static bool do_add_3Dcloud (const SGPropertyNode *arg); FGClouds::FGClouds() : #if 0 @@ -158,7 +161,7 @@ double FGClouds::buildCloud(SGPropertyNode *cloud_def_root, SGPropertyNode *box_ y = w * (y - 0.5) + pos[1]; // E/W z = h * z + pos[2]; // Up/Down. pos[2] is the cloudbase - SGVec3f newpos = SGVec3f(x, y, z); + //SGVec3f newpos = SGVec3f(x, y, z); SGNewCloud cld = SGNewCloud(texture_root, cld_def); //layer->addCloud(newpos, cld.genCloud()); diff --git a/src/Environment/fgclouds.hxx b/src/Environment/fgclouds.hxx index 61ccaccfe..7eab7f128 100644 --- a/src/Environment/fgclouds.hxx +++ b/src/Environment/fgclouds.hxx @@ -64,9 +64,5 @@ public: }; -static bool do_delete_3Dcloud (const SGPropertyNode *arg); -static bool do_move_3Dcloud (const SGPropertyNode *arg); -static bool do_add_3Dcloud (const SGPropertyNode *arg); - #endif // _FGCLOUDS_HXX diff --git a/src/Environment/gravity.cxx b/src/Environment/gravity.cxx new file mode 100644 index 000000000..cd32feeb4 --- /dev/null +++ b/src/Environment/gravity.cxx @@ -0,0 +1,88 @@ +// gravity.cxx -- interface for earth gravitational model +// +// Written by Torsten Dreyer, June 2011 +// +// Copyright (C) 2011 Torsten Dreyer - torsten (at) t3r _dot_ de +// +// 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. +// + +#include "gravity.hxx" + +#include <simgear/structure/exception.hxx> + +namespace Environment { + +/* +http://de.wikipedia.org/wiki/Normalschwereformel +*/ +class Somigliana : public Gravity { +public: + Somigliana(); + virtual ~Somigliana(); + virtual double getGravity( const SGGeod & position ) const; +}; + +Somigliana::Somigliana() +{ +} + +Somigliana::~Somigliana() +{ +} + +double Somigliana::getGravity( const SGGeod & position ) const +{ +// Geodetic Reference System 1980 parameter +#define A 6378137.0 // equatorial radius of earth +#define B 6356752.3141 // semiminor axis +#define AGA (A*9.7803267715) // A times normal gravity at equator +#define BGB (B*9.8321863685) // B times normal gravity at pole + // forumla of Somigliana + double cosphi = ::cos(position.getLatitudeRad()); + double cos2phi = cosphi*cosphi; + double sinphi = ::sin(position.getLatitudeRad()); + double sin2phi = sinphi*sinphi; + double g0 = (AGA * cos2phi + BGB * sin2phi) / sqrt( A*A*cos2phi+B*B*sin2phi ); + + static const double k1 = 3.15704e-7; + static const double k2 = 2.10269e-9; + static const double k3 = 7.37452e-14; + + double h = position.getElevationM(); + + return g0*(1-(k1-k2*sin2phi)*h+k3*h*h); +} + +static Somigliana _somigliana; + +/* --------------------- Gravity implementation --------------------- */ +Gravity * Gravity::_instance = NULL; + +Gravity::~Gravity() +{ +} + +//double Gravity::getGravity( const SGGeoc & position ) = 0; + +const Gravity * Gravity::instance() +{ + if( _instance == NULL ) + _instance = &_somigliana; + + return _instance; +} + +} // namespace diff --git a/src/Environment/gravity.hxx b/src/Environment/gravity.hxx new file mode 100644 index 000000000..d99ca1867 --- /dev/null +++ b/src/Environment/gravity.hxx @@ -0,0 +1,43 @@ +// gravity.hxx -- interface for earth gravitational model +// +// Written by Torsten Dreyer, June 2011 +// +// Copyright (C) 2011 Torsten Dreyer - torsten (at) t3r _dot_ de +// +// 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. +// + +#ifndef __GRAVITY_HXX +#define __GRAVITY_HXX + +#include <simgear/math/SGMath.hxx> + +namespace Environment { + +class Gravity +{ +public: + virtual ~Gravity(); + virtual double getGravity( const SGGeod & position ) const = 0; + + const static Gravity * instance(); + +private: + static Gravity * _instance; + +}; + +} // namespace +#endif // __GRAVITY_HXX diff --git a/src/Environment/metarproperties.cxx b/src/Environment/metarproperties.cxx index 171d716af..11971f08c 100644 --- a/src/Environment/metarproperties.cxx +++ b/src/Environment/metarproperties.cxx @@ -301,9 +301,6 @@ void MetarProperties::set_metar( const char * metar ) } } - vector<SGMetarCloud> cv = m->getClouds(); - vector<SGMetarCloud>::const_iterator cloud, cloud_end = cv.end(); - { static const char * LAYER = "layer"; SGPropertyNode_ptr cloudsNode = _rootNode->getNode("clouds", true ); diff --git a/src/Environment/terrainsampler.cxx b/src/Environment/terrainsampler.cxx index 0d08af84e..293eb2c86 100644 --- a/src/Environment/terrainsampler.cxx +++ b/src/Environment/terrainsampler.cxx @@ -285,6 +285,7 @@ void AreaSampler::analyse() } } +/* double alt_low_min = 0.0; double n_max = 0.0; sum = 0.0; @@ -296,7 +297,7 @@ void AreaSampler::analyse() break; } } - +*/ _altLayered = 0.5 * (_altMin + _altOffset); #if 0