]> git.mxchange.org Git - flightgear.git/blobdiff - src/ATCDCL/AILocalTraffic.cxx
Port over remaining Point3D usage to the more type and unit safe SG* classes.
[flightgear.git] / src / ATCDCL / AILocalTraffic.cxx
index bcaab722e3ae18386c0da2f43ea79a3b3d90fdb1..0e81570aeb5b9f1c7137ab19b3a777556f3609c0 100644 (file)
@@ -34,15 +34,12 @@ during descent to avoid occasionally landing short or long.
 #  include <config.h>
 #endif
 
-#include <simgear/scene/model/location.hxx>
-
 #include <Airports/runways.hxx>
 #include <Main/globals.hxx>
 #include <Main/viewer.hxx>
 #include <Scenery/scenery.hxx>
 #include <Scenery/tilemgr.hxx>
-#include <simgear/math/point3d.hxx>
-#include <simgear/math/sg_geodesy.hxx>
+#include <simgear/math/SGMath.hxx>
 #include <simgear/misc/sg_path.hxx>
 #include <string>
 #include <math.h>
@@ -55,16 +52,6 @@ using std::string;
 #include "AIMgr.hxx"
 
 FGAILocalTraffic::FGAILocalTraffic() {
-       /*ssgBranch *model = sgLoad3DModel( globals->get_fg_root(),
-                                         planepath.c_str(),
-                                         globals->get_props(),
-                                         globals->get_sim_time_sec() );
-       *//*
-       _model = model;
-       _aip.init(_model);
-       */
-       //SetModel(model);
-       
        ATC = globals->get_ATC_mgr();
        
        // TODO - unhardwire this
@@ -167,9 +154,9 @@ void FGAILocalTraffic::GetRwyDetails(const string& id) {
        
   const FGAirport* apt = fgFindAirportID(id);
   assert(apt);
-  FGRunway runway(apt->getActiveRunwayForUsage());
+  FGRunway* runway(apt->getActiveRunwayForUsage());
 
-  double hdg = runway._heading;
+  double hdg = runway->headingDeg();
   double other_way = hdg - 180.0;
   while(other_way <= 0.0) {
     other_way += 360.0;
@@ -177,20 +164,18 @@ void FGAILocalTraffic::GetRwyDetails(const string& id) {
   
        // move to the +l end/center of the runway
                //cout << "Runway center is at " << runway._lon << ", " << runway._lat << '\n';
-       Point3D origin = Point3D(runway._lon, runway._lat, aptElev);
-               Point3D ref = origin;
        double tshlon, tshlat, tshr;
                double tolon, tolat, tor;
-               rwy.length = runway._length * SG_FEET_TO_METER;
-               rwy.width = runway._width * SG_FEET_TO_METER;
-       geo_direct_wgs_84 ( aptElev, ref.lat(), ref.lon(), other_way, 
+               rwy.length = runway->lengthM();
+               rwy.width = runway->widthM();
+       geo_direct_wgs_84 ( aptElev, runway->latitude(), runway->longitude(), other_way, 
                                rwy.length / 2.0 - 25.0, &tshlat, &tshlon, &tshr );
-       geo_direct_wgs_84 ( aptElev, ref.lat(), ref.lon(), hdg, 
+       geo_direct_wgs_84 ( aptElev, runway->latitude(), runway->longitude(), hdg, 
                                rwy.length / 2.0 - 25.0, &tolat, &tolon, &tor );
                // Note - 25 meters in from the runway end is a bit of a hack to put the plane ahead of the user.
                // now copy what we need out of runway into rwy
-       rwy.threshold_pos = Point3D(tshlon, tshlat, aptElev);
-               Point3D takeoff_end = Point3D(tolon, tolat, aptElev);
+       rwy.threshold_pos = SGGeod::fromDegM(tshlon, tshlat, aptElev);
+               SGGeod takeoff_end = SGGeod::fromDegM(tolon, tolat, aptElev);
                //cout << "Threshold position = " << tshlon << ", " << tshlat << ", " << aptElev << '\n';
                //cout << "Takeoff position = " << tolon << ", " << tolat << ", " << aptElev << '\n';
                rwy.hdg = hdg;
@@ -248,7 +233,7 @@ bool FGAILocalTraffic::Init(const string& callsign, const string& ICAO, Operatin
 
        //cout << "In Init(), initialState = " << initialState << endl;
        operatingState = initialState;
-       Point3D orthopos;
+       SGVec3d orthopos;
        switch(operatingState) {
        case PARKED:
                tuned_station = ground;
@@ -264,7 +249,7 @@ bool FGAILocalTraffic::Init(const string& callsign, const string& ICAO, Operatin
                vel = 0.0;
                slope = 0.0;
                _pos = ourGate->pos;
-               _pos.setelev(aptElev);
+               _pos.setElevationM(aptElev);
                _hdg = ourGate->heading;
                Transform();
                
@@ -287,10 +272,10 @@ bool FGAILocalTraffic::Init(const string& callsign, const string& ICAO, Operatin
                freeTaxi = true;
                // Set a position and orientation in an approximate place for hold short.
                //cout << "rwy.width = " << rwy.width << '\n';
-               orthopos = Point3D((rwy.width / 2.0 + 10.0) * -1.0, 0.0, 0.0);
+               orthopos = SGVec3d((rwy.width / 2.0 + 10.0) * -1.0, 0.0, 0.0);
                // TODO - set the x pos to be +ve if a RH parallel rwy.
                _pos = ortho.ConvertFromLocal(orthopos);
-               _pos.setelev(aptElev);
+               _pos.setElevationM(aptElev);
                _hdg = rwy.hdg + 90.0;
                // TODO - reset the heading if RH rwy.
                _pitch = 0.0;
@@ -330,8 +315,8 @@ bool FGAILocalTraffic::Init(const string& callsign, const string& ICAO, Operatin
                touchAndGo = false;
 
                if(initialLeg == DOWNWIND) {
-                       _pos = ortho.ConvertFromLocal(Point3D(1000*patternDirection, 800, 0.0));
-                       _pos.setelev(rwy.threshold_pos.elev() + 1000 * SG_FEET_TO_METER);
+                        _pos = ortho.ConvertFromLocal(SGVec3d(1000*patternDirection, 800, 0.0));
+                       _pos.setElevationM(rwy.threshold_pos.getElevationM() + 1000 * SG_FEET_TO_METER);
                        _hdg = rwy.hdg + 180.0;
                        leg = DOWNWIND;
                        elevInitGood = false;
@@ -349,9 +334,7 @@ bool FGAILocalTraffic::Init(const string& callsign, const string& ICAO, Operatin
                        Transform();
                } else {                        
                        // Default to initial position on threshold for now
-                       _pos.setlat(rwy.threshold_pos.lat());
-                       _pos.setlon(rwy.threshold_pos.lon());
-                       _pos.setelev(rwy.threshold_pos.elev());
+                        _pos = rwy.threshold_pos;
                        _hdg = rwy.hdg;
                        
                        // Now we've set the position we can do the ground elev
@@ -462,7 +445,7 @@ void FGAILocalTraffic::Update(double dt) {
        // we shouldn't really need this since there's a LOD of 10K on the whole plane anyway I think.
        // At the moment though I need to to avoid DList overflows - the whole plane LOD obviously isn't getting picked up.
        if(!_invisible) {
-               if(dclGetHorizontalSeparation(_pos, Point3D(fgGetDouble("/position/longitude-deg"), fgGetDouble("/position/latitude-deg"), 0.0)) > 8000) _aip.setVisible(false);
+                if(dclGetHorizontalSeparation(_pos, SGGeod::fromDegM(fgGetDouble("/position/longitude-deg"), fgGetDouble("/position/latitude-deg"), 0.0)) > 8000) _aip.setVisible(false);
                else _aip.setVisible(true);
        } else {
                _aip.setVisible(false);
@@ -578,8 +561,8 @@ void FGAILocalTraffic::Update(double dt) {
                if(!inAir) {
                        DoGroundElev();
                        if(!elevInitGood) {
-                               if(_aip.getSGLocation()->get_cur_elev_m() > -9990.0) {
-                                       _pos.setelev(_aip.getSGLocation()->get_cur_elev_m() + wheelOffset);
+                               if(_ground_elevation_m > -9990.0) {
+                                       _pos.setElevationM(_ground_elevation_m + wheelOffset);
                                        //cout << "TAKEOFF_ROLL, POS = " << pos.lon() << ", " << pos.lat() << ", " << pos.elev() << '\n';
                                        //Transform();
                                        _aip.setVisible(true);
@@ -596,8 +579,8 @@ void FGAILocalTraffic::Update(double dt) {
                //cout << "*" << flush;
                if(!elevInitGood) {
                        //DoGroundElev();
-                       if(_aip.getSGLocation()->get_cur_elev_m() > -9990.0) {
-                               _pos.setelev(_aip.getSGLocation()->get_cur_elev_m() + wheelOffset);
+                       if(_ground_elevation_m > -9990.0) {
+                               _pos.setElevationM(_ground_elevation_m + wheelOffset);
                                //Transform();
                                _aip.setVisible(true);
                                //Transform();
@@ -623,7 +606,7 @@ void FGAILocalTraffic::Update(double dt) {
                                //cout << "C" << endl;
                                node* np = new node;
                                np->struct_type = NODE;
-                               np->pos = ortho.ConvertFromLocal(Point3D(0.0, 10.0, 0.0));
+                               np->pos = ortho.ConvertFromLocal(SGVec3d(0.0, 10.0, 0.0));
                                path.push_back(np);
                        } else {
                                //cout << "D" << endl;
@@ -656,8 +639,8 @@ void FGAILocalTraffic::Update(double dt) {
                //cout << "In PARKED\n";
                if(!elevInitGood) {
                        DoGroundElev();
-                       if(_aip.getSGLocation()->get_cur_elev_m() > -9990.0) {
-                               _pos.setelev(_aip.getSGLocation()->get_cur_elev_m() + wheelOffset);
+                       if(_ground_elevation_m > -9990.0) {
+                               _pos.setElevationM(_ground_elevation_m + wheelOffset);
                                //Transform();
                                _aip.setVisible(true);
                                //Transform();
@@ -812,8 +795,8 @@ void FGAILocalTraffic::FlyTrafficPattern(double dt) {
        double turn_time = 60.0;        // seconds - TODO - check this guess
        double turn_circumference;
        double turn_radius;
-       Point3D orthopos = ortho.ConvertToLocal(_pos);  // ortho position of the plane
-       //cout << "runway elev = " << rwy.threshold_pos.elev() << ' ' << rwy.threshold_pos.elev() * SG_METER_TO_FEET << '\n';
+       SGVec3d orthopos = ortho.ConvertToLocal(_pos);  // ortho position of the plane
+       //cout << "runway elev = " << rwy.threshold_pos.getElevationM() << ' ' << rwy.threshold_pos.getElevationM() * SG_METER_TO_FEET << '\n';
        //cout << "elev = " << _pos.elev() << ' ' << _pos.elev() * SG_METER_TO_FEET << '\n';
 
        // HACK FOR TESTING - REMOVE
@@ -836,8 +819,8 @@ void FGAILocalTraffic::FlyTrafficPattern(double dt) {
                        double dveldt = 5.0;
                        vel += dveldt * dt;
                }
-               if(_aip.getSGLocation()->get_cur_elev_m() > -9990.0) {
-                       _pos.setelev(_aip.getSGLocation()->get_cur_elev_m() + wheelOffset);
+               if(_ground_elevation_m > -9990.0) {
+                       _pos.setElevationM(_ground_elevation_m + wheelOffset);
                }
                IAS = vel + (cos((_hdg - wind_from) * DCL_DEGREES_TO_RADIANS) * wind_speed);
                if(IAS >= 70) {
@@ -855,7 +838,7 @@ void FGAILocalTraffic::FlyTrafficPattern(double dt) {
                // (decided in FGTower and accessed through GetCrosswindConstraint(...)).
                // According to AIM, traffic should climb to within 300ft of pattern altitude before commencing crosswind turn.
                // TODO - At hot 'n high airports this may be 500ft AGL though - need to make this a variable.
-               if((_pos.elev() - rwy.threshold_pos.elev()) * SG_METER_TO_FEET > 700) {
+               if((_pos.getElevationM() - rwy.threshold_pos.getElevationM()) * SG_METER_TO_FEET > 700) {
                        double cc = 0.0;
                        if(tower->GetCrosswindConstraint(cc)) {
                                if(orthopos.y() > cc) {
@@ -870,7 +853,7 @@ void FGAILocalTraffic::FlyTrafficPattern(double dt) {
                }
                // Need to check for levelling off in case we can't turn crosswind as soon
                // as we would like due to other traffic.
-               if((_pos.elev() - rwy.threshold_pos.elev()) * SG_METER_TO_FEET > 1000) {
+               if((_pos.getElevationM() - rwy.threshold_pos.getElevationM()) * SG_METER_TO_FEET > 1000) {
                        slope = 0.0;
                        _pitch = 0.0;
                        IAS = 80.0;             // FIXME - use smooth transistion to new speed and attitude.
@@ -892,7 +875,7 @@ void FGAILocalTraffic::FlyTrafficPattern(double dt) {
                break;
        case CROSSWIND:
                goAround = false;
-               if((_pos.elev() - rwy.threshold_pos.elev()) * SG_METER_TO_FEET > 1000) {
+               if((_pos.getElevationM() - rwy.threshold_pos.getElevationM()) * SG_METER_TO_FEET > 1000) {
                        slope = 0.0;
                        _pitch = 0.0;
                        IAS = 80.0;             // FIXME - use smooth transistion to new speed
@@ -914,7 +897,7 @@ void FGAILocalTraffic::FlyTrafficPattern(double dt) {
        case TURN2:
                SetTrack(rwy.hdg - (180 * patternDirection));
                // just in case we didn't make height on crosswind
-               if((_pos.elev() - rwy.threshold_pos.elev()) * SG_METER_TO_FEET > 1000) {
+               if((_pos.getElevationM() - rwy.threshold_pos.getElevationM()) * SG_METER_TO_FEET > 1000) {
                        slope = 0.0;
                        _pitch = 0.0;
                        IAS = 80.0;             // FIXME - use smooth transistion to new speed
@@ -926,12 +909,12 @@ void FGAILocalTraffic::FlyTrafficPattern(double dt) {
                break;
        case DOWNWIND:
                // just in case we didn't make height on crosswind
-               if(((_pos.elev() - rwy.threshold_pos.elev()) * SG_METER_TO_FEET > 995) && ((_pos.elev() - rwy.threshold_pos.elev()) * SG_METER_TO_FEET < 1015)) {
+               if(((_pos.getElevationM() - rwy.threshold_pos.getElevationM()) * SG_METER_TO_FEET > 995) && ((_pos.getElevationM() - rwy.threshold_pos.getElevationM()) * SG_METER_TO_FEET < 1015)) {
                        slope = 0.0;
                        _pitch = 0.0;
                        IAS = 90.0;             // FIXME - use smooth transistion to new speed
                }
-               if((_pos.elev() - rwy.threshold_pos.elev()) * SG_METER_TO_FEET >= 1015) {
+               if((_pos.getElevationM() - rwy.threshold_pos.getElevationM()) * SG_METER_TO_FEET >= 1015) {
                        slope = -1.0;
                        _pitch = -1.0;
                        IAS = 90.0;             // FIXME - use smooth transistion to new speed
@@ -1056,20 +1039,20 @@ void FGAILocalTraffic::FlyTrafficPattern(double dt) {
                if(descending) {
                        if(orthopos.y() < -50.0) {
                                double thesh_offset = 30.0;
-                               slope = atan((_pos.elev() - fgGetAirportElev(airportID)) / (orthopos.y() - thesh_offset)) * DCL_RADIANS_TO_DEGREES;
+                               slope = atan((_pos.getElevationM() - fgGetAirportElev(airportID)) / (orthopos.y() - thesh_offset)) * DCL_RADIANS_TO_DEGREES;
                                //cout << "slope = " << slope << ", elev = " << _pos.elev() << ", apt_elev = " << fgGetAirportElev(airportID) << ", op.y = " << orthopos.y() << '\n';
                                if(slope < -10.0) slope = -10.0;
                                _savedSlope = slope;
                                _pitch = -4.0;
                                IAS = 70.0;
                        } else {
-                               if(_pos.elev() < (rwy.threshold_pos.elev()+10.0+wheelOffset)) {
-                                       if(_aip.getSGLocation()->get_cur_elev_m() > -9990.0) {
-                                               if(_pos.elev() < (_aip.getSGLocation()->get_cur_elev_m() + wheelOffset + 1.0)) {
+                               if(_pos.getElevationM() < (rwy.threshold_pos.getElevationM()+10.0+wheelOffset)) {
+                                       if(_ground_elevation_m > -9990.0) {
+                                               if(_pos.getElevationM() < (_ground_elevation_m + wheelOffset + 1.0)) {
                                                        slope = -2.0;
                                                        _pitch = 1.0;
                                                        IAS = 55.0;
-                                               } else if(_pos.elev() < (_aip.getSGLocation()->get_cur_elev_m() + wheelOffset + 5.0)) {
+                                               } else if(_pos.getElevationM() < (_ground_elevation_m + wheelOffset + 5.0)) {
                                                        slope = -4.0;
                                                        _pitch = -2.0;
                                                        IAS = 60.0;
@@ -1094,15 +1077,15 @@ void FGAILocalTraffic::FlyTrafficPattern(double dt) {
                // Try and track the extended centreline
                SetTrack(rwy.hdg - (0.2 * orthopos.x()));
                //cout << "orthopos.x() = " << orthopos.x() << " hdg = " << hdg << '\n';
-               if(_pos.elev() < (rwy.threshold_pos.elev()+20.0+wheelOffset)) {
+               if(_pos.getElevationM() < (rwy.threshold_pos.getElevationM()+20.0+wheelOffset)) {
                        DoGroundElev(); // Need to call it here expicitly on final since it's only called
                                        // for us in update(...) when the inAir flag is false.
                }
-               if(_pos.elev() < (rwy.threshold_pos.elev()+10.0+wheelOffset)) {
+               if(_pos.getElevationM() < (rwy.threshold_pos.getElevationM()+10.0+wheelOffset)) {
                        //slope = -1.0;
                        //_pitch = 1.0;
-                       if(_aip.getSGLocation()->get_cur_elev_m() > -9990.0) {
-                               if((_aip.getSGLocation()->get_cur_elev_m() + wheelOffset) > _pos.elev()) {
+                       if(_ground_elevation_m > -9990.0) {
+                               if((_ground_elevation_m + wheelOffset) > _pos.getElevationM()) {
                                        slope = 0.0;
                                        _pitch = 0.0;
                                        leg = LANDING_ROLL;
@@ -1118,8 +1101,8 @@ void FGAILocalTraffic::FlyTrafficPattern(double dt) {
        case LANDING_ROLL:
                //inAir = false;
                descending = false;
-               if(_aip.getSGLocation()->get_cur_elev_m() > -9990.0) {
-                       _pos.setelev(_aip.getSGLocation()->get_cur_elev_m() + wheelOffset);
+               if(_ground_elevation_m > -9990.0) {
+                       _pos.setElevationM(_ground_elevation_m + wheelOffset);
                }
                track = rwy.hdg;
                dveldt = -5.0;
@@ -1301,7 +1284,7 @@ void FGAILocalTraffic::ProcessCallback(int code) {
        }
 }
 
-void FGAILocalTraffic::ExitRunway(const Point3D& orthopos) {
+void FGAILocalTraffic::ExitRunway(const SGVec3d& orthopos) {
        //cout << "In ExitRunway" << endl;
        //cout << "Runway ID is " << rwy.ID << endl;
        
@@ -1324,7 +1307,7 @@ void FGAILocalTraffic::ExitRunway(const Point3D& orthopos) {
                node* rwyExit = *(exitNodes.begin());
                //int gateID;           //This might want to be more persistant at some point
                while(nItr != exitNodes.end()) {
-                       d = ortho.ConvertToLocal((*nItr)->pos).y() - ortho.ConvertToLocal(_pos).y();    //FIXME - consider making orthopos a class variable
+                        d = ortho.ConvertToLocal((*nItr)->pos).y() - ortho.ConvertToLocal(_pos).y();   //FIXME - consider making orthopos a class variable
                        if(d > 0.0) {
                                if(d < dist) {
                                        dist = d;
@@ -1472,8 +1455,7 @@ void FGAILocalTraffic::Taxi(double dt) {
        // If we have reached turning point then get next point and turn onto that heading
        // Look out for the finish!!
 
-       //Point3D orthopos = ortho.ConvertToLocal(pos); // ortho position of the plane
-       desiredTaxiHeading = GetHeadingFromTo(_pos, nextTaxiNode->pos);
+        desiredTaxiHeading = GetHeadingFromTo(_pos, nextTaxiNode->pos);
        
        bool lastNode = (taxiPathPos == path.size() ? true : false);
        if(lastNode) {
@@ -1505,8 +1487,8 @@ void FGAILocalTraffic::Taxi(double dt) {
                double slope = 0.0;
                _pos = dclUpdatePosition(_pos, track, slope, dist);
                //cout << "Updated position...\n";
-               if(_aip.getSGLocation()->get_cur_elev_m() > -9990) {
-                       _pos.setelev(_aip.getSGLocation()->get_cur_elev_m() + wheelOffset);
+               if(_ground_elevation_m > -9990) {
+                       _pos.setElevationM(_ground_elevation_m + wheelOffset);
                } // else don't change the elev until we get a valid ground elev again!
        } else if(lastNode) {
                if(taxiState == TD_LINING_UP) {
@@ -1524,8 +1506,8 @@ void FGAILocalTraffic::Taxi(double dt) {
                                double slope = 0.0;
                                _pos = dclUpdatePosition(_pos, track, slope, dist);
                                //cout << "Updated position...\n";
-                               if(_aip.getSGLocation()->get_cur_elev_m() > -9990) {
-                                       _pos.setelev(_aip.getSGLocation()->get_cur_elev_m() + wheelOffset);
+                               if(_ground_elevation_m > -9990) {
+                                       _pos.setElevationM(_ground_elevation_m + wheelOffset);
                                } // else don't change the elev until we get a valid ground elev again!
                                if(fabs(_hdg - rwy.hdg) <= 1.0) {
                                        operatingState = IN_PATTERN;
@@ -1554,32 +1536,24 @@ void FGAILocalTraffic::Taxi(double dt) {
 // Either this function or the logic of how often it is called
 // will almost certainly change.
 void FGAILocalTraffic::DoGroundElev() {
-       // It would be nice if we could set the correct tile center here in order to get a correct
-       // answer with one call to the function, but what I tried in the two commented-out lines
-       // below only intermittently worked, and I haven't quite groked why yet.
-       //SGBucket buck(pos.lon(), pos.lat());
-       //aip.getSGLocation()->set_tile_center(Point3D(buck.get_center_lon(), buck.get_center_lat(), 0.0));
-       
        // Only do the proper hitlist stuff if we are within visible range of the viewer.
        double visibility_meters = fgGetDouble("/environment/visibility-m");
        FGViewer* vw = globals->get_current_view();
-       if(dclGetHorizontalSeparation(_pos, Point3D(vw->getLongitude_deg(), vw->getLatitude_deg(), 0.0)) > visibility_meters) {
-               _aip.getSGLocation()->set_cur_elev_m(aptElev);
+       if(dclGetHorizontalSeparation(_pos, SGGeod::fromDegM(vw->getLongitude_deg(), vw->getLatitude_deg(), 0.0)) > visibility_meters) {
+               _ground_elevation_m = aptElev;
                return;
        }
 
         // FIXME: make shure the pos.lat/pos.lon values are in degrees ...
         double range = 500.0;
-        double lat = _aip.getSGLocation()->getLatitude_deg();
-        double lon = _aip.getSGLocation()->getLongitude_deg();
-        if (!globals->get_tile_mgr()->scenery_available(lat, lon, range)) {
+        if (!globals->get_tile_mgr()->scenery_available(_aip.getPosition(), range)) {
           // Try to shedule tiles for that position.
-          globals->get_tile_mgr()->update( _aip.getSGLocation(), range );
+          globals->get_tile_mgr()->update( _aip.getPosition(), range );
         }
 
         // FIXME: make shure the pos.lat/pos.lon values are in degrees ...
         double alt;
-        if (globals->get_scenery()->get_elevation_m(lat, lon, 20000.0, alt, 0))
-          _aip.getSGLocation()->set_cur_elev_m(alt);
+        if (globals->get_scenery()->get_elevation_m(SGGeod::fromGeodM(_aip.getPosition(), 20000), alt, 0))
+          _ground_elevation_m = alt;
 }