]> git.mxchange.org Git - flightgear.git/blobdiff - src/Environment/ridge_lift.cxx
Adapt to simgear SGMath change.
[flightgear.git] / src / Environment / ridge_lift.cxx
index 7d05096b0702754894c24faf4a0b3d36ea5a76a4..cac1388aa90dfb6644c5f2aa4df6d959e4f5707f 100644 (file)
 
 #include <Main/fg_props.hxx>
 #include <Main/globals.hxx>
+#include <Main/util.hxx>
 #include <Scenery/scenery.hxx>
 #include <string>
 #include <math.h>
+#include <simgear/sg_inlines.h>
 
 using std::string;
 
 #include "ridge_lift.hxx"
 
+static const double BOUNDARY1_m = 40.0;
+
+const double FGRidgeLift::dist_probe_m[] = { // in meters
+     0.0, 
+   250.0,
+   750.0,
+  2000.0,
+  -100.0
+};
+
 //constructor
 FGRidgeLift::FGRidgeLift ()
 {      
-       dist_probe_m[0] = 0.0; // in meters
-       dist_probe_m[1] = 250.0;
-       dist_probe_m[2] = 750.0;
-       dist_probe_m[3] = 2000.0;
-       dist_probe_m[4] = -100.0;
-
-       BOUNDARY1_m = 40.0; // in meters
-       BOUNDARY2_m = 130.0; 
-
-       PI = 4.0*atan(1.0); // pi
-       deg2rad = (PI/180.0);
-       rad2deg = (180.0/PI);
        strength = 0.0;
        timer = 0.0;
-       scanned = false;
+       for( int i = 0; i < 5; i++ )
+               probe_elev_m[i] = probe_lat_deg[i] = probe_lon_deg[i] = 0.0;
 
-       earth_rad_ft=20899773.07;
-        for( int i = 0; i < sizeof(probe_elev_m)/sizeof(probe_elev_m[0]); i++ )
-          probe_elev_m[i] = 0.0;
+       for( int i = 0; i < 4; i++ )
+               slope[i] = 0.0;
 }
 
 //destructor
@@ -72,259 +72,140 @@ FGRidgeLift::~FGRidgeLift()
 
 void FGRidgeLift::init(void)
 {
-       _ridge_lift_fps_node =
-                       fgGetNode("/environment/ridge-lift-fps"
-                       , true);
+       _enabled_node = fgGetNode( "/environment/ridge-lift/enabled", false );
+
+       _ridge_lift_fps_node = fgGetNode("/environment/ridge-lift-fps", true);
        _surface_wind_from_deg_node =
                        fgGetNode("/environment/config/boundary/entry[0]/wind-from-heading-deg"
                        , true);
        _surface_wind_speed_node =
                        fgGetNode("/environment/config/boundary/entry[0]/wind-speed-kt"
                        , true);
-       _earth_radius_node =
-                       fgGetNode("/position/sea-level-radius-ft"
-                       , true);
-       _user_longitude_node =
-                       fgGetNode("/position/longitude-deg"
-                       , true);
-       _user_latitude_node =
-                       fgGetNode("/position/latitude-deg"
-                       , true);
-       _user_altitude_ft_node =
-                       fgGetNode("/position/altitude-ft"
-                       , true);
-       _user_altitude_agl_ft_node =
-                       fgGetNode("/position/altitude-agl-ft"
-                       , true);
+       _user_longitude_node = fgGetNode("/position/longitude-deg", true);
+       _user_latitude_node = fgGetNode("/position/latitude-deg", true);
+       _user_altitude_agl_ft_node = fgGetNode("/position/altitude-agl-ft", true);
+       _ground_elev_node = fgGetNode("/position/ground-elev-ft", true );
 }
 
 void FGRidgeLift::bind() {
+       string prop;
 
-       fgTie("/environment/ridge-lift/probe-elev-m[0]", this,
-               &FGRidgeLift::get_probe_elev_m_0); // read-only
-       fgTie("/environment/ridge-lift/probe-elev-m[1]", this,
-               &FGRidgeLift::get_probe_elev_m_1); // read-only
-       fgTie("/environment/ridge-lift/probe-elev-m[2]", this,
-               &FGRidgeLift::get_probe_elev_m_2); // read-only
-       fgTie("/environment/ridge-lift/probe-elev-m[3]", this,
-               &FGRidgeLift::get_probe_elev_m_3); // read-only
-       fgTie("/environment/ridge-lift/probe-elev-m[4]", this,
-               &FGRidgeLift::get_probe_elev_m_4); // read-only
-
-       fgTie("/environment/ridge-lift/probe-lat-deg[0]", this,
-               &FGRidgeLift::get_probe_lat_0); // read-only
-       fgTie("/environment/ridge-lift/probe-lat-deg[1]", this,
-               &FGRidgeLift::get_probe_lat_1); // read-only
-       fgTie("/environment/ridge-lift/probe-lat-deg[2]", this,
-               &FGRidgeLift::get_probe_lat_2); // read-only
-       fgTie("/environment/ridge-lift/probe-lat-deg[3]", this,
-               &FGRidgeLift::get_probe_lat_3); // read-only
-       fgTie("/environment/ridge-lift/probe-lat-deg[4]", this,
-               &FGRidgeLift::get_probe_lat_4); // read-only
-
-       fgTie("/environment/ridge-lift/probe-lon-deg[0]", this,
-               &FGRidgeLift::get_probe_lon_0); // read-only
-       fgTie("/environment/ridge-lift/probe-lon-deg[1]", this,
-               &FGRidgeLift::get_probe_lon_1); // read-only
-       fgTie("/environment/ridge-lift/probe-lon-deg[2]", this,
-               &FGRidgeLift::get_probe_lon_2); // read-only
-       fgTie("/environment/ridge-lift/probe-lon-deg[3]", this,
-               &FGRidgeLift::get_probe_lon_3); // read-only
-       fgTie("/environment/ridge-lift/probe-lon-deg[4]", this,
-               &FGRidgeLift::get_probe_lon_4); // read-only
+       _tiedProperties.setRoot( fgGetNode("/environment/ridge-lift",true));
+       for( int i = 0; i < 5; i++ ) {
+               _tiedProperties.Tie( "probe-elev-m", i, this, i, &FGRidgeLift::get_probe_elev_m );
+               _tiedProperties.Tie( "probe-lat-deg", i, this, i, &FGRidgeLift::get_probe_lat_deg );
+               _tiedProperties.Tie( "probe-lon-deg", i, this, i, &FGRidgeLift::get_probe_lon_deg );
+       }
 
-       fgTie("/environment/ridge-lift/slope[0]", this,
-               &FGRidgeLift::get_slope_0); // read-only
-       fgTie("/environment/ridge-lift/slope[1]", this,
-               &FGRidgeLift::get_slope_1); // read-only
-       fgTie("/environment/ridge-lift/slope[2]", this,
-               &FGRidgeLift::get_slope_2); // read-only
-       fgTie("/environment/ridge-lift/slope[3]", this,
-               &FGRidgeLift::get_slope_3); // read-only
-       
+       for( int i = 0; i < 4; i++ ) {
+               _tiedProperties.Tie( "slope", i, this, i, &FGRidgeLift::get_slope );
+       }
 }
 
 void FGRidgeLift::unbind() {
-
-       fgUntie("/environment/ridge-lift/probe-elev-m[0]");
-       fgUntie("/environment/ridge-lift/probe-elev-m[1]");
-       fgUntie("/environment/ridge-lift/probe-elev-m[2]");
-       fgUntie("/environment/ridge-lift/probe-elev-m[3]");
-       fgUntie("/environment/ridge-lift/probe-elev-m[4]");
-
-       fgUntie("/environment/ridge-lift/probe-lat-deg[0]");
-       fgUntie("/environment/ridge-lift/probe-lat-deg[1]");
-       fgUntie("/environment/ridge-lift/probe-lat-deg[2]");
-       fgUntie("/environment/ridge-lift/probe-lat-deg[3]");
-       fgUntie("/environment/ridge-lift/probe-lat-deg[4]");
-
-       fgUntie("/environment/ridge-lift/probe-lon-deg[0]");
-       fgUntie("/environment/ridge-lift/probe-lon-deg[1]");
-       fgUntie("/environment/ridge-lift/probe-lon-deg[2]");
-       fgUntie("/environment/ridge-lift/probe-lon-deg[3]");
-       fgUntie("/environment/ridge-lift/probe-lon-deg[4]");
-
-       fgUntie("/environment/ridge-lift/slope[0]");
-       fgUntie("/environment/ridge-lift/slope[1]");
-       fgUntie("/environment/ridge-lift/slope[2]");
-       fgUntie("/environment/ridge-lift/slope[3]");
-       
+       _tiedProperties.Untie();
 }
 
 void FGRidgeLift::update(double dt) {
-       Run(dt);
-}
-
-double FGRidgeLift::sign(double x) {
-    if (x == 0.0)
-        return x;
-    else
-        return x/fabs(x);
-}
-
-void FGRidgeLift::Run(double dt) {
 
-       // copy values 
-
-       user_latitude_deg  = _user_latitude_node->getDoubleValue();
-       user_longitude_deg = _user_longitude_node->getDoubleValue();
-       //user_altitude_ft  = _user_altitude_ft_node->getDoubleValue();
-       
-       if ( ( _earth_radius_node->getDoubleValue() ) > 1.0 ) {
-       earth_rad_ft =_earth_radius_node->getDoubleValue(); }
-       else {  earth_rad_ft=20899773.07; }
-
-       //earth_rad_m = earth_rad_ft * 0.3048 ;
-       earth_rad_m = earth_rad_ft * SG_FEET_TO_METER ;
-       
-       //get the windspeed at ground level
-
-       double ground_wind_from_deg = _surface_wind_from_deg_node->getDoubleValue();
-       double ground_wind_speed_kts  = _surface_wind_speed_node->getDoubleValue();
-       //double ground_wind_speed_mps = ground_wind_speed_kts / SG_METER_TO_FEET;
-       double ground_wind_speed_mps = ground_wind_speed_kts / 3.2808399;
-
-       //double ground_wind_from_rad = (user_longitude_deg < 0.0)  ? 
-       //      PI*( ground_wind_from_deg/180.0) +PI : PI*( ground_wind_from_deg/180.0);
-       double ground_wind_from_rad = PI*( ground_wind_from_deg/180.0);
-
-       // Placing the probes
-       
-       for (int i = 0; i <= 4; i++)
-       {
-                       probe_lat_rad[i] = asin(sin(deg2rad*user_latitude_deg)*cos(dist_probe_m[i]/earth_rad_m)
-                               +cos(deg2rad*user_latitude_deg)*sin(dist_probe_m[i]/earth_rad_m)*cos(ground_wind_from_rad));
-               if (probe_lat_rad[i] == 0.0) {
-                       probe_lon_rad[i] = (deg2rad*user_latitude_deg);      // probe on a pole 
-               }
-               else {
-                       probe_lon_rad[i] = fmod((deg2rad*user_longitude_deg+asin(sin(ground_wind_from_rad)
-                                               *sin(dist_probe_m[i]/earth_rad_m)/cos(probe_lat_rad[i]))+PI)
-                                       ,(2.0*PI))-PI;
+       if( dt <= SGLimitsd::min() ) // paused, do nothing but keep current lift
+               return;
+
+       if( _enabled_node && false == _enabled_node->getBoolValue() ) {
+               // do nothing if lift has been zeroed
+               if( strength != 0.0 ) {
+                       if( strength > 0.1 ) {
+                               // slowly fade out strong lifts
+                               strength = fgGetLowPass( strength, 0, dt );
+                       } else {
+                               strength = 0.0;
+                       }
+                       _ridge_lift_fps_node->setDoubleValue( strength );
                }
-               probe_lat_deg[i]= rad2deg*probe_lat_rad[i];
-               probe_lon_deg[i]= rad2deg*probe_lon_rad[i];
+               return;
        }
-       
-       // ground elevations
-       // every second
-       
+
        timer -= dt;
        if (timer <= 0.0 ) {
-               for (int i = 0; i <= 4; i++)
-               {
-                       if (globals->get_scenery()->get_elevation_m(SGGeod::fromGeodM(
-                           SGGeod::fromRad(probe_lon_rad[i],probe_lat_rad[i]), 20000), alt, 0))
-                       {
-                               if ( alt > 0.1 ) { probe_elev_m[i] =  alt; } else { probe_elev_m[i] = 0.1 ;};
+
+               // probe0 is current position
+               probe_lat_deg[0] = _user_latitude_node->getDoubleValue();
+               probe_lon_deg[0] = _user_longitude_node->getDoubleValue();
+               probe_elev_m[0]  = _ground_elev_node->getDoubleValue() * SG_FEET_TO_METER;
+
+               // position is geodetic, need geocentric for advanceRadM
+               SGGeod myGeodPos = SGGeod::fromDegM( probe_lon_deg[0], probe_lat_deg[0], 20000.0 );
+               SGGeoc myGeocPos = SGGeoc::fromGeod( myGeodPos );
+               double ground_wind_from_rad = _surface_wind_from_deg_node->getDoubleValue() * SG_DEGREES_TO_RADIANS;
+
+               // compute the remaining probes
+               for (unsigned i = 1; i < sizeof(probe_elev_m)/sizeof(probe_elev_m[0]); i++) {
+                       SGGeoc probe = myGeocPos.advanceRadM( ground_wind_from_rad, dist_probe_m[i] );
+                       // convert to geodetic position for ground level computation
+                       SGGeod probeGeod = SGGeod::fromGeoc( probe );
+                       probe_lat_deg[i] = probeGeod.getLatitudeDeg();
+                       probe_lon_deg[i] = probeGeod.getLongitudeDeg();
+                       if (!globals->get_scenery()->get_elevation_m( probeGeod, probe_elev_m[i], NULL )) {
+                               // no ground found? use elevation of previous probe :-(
+                               probe_elev_m[i] = probe_elev_m[i-1];
                        }
-                       else { probe_elev_m[i] = 0.1;};
                }
-               timer = 1.0;
-               
-       }
 
-       // slopes
-       
-       double adj_slope[5];
-       
-       slope[0] = (probe_elev_m[0] - probe_elev_m[1]) / dist_probe_m[1];
-       slope[1] = (probe_elev_m[1] - probe_elev_m[2]) / dist_probe_m[2];
-       slope[2] = (probe_elev_m[2] - probe_elev_m[3]) / dist_probe_m[3];
-       slope[3] = (probe_elev_m[4] - probe_elev_m[0]) / -dist_probe_m[4];
-       
-       for (int i = 0; i <= 4; i++)
-       {       
-               adj_slope[i] = sin(atan(5.0 * pow ( (fabs(slope[i])),1.7) ) ) *sign(slope[i]);
-       }
-       
-       //adjustment
+               // slopes
+               double adj_slope[sizeof(slope)];
+               slope[0] = (probe_elev_m[0] - probe_elev_m[1]) / dist_probe_m[1];
+               slope[1] = (probe_elev_m[1] - probe_elev_m[2]) / dist_probe_m[2];
+               slope[2] = (probe_elev_m[2] - probe_elev_m[3]) / dist_probe_m[3];
+               slope[3] = (probe_elev_m[4] - probe_elev_m[0]) / -dist_probe_m[4];
+       
+               for (unsigned i = 0; i < sizeof(slope)/sizeof(slope[0]); i++)
+                       adj_slope[i] = sin(atan(5.0 * pow ( (fabs(slope[i])),1.7) ) ) *SG_SIGN<double>(slope[i]);
+       
+               //adjustment
+               adj_slope[0] *= 0.2;
+               adj_slope[1] *= 0.2;
+               if ( adj_slope [2] < 0.0 ) {
+                       adj_slope[2] *= 0.5;
+               } else {
+                       adj_slope[2] = 0.0 ;
+               }
        
-       adj_slope[0] = 0.2 * adj_slope[0];
-       adj_slope[1] = 0.2 * adj_slope[1];
-       if ( adj_slope [2] < 0.0 )
-       {
-               adj_slope[2] = 0.5 * adj_slope[2];
-       }
-       else 
-       {
-               adj_slope[2] = 0.0 ;
-       }
+               if ( ( adj_slope [0] >= 0.0 ) && ( adj_slope [3] < 0.0 ) ) {
+                       adj_slope[3] = 0.0;
+               } else {
+                       adj_slope[3] *= 0.2;
+               }
+               lift_factor = adj_slope[0]+adj_slope[1]+adj_slope[2]+adj_slope[3];
        
-       if ( ( adj_slope [0] >= 0.0 ) && ( adj_slope [3] < 0.0 ) )
-       {
-               adj_slope[3] = 0.0;
-       }
-       else 
-       {
-               adj_slope[3] = 0.2 * adj_slope[3];
+               // restart the timer
+               timer = 1.0;
        }
        
-       double lift_factor = adj_slope[0]+adj_slope[1]+adj_slope[2]+adj_slope[3];
-       
        //user altitude above ground
-       
-       user_altitude_agl_ft = _user_altitude_agl_ft_node->getDoubleValue();
-       user_altitude_agl_m = ( user_altitude_agl_ft / SG_METER_TO_FEET );
+       double user_altitude_agl_m = _user_altitude_agl_ft_node->getDoubleValue() * SG_FEET_TO_METER;
        
        //boundaries
-       double agl_factor;
-
-       if (lift_factor < 0.0) // in the sink
-       {
-               double highest_probe_temp= max ( probe_elev_m[1], probe_elev_m[2] );
-               double highest_probe_downwind_m= max ( highest_probe_temp, probe_elev_m[3] );
-               BOUNDARY2_m = highest_probe_downwind_m - probe_elev_m[0];
-       }
-       else // in the lift
-       {
-               BOUNDARY2_m = 130.0;
+       double boundary2_m = 130.0; // in the lift
+       if (lift_factor < 0.0) { // in the sink
+               double highest_probe_temp= std::max ( probe_elev_m[1], probe_elev_m[2] );
+               double highest_probe_downwind_m= std::max ( highest_probe_temp, probe_elev_m[3] );
+               boundary2_m = highest_probe_downwind_m - probe_elev_m[0];
        }
 
-       if ( user_altitude_agl_m < BOUNDARY1_m )
-       {
+       double agl_factor;
+       if ( user_altitude_agl_m < BOUNDARY1_m ) {
                agl_factor = 0.5+0.5*user_altitude_agl_m /BOUNDARY1_m ;
-       }
-       else if ( user_altitude_agl_m < BOUNDARY2_m )
-       {
+       } else if ( user_altitude_agl_m < boundary2_m ) {
                agl_factor = 1.0;
-       }
-       else
-       {
-               agl_factor =  exp(-(2 + 2 * probe_elev_m[0] / 4000) * 
-                               (user_altitude_agl_m - BOUNDARY2_m) / max(probe_elev_m[0],200.0));
+       } else {
+               agl_factor = exp(-(2 + probe_elev_m[0] / 2000) * 
+                     (user_altitude_agl_m - boundary2_m) / std::max(probe_elev_m[0],200.0));
        }
        
+       double ground_wind_speed_mps = _surface_wind_speed_node->getDoubleValue() * SG_NM_TO_METER / 3600;
        double lift_mps = lift_factor* ground_wind_speed_mps * agl_factor;
        
        //the updraft, finally, in ft per second
-       strength = lift_mps * SG_METER_TO_FEET ;
-//     if(isnan(strength)) strength=0; 
-        _ridge_lift_fps_node->setDoubleValue( strength );
+       strength = fgGetLowPass( strength, lift_mps * SG_METER_TO_FEET, dt );
+       _ridge_lift_fps_node->setDoubleValue( strength );
 }
-
-
-
-
-
-