]> git.mxchange.org Git - flightgear.git/commitdiff
Improved AI taxi behavior:
authorDurk Talsma <durktals@gmail.com>
Thu, 27 Oct 2011 21:24:56 +0000 (23:24 +0200)
committerDurk Talsma <durktals@gmail.com>
Thu, 27 Oct 2011 21:24:56 +0000 (23:24 +0200)
* Use aircraft specific time-stamps for blocking taxiways
* Issue a stop instruction well-ahead of moving onto a blocked taxiway. This still needs some more braking power.

src/Airports/groundnetwork.cxx
src/Airports/groundnetwork.hxx

index f4a49dff1c10f028b833348b946ef88ccf8435b2..f817e30351f6935370094579b5a87b42acc64f4c 100644 (file)
@@ -115,6 +115,44 @@ void FGTaxiSegment::setDimensions(double elevation)
 //        headingDiff = fabs(headingDiff - 360);
 //}
 
+void FGTaxiSegment::block(int id, time_t blockTime, time_t now)
+{
+    BlockListIterator i = blockTimes.begin();
+    while (i != blockTimes.end()) {
+        if (i->getId() == id) 
+            break;
+        i++;
+    }
+    if (i == blockTimes.end()) {
+        blockTimes.push_back(Block(id, blockTime, now));
+        sort(blockTimes.begin(), blockTimes.end());
+    } else {
+        i->updateTimeStamps(blockTime, now);
+    }
+}
+
+// The segment has a block if any of the block times listed in the block list is
+// smaller than the current time.
+bool FGTaxiSegment::hasBlock(time_t now)
+{
+    for (BlockListIterator i = blockTimes.begin(); i != blockTimes.end(); i++) {
+        if (i->getBlockTime() < now)
+            return true;
+    }
+    return false;
+}
+
+void FGTaxiSegment::unblock(time_t now)
+{
+    if (blockTimes.size()) {
+        BlockListIterator i = blockTimes.begin();
+        if (i->getTimeStamp() < (now - 30)) {
+            blockTimes.erase(i);
+        }
+    }
+}
+
+
 
 /***************************************************************************
  * FGTaxiRoute
@@ -713,7 +751,7 @@ bool FGGroundNetwork::checkTransmissionState(int minState, int maxState, Traffic
                 trans_num->setIntValue(-1);
                 // PopupCallback(n);
                 //cerr << "Selected transmission message " << n << endl;
-                FGATCManager *atc = (FGATCManager*) globals->get_subsystem("atc");
+                //FGATCManager *atc = (FGATCManager*) globals->get_subsystem("atc");
                 FGATCDialogNew::instance()->removeEntry(1);
             } else {
                 //cerr << "creating message for " << i->getAircraft()->getCallSign() << endl;
@@ -1026,85 +1064,29 @@ void FGGroundNetwork::checkHoldPosition(int id, double lat,
         } else {
             nx = tx;
         }
-        if (tx->hasBlock(now) || nx->hasBlock(now) ) {
-            current->setHoldPosition(true);
-        }
-    }
-
-
-    /*    for (i = activeTraffic.begin(); i != activeTraffic.end(); i++) {
-            if (i->getId() != current->getId()) {
-                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;
-
-                    SGGeod other(SGGeod::
-                                 fromDegM(i->getLongitude(), i->getLatitude(),
-                                          i->getAltitude()));
-                    bool needsToWait;
-                    bool opposing;
-                    if (current->isOpposing(this, *i, node)) {
-                        needsToWait = true;
-                        opposing = true;
-                        //cerr << "Hold check 2 : " << node << "  has opposing segment " << endl;
-                        // issue a "Hold Position" as soon as we're close to the offending node
-                        // For now, I'm doing this as long as the other aircraft doesn't
-                        // have a hold instruction as soon as we're within a reasonable
-                        // distance from the offending node.
-                        // This may be a bit of a conservative estimate though, as it may
-                        // be well possible that both aircraft can both continue to taxi
-                        // without crashing into each other.
-                    } else {
-                        opposing = false;
-                        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 "
-                            //           << endl;
-                        } else {
-                            needsToWait = true;
-                            //cerr << "Hold check 4: " << id << "  Would need to wait for other aircraft : distance = " << dist << " meters" << endl;
-                        }
-                    }
+        //if (tx->hasBlock(now) || nx->hasBlock(now) ) {
+        //   current->setHoldPosition(true);
+        //}
+        SGGeod start(SGGeod::fromDeg((i->getLongitude()), (i->getLatitude())));
+        SGGeod end  (SGGeod::fromDeg(nx->getStart()->getLongitude(), nx->getStart()->getLatitude()));
 
-                    double dist =
-                        SGGeodesy::distanceM(curr, taxiNode->getGeod());
-                    if (!(i->hasHoldPosition())) {
-
-                        if ((dist < 200) && //2.5*current->getRadius()) &&
-                            (needsToWait) && (i->onRoute(this, *current)) &&
-                            //((i->onRoute(this, *current)) || ((!(i->getSpeedAdjustment())))) &&
-                            (!(current->getId() == i->getWaitsForId())))
-                            //(!(i->getSpeedAdjustment()))) // &&
-                            //(!(current->getSpeedAdjustment())))
-
-                        {
-                            if (!(isUserAircraft(i->getAircraft()))) { // test code. Don't wait for the user, let the user wait for you.
-                                current->setHoldPosition(true);
-                                current->setWaitsForId(i->getId());
-                            }
-                            //cerr << "Hold check 5: " << current->getCallSign() <<"  Setting Hold Position: distance to node ("  << node << ") "
-                            //           << dist << " meters. Waiting for " << i->getCallSign();
-                            //if (opposing)
-                            //cerr <<" [opposing] " << endl;
-                            //else
-                            //        cerr << "[non-opposing] " << endl;
-                            //if (i->hasSpeefAdjustment())
-                            //        {
-                            //          cerr << " (which in turn waits for ) " << i->
-                        } else {
-                            //cerr << "Hold check 6: " << id << "  No need to hold yet: Distance to node : " << dist << " nm"<< endl;
-                        }
+        double distance = SGGeodesy::distanceM(start, end);
+        if (nx->hasBlock(now) && (distance < i->getRadius() * 4)) {
+            current->setHoldPosition(true);
+        } else {
+            intVecIterator ivi = i->getIntentions().begin();
+            while (ivi != i->getIntentions().end()) {
+                if ((*ivi) > 0) {
+                    distance += segments[(*ivi)-1]->getLength();
+                    if ((segments[(*ivi)-1]->hasBlock(now)) && (distance < i->getRadius() * 4)) {
+                        current->setHoldPosition(true);
+                        break;
                     }
                 }
+                ivi++;
             }
-        } */
+        } 
+    }
     bool currStatus = current->hasHoldPosition();
     current->setHoldPosition(origStatus);
     // Either a Hold Position or a resume taxi transmission has been issued
@@ -1552,7 +1534,7 @@ void FGGroundNetwork::update(double dt)
                         for (intVecIterator k = i->getIntentions().begin(); k != i->getIntentions().end(); k++) {
                             if ((*k) == posReverse) {
                                 i->denyPushBack();
-                                segments[posReverse-1]->block(now);
+                                segments[posReverse-1]->block(i->getId(), now, now);
                             }
                         }
                     }
@@ -1568,7 +1550,7 @@ void FGGroundNetwork::update(double dt)
                     length = seg->getLength();
                     for (FGTaxiSegmentVectorIterator tsi = segments.begin(); tsi != segments.end(); tsi++) {
                         if (((*tsi)->getEnd() == node) && ((*tsi) != seg)) {
-                            (*tsi)->block(now);
+                            (*tsi)->block(i->getId(), now, now);
                         }
                     }
                 }
@@ -1581,7 +1563,7 @@ void FGGroundNetwork::update(double dt)
                         time_t blockTime = now + (length / vTaxi);
                         for (FGTaxiSegmentVectorIterator tsi = segments.begin(); tsi != segments.end(); tsi++) {
                             if (((*tsi)->getEnd() == node) && ((*tsi) != seg)) {
-                                (*tsi)->block(blockTime-30);
+                                (*tsi)->block(i->getId(), blockTime-30, now);
                             }
                         }
                     }
@@ -1619,7 +1601,7 @@ void FGGroundNetwork::update(double dt)
                 for (FGTaxiSegmentVectorIterator tsi = segments.begin(); tsi != segments.end(); tsi++) {
                     if (((*tsi)->getEnd() == node) && ((*tsi) != seg)) {
                         time_t blockTime = now + (length / vTaxi);
-                        (*tsi)->block(blockTime - 30);
+                        (*tsi)->block(i->getId(), blockTime - 30, now);
                     }
                 }
             }
index 0f1eefc077c6091aabc24aa6cb12e5a49482f79c..78f1282d6d1b35ba298519e43afd404c32fb5f80 100644 (file)
 
 #include <string>
 #include <vector>
+#include <list>
 
+class Block;
 using std::string;
 using std::vector;
+using std::list;
 
 #include "gnnode.hxx"
 #include "parking.hxx"
@@ -54,6 +57,25 @@ typedef vector<FGTaxiSegment*>::iterator FGTaxiSegmentVectorIterator;
 //typedef vector<FGTaxiSegment*> FGTaxiSegmentPointerVector;
 //typedef vector<FGTaxiSegment*>::iterator FGTaxiSegmentPointerVectorIterator;
 
+class Block
+{
+private:
+    int id;
+    time_t blocktime;
+    time_t touch;
+public:
+    Block(int i, time_t bt, time_t curr) { id = i; blocktime= bt; touch = curr; };
+    ~Block() {};
+    int getId() { return id; };
+    void updateTimeStamps(time_t bt, time_t now) { blocktime = (bt < blocktime) ? bt : blocktime; touch = now; };
+    const time_t getBlockTime() const { return blocktime; };
+    time_t getTimeStamp() { return touch; };
+    bool operator< (const Block &other) const { return blocktime < other.blocktime; };
+};
+
+typedef vector<Block> BlockList;
+typedef BlockList::iterator BlockListIterator;
+
 /***************************************************************************************
  * class FGTaxiSegment
  **************************************************************************************/
@@ -67,7 +89,7 @@ private:
     SGGeod center;
     bool isActive;
     bool isPushBackRoute;
-    time_t isBlocked;
+    BlockList blockTimes;
     FGTaxiNode *start;
     FGTaxiNode *end;
     int index;
@@ -83,7 +105,6 @@ public:
             heading(0),
             isActive(0),
             isPushBackRoute(0),
-            isBlocked(0),
             start(0),
             end(0),
             index(0),
@@ -99,7 +120,7 @@ public:
             center            (other.center),
             isActive          (other.isActive),
             isPushBackRoute   (other.isPushBackRoute),
-            isBlocked         (other.isBlocked),
+            blockTimes        (other.blockTimes),
             start             (other.start),
             end               (other.end),
             index             (other.index),
@@ -116,7 +137,7 @@ public:
         center             = other.center;
         isActive           = other.isActive;
         isPushBackRoute    = other.isPushBackRoute;
-        isBlocked          = other.isBlocked;
+        blockTimes         = other.blockTimes;
         start              = other.start;
         end                = other.end;
         index              = other.index;
@@ -144,22 +165,9 @@ public:
         isPushBackRoute = val;
     };
     void setDimensions(double elevation);
-    void block(time_t time) {
-        if (isBlocked) {
-            if (time < isBlocked) {
-                isBlocked = time;
-            }
-        } else {
-            isBlocked = time;
-        }
-    }
-    void unblock(time_t now) {
-        if ((now - isBlocked) > 60)
-            isBlocked = 0;
-    };
-    bool hasBlock(time_t now) {
-        return isBlocked ? (isBlocked < now) : 0;
-    };
+    void block(int id, time_t blockTime, time_t now);
+    void unblock(time_t now); 
+    bool hasBlock(time_t now);
 
     FGTaxiNode * getEnd() {
         return end;