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:
parent
8eca759077
commit
7ae1aa4846
2 changed files with 90 additions and 100 deletions
|
@ -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) ) {
|
||||
//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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* 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;
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
} 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -35,9 +35,12 @@
|
|||
|
||||
#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;
|
||||
|
|
Loading…
Reference in a new issue