]> git.mxchange.org Git - flightgear.git/blobdiff - src/Airports/groundnetwork.cxx
Land the GPS/route-manager re-write. Many things are better, many other things will...
[flightgear.git] / src / Airports / groundnetwork.cxx
index 99c9d9cd39ee00210caacc43bd9d5c978c4d527b..8bdd947fc5ce4243123f2651c85b8546062d8837 100644 (file)
 #include <math.h>
 #include <algorithm>
 
-//#include <plib/sg.h>
-//#include <plib/ul.h>
-
-//#include <Environment/environment_mgr.hxx>
-//#include <Environment/environment.hxx>
-//#include <simgear/misc/sg_path.hxx>
-//#include <simgear/props/props.hxx>
-//#include <simgear/structure/subsystem_mgr.hxx>
 #include <simgear/debug/logstream.hxx>
 #include <simgear/route/waypoint.hxx>
-//#include <Main/globals.hxx>
-//#include <Main/fg_props.hxx>
-//#include <Airports/runways.hxx>
 
-#include <AIModel/AIFlightPlan.hxx>
+#include <Airports/dynamics.hxx>
 
-//#include STL_STRING
+#include <AIModel/AIFlightPlan.hxx>
 
 #include "groundnetwork.hxx"
 
@@ -90,14 +79,7 @@ void FGTaxiSegment::setEnd(FGTaxiNodeVector *nodes)
 // doing this.
 void FGTaxiSegment::setTrackDistance()
 {
-  //double course;
-  SGWayPoint first  (start->getLongitude(),
-                    start->getLatitude(),
-                    0);
-  SGWayPoint second (end->getLongitude(),
-                    end->getLatitude(),
-                    0);
-  first.CourseAndDistance(second, &course, &length);
+  length = SGGeodesy::distanceM(start->getGeod(), end->getGeod());
 }
 
 
@@ -285,11 +267,11 @@ void FGGroundNetwork::init()
       {
        if ((*j)->getEnd()->getIndex() == (*i)->getStart()->getIndex())
          {
-           int start1 = (*i)->getStart()->getIndex();
-           int end1   = (*i)->getEnd()  ->getIndex();
-           int start2 = (*j)->getStart()->getIndex();
-           int end2   = (*j)->getEnd()->getIndex();
-           int oppIndex = (*j)->getIndex();
+//         int start1 = (*i)->getStart()->getIndex();
+//         int end1   = (*i)->getEnd()  ->getIndex();
+//         int start2 = (*j)->getStart()->getIndex();
+//         int end2   = (*j)->getEnd()->getIndex();
+//         int oppIndex = (*j)->getIndex();
            //cerr << "Opposite of  " << (*i)->getIndex() << " (" << start1 << "," << end1 << ") "
            //   << "happens to be " << oppIndex      << " (" << start2 << "," << end2 << ") " << endl;
            (*i)->setOpposite(*j);
@@ -310,37 +292,31 @@ void FGGroundNetwork::init()
   //exit(1);
 }
 
-
-
-int FGGroundNetwork::findNearestNode(double lat, double lon)
+int FGGroundNetwork::findNearestNode(const SGGeod& aGeod)
 {
   double minDist = HUGE_VAL;
-  double dist;
-  int index;
-  SGWayPoint first  (lon,
-                    lat,
-                    0);
+  int index = -1;
   
-  for (FGTaxiNodeVectorIterator 
-        itr = nodes.begin();
-       itr != nodes.end(); itr++)
+  for (FGTaxiNodeVectorIterator itr = nodes.begin(); itr != nodes.end(); itr++)
+  {
+    double d = SGGeodesy::distanceM(aGeod, (*itr)->getGeod());
+    if (d < minDist)
     {
-      double course;
-      SGWayPoint second ((*itr)->getLongitude(),
-                        (*itr)->getLatitude(),
-                        0);
-      first.CourseAndDistance(second, &course, &dist);
-      if (dist < minDist)
-       {
-         minDist = dist;
-         index = (*itr)->getIndex();
-         //cerr << "Minimum distance of " << minDist << " for index " << index << endl;
-       }
+      minDist = d;
+      index = (*itr)->getIndex();
+      //cerr << "Minimum distance of " << minDist << " for index " << index << endl;
     }
+  }
+  
   return index;
 }
 
-FGTaxiNode *FGGroundNetwork::findNode(int idx)
+int FGGroundNetwork::findNearestNode(double lat, double lon)
+{
+  return findNearestNode(SGGeod::fromDeg(lon, lat));
+}
+
+FGTaxiNode *FGGroundNetwork::findNode(unsigned idx)
 { /*
     for (FGTaxiNodeVectorIterator 
     itr = nodes.begin();
@@ -356,7 +332,7 @@ FGTaxiNode *FGGroundNetwork::findNode(int idx)
     return 0;
 }
 
-FGTaxiSegment *FGGroundNetwork::findSegment(int idx)
+FGTaxiSegment *FGGroundNetwork::findSegment(unsigned idx)
 {/*
   for (FGTaxiSegmentVectorIterator 
         itr = segments.begin();
@@ -476,189 +452,12 @@ int FGTaxiSegment::getPenalty(int nGates) {
      return penalty;
 }
 
-// void FGGroundNetwork::trace(FGTaxiNode *currNode, int end, int depth, double distance)
-// {
-//   // Just check some preconditions of the trace algorithm
-//   if (nodesStack.size() != routesStack.size()) 
-//     {
-//       SG_LOG(SG_GENERAL, SG_ALERT, "size of nodesStack and routesStack is not equal. NodesStack :" 
-//          << nodesStack.size() << ". RoutesStack : " << routesStack.size());
-//     }
-//   nodesStack.push_back(currNode->getIndex());
-//   totalDistance += distance;
-//   //cerr << "Starting trace " << currNode->getIndex() << " " << "total distance: " << totalDistance << endl;
-//   //     << currNode->getIndex() << endl;
-// 
-//   // If the current route matches the required end point we found a valid route
-//   // So we can add this to the routing table
-//   if (currNode->getIndex() == end)
-//     {
-//       maxDepth = depth;
-//       //cerr << "Found route : " <<  totalDistance << "" << " " << *(nodesStack.end()-1) << " Depth = " << depth << endl;
-//       routes.push_back(FGTaxiRoute(nodesStack,routesStack,totalDistance, depth));
-//       if (nodesStack.empty() || routesStack.empty())
-//     {
-//       printRoutingError(string("while finishing route"));
-//     }
-//       nodesStack.pop_back();
-//       routesStack.pop_back();
-//       if (!(foundRoute)) {
-//     maxDistance = totalDistance;
-//       }
-//       else
-//     if (totalDistance < maxDistance)
-//       maxDistance = totalDistance;
-//       foundRoute = true;
-//       totalDistance -= distance;
-//       return;
-//     }
-//  
-// 
-//   // search if the currentNode has been encountered before
-//   // if so, we should step back one level, because it is
-//   // rather rediculous to proceed further from here. 
-//   // if the current node has not been encountered before,
-//   // i should point to nodesStack.end()-1; and we can continue
-//   // if i is not nodesStack.end, the previous node was found, 
-//   // and we should return. 
-//   // This only works at trace levels of 1 or higher though
-//   if (depth > 0) {
-//     intVecIterator i = nodesStack.begin();
-//     while ((*i) != currNode->getIndex()) {
-//       //cerr << "Route so far : " << (*i) << endl;
-//       i++;
-//     }
-//     if (i != nodesStack.end()-1) {
-//       if (nodesStack.empty() || routesStack.empty())
-//     {
-//       printRoutingError(string("while returning from an already encountered node"));
-//     }
-//       nodesStack.pop_back();
-//       routesStack.pop_back();
-//       totalDistance -= distance;
-//       return;
-//     }
-//     if (depth >= maxDepth) {
-//       count++;
-//       if (!(count % 100000)) {
-//     maxDepth--; // Gradually decrease maxdepth, to prevent "eternal searches"
-//     //cerr << "Reducing maxdepth to " << maxDepth << endl;
-//       }
-//       nodesStack.pop_back();
-//       routesStack.pop_back();
-//       totalDistance -= distance;
-//       return;
-//     }
-//     // If the total distance from start to the current waypoint
-//     // is longer than that of a route we can also stop this trace 
-//     // and go back one level. 
-//     if ((totalDistance > maxDistance) && foundRoute)
-//       //if (foundRoute)
-//       {
-//     //cerr << "Stopping rediculously long trace: " << totalDistance << endl;
-//     if (nodesStack.empty() || routesStack.empty())
-//     {
-//       printRoutingError(string("while returning from finding a rediculously long route"));
-//     }
-//     nodesStack.pop_back();
-//     routesStack.pop_back();
-//     totalDistance -= distance;
-//     return;
-//       }
-//   }
-/*  
-  //cerr << "2" << endl;
-  if (currNode->getBeginRoute() != currNode->getEndRoute())
-    {
-      double course, length;
-      //cerr << "3" << endl;
-      // calculate distance and heading "as the crow flies" between starn and end points"
-      SGWayPoint first(currNode->getLongitude(),
-                      currNode->getLatitude(),
-                      0);
-      //SGWayPoint second (lastNode->getLongitude(),
-      //                lastNode->getLatitude(),
-      //                    0);
-  
-      first.CourseAndDistance(destination, &course, &length);
-      //for (FGTaxiSegmentVectorIterator 
-      //            itr = segments.begin();
-      //          itr != segments.end(); itr++)
-      //       {
-      //         (*itr)->setCourseDiff(course);
-      //       } 
-      //FGTaxiNodeVectorIterator nde = nodes.begin();
-      //while (nde != nodes.end()) {
-      //(*nde)->sortEndSegments();
-      //nde++;
-      
-      for (FGTaxiSegmentVectorIterator 
-            i = currNode->getBeginRoute();
-          i != currNode->getEndRoute();
-          i++)
-       {
-         (*i)->setCourseDiff(course);
-       }
-      currNode->sortEndSegments(foundRoute);
-      for (FGTaxiSegmentVectorIterator 
-            i = currNode->getBeginRoute();
-          i != currNode->getEndRoute();
-          i++)
-       {
-         //cerr << (*i)->getLength() << endl;
-         //cerr << (*i)->getIndex() << endl;
-         int idx = (*i)->getIndex();
-         routesStack.push_back((*i)->getIndex());
-         trace((*i)->getEnd(), end, depth+1, (*i)->getLength());
-       //  {
-       //      // cerr << currNode -> getIndex() << " ";
-       //      route.push_back(currNode->getIndex());
-       //      return true;
-       //    }
-       }
-    }
-  else
-    {
-      //SG_LOG( SG_GENERAL, SG_DEBUG, "4" );
-    }
-  if (nodesStack.empty())
-    {
-      printRoutingError(string("while finishing trace"));
-    }
-  nodesStack.pop_back();
-  // Make sure not to dump the level-zero routesStack entry, because that was never created.
-  if (depth)
-    {
-      routesStack.pop_back();
-      //cerr << "leaving trace " << routesStack.size() << endl;
-    }
-  totalDistance -= distance;
-  return;
-}*/
-/*
-void FGGroundNetwork::printRoutingError(string mess)
-{
-  SG_LOG(SG_GENERAL, SG_ALERT,  "Error in ground network trace algorithm " << mess);
-  if (nodesStack.empty())
-    {
-      SG_LOG(SG_GENERAL, SG_ALERT, " nodesStack is empty. Dumping routesStack");
-      for (intVecIterator i = routesStack.begin() ; i != routesStack.end(); i++)
-       SG_LOG(SG_GENERAL, SG_ALERT, "Route " << (*i));
-    }
-  if (routesStack.empty())
-    {
-      SG_LOG(SG_GENERAL, SG_ALERT, " routesStack is empty. Dumping nodesStack"); 
-      for (intVecIterator i = nodesStack.begin() ; i != nodesStack.end(); i++)
-       SG_LOG(SG_GENERAL, SG_ALERT, "Node " << (*i));
-    }
-  //exit(1);
-}
-*/
+/* ATC Related Functions */
 
 void FGGroundNetwork::announcePosition(int id, FGAIFlightPlan *intendedRoute, int currentPosition,
                                       double lat, double lon, double heading, 
                                       double speed, double alt, double radius, int leg,
-                                      string callsign)
+                                      FGAIAircraft *aircraft)
 {
    TrafficVectorIterator i = activeTraffic.begin();
    // Search search if the current id alread has an entry
@@ -679,7 +478,7 @@ void FGGroundNetwork::announcePosition(int id, FGAIFlightPlan *intendedRoute, in
      rec.setPositionAndIntentions(currentPosition, intendedRoute);
      rec.setPositionAndHeading(lat, lon, heading, speed, alt);
      rec.setRadius(radius); // only need to do this when creating the record.
-     rec.setCallSign(callsign);
+     rec.setAircraft(aircraft);
      activeTraffic.push_back(rec);
    } else {
      i->setPositionAndIntentions(currentPosition, intendedRoute); 
@@ -791,27 +590,24 @@ void FGGroundNetwork::checkSpeedAdjustment(int id, double lat,
   //closest = current;
   
   previousInstruction = current->getSpeedAdjustment();
-  double mindist = HUGE;
+  double mindist = HUGE_VAL;
   if (activeTraffic.size()) 
     {
-      double course, dist, bearing, minbearing;
-      SGWayPoint curr  (lon,
-                       lat,
-                       alt);
+      double course, dist, bearing, minbearing, az2;
+      SGGeod curr(SGGeod::fromDegM(lon, lat, alt));
       //TrafficVector iterator closest;
       closest = current;
       for (TrafficVectorIterator i = activeTraffic.begin(); 
           i != activeTraffic.end(); i++)
        {
-         if (i != current) {
-           //SGWayPoint curr  (lon,
-           //        lat,
-           //        alt);
-           SGWayPoint other    (i->getLongitude  (),
-                                i->getLatitude (),
-                                i->getAltitude  ());
-           other.CourseAndDistance(curr, &course, &dist);
-           bearing = fabs(heading-course);
+         if (i == current) {
+        continue;
+      }
+      
+        SGGeod other(SGGeod::fromDegM(i->getLongitude(),
+          i->getLatitude(), i->getAltitude()));
+        SGGeodesy::inverse(curr, other, course, az2, dist);
+        bearing = fabs(heading-course);
            if (bearing > 180)
              bearing = 360-bearing;
            if ((dist < mindist) && (bearing < 60.0))
@@ -820,7 +616,6 @@ void FGGroundNetwork::checkSpeedAdjustment(int id, double lat,
                closest = i;
                minbearing = bearing;
              }
-         }
        }
       //Check traffic at the tower controller
       if (towerController->hasActiveTraffic())
@@ -829,16 +624,12 @@ void FGGroundNetwork::checkSpeedAdjustment(int id, double lat,
               i != towerController->getActiveTraffic().end(); i++)
            {
              //cerr << "Comparing " << current->getId() << " and " << i->getId() << endl;
-             //SGWayPoint curr  (lon,
-             //                  lat,
-             //                  alt);
-             SGWayPoint other    (i->getLongitude  (),
-                                  i->getLatitude (),
-                                  i->getAltitude  ());
-             other.CourseAndDistance(curr, &course, &dist);
-             bearing = fabs(heading-course);
+             SGGeod other(SGGeod::fromDegM(i->getLongitude(),
+          i->getLatitude(), i->getAltitude()));
+        SGGeodesy::inverse(curr, other, course, az2, dist);
+        bearing = fabs(heading-course);
              if (bearing > 180)
-               bearing = 360-bearing;
+          bearing = 360-bearing;
              if ((dist < mindist) && (bearing < 60.0))
                {
                  mindist = dist;
@@ -851,10 +642,9 @@ void FGGroundNetwork::checkSpeedAdjustment(int id, double lat,
       // Finally, check UserPosition
       double userLatitude  = fgGetDouble("/position/latitude-deg");
       double userLongitude = fgGetDouble("/position/longitude-deg");
-      SGWayPoint user    (userLongitude,
-                         userLatitude,
-                         alt); // Alt is not really important here. 
-      user.CourseAndDistance(curr, &course, &dist);
+      SGGeod user(SGGeod::fromDeg(userLatitude,userLongitude));
+      SGGeodesy::inverse(user, curr, course, az2, dist);
+      
       bearing = fabs(heading-course);
       if (bearing > 180)
        bearing = 360-bearing;
@@ -935,10 +725,8 @@ void FGGroundNetwork::checkHoldPosition(int id, double lat,
   }
   current = i;
   current->setHoldPosition(false);
-  SGWayPoint curr  (lon,
-                   lat,
-                   alt);
-  double course, dist, bearing, minbearing;
+  SGGeod curr(SGGeod::fromDegM(lon, lat, alt));
+  
   for (i = activeTraffic.begin(); 
        i != activeTraffic.end(); i++)
     {
@@ -947,20 +735,16 @@ void FGGroundNetwork::checkHoldPosition(int id, double lat,
          int node = current->crosses(this, *i);
          if (node != -1)
            {
+          FGTaxiNode* taxiNode = findNode(node);
+          
              // Determine whether it's save to continue or not. 
              // If we have a crossing route, there are two possibilities:
              // 1) This is an interestion
              // 2) This is oncoming two-way traffic, using the same taxiway.
              //cerr << "Hold check 1 : " << id << " has common node " << node << endl;
-             SGWayPoint nodePos(findNode(node)->getLongitude  (),
-                                findNode(node)->getLatitude   (),
-                                alt);
-
-             SGWayPoint other    (i->getLongitude  (),
-                                  i->getLatitude (),
-                                  i->getAltitude  ());
-             //other.CourseAndDistance(curr, &course, &dist);
-             bool needsToWait;
+            
+        SGGeod other(SGGeod::fromDegM(i->getLongitude(), i->getLatitude(), i->getAltitude()));
+        bool needsToWait;
              bool opposing;
              if (current->isOpposing(this, *i, node))
                {
@@ -978,8 +762,7 @@ void FGGroundNetwork::checkHoldPosition(int id, double lat,
              else 
                {
                  opposing = false;
-                 other.CourseAndDistance(nodePos, &course, &dist);
-                 if (dist > 200) // 2.0*i->getRadius())
+                 if (SGGeodesy::distanceM(other, taxiNode->getGeod()) > 200) // 2.0*i->getRadius())
                    {
                      needsToWait = false; 
                      //cerr << "Hold check 3 : " << id <<"  Other aircraft approaching node is still far away. (" << dist << " nm). Can safely continue " 
@@ -991,8 +774,9 @@ void FGGroundNetwork::checkHoldPosition(int id, double lat,
                      //cerr << "Hold check 4: " << id << "  Would need to wait for other aircraft : distance = " << dist << " meters" << endl;
                    }
                }
-             curr.CourseAndDistance(nodePos, &course, &dist);
-             if (!(i->hasHoldPosition()))
+      
+      double dist = SGGeodesy::distanceM(curr, taxiNode->getGeod());
+      if (!(i->hasHoldPosition()))
                {
                  
                  if ((dist < 200) && //2.5*current->getRadius()) &&