1
0
Fork 0

#2358 AI Aircraft not taking off

This commit is contained in:
portree_kid 2022-11-20 21:55:25 +01:00
parent 9b4bd6fdcb
commit b8d173c3e4
9 changed files with 195 additions and 74 deletions

View file

@ -102,7 +102,7 @@ FGAIAircraft::FGAIAircraft(FGAISchedule* ref) : /* HOT must be disabled for AI A
_performance = PerformanceData::getDefaultData(); _performance = PerformanceData::getDefaultData();
} }
takeOffStatus = 0; takeOffStatus = AITakeOffStatus::NONE;
timeElapsed = 0; timeElapsed = 0;
trackCache.remainingLength = 0; trackCache.remainingLength = 0;
@ -195,7 +195,7 @@ void FGAIAircraft::setPerformance(const std::string& acType, const std::string&
} }
} }
void FGAIAircraft::Run(double dt) void FGAIAircraft::Run(double dt)
{ {
// We currently have one situation in which an AIAircraft object is used that is not attached to the // We currently have one situation in which an AIAircraft object is used that is not attached to the
// AI manager. In this particular case, the AIAircraft is used to shadow the user's aircraft's behavior in the AI world. // AI manager. In this particular case, the AIAircraft is used to shadow the user's aircraft's behavior in the AI world.
@ -213,6 +213,8 @@ void FGAIAircraft::setPerformance(const std::string& acType, const std::string&
if (outOfSight) { if (outOfSight) {
return; return;
} }
} else {
updateUserFlightPlan(dt);
} }
if (!flightplanActive) { if (!flightplanActive) {
@ -1047,7 +1049,7 @@ bool FGAIAircraft::handleAirportEndPoints(FGAIWaypoint* prev, time_t now) {
scheduleForATCTowerDepartureControl(1); scheduleForATCTowerDepartureControl(1);
} }
if (prev->contains(string("Accel"))) { if (prev->contains(string("Accel"))) {
takeOffStatus = 3; takeOffStatus = AITakeOffStatus::CLEARED_FOR_TAKEOFF;
} }
// This is the last taxi waypoint, and marks the the end of the flight plan // This is the last taxi waypoint, and marks the the end of the flight plan
@ -1405,6 +1407,42 @@ void FGAIAircraft::handleATCRequests(double dt)
} }
} }
void FGAIAircraft::updateUserFlightPlan(double dt)
{
// If the aircraft leaves the airport proximity increase the flightplan leg to sign off
// from the tower controller and free the runway #2358 The user doesn't
// need to fly out straight
if (fp) {
switch (fp->getLeg())
{
case AILeg::TAKEOFF:
{
auto current = fp->getCurrentWaypoint();
auto last = fp->getLastWaypoint();
int legDistance = SGGeodesy::distanceM(current->getPos(), last->getPos());
int currDist = SGGeodesy::distanceM(getGeodPos(), current->getPos());
int lastDist = SGGeodesy::distanceM(getGeodPos(), last->getPos());
SG_LOG(SG_ATC, SG_BULK, "Signing off from Tower "
<< "\t currDist\t" << currDist
<< "\t legDistance\t" << legDistance
<< "\t" << lastDist
<< "\t" << getGeodPos().getLatitudeDeg()
<< "\t" << getGeodPos().getLongitudeDeg()
<< "\t" << current->getPos().getLatitudeDeg()
<< "\t" << current->getPos().getLongitudeDeg());
if ( currDist>legDistance ) {
// We are definetly beyond the airport
fp->incrementLeg();
}
}
break;
default:
break;
}
//TODO
}
}
void FGAIAircraft::updateActualState(double dt) void FGAIAircraft::updateActualState(double dt)
{ {
//update current state //update current state

View file

@ -50,6 +50,17 @@ namespace AILeg
}; };
} }
// 1 = joined departure queue; 2 = Passed DepartureHold waypoint; handover control to tower; 0 = any other state.
namespace AITakeOffStatus
{
enum Type
{
NONE = 0,
QUEUED = 1, // joined departure queue
CLEARED_FOR_TAKEOFF = 2 // Passed DepartureHold waypoint; handover control to tower;
};
}
class FGAIAircraft : public FGAIBaseAircraft { class FGAIAircraft : public FGAIBaseAircraft {
public: public:
@ -106,7 +117,7 @@ public:
bool getTaxiClearanceRequest() { return needsTaxiClearance; }; bool getTaxiClearanceRequest() { return needsTaxiClearance; };
FGAISchedule * getTrafficRef() { return trafficRef; }; FGAISchedule * getTrafficRef() { return trafficRef; };
void setTrafficRef(FGAISchedule *ref) { trafficRef = ref; }; void setTrafficRef(FGAISchedule *ref) { trafficRef = ref; };
void resetTakeOffStatus() { takeOffStatus = 0;}; void resetTakeOffStatus() { takeOffStatus = AITakeOffStatus::NONE;};
void setTakeOffStatus(int status) { takeOffStatus = status; }; void setTakeOffStatus(int status) { takeOffStatus = status; };
int getTakeOffStatus() { return takeOffStatus; }; int getTakeOffStatus() { return takeOffStatus; };
void setTakeOffSlot(time_t timeSlot) { takeOffTimeSlot = timeSlot;}; void setTakeOffSlot(time_t timeSlot) { takeOffTimeSlot = timeSlot;};
@ -186,6 +197,8 @@ private:
void updatePitchAngleTarget(); void updatePitchAngleTarget();
void updateActualState(double dt); void updateActualState(double dt);
void updateModelProperties(double dt); void updateModelProperties(double dt);
/**Handle special cases for the User AI shadow*/
void updateUserFlightPlan(double dt);
void handleATCRequests(double dt); void handleATCRequests(double dt);

View file

@ -467,7 +467,6 @@ FGAIManager::getNumAiObjects() const
void void
FGAIManager::fetchUserState( double dt ) FGAIManager::fetchUserState( double dt )
{ {
globals->get_aircraft_orientation(user_heading, user_pitch, user_roll); globals->get_aircraft_orientation(user_heading, user_pitch, user_roll);
user_speed = user_speed_node->getDoubleValue() * 0.592484; user_speed = user_speed_node->getDoubleValue() * 0.592484;
wind_from_east = wind_from_east_node->getDoubleValue(); wind_from_east = wind_from_east_node->getDoubleValue();

View file

@ -35,6 +35,35 @@
#include <ATC/trafficcontrol.hxx> #include <ATC/trafficcontrol.hxx>
namespace ATCMessageState
{
enum Type
{
// 0 = Normal; no action required
NORMAL = 0,
// 1 = "Acknowledge "Hold position
ACK_HOLD = 1,
// 2 = "Acknowledge "Resume taxi".
ACK_RESUME_TAXI = 2,
// 3 = "Issue TaxiClearance"
TAXI_CLEARED = 3,
// 4 = Acknowledge Taxi Clearance"
ACK_TAXI_CLEARED = 4,
// 5 = Post acknowlegde taxiclearance: Start taxiing
START_TAXI = 5,
// 6 = Report runway
REPORT_RUNWAY = 6,
// 7 = Acknowledge report runway
ACK_REPORT_RUNWAY = 7,
// 8 = Switch tower frequency
SWITCH_TOWER = 8,
// 9 = Acknowledge switch tower frequency
ACK_SWITCH_TOWER = 9,
// 10 = Cleared for takeoff
CLEARED_TAKEOFF = 10,
};
}
/** /**
* class FGATCController * class FGATCController
* NOTE: this class serves as an abstraction layer for all sorts of ATC controllers. * NOTE: this class serves as an abstraction layer for all sorts of ATC controllers.

View file

@ -222,16 +222,16 @@ void FGGroundController::updateAircraftInformation(int id, SGGeod geod,
available = true; available = true;
} }
if (checkTransmissionState(0,2, current, now, MSG_REQUEST_TAXI_CLEARANCE, ATC_AIR_TO_GROUND)) { if (checkTransmissionState(0,2, current, now, MSG_REQUEST_TAXI_CLEARANCE, ATC_AIR_TO_GROUND)) {
current->setState(3); current->setState(ATCMessageState::TAXI_CLEARED);
} }
if (checkTransmissionState(3,3, current, now, MSG_ISSUE_TAXI_CLEARANCE, ATC_GROUND_TO_AIR)) { if (checkTransmissionState(3,3, current, now, MSG_ISSUE_TAXI_CLEARANCE, ATC_GROUND_TO_AIR)) {
current->setState(4); current->setState(ATCMessageState::ACK_TAXI_CLEARED);
} }
if (checkTransmissionState(4,4, current, now, MSG_ACKNOWLEDGE_TAXI_CLEARANCE, ATC_AIR_TO_GROUND)) { if (checkTransmissionState(4,4, current, now, MSG_ACKNOWLEDGE_TAXI_CLEARANCE, ATC_AIR_TO_GROUND)) {
current->setState(5); current->setState(ATCMessageState::START_TAXI);
} }
if ((state == 5) && available) { if ((state == 5) && available) {
current->setState(0); current->setState(ATCMessageState::NORMAL);
current->getAircraft()->setTaxiClearanceRequest(false); current->getAircraft()->setTaxiClearanceRequest(false);
current->setHoldPosition(false); current->setHoldPosition(false);
available = false; available = false;
@ -491,11 +491,11 @@ void FGGroundController::checkHoldPosition(int id, double lat,
if (currStatus == true) { // No has a hold short instruction if (currStatus == true) { // No has a hold short instruction
transmit(&(*current), parent, MSG_HOLD_POSITION, ATC_GROUND_TO_AIR, true); transmit(&(*current), parent, MSG_HOLD_POSITION, ATC_GROUND_TO_AIR, true);
SG_LOG(SG_ATC, SG_DEBUG, "Transmitting hold short instruction " << currStatus << " " << available); SG_LOG(SG_ATC, SG_DEBUG, "Transmitting hold short instruction " << currStatus << " " << available);
current->setState(1); current->setState(ATCMessageState::ACK_HOLD);
} else { } else {
transmit(&(*current), parent, MSG_RESUME_TAXI, ATC_GROUND_TO_AIR, true); transmit(&(*current), parent, MSG_RESUME_TAXI, ATC_GROUND_TO_AIR, true);
SG_LOG(SG_ATC, SG_DEBUG, "Transmitting resume instruction " << currStatus << " " << available); SG_LOG(SG_ATC, SG_DEBUG, "Transmitting resume instruction " << currStatus << " " << available);
current->setState(2); current->setState(ATCMessageState::ACK_RESUME_TAXI);
} }
lastTransmission = now; lastTransmission = now;
available = false; available = false;
@ -512,16 +512,16 @@ void FGGroundController::checkHoldPosition(int id, double lat,
//int state = current->getState(); //int state = current->getState();
if (checkTransmissionState(1,1, current, now, MSG_ACKNOWLEDGE_HOLD_POSITION, ATC_AIR_TO_GROUND)) { if (checkTransmissionState(1,1, current, now, MSG_ACKNOWLEDGE_HOLD_POSITION, ATC_AIR_TO_GROUND)) {
current->setState(0); current->setState(ATCMessageState::NORMAL);
current->setHoldPosition(true); current->setHoldPosition(true);
} }
if (checkTransmissionState(2,2, current, now, MSG_ACKNOWLEDGE_RESUME_TAXI, ATC_AIR_TO_GROUND)) { if (checkTransmissionState(2,2, current, now, MSG_ACKNOWLEDGE_RESUME_TAXI, ATC_AIR_TO_GROUND)) {
current->setState(0); current->setState(ATCMessageState::NORMAL);
current->setHoldPosition(false); current->setHoldPosition(false);
} }
if (current->getAircraft()->getTakeOffStatus() && (current->getState() == 0)) { if (current->getAircraft()->getTakeOffStatus() && (current->getState() == 0)) {
SG_LOG(SG_ATC, SG_DEBUG, "Scheduling " << current->getAircraft()->getCallSign() << " for hold short"); SG_LOG(SG_ATC, SG_DEBUG, "Scheduling " << current->getAircraft()->getCallSign() << " for hold short");
current->setState(6); current->setState(ATCMessageState::REPORT_RUNWAY);
} }
if (checkTransmissionState(6,6, current, now, MSG_REPORT_RUNWAY_HOLD_SHORT, ATC_AIR_TO_GROUND)) { if (checkTransmissionState(6,6, current, now, MSG_REPORT_RUNWAY_HOLD_SHORT, ATC_AIR_TO_GROUND)) {
} }

View file

@ -181,15 +181,15 @@ void FGTowerController::updateAircraftInformation(int id, SGGeod geod,
// only bother with aircraft that have a takeoff status of 2, since those are essentially under tower control // only bother with aircraft that have a takeoff status of 2, since those are essentially under tower control
auto ac = rwy->getFirstAircraftInDepartureQueue(); auto ac = rwy->getFirstAircraftInDepartureQueue();
if (ac) { if (ac) {
if (ac->getTakeOffStatus() == 1) { if (ac->getTakeOffStatus() == AITakeOffStatus::QUEUED) {
// transmit takeoff clearance // transmit takeoff clearance
ac->setTakeOffStatus(2); ac->setTakeOffStatus(AITakeOffStatus::CLEARED_FOR_TAKEOFF);
transmit(&(*i), &(*parent), MSG_CLEARED_FOR_TAKEOFF, ATC_GROUND_TO_AIR, true); transmit(&(*i), &(*parent), MSG_CLEARED_FOR_TAKEOFF, ATC_GROUND_TO_AIR, true);
i->setState(10); i->setState(ATCMessageState::CLEARED_TAKEOFF);
} }
} }
//FIXME Make it an member of traffic record //FIXME Make it an member of traffic record
if (current.getAircraft()->getTakeOffStatus() == 2) { if (current.getAircraft()->getTakeOffStatus() == AITakeOffStatus::CLEARED_FOR_TAKEOFF) {
current.setHoldPosition(false); current.setHoldPosition(false);
} else { } else {
current.setHoldPosition(true); current.setHoldPosition(true);
@ -200,7 +200,7 @@ void FGTowerController::updateAircraftInformation(int id, SGGeod geod,
SG_LOG(SG_ATC, SG_BULK, "Unset Hold " << clearanceId << " for " << rwy->getRunwayName()); SG_LOG(SG_ATC, SG_BULK, "Unset Hold " << clearanceId << " for " << rwy->getRunwayName());
current.setHoldPosition(false); current.setHoldPosition(false);
} else { } else {
SG_LOG(SG_ATC, SG_WARN, "Not cleared " << id << " " << clearanceId); SG_LOG(SG_ATC, SG_WARN, "Not cleared " << id << " Currently cleared " << clearanceId);
} }
} else { } else {
if (current.getAircraft() == rwy->getFirstAircraftInDepartureQueue()) { if (current.getAircraft() == rwy->getFirstAircraftInDepartureQueue()) {
@ -209,7 +209,7 @@ void FGTowerController::updateAircraftInformation(int id, SGGeod geod,
rwy->setCleared(id); rwy->setCleared(id);
auto ac = rwy->getFirstOfStatus(1); auto ac = rwy->getFirstOfStatus(1);
if (ac) { if (ac) {
ac->setTakeOffStatus(2); ac->setTakeOffStatus(AITakeOffStatus::QUEUED);
// transmit takeoff clearacne? But why twice? // transmit takeoff clearacne? But why twice?
} }
} else { } else {

View file

@ -154,7 +154,7 @@ void FGATCManager::postinit()
SG_LOG(SG_ATC, SG_DEBUG, "Setting radio frequency to : " << stationFreq); SG_LOG(SG_ATC, SG_DEBUG, "Setting radio frequency to : " << stationFreq);
fgSetDouble("/instrumentation/comm[0]/frequencies/selected-mhz", ((double) stationFreq / 100.0)); fgSetDouble("/instrumentation/comm[0]/frequencies/selected-mhz", ((double) stationFreq / 100.0));
} }
leg = 1; leg = AILeg::STARTUP_PUSHBACK;
//double, lat, lon, head; // Unused variables; //double, lat, lon, head; // Unused variables;
//int getId = apt->getDynamics()->getParking(gateId, &lat, &lon, &head); //int getId = apt->getDynamics()->getParking(gateId, &lat, &lon, &head);
aircraftRadius = pk.parking()->getRadius(); aircraftRadius = pk.parking()->getRadius();
@ -186,11 +186,11 @@ void FGATCManager::postinit()
fgSetDouble("/instrumentation/comm[0]/frequencies/selected-mhz", ((double) stationFreq / 100.0)); fgSetDouble("/instrumentation/comm[0]/frequencies/selected-mhz", ((double) stationFreq / 100.0));
} }
fp.reset(new FGAIFlightPlan); fp.reset(new FGAIFlightPlan);
leg = 3; leg = AILeg::TAKEOFF;
string fltType = "ga"; string fltType = "ga";
fp->setRunway(runway); fp->setRunway(runway);
fp->createTakeOff(userAircraft, false, dcs->parent(), {}, 0, fltType); fp->createTakeOff(userAircraft, false, dcs->parent(), userAircraft->getGeodPos(), 0, fltType);
userAircraft->setTakeOffStatus(2); userAircraft->setTakeOffStatus(AITakeOffStatus::QUEUED);
} else { } else {
// We're on the ground somewhere. Handle this case later. // We're on the ground somewhere. Handle this case later.
@ -210,7 +210,7 @@ void FGATCManager::postinit()
fp->getLastWaypoint()->setName( fp->getLastWaypoint()->getName() + string("legend")); fp->getLastWaypoint()->setName( fp->getLastWaypoint()->getName() + string("legend"));
} }
} else { } else {
controller = 0; controller = nullptr;
} }
// Create an initial flightplan and assign it to the ai_ac. We won't use this flightplan, but it is necessary to // Create an initial flightplan and assign it to the ai_ac. We won't use this flightplan, but it is necessary to
@ -347,20 +347,21 @@ void FGATCManager::update ( double time ) {
#endif #endif
} }
if (fp) { if (fp) {
SG_LOG(SG_ATC, SG_DEBUG, "User aircraft currently at leg : " << fp->getLeg()); SG_LOG(SG_ATC, SG_BULK, "User aircraft currently at leg : " << fp->getLeg());
} }
// Call getATCController method; returns what FGATCController presently controls the user aircraft // Call getATCController method; returns what FGATCController presently controls the user aircraft
// - e.g. FGStartupController // - e.g. FGStartupController
controller = user_ai_ac->getATCController(); // controller = user_ai_ac->getATCController();
// FIXME the AIAircraft currently doesn't set this for the user aircraft
// Update the ATC dialog // Update the ATC dialog
//FGATCDialogNew::instance()->update(time); //FGATCDialogNew::instance()->update(time);
// Controller manager - if controller is set, then will update controller // Controller manager - if controller is set, then will update controller
if (controller) { if (controller) {
SG_LOG(SG_ATC, SG_DEBUG, "name of previous waypoint : " << fp->getPreviousWaypoint()->getName()); // SG_LOG(SG_ATC, SG_DEBUG, "name of previous waypoint : " << fp->getPreviousWaypoint()->getName());
SG_LOG(SG_ATC, SG_DEBUG, "Currently under control of " << controller->getName()); SG_LOG(SG_ATC, SG_BULK, "Currently under control of " << controller->getName());
// update aircraft information (simulates transponder) // update aircraft information (simulates transponder)
@ -370,6 +371,49 @@ void FGATCManager::update ( double time ) {
user_ai_ac->getSpeed(), user_ai_ac->getSpeed(),
user_ai_ac->getAltitude(), time); user_ai_ac->getAltitude(), time);
if (fp) {
switch (fp->getLeg()) {
case AILeg::STARTUP_PUSHBACK: // Startup and Push back
if (userAircraftTrafficRef->getDepartureAirport()->getDynamics())
controller = userAircraftTrafficRef->getDepartureAirport()->getDynamics()->getStartupController();
break;
case AILeg::TAXI: // Taxiing to runway
if (userAircraftTrafficRef->getDepartureAirport()->getDynamics()->getGroundController()->exists())
controller = userAircraftTrafficRef->getDepartureAirport()->getDynamics()->getGroundController();
break;
case AILeg::TAKEOFF: //Take off tower controller
if (userAircraftTrafficRef->getDepartureAirport()->getDynamics()) {
controller = userAircraftTrafficRef->getDepartureAirport()->getDynamics()->getTowerController();
} else {
SG_LOG(SG_AI, SG_BULK, "Error: Could not find Dynamics at airport : " << userAircraftTrafficRef->getDepartureAirport()->getId());
}
break;
/* TODO link up with state system?
case AILeg::APPROACH:
if (userAircraftTrafficRef->getArrivalAirport()->getDynamics()) {
controller = trafficRef->getArrivalAirport()->getDynamics()->getApproachController();
}
break;
case AILeg::PARKING_TAXI: // Taxiing for parking
if (trafficRef->getArrivalAirport()->getDynamics()->getGroundController()->exists())
controller = trafficRef->getArrivalAirport()->getDynamics()->getGroundController();
break;
*/
default:
if(prevController) {
SG_LOG(SG_AI, SG_BULK, "Will be signing off user ai " << user_ai_ac->getID() << " from " << prevController->getName());
}
controller = nullptr;
break;
}
if ((controller != prevController) && prevController && !user_ai_ac->getDie()) {
//If we are dead we are automatically erased
prevController->signOff(user_ai_ac->getID());
}
prevController = controller;
}
//string airport = fgGetString("/sim/presets/airport-id"); //string airport = fgGetString("/sim/presets/airport-id");
//FGAirport *apt = FGAirport::findByIdent(airport); //FGAirport *apt = FGAirport::findByIdent(airport);
// AT this stage we should update the flightplan, so that waypoint incrementing is conducted as well as leg loading. // AT this stage we should update the flightplan, so that waypoint incrementing is conducted as well as leg loading.
@ -392,10 +436,11 @@ void FGATCManager::update ( double time ) {
prevController->render(false); prevController->render(false);
} }
if (controller) {
// render the path for the present controller if the ground network is set to visible // render the path for the present controller if the ground network is set to visible
controller->render(networkVisible); controller->render(networkVisible);
SG_LOG(SG_ATC, SG_BULK, "Adding ground network to the scenegraph::update"); SG_LOG(SG_ATC, SG_BULK, "Adding ground network to the scenegraph::update");
}
// reset previous controller for next update() iteration // reset previous controller for next update() iteration
prevController = controller; prevController = controller;

View file

@ -68,8 +68,6 @@ public:
void shutdown() override; void shutdown() override;
void update(double time) override; void update(double time) override;
// Subsystem identification. // Subsystem identification.
static const char* staticSubsystemClassId() { return "ATC"; } static const char* staticSubsystemClassId() { return "ATC"; }

View file

@ -264,7 +264,7 @@ FGTrafficRecord::~FGTrafficRecord()
void FGTrafficRecord::setPositionAndIntentions(int pos, void FGTrafficRecord::setPositionAndIntentions(int pos,
FGAIFlightPlan * route) FGAIFlightPlan * route)
{ {
SG_LOG(SG_ATC, SG_DEBUG, "Position: " << pos); SG_LOG(SG_AI, SG_DEBUG, "Traffic record position: " << pos);
currentPos = pos; currentPos = pos;
if (!intentions.empty()) { if (!intentions.empty()) {
intVecIterator i = intentions.begin(); intVecIterator i = intentions.begin();
@ -276,8 +276,7 @@ void FGTrafficRecord::setPositionAndIntentions(int pos,
} else { } else {
//FGAIFlightPlan::waypoint* const wpt= route->getCurrentWaypoint(); //FGAIFlightPlan::waypoint* const wpt= route->getCurrentWaypoint();
int size = route->getNrOfWayPoints(); int size = route->getNrOfWayPoints();
SG_LOG(SG_ATC, SG_DEBUG, "Setting pos" << currentPos); SG_LOG(SG_ATC, SG_DEBUG, "Setting pos to " << currentPos << " and intentions");
SG_LOG(SG_ATC, SG_DEBUG, "Setting intentions");
for (int i = 2; i < size; i++) { for (int i = 2; i < size; i++) {
int val = route->getRouteIndex(i); int val = route->getRouteIndex(i);
intentions.push_back(val); intentions.push_back(val);