]> git.mxchange.org Git - flightgear.git/blobdiff - src/ATCDCL/AILocalTraffic.cxx
Fix two bugs in the new autopilot code
[flightgear.git] / src / ATCDCL / AILocalTraffic.cxx
index 4a5dfaa3b15268d2a32f63be3e7b139e8e70141f..8a66eda6e0a976cc67e1ac5c96c86599bc9b887c 100644 (file)
@@ -164,8 +164,8 @@ 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';
-       double tshlon, tshlat, tshr;
-               double tolon, tolat, tor;
+       double tshlon = 0.0, tshlat = 0.0, tshr;
+               double tolon = 0.0, tolat = 0.0, tor;
                rwy.length = runway->lengthM();
                rwy.width = runway->widthM();
        geo_direct_wgs_84 ( aptElev, runway->latitude(), runway->longitude(), other_way, 
@@ -546,6 +546,7 @@ void FGAILocalTraffic::Update(double dt) {
                // And to avoid compiler warnings...
                case APPROACH:  break;
                case ATIS:      break;
+    case AWOS:      break;
                case ENROUTE:   break;
                case DEPARTURE: break;
                case INVALID:   break;
@@ -840,7 +841,7 @@ void FGAILocalTraffic::FlyTrafficPattern(double dt) {
                // TODO - At hot 'n high airports this may be 500ft AGL though - need to make this a variable.
                if((_pos.getElevationM() - rwy.threshold_pos.getElevationM()) * SG_METER_TO_FEET > 700) {
                        double cc = 0.0;
-                       if(tower->GetCrosswindConstraint(cc)) {
+                       if(_controlled && tower->GetCrosswindConstraint(cc)) {
                                if(orthopos.y() > cc) {
                                        //cout << "Turning to crosswind, distance from threshold = " << orthopos.y() << '\n'; 
                                        leg = TURN1;
@@ -883,7 +884,7 @@ void FGAILocalTraffic::FlyTrafficPattern(double dt) {
                // turn 1000m out for now, taking other traffic into accout
                if(fabs(orthopos.x()) > 900) {
                        double dd = 0.0;
-                       if(tower->GetDownwindConstraint(dd)) {
+                       if(_controlled && tower->GetDownwindConstraint(dd)) {
                                if(fabs(orthopos.x()) > fabs(dd)) {
                                        //cout << "Turning to downwind, distance from centerline = " << fabs(orthopos.x()) << '\n'; 
                                        leg = TURN2;
@@ -929,7 +930,7 @@ void FGAILocalTraffic::FlyTrafficPattern(double dt) {
                        // For now we're assuming that we aim to follow the same glidepath regardless of wind.
                        double d1;
                        double d2;
-                       CalculateSoD((tower->GetBaseConstraint(d1) ? d1 : -1000.0), (tower->GetDownwindConstraint(d2) ? d2 : 1000.0 * patternDirection), (patternDirection ? true : false));
+                       CalculateSoD(((_controlled && tower->GetBaseConstraint(d1)) ? d1 : -1000.0), ((_controlled && tower->GetDownwindConstraint(d2)) ? d2 : 1000.0 * patternDirection), (patternDirection ? true : false));
                        if(SoD.leg == DOWNWIND) {
                                descending = (orthopos.y() < SoD.y ? true : false);
                        }
@@ -949,7 +950,7 @@ void FGAILocalTraffic::FlyTrafficPattern(double dt) {
                if(orthopos.y() < -1000.0 + turn_radius) {
                //if(orthopos.y() < -980) {
                        double bb = 0.0;
-                       if(tower->GetBaseConstraint(bb)) {
+                       if(_controlled && tower->GetBaseConstraint(bb)) {
                                if(fabs(orthopos.y()) > fabs(bb)) {
                                        //cout << "Turning to base, distance from threshold = " << fabs(orthopos.y()) << '\n'; 
                                        leg = TURN3;
@@ -981,7 +982,7 @@ void FGAILocalTraffic::FlyTrafficPattern(double dt) {
                        double d1;
                        // Make downwind leg position artifically large to avoid any chance of SoD being returned as
                        // on downwind when we are already on base.
-                       CalculateSoD((tower->GetBaseConstraint(d1) ? d1 : -1000.0), (10000.0 * patternDirection), (patternDirection ? true : false));
+                       CalculateSoD(((_controlled && tower->GetBaseConstraint(d1)) ? d1 : -1000.0), (10000.0 * patternDirection), (patternDirection ? true : false));
                        if(SoD.leg == BASE) {
                                descending = (fabs(orthopos.y()) < fabs(SoD.y) ? true : false);
                        }
@@ -1126,43 +1127,24 @@ void FGAILocalTraffic::FlyTrafficPattern(double dt) {
     }
 
        if(inAir) {
-               // FIXME - at the moment this is a bit screwy
-               // The velocity correction is applied based on the relative headings.
-               // Then the heading is changed based on the velocity.
-               // Which comes first, the chicken or the egg?
-               // Does it really matter?
-               
-               // Apply wind to ground-relative velocity if in the air
-               vel = IAS - (cos((_hdg - wind_from) * DCL_DEGREES_TO_RADIANS) * wind_speed);
-               //crab = f(track, wind, vel);
-               // The vector we need to fly is our desired vector minus the wind vector
-               // TODO - we probably ought to use plib's built in vector types and operations for this
-               // ie.  There's almost *certainly* a better way to do this!
-               double gxx = vel * sin(track * DCL_DEGREES_TO_RADIANS); // Plane desired velocity x component wrt ground
-               double gyy = vel * cos(track * DCL_DEGREES_TO_RADIANS); // Plane desired velocity y component wrt ground
-               double wxx = wind_speed * sin((wind_from + 180.0) * DCL_DEGREES_TO_RADIANS);    // Wind velocity x component
-               double wyy = wind_speed * cos((wind_from + 180.0) * DCL_DEGREES_TO_RADIANS);    // Wind velocity y component
-               double axx = gxx - wxx; // Plane in-air velocity x component
-               double ayy = gyy - wyy; // Plane in-air velocity y component
-               // Now we want the angle between gxx and axx (which is the crab)
-               double maga = sqrt(axx*axx + ayy*ayy);
-               double magg = sqrt(gxx*gxx + gyy*gyy);
-               crab = acos((axx*gxx + ayy*gyy) / (maga * magg));
-               // At this point this works except we're getting the modulus of the angle
-               //cout << "crab = " << crab << '\n';
-               
-               // Make sure both headings are in the 0->360 circle in order to get sane differences
-               dclBoundHeading(wind_from);
-               dclBoundHeading(track);
-               if(track > wind_from) {
-                       if((track - wind_from) <= 180) {
-                               crab *= -1.0;
-                       }
+               // calculate ground speed and crab from the wind triangle
+               double wind_angle = GetAngleDiff_deg(wind_from + 180, track);
+               double wind_side = (wind_angle < 0) ? -1.0 : 1.0;
+
+               double sine_of_crab = wind_speed / IAS * sin(fabs(wind_angle) * DCL_DEGREES_TO_RADIANS);
+               if (sine_of_crab >= 1.0) {
+                       // The crosswind component is greater than the IAS,
+                       // we can't keep the aircraft on track.
+                       // Assume increased IAS such that it cancels lateral speed.
+                       // This is unrealistic, but not sure how the rest of the sim
+                       // would react to the aircraft going off course.
+                       // Should be a rare case anyway.
+                       crab = wind_side * 90.0;
                } else {
-                       if((wind_from - track) >= 180) {
-                               crab *= -1.0;
-                       }
+                       crab = asin(sine_of_crab) * DCL_RADIANS_TO_DEGREES * wind_side;
                }
+               vel = cos(wind_angle * DCL_DEGREES_TO_RADIANS) * wind_speed
+                       + cos(crab * DCL_DEGREES_TO_RADIANS) * IAS;
        } else {        // on the ground - crab dosen't apply
                crab = 0.0;
        }
@@ -1170,6 +1152,7 @@ void FGAILocalTraffic::FlyTrafficPattern(double dt) {
        //cout << "X " << orthopos.x() << "  Y " << orthopos.y() << "  SLOPE " << slope << "  elev " << _pos.elev() * SG_METER_TO_FEET << '\n';
        
        _hdg = track + crab;
+       dclBoundHeading(_hdg);
        dist = vel * 0.514444 * dt;
        _pos = dclUpdatePosition(_pos, track, slope, dist);
 }
@@ -1206,10 +1189,11 @@ void FGAILocalTraffic::CalculateSoD(double base_leg_pos, double downwind_leg_pos
 
 void FGAILocalTraffic::TransmitPatternPositionReport(void) {
        // airport name + "traffic" + airplane callsign + pattern direction + pattern leg + rwy + ?
-       string trns = "";
+       string trns;
        int code = 0;
-       
-       trns += tower->get_name();
+       const string& apt_name = _controlled ? tower->get_name() : airportID;
+
+       trns += apt_name;
        trns += " Traffic ";
        trns += plane.callsign;
        if(patternDirection == 1) {
@@ -1248,10 +1232,10 @@ void FGAILocalTraffic::TransmitPatternPositionReport(void) {
        }
        trns += ConvertRwyNumToSpokenString(rwy.rwyID);
        
-       trns += " ";
+       trns += ' ';
        
        // And add the airport name again
-       trns += tower->get_name();
+       trns += apt_name;
        
        pending_transmission = trns;
        ConditionalTransmit(60.0, code);                // Assume a report of this leg will be invalid if we can't transmit within a minute.
@@ -1553,7 +1537,7 @@ void FGAILocalTraffic::DoGroundElev() {
 
   // FIXME: make shure the pos.lat/pos.lon values are in degrees ...
   double alt;
-  if (globals->get_scenery()->get_elevation_m(SGGeod::fromGeodM(_aip.getPosition(), 20000), alt, 0))
+  if (globals->get_scenery()->get_elevation_m(SGGeod::fromGeodM(_aip.getPosition(), 20000), alt, 0, _aip.getSceneGraph()))
     _ground_elevation_m = alt;
 }