1
0
Fork 0

Improved AI taxi behavior:

* 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.
This commit is contained in:
Durk Talsma 2011-10-27 23:24:56 +02:00
parent 8eca759077
commit 7ae1aa4846
2 changed files with 90 additions and 100 deletions

View file

@ -115,6 +115,44 @@ void FGTaxiSegment::setDimensions(double elevation)
// headingDiff = fabs(headingDiff - 360); // 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 * FGTaxiRoute
@ -713,7 +751,7 @@ bool FGGroundNetwork::checkTransmissionState(int minState, int maxState, Traffic
trans_num->setIntValue(-1); trans_num->setIntValue(-1);
// PopupCallback(n); // PopupCallback(n);
//cerr << "Selected transmission message " << n << endl; //cerr << "Selected transmission message " << n << endl;
FGATCManager *atc = (FGATCManager*) globals->get_subsystem("atc"); //FGATCManager *atc = (FGATCManager*) globals->get_subsystem("atc");
FGATCDialogNew::instance()->removeEntry(1); FGATCDialogNew::instance()->removeEntry(1);
} else { } else {
//cerr << "creating message for " << i->getAircraft()->getCallSign() << endl; //cerr << "creating message for " << i->getAircraft()->getCallSign() << endl;
@ -1026,85 +1064,29 @@ void FGGroundNetwork::checkHoldPosition(int id, double lat,
} else { } else {
nx = tx; nx = tx;
} }
if (tx->hasBlock(now) || nx->hasBlock(now) ) { //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 distance = SGGeodesy::distanceM(start, end);
if (nx->hasBlock(now) && (distance < i->getRadius() * 4)) {
current->setHoldPosition(true); current->setHoldPosition(true);
} } else {
} intVecIterator ivi = i->getIntentions().begin();
while (ivi != i->getIntentions().end()) {
if ((*ivi) > 0) {
/* for (i = activeTraffic.begin(); i != activeTraffic.end(); i++) { distance += segments[(*ivi)-1]->getLength();
if (i->getId() != current->getId()) { if ((segments[(*ivi)-1]->hasBlock(now)) && (distance < i->getRadius() * 4)) {
int node = current->crosses(this, *i); current->setHoldPosition(true);
if (node != -1) { break;
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;
}
}
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;
}
} }
} }
ivi++;
} }
} */ }
}
bool currStatus = current->hasHoldPosition(); bool currStatus = current->hasHoldPosition();
current->setHoldPosition(origStatus); current->setHoldPosition(origStatus);
// Either a Hold Position or a resume taxi transmission has been issued // 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++) { for (intVecIterator k = i->getIntentions().begin(); k != i->getIntentions().end(); k++) {
if ((*k) == posReverse) { if ((*k) == posReverse) {
i->denyPushBack(); 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(); length = seg->getLength();
for (FGTaxiSegmentVectorIterator tsi = segments.begin(); tsi != segments.end(); tsi++) { for (FGTaxiSegmentVectorIterator tsi = segments.begin(); tsi != segments.end(); tsi++) {
if (((*tsi)->getEnd() == node) && ((*tsi) != seg)) { 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); time_t blockTime = now + (length / vTaxi);
for (FGTaxiSegmentVectorIterator tsi = segments.begin(); tsi != segments.end(); tsi++) { for (FGTaxiSegmentVectorIterator tsi = segments.begin(); tsi != segments.end(); tsi++) {
if (((*tsi)->getEnd() == node) && ((*tsi) != seg)) { 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++) { for (FGTaxiSegmentVectorIterator tsi = segments.begin(); tsi != segments.end(); tsi++) {
if (((*tsi)->getEnd() == node) && ((*tsi) != seg)) { if (((*tsi)->getEnd() == node) && ((*tsi) != seg)) {
time_t blockTime = now + (length / vTaxi); time_t blockTime = now + (length / vTaxi);
(*tsi)->block(blockTime - 30); (*tsi)->block(i->getId(), blockTime - 30, now);
} }
} }
} }

View file

@ -35,9 +35,12 @@
#include <string> #include <string>
#include <vector> #include <vector>
#include <list>
class Block;
using std::string; using std::string;
using std::vector; using std::vector;
using std::list;
#include "gnnode.hxx" #include "gnnode.hxx"
#include "parking.hxx" #include "parking.hxx"
@ -54,6 +57,25 @@ typedef vector<FGTaxiSegment*>::iterator FGTaxiSegmentVectorIterator;
//typedef vector<FGTaxiSegment*> FGTaxiSegmentPointerVector; //typedef vector<FGTaxiSegment*> FGTaxiSegmentPointerVector;
//typedef vector<FGTaxiSegment*>::iterator FGTaxiSegmentPointerVectorIterator; //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 * class FGTaxiSegment
**************************************************************************************/ **************************************************************************************/
@ -67,7 +89,7 @@ private:
SGGeod center; SGGeod center;
bool isActive; bool isActive;
bool isPushBackRoute; bool isPushBackRoute;
time_t isBlocked; BlockList blockTimes;
FGTaxiNode *start; FGTaxiNode *start;
FGTaxiNode *end; FGTaxiNode *end;
int index; int index;
@ -83,7 +105,6 @@ public:
heading(0), heading(0),
isActive(0), isActive(0),
isPushBackRoute(0), isPushBackRoute(0),
isBlocked(0),
start(0), start(0),
end(0), end(0),
index(0), index(0),
@ -99,7 +120,7 @@ public:
center (other.center), center (other.center),
isActive (other.isActive), isActive (other.isActive),
isPushBackRoute (other.isPushBackRoute), isPushBackRoute (other.isPushBackRoute),
isBlocked (other.isBlocked), blockTimes (other.blockTimes),
start (other.start), start (other.start),
end (other.end), end (other.end),
index (other.index), index (other.index),
@ -116,7 +137,7 @@ public:
center = other.center; center = other.center;
isActive = other.isActive; isActive = other.isActive;
isPushBackRoute = other.isPushBackRoute; isPushBackRoute = other.isPushBackRoute;
isBlocked = other.isBlocked; blockTimes = other.blockTimes;
start = other.start; start = other.start;
end = other.end; end = other.end;
index = other.index; index = other.index;
@ -144,22 +165,9 @@ public:
isPushBackRoute = val; isPushBackRoute = val;
}; };
void setDimensions(double elevation); void setDimensions(double elevation);
void block(time_t time) { void block(int id, time_t blockTime, time_t now);
if (isBlocked) { void unblock(time_t now);
if (time < isBlocked) { bool hasBlock(time_t now);
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;
};
FGTaxiNode * getEnd() { FGTaxiNode * getEnd() {
return end; return end;