1
0
Fork 0

Additional AI Aircraft properties for animation

Add a number of properties set by both AI Traffic and Swift aircraft:

gear/gear[0..5]/position-norm
surface-positions/flap-pos-norm
surface-positions/spoiler-pos-norm
surface-positions/speedbrake-pos-norm
controls/lighting/beacon
controls/lighting/cabin-lights
controls/lighting/landing-lights
controls/lighting/nav-lights
controls/lighting/strobe
controls/lighting/taxi-lights

Also improve take-off behaviour
This commit is contained in:
Stuart Buchanan 2020-08-16 14:49:33 +01:00
parent 06e6883396
commit 51173f32ff
12 changed files with 478 additions and 170 deletions

View file

@ -56,7 +56,7 @@ using std::endl;
FGAIAircraft::FGAIAircraft(FGAISchedule *ref) :
/* HOT must be disabled for AI Aircraft,
* otherwise traffic detection isn't working as expected.*/
FGAIBase(otAircraft, false),
FGAIBaseAircraft(),
_performance(0)
{
trafficRef = ref;
@ -134,7 +134,7 @@ void FGAIAircraft::readFromScenario(SGPropertyNode* scFileNode) {
void FGAIAircraft::bind() {
FGAIBase::bind();
FGAIBaseAircraft::bind();
tie("transponder-id",
SGRawValueMethods<FGAIAircraft,const char*>(*this,
@ -169,8 +169,8 @@ void FGAIAircraft::setPerformance(const std::string& acType, const std::string&
void FGAIAircraft::Run(double dt)
{
bool outOfSight = false,
flightplanActive = true;
bool outOfSight = false,
flightplanActive = true;
updatePrimaryTargetValues(dt, flightplanActive, outOfSight); // target hdg, alt, speed
if (outOfSight) {
return;
@ -183,11 +183,8 @@ void FGAIAircraft::setPerformance(const std::string& acType, const std::string&
handleATCRequests(dt); // ATC also has a word to say
updateSecondaryTargetValues(dt); // target roll, vertical speed, pitch
updateActualState(dt);
#if 0
// 25/11/12 - added but disabled, since setting properties isn't
// affecting the AI-model as expected.
updateModelProperties(dt);
#endif
// 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.
@ -195,7 +192,7 @@ void FGAIAircraft::setPerformance(const std::string& acType, const std::string&
// enough
if (manager){
UpdateRadar(manager);
invisible = !manager->isVisible(pos);
invisible = !manager->isVisible(pos);
}
}
@ -372,27 +369,52 @@ void FGAIAircraft::ProcessFlightPlan( double dt, time_t now ) {
fp->setLeadDistance(tgt_speed, tgt_heading, curr, next);
}
// Calculate a target altitude for any leg in which at least one waypoint is in the air.
if (!(prev->getOn_ground())) // only update the tgt altitude from flightplan if not on the ground
{
tgt_altitude_ft = prev->getAltitude();
if (prev->getInAir() && curr->getInAir()) {
// Completely in-air leg, so calculate the target altitude and VS.
if (curr->getCrossat() > -1000.0) {
use_perf_vs = false;
// Distance to go in meters
double vert_dist_ft = curr->getCrossat() - altitude_ft;
double err_dist = prev->getCrossat() - altitude_ft;
double dist_m = fp->getDistanceToGo(pos.getLatitudeDeg(), pos.getLongitudeDeg(), curr);
double vert_dist_ft = curr->getCrossat() - altitude_ft;
double err_dist = prev->getCrossat() - altitude_ft;
tgt_vs = calcVerticalSpeed(vert_dist_ft, dist_m, speed, err_dist);
tgt_altitude_ft = curr->getCrossat();
checkTcas();
tgt_altitude_ft = curr->getCrossat();
} else {
use_perf_vs = true;
tgt_altitude_ft = prev->getCrossat();
}
} else if (curr->getInAir()) {
// Take-off leg (prev is on ground)
if (curr->getCrossat() > -1000.0) {
// Altitude restriction
use_perf_vs = false;
double dist_m = fp->getDistanceToGo(pos.getLatitudeDeg(), pos.getLongitudeDeg(), curr);
double vert_dist_ft = curr->getCrossat() - altitude_ft;
double err_dist = - altitude_ft;
tgt_vs = calcVerticalSpeed(vert_dist_ft, dist_m, speed, err_dist);
tgt_altitude_ft = curr->getCrossat();
} else {
// no cross-at, so assume same as previous
use_perf_vs = true;
tgt_altitude_ft = prev->getCrossat();
}
} else if (prev->getInAir()) {
// Landing Leg (curr is on ground).
// Assume we want to touch down on the point, and not early!
use_perf_vs = false;
double dist_m = fp->getDistanceToGo(pos.getLatitudeDeg(), pos.getLongitudeDeg(), curr);
double vert_dist_ft = curr->getAltitude() - altitude_ft;
double err_dist = - altitude_ft;
tgt_vs = calcVerticalSpeed(vert_dist_ft, dist_m, speed, err_dist);
tgt_altitude_ft = curr->getAltitude();
}
AccelTo(prev->getSpeed());
hdg_lock = alt_lock = true;
no_roll = prev->getOn_ground();
no_roll = (prev->getOn_ground() && curr->getOn_ground());
}
}
@ -817,6 +839,7 @@ bool FGAIAircraft::leadPointReached(FGAIWaypoint* curr) {
fp->getPreviousWaypoint()->setSpeed(tgt_speed);
}
}
if (lead_dist < fabs(2*speed)) {
//don't skip over the waypoint
lead_dist = fabs(2*speed);
@ -1417,34 +1440,50 @@ double limitRateOfChange(double cur, double target, double maxDeltaSec, double d
return (fabs(delta) < maxDelta) ? delta : copysign(maxDelta, delta);
}
// drive various properties in a semi-realistic fashion.
// Drive various properties in a semi-realistic fashion.
// Note that we assume that the properties are set at
// a waypoint rather than in the leg before. So we need
// to use the previous waypoint (i.e. the one just passed)
// rather than the current one (i.e. the next one on the route)
void FGAIAircraft::updateModelProperties(double dt)
{
if (!props) {
if ((!fp) || (!fp->getPreviousWaypoint())) {
return;
}
SGPropertyNode* gear = props->getChild("gear", 0, true);
double targetGearPos = fp->getCurrentWaypoint()->getGear_down() ? 1.0 : 0.0;
if (!gear->hasValue("gear/position-norm")) {
gear->setDoubleValue("gear/position-norm", targetGearPos);
}
double targetGearPos = fp->getPreviousWaypoint()->getGear_down() ? 1.0 : 0.0;
double gearPos = getGearPos();
double gearPosNorm = gear->getDoubleValue("gear/position-norm");
if (gearPosNorm != targetGearPos) {
gearPosNorm += limitRateOfChange(gearPosNorm, targetGearPos, 0.1, dt);
if (gearPosNorm < 0.001) {
gearPosNorm = 0.0;
} else if (gearPosNorm > 0.999) {
gearPosNorm = 1.0;
if (gearPos != targetGearPos) {
gearPos = gearPos + limitRateOfChange(gearPos, targetGearPos, 0.1, dt);
if (gearPos < 0.001) {
gearPos = 0.0;
} else if (gearPos > 0.999) {
gearPos = 1.0;
}
for (int i=0; i<6; ++i) {
SGPropertyNode* g = gear->getChild("gear", i, true);
g->setDoubleValue("position-norm", gearPosNorm);
} // of gear setting loop
} // of gear in-transit
// double flapPosNorm = props->getDoubleValue();
setGearPos(gearPos);
}
double targetFlapsPos = fp->getPreviousWaypoint()->getFlaps();
double flapsPos = getFlapsPos();
if (flapsPos != targetFlapsPos) {
flapsPos = flapsPos + limitRateOfChange(flapsPos, targetFlapsPos, 0.05, dt);
if (flapsPos < 0.001) {
flapsPos = 0.0;
} else if (flapsPos > 0.999) {
flapsPos = 1.0;
}
setFlapsPos(flapsPos);
}
setSpeedBrakePos(fp->getPreviousWaypoint()->getSpeedBrakes());
setSpoilerPos(fp->getPreviousWaypoint()->getSpoilers());
setCabinLight(fp->getPreviousWaypoint()->getCabinLight());
setBeaconLight(fp->getPreviousWaypoint()->getBeaconLight());
setLandingLight(fp->getPreviousWaypoint()->getLandingLight());
setNavLight(fp->getPreviousWaypoint()->getNavLight());
setStrobeLight(fp->getPreviousWaypoint()->getStrobeLight());
setTaxiLight(fp->getPreviousWaypoint()->getTaxiLight());
}

View file

@ -21,7 +21,7 @@
#ifndef _FG_AIAircraft_HXX
#define _FG_AIAircraft_HXX
#include "AIBase.hxx"
#include "AIBaseAircraft.hxx"
#include <string>
@ -32,7 +32,7 @@ class FGATCController;
class FGATCInstruction;
class FGAIWaypoint;
class FGAIAircraft : public FGAIBase {
class FGAIAircraft : public FGAIBaseAircraft {
public:
FGAIAircraft(FGAISchedule *ref=0);

View file

@ -664,7 +664,6 @@ bool FGAIBase::isa( object_type otype ) {
return otype == _otype;
}
void FGAIBase::bind() {
_tiedProperties.setRoot(props);
tie("id", SGRawValueMethods<FGAIBase,int>(*this,
@ -723,11 +722,9 @@ void FGAIBase::bind() {
tie("radar/rotation", SGRawValuePointer<double>(&rotation));
tie("radar/ht-diff-ft", SGRawValuePointer<double>(&ht_diff));
tie("subID", SGRawValuePointer<int>(&_subID));
tie("controls/lighting/nav-lights", SGRawValueFunctions<bool>(_isNight));
props->setStringValue("sim/model/path", model_path);
props->setBoolValue("controls/lighting/beacon", true);
props->setBoolValue("controls/lighting/strobe", true);
props->setBoolValue("controls/glide-path", true);
props->setStringValue("controls/flight/lateral-mode", "roll");

View file

@ -0,0 +1,93 @@
// FGAIBaseAircraft - abstract base class for AI aircraft
// Written by Stuart Buchanan, started August 2002
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License as
// published by the Free Software Foundation; either version 2 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#include "AIBaseAircraft.hxx"
#include <src/Main/globals.hxx>
FGAIBaseAircraft::FGAIBaseAircraft() : FGAIBase(otStatic, false)
{
m_gearPos = 0.0f;
m_flapsPos = 0.0f;
m_spoilerPos = 0.0f;
m_speedbrakePos = 0.0f;
// Light properties.
m_beaconLight = false;
m_cabinLight = false;
m_landingLight = false;
m_navLight = false;
m_strobeLight = false;
m_taxiLight = false;
}
void FGAIBaseAircraft::bind() {
FGAIBase::bind();
// All gear positions are linked for simplicity
tie("gear/gear[0]/position-norm", SGRawValuePointer<double>(&m_gearPos));
tie("gear/gear[1]/position-norm", SGRawValuePointer<double>(&m_gearPos));
tie("gear/gear[2]/position-norm", SGRawValuePointer<double>(&m_gearPos));
tie("gear/gear[3]/position-norm", SGRawValuePointer<double>(&m_gearPos));
tie("gear/gear[4]/position-norm", SGRawValuePointer<double>(&m_gearPos));
tie("gear/gear[5]/position-norm", SGRawValuePointer<double>(&m_gearPos));
tie("surface-positions/flap-pos-norm",
SGRawValueMethods<FGAIBaseAircraft,double>(*this,
&FGAIBaseAircraft::getFlapsPos,
&FGAIBaseAircraft::setFlapsPos));
tie("surface-positions/spoiler-pos-norm",
SGRawValueMethods<FGAIBaseAircraft,double>(*this,
&FGAIBaseAircraft::getSpoilerPos,
&FGAIBaseAircraft::setSpoilerPos));
tie("surface-positions/speedbrake-pos-norm",
SGRawValueMethods<FGAIBaseAircraft,double>(*this,
&FGAIBaseAircraft::getSpeedBrakePos,
&FGAIBaseAircraft::setSpeedBrakePos));
tie("controls/lighting/beacon",
SGRawValueMethods<FGAIBaseAircraft,bool>(*this,
&FGAIBaseAircraft::getBeaconLight,
&FGAIBaseAircraft::setBeaconLight));
tie("controls/lighting/cabin-lights",
SGRawValueMethods<FGAIBaseAircraft,bool>(*this,
&FGAIBaseAircraft::getCabinLight,
&FGAIBaseAircraft::setCabinLight));
tie("controls/lighting/landing-lights",
SGRawValueMethods<FGAIBaseAircraft,bool>(*this,
&FGAIBaseAircraft::getLandingLight,
&FGAIBaseAircraft::setLandingLight));
tie("controls/lighting/nav-lights",
SGRawValueMethods<FGAIBaseAircraft,bool>(*this,
&FGAIBaseAircraft::getNavLight,
&FGAIBaseAircraft::setNavLight));
tie("controls/lighting/strobe",
SGRawValueMethods<FGAIBaseAircraft,bool>(*this,
&FGAIBaseAircraft::getStrobeLight,
&FGAIBaseAircraft::setStrobeLight));
tie("controls/lighting/taxi-lights",
SGRawValueMethods<FGAIBaseAircraft,bool>(*this,
&FGAIBaseAircraft::getTaxiLight,
&FGAIBaseAircraft::setTaxiLight));
}

View file

@ -0,0 +1,73 @@
// FGAIBaseAircraft - abstract base class for AI aircraft
// Written by Stuart Buchanan, started August 2002
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License as
// published by the Free Software Foundation; either version 2 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#ifndef _FG_AIBaseAircraft_HXX
#define _FG_AIBaseAircraft_HXX
#include "AIBase.hxx"
#include <string>
class FGAIBaseAircraft : public FGAIBase {
public:
FGAIBaseAircraft();
void bind();
// Note that this is mapped to all 6 gear indices gear/gear[0..5]
void setGearPos(double pos) { m_gearPos = pos; };
void setFlapsPos(double pos) { m_flapsPos = pos; };
void setSpoilerPos(double pos) { m_spoilerPos = pos; };
void setSpeedBrakePos(double pos) { m_speedbrakePos = pos; };
void setBeaconLight(bool light) { m_beaconLight = light; };
void setLandingLight(bool light) { m_landingLight = light; };
void setNavLight(bool light) { m_navLight = light; };
void setStrobeLight(bool light) { m_strobeLight = light; };
void setTaxiLight(bool light) { m_taxiLight = light; };
void setCabinLight(bool light) { m_cabinLight = light; };
double getGearPos() const { return m_gearPos; };
double getFlapsPos() const { return m_flapsPos; };
double getSpoilerPos() const { return m_spoilerPos; };
double getSpeedBrakePos() const { return m_speedbrakePos; };
bool getBeaconLight() const { return m_beaconLight; };
bool getLandingLight() const { return m_landingLight; };
bool getNavLight() const { return m_navLight; };
bool getStrobeLight() const { return m_strobeLight; };
bool getTaxiLight() const { return m_taxiLight; };
bool getCabinLight() const { return m_cabinLight; };
protected:
// Aircraft properties.
double m_gearPos;
double m_flapsPos;
double m_spoilerPos;
double m_speedbrakePos;
// Light properties.
bool m_beaconLight;
bool m_cabinLight;
bool m_landingLight;
bool m_navLight;
bool m_strobeLight;
bool m_taxiLight;
};
#endif

View file

@ -52,7 +52,7 @@ FGAIWaypoint::FGAIWaypoint() {
crossat = 0;
finished = 0;
gear_down = 0;
flaps_down = 0;
flaps = 0;
on_ground = 0;
routeIndex = 0;
time_sec = 0;
@ -240,18 +240,51 @@ bool FGAIFlightPlan::parseProperties(const std::string& filename)
for (int i = 0; i < node->nChildren(); i++) {
FGAIWaypoint* wpt = new FGAIWaypoint;
SGPropertyNode * wpt_node = node->getChild(i);
wpt->setName (wpt_node->getStringValue("name", "END" ));
wpt->setLatitude (wpt_node->getDoubleValue("lat", 0 ));
wpt->setLongitude (wpt_node->getDoubleValue("lon", 0 ));
wpt->setAltitude (wpt_node->getDoubleValue("alt", 0 ));
wpt->setSpeed (wpt_node->getDoubleValue("ktas", 0 ));
wpt->setCrossat (wpt_node->getDoubleValue("crossat", -10000 ));
wpt->setGear_down (wpt_node->getBoolValue("gear-down", false ));
wpt->setFlaps_down (wpt_node->getBoolValue("flaps-down", false ));
wpt->setOn_ground (wpt_node->getBoolValue("on-ground", false ));
wpt->setTime_sec (wpt_node->getDoubleValue("time-sec", 0 ));
wpt->setTime (wpt_node->getStringValue("time", "" ));
wpt->setFinished ((wpt->getName() == "END"));
bool gear, flaps;
// Calculate some default values if they are not set explicitly in the flightplan
if (wpt_node->getDoubleValue("ktas", 0) < 1.0f ) {
// Not moving so assume shut down.
wpt->setPowerDownLights();
flaps = false;
gear = true;
} else if (wpt_node->getDoubleValue("alt", 0) > 10000.0f ) {
// Cruise flight;
wpt->setCruiseLights();
flaps = false;
gear = false;
} else if (wpt_node->getBoolValue("on-ground", false)) {
// On ground
wpt->setGroundLights();
flaps = true;
gear = true;
} else if (wpt_node->getDoubleValue("alt", 0) < 3000.0f ) {
// In the air below 3000 ft, so flaps and gear down.
wpt->setApproachLights();
flaps = true;
gear = true;
} else {
// In the air 3000-10000 ft
wpt->setApproachLights();
flaps = false;
gear = false;
}
wpt->setName (wpt_node->getStringValue("name", "END" ));
wpt->setLatitude (wpt_node->getDoubleValue("lat", 0 ));
wpt->setLongitude (wpt_node->getDoubleValue("lon", 0 ));
wpt->setAltitude (wpt_node->getDoubleValue("alt", 0 ));
wpt->setSpeed (wpt_node->getDoubleValue("ktas", 0 ));
wpt->setCrossat (wpt_node->getDoubleValue("crossat", -10000 ));
wpt->setGear_down (wpt_node->getBoolValue("gear-down", gear ));
wpt->setFlaps (wpt_node->getBoolValue("flaps-down", flaps ) ? 1.0 : 0.0);
wpt->setSpoilers (wpt_node->getBoolValue("spoilers", false ) ? 1.0 : 0.0);
wpt->setSpeedBrakes (wpt_node->getBoolValue("speedbrakes", false ) ? 1.0 : 0.0);
wpt->setOn_ground (wpt_node->getBoolValue("on-ground", false ));
wpt->setTime_sec (wpt_node->getDoubleValue("time-sec", 0 ));
wpt->setTime (wpt_node->getStringValue("time", "" ));
wpt->setFinished ((wpt->getName() == "END"));
pushBackWaypoint( wpt );
}
if( getLastWaypoint()->getName().compare("END") != 0 ) {
@ -356,16 +389,17 @@ void FGAIFlightPlan::setLeadDistance(double speed, double bearing,
lead_distance = 0.5;
return;
}
if (speed < 25) {
turn_radius = ((360/30)*fabs(speed)) / (2*M_PI);
} else
turn_radius = ((360/30)*fabs(speed)) / (2*M_PI);
} else {
turn_radius = 0.1911 * speed * speed; // an estimate for 25 degrees bank
}
double inbound = bearing;
double outbound = getBearing(current, next);
leadInAngle = fabs(inbound - outbound);
if (leadInAngle > 180.0)
leadInAngle = 360.0 - leadInAngle;
if (leadInAngle > 180.0) leadInAngle = 360.0 - leadInAngle;
//if (leadInAngle < 30.0) // To prevent lead_dist from getting so small it is skipped
// leadInAngle = 30.0;
@ -422,7 +456,14 @@ void FGAIFlightPlan::resetWaypoints()
wpt->setPos ( (*i)->getPos() );
wpt->setCrossat ( (*i)->getCrossat() );
wpt->setGear_down ( (*i)->getGear_down() );
wpt->setFlaps_down ( (*i)->getFlaps_down() );
wpt->setFlaps ( (*i)->getFlaps() );
wpt->setSpoilers ( (*i)->getSpoilers() );
wpt->setSpeedBrakes ( (*i)->getSpeedBrakes());
wpt->setBeaconLight ( (*i)->getBeaconLight() );
wpt->setLandingLight( (*i)->getLandingLight() );
wpt->setNavLight ( (*i)->getNavLight() );
wpt->setStrobeLight ( (*i)->getStrobeLight());
wpt->setTaxiLight ( (*i)->getTaxiLight() );
wpt->setFinished ( false );
wpt->setOn_ground ( (*i)->getOn_ground() );
SG_LOG(SG_AI, SG_DEBUG, "Recycling waypoint " << wpt->getName());

View file

@ -36,12 +36,20 @@ private:
double crossat;
bool finished;
bool gear_down;
bool flaps_down;
double flaps;
double spoilers;
double speedbrakes;
bool on_ground;
int routeIndex; // For AI/ATC purposes;
double time_sec;
double trackLength; // distance from previous FGAIWaypoint (for AI purposes);
std::string time;
bool beacon_light;
bool landing_light;
bool nav_light;
bool strobe_light;
bool taxi_light;
bool cabin_light;
public:
FGAIWaypoint();
@ -55,12 +63,33 @@ public:
void setCrossat (double val) { crossat = val; };
void setFinished (bool fin) { finished = fin; };
void setGear_down (bool grd) { gear_down = grd; };
void setFlaps_down (bool fld) { flaps_down = fld; };
void setFlaps (double val) { flaps = val; };
void setSpoilers (double val) { spoilers = val; };
void setSpeedBrakes (double val) { speedbrakes = val; };
void setOn_ground (bool grn) { on_ground = grn; };
void setRouteIndex (int rte) { routeIndex = rte; };
void setTime_sec (double ts ) { time_sec = ts; };
void setTrackLength (double tl ) { trackLength = tl; };
void setTime (const std::string& tme) { time = tme; };
void setLights (bool beacon, bool cabin, bool ldg, bool nav, bool strobe, bool taxi) {
beacon_light = beacon;
cabin_light = cabin;
landing_light = ldg;
nav_light = nav;
strobe_light = strobe;
taxi_light = taxi; };
// beacon cabin ldg nav strobe taxi
void setPowerDownLights() { setLights(false, true, false, false, false, false); };
void setGroundLights() { setLights(true, true, false, true, false, true ); };
void setCruiseLights() { setLights(true, true, false, true, true, false); };
void setTakeOffLights() { setLights(true, false, true, true, true, false); };
void setApproachLights() { setLights(true, false, true, true, true, false); };
void setBeaconLight (bool beacon) { beacon_light = beacon; };
void setCabinLight (bool cabin) { cabin_light = cabin; };
void setLandingLight (bool ldg) { landing_light = ldg; };
void setNavLight (bool nav) { nav_light = nav; };
void setStrobeLight (bool strobe) { strobe_light = strobe; };
void setTaxiLight (bool taxi) { taxi_light = taxi; };
bool contains(const std::string& name);
@ -73,13 +102,22 @@ public:
double getCrossat () { return crossat; };
bool getGear_down () { return gear_down; };
bool getFlaps_down () { return flaps_down; };
double getFlaps () { return flaps; };
double getSpoilers () { return spoilers; };
double getSpeedBrakes() { return speedbrakes; };
bool getOn_ground () { return on_ground; };
bool getInAir () { return ! on_ground; };
int getRouteIndex () { return routeIndex; };
bool isFinished () { return finished; };
double getTime_sec () { return time_sec; };
double getTrackLength() { return trackLength; };
const std::string& getTime () { return time; };
bool getBeaconLight() { return beacon_light; };
bool getCabinLight() { return cabin_light; };
bool getLandingLight() { return landing_light; };
bool getNavLight() { return nav_light; };
bool getStrobeLight() { return strobe_light;};
bool getTaxiLight() { return taxi_light; };
};
@ -115,13 +153,13 @@ public:
double getDistanceToGo(double lat, double lon, FGAIWaypoint* wp) const;
int getLeg () const { return leg;};
void setLeadDistance(double speed, double bearing, FGAIWaypoint* current, FGAIWaypoint* next);
void setLeadDistance(double distance_ft);
double getLeadDistance( void ) const {return lead_distance;}
double getBearing(FGAIWaypoint* previous, FGAIWaypoint* next) const;
double getBearing(const SGGeod& aPos, FGAIWaypoint* next) const;
double checkTrackLength(const std::string& wptName) const;
time_t getStartTime() const { return start_time; }
time_t getArrivalTime() const { return arrivalTime; }
@ -137,7 +175,7 @@ public:
double getLeadInAngle() const { return leadInAngle; }
const std::string& getRunway() const;
void setRepeat(bool r) { repeat = r; }
bool getRepeat(void) const { return repeat; }
void restart(void);
@ -162,7 +200,7 @@ public:
FGAIFlightPlan* getSID() { return sid; };
FGAIWaypoint *getWayPoint(int i) { return waypoints[i]; };
FGAIWaypoint *getLastWaypoint() { return waypoints.back(); };
void shortenToFirst(unsigned int number, std::string name);
void setGate(const ParkingAssignment& pka);
@ -192,14 +230,14 @@ private:
std::string name;
bool isValid;
FGAirportRef departure, arrival;
void createPushBackFallBack(FGAIAircraft *, bool, FGAirport*, double radius, const std::string&, const std::string&, const std::string&);
bool createClimb(FGAIAircraft *, bool, FGAirport *, FGAirport* arrival, double, double, const std::string&);
bool createCruise(FGAIAircraft *, bool, FGAirport*, FGAirport*, double, double, double, double, const std::string&);
bool createDescent(FGAIAircraft *, FGAirport *, double latitude, double longitude, double speed, double alt,const std::string&, double distance);
bool createLanding(FGAIAircraft *, FGAirport *, const std::string&);
bool createParking(FGAIAircraft *, FGAirport *, double radius);
void deleteWaypoints();
void deleteWaypoints();
void resetWaypoints();
void eraseLastWaypoint();
void pushBackWaypoint(FGAIWaypoint *wpt);
@ -210,22 +248,23 @@ private:
bool createTakeoffTaxi(FGAIAircraft *, bool firstFlight, FGAirport *apt, double radius, const std::string& fltType, const std::string& acType, const std::string& airline);
double getTurnRadius(double, bool);
FGAIWaypoint* createOnGround(FGAIAircraft *, const std::string& aName, const SGGeod& aPos, double aElev, double aSpeed);
FGAIWaypoint* createOnRunway(FGAIAircraft *, const std::string& aName, const SGGeod& aPos, double aElev, double aSpeed);
FGAIWaypoint* createInAir(FGAIAircraft *, const std::string& aName, const SGGeod& aPos, double aElev, double aSpeed);
FGAIWaypoint* cloneWithPos(FGAIAircraft *, FGAIWaypoint* aWpt, const std::string& aName, const SGGeod& aPos);
FGAIWaypoint* clone(FGAIWaypoint* aWpt);
//void createCruiseFallback(bool, FGAirport*, FGAirport*, double, double, double, double);
void evaluateRoutePart(double deplat, double deplon, double arrlat, double arrlon);
/**
* look for and parse an PropertyList flight-plan file - essentially
* a flat list waypoint objects, encoded to properties
*/
bool parseProperties(const std::string& filename);
void createWaypoints(FGAIAircraft *ac,
double course,
time_t start,
@ -240,7 +279,7 @@ private:
const std::string& fltType,
const std::string& acType,
const std::string& airline);
public:
wpt_vector_iterator getFirstWayPoint() { return waypoints.begin(); };
wpt_vector_iterator getLastWayPoint() { return waypoints.end(); };

View file

@ -52,7 +52,7 @@ using std::string;
/* FGAIFlightPlan::create()
* dynamically create a flight plan for AI traffic, based on data provided by the
* Traffic Manager, when reading a filed flightplan failes. (DT, 2004/07/10)
* Traffic Manager, when reading a filed flightplan fails. (DT, 2004/07/10)
*
* This is the top-level function, and the only one that is publicly available.
*
@ -133,17 +133,34 @@ FGAIWaypoint * FGAIFlightPlan::createOnGround(FGAIAircraft * ac,
double aSpeed)
{
FGAIWaypoint *wpt = new FGAIWaypoint;
wpt->setName (aName );
wpt->setLongitude (aPos.getLongitudeDeg() );
wpt->setLatitude (aPos.getLatitudeDeg() );
wpt->setAltitude (aElev );
wpt->setSpeed (aSpeed );
wpt->setCrossat (-10000.1 );
wpt->setGear_down (true );
wpt->setFlaps_down (true );
wpt->setFinished (false );
wpt->setOn_ground (true );
wpt->setRouteIndex (0 );
wpt->setName (aName );
wpt->setLongitude (aPos.getLongitudeDeg() );
wpt->setLatitude (aPos.getLatitudeDeg() );
wpt->setAltitude (aElev );
wpt->setSpeed (aSpeed );
wpt->setCrossat (-10000.1 );
wpt->setGear_down (true );
wpt->setFlaps (0.0f );
wpt->setSpoilers (0.0f );
wpt->setSpeedBrakes (0.0f );
wpt->setFinished (false );
wpt->setOn_ground (true );
wpt->setRouteIndex (0 );
if (aSpeed > 0.0f) {
wpt->setGroundLights();
} else {
wpt->setPowerDownLights();
}
return wpt;
}
FGAIWaypoint * FGAIFlightPlan::createOnRunway(FGAIAircraft * ac,
const std::string & aName,
const SGGeod & aPos, double aElev,
double aSpeed)
{
FGAIWaypoint * wpt = createOnGround(ac, aName, aPos, aElev, aSpeed);
wpt->setTakeOffLights();
return wpt;
}
@ -154,9 +171,17 @@ FGAIWaypoint * FGAIFlightPlan::createInAir(FGAIAircraft * ac,
{
FGAIWaypoint * wpt = createOnGround(ac, aName, aPos, aElev, aSpeed);
wpt->setGear_down (false );
wpt->setFlaps_down (false );
wpt->setFlaps (0.0f );
wpt->setSpoilers (0.0f );
wpt->setSpeedBrakes(0.0f );
wpt->setOn_ground (false );
wpt->setCrossat (aElev );
if (aPos.getElevationFt() < 10000.0f) {
wpt->setApproachLights();
} else {
wpt->setCruiseLights();
}
return wpt;
}
@ -170,9 +195,13 @@ FGAIWaypoint * FGAIFlightPlan::clone(FGAIWaypoint * aWpt)
wpt->setSpeed ( aWpt->getSpeed() );
wpt->setCrossat ( aWpt->getCrossat() );
wpt->setGear_down ( aWpt->getGear_down() );
wpt->setFlaps_down ( aWpt->getFlaps_down() );
wpt->setFlaps ( aWpt->getFlaps() );
wpt->setFinished ( aWpt->isFinished() );
wpt->setOn_ground ( aWpt->getOn_ground() );
wpt->setLandingLight (aWpt->getLandingLight() );
wpt->setNavLight (aWpt->getNavLight() );
wpt->setStrobeLight (aWpt->getStrobeLight() );
wpt->setTaxiLight (aWpt->getTaxiLight() );
wpt->setRouteIndex ( 0 );
return wpt;
@ -206,14 +235,14 @@ void FGAIFlightPlan::createDefaultTakeoffTaxi(FGAIAircraft * ac,
ac->getPerformance()->vTaxi());
pushBackWaypoint(wpt);
wpt =
createOnGround(ac, "Runway Takeoff", runwayTakeoff, airportElev,
createOnRunway(ac, "Runway Takeoff", runwayTakeoff, airportElev,
ac->getPerformance()->vTaxi());
wpt->setFlaps(0.5f);
pushBackWaypoint(wpt);
// Acceleration point, 105 meters into the runway,
SGGeod accelPoint = aRunway->pointOnCenterline(105.0);
wpt = createOnGround(ac, "Accel", accelPoint, airportElev,
wpt = createOnRunway(ac, "Accel", accelPoint, airportElev,
ac->getPerformance()->vRotate());
pushBackWaypoint(wpt);
}
@ -341,15 +370,20 @@ bool FGAIFlightPlan::createTakeoffTaxi(FGAIAircraft * ac, bool firstFlight,
// Note that we actually have hold points in the ground network, but this is just an initial test.
//cerr << "Setting departurehold point: " << endl;
wpt->setName( wpt->getName() + string("DepartureHold"));
wpt->setFlaps(0.5f);
wpt->setTakeOffLights();
}
if (taxiRoute.nodesLeft() == 0) {
wpt->setName(wpt->getName() + string("Accel"));
wpt->setTakeOffLights();
wpt->setFlaps(0.5f);
}
pushBackWaypoint(wpt);
}
// Acceleration point, 105 meters into the runway,
SGGeod accelPoint = rwy->pointOnCenterline(105.0);
FGAIWaypoint *wpt = createOnGround(ac, "Accel", accelPoint, apt->getElevation(), ac->getPerformance()->vRotate());
FGAIWaypoint *wpt = createOnRunway(ac, "Accel", accelPoint, apt->getElevation(), ac->getPerformance()->vRotate());
wpt->setFlaps(0.5f);
pushBackWaypoint(wpt);
//cerr << "[done]" << endl;
@ -483,6 +517,7 @@ bool FGAIFlightPlan::createTakeOff(FGAIAircraft * ac, bool firstFlight,
double accelMetric = accel * SG_KT_TO_MPS;
double vTaxiMetric = vTaxi * SG_KT_TO_MPS;
double vRotateMetric = vRotate * SG_KT_TO_MPS;
double vTakeoffMetric = vTakeoff * SG_KT_TO_MPS;
FGAIWaypoint *wpt;
// Get the current active runway, based on code from David Luff
@ -503,38 +538,47 @@ bool FGAIFlightPlan::createTakeOff(FGAIAircraft * ac, bool firstFlight,
double airportElev = apt->getElevation();
// distance from the runway threshold to accelerate to rotation speed.
double d = accelDistance(vTaxiMetric, vRotateMetric, accelMetric) + ACCEL_POINT;
SGGeod accelPoint = rwy->pointOnCenterline(d);
wpt = createOnGround(ac, "rotate", accelPoint, airportElev, vTakeoff);
SGGeod rotatePoint = rwy->pointOnCenterline(d);
wpt = createOnRunway(ac, "rotate", rotatePoint, airportElev, vRotate);
wpt->setFlaps(0.5f);
pushBackWaypoint(wpt);
// After rotation, we still need to accelerate to the take-off speed.
double t = d + accelDistance(vRotateMetric, vTakeoffMetric, accelMetric);
SGGeod takeoffPoint = rwy->pointOnCenterline(t);
wpt = createOnRunway(ac, "takeoff", takeoffPoint, airportElev, vTakeoff);
wpt->setGear_down(true);
wpt->setFlaps(0.5f);
pushBackWaypoint(wpt);
double vRef = vTakeoff + 20; // climb-out at v2 + 20kts
double gearUpDist = d + pitchDistance(INITIAL_PITCH_ANGLE, 400 * SG_FEET_TO_METER);
accelPoint = rwy->pointOnCenterline(gearUpDist);
wpt = cloneWithPos(ac, wpt, "gear-up", accelPoint);
wpt->setSpeed(vRef);
wpt->setCrossat(airportElev + 400);
wpt->setOn_ground(false);
wpt->setGear_down(false);
// We want gear-up to take place at ~400ft AGL. However, the flightplan
// will move onto the next leg once it gets within 2xspeed of the next waypoint.
// With closely spaced waypoints on climb-out this can occur almost immediately,
// so we put the waypoint further away.
double gearUpDist = t + 2*vRef*SG_FEET_TO_METER + pitchDistance(INITIAL_PITCH_ANGLE, 400 * SG_FEET_TO_METER);
SGGeod gearUpPoint = rwy->pointOnCenterline(gearUpDist);
wpt = createInAir(ac, "gear-up", gearUpPoint, airportElev + 400, vRef);
wpt->setFlaps(0.5f);
pushBackWaypoint(wpt);
// limit climbout speed to 240kts below 10000'
// limit climbout speed to 240kts below 10000'
double vClimbBelow10000 = std::min(240.0, ac->getPerformance()->vClimb());
// create two climb-out points. This is important becuase the first climb point will
// be a (sometimes large) turn towards the destination, and we don't want to
// commence that turn below 2000'
double climbOut = d + pitchDistance(INITIAL_PITCH_ANGLE, 2000 * SG_FEET_TO_METER);
accelPoint = rwy->pointOnCenterline(climbOut);
wpt = createInAir(ac, "2000'", accelPoint, airportElev + 2000, vClimbBelow10000);
// create two climb-out points. This is important becuase the first climb point will
// be a (sometimes large) turn towards the destination, and we don't want to
// commence that turn below 2000'
double climbOut = t + 2*vClimbBelow10000*SG_FEET_TO_METER + pitchDistance(INITIAL_PITCH_ANGLE, 2000 * SG_FEET_TO_METER);
SGGeod climbOutPoint = rwy->pointOnCenterline(climbOut);
wpt = createInAir(ac, "2000'", climbOutPoint, airportElev + 2000, vClimbBelow10000);
pushBackWaypoint(wpt);
climbOut = d + pitchDistance(INITIAL_PITCH_ANGLE, 2500 * SG_FEET_TO_METER);
accelPoint = rwy->pointOnCenterline(climbOut);
wpt = createInAir(ac, "2500'", accelPoint, airportElev + 2500, vClimbBelow10000);
climbOut = t + 2*vClimbBelow10000*SG_FEET_TO_METER + pitchDistance(INITIAL_PITCH_ANGLE, 2500 * SG_FEET_TO_METER);
SGGeod climbOutPoint2 = rwy->pointOnCenterline(climbOut);
wpt = createInAir(ac, "2500'", climbOutPoint2, airportElev + 2500, vClimbBelow10000);
pushBackWaypoint(wpt);
return true;
@ -542,7 +586,7 @@ bool FGAIFlightPlan::createTakeOff(FGAIAircraft * ac, bool firstFlight,
/*******************************************************************
* CreateClimb
* initialize the Aircraft at the parking location
* initialize the Aircraft in a climb.
******************************************************************/
bool FGAIFlightPlan::createClimb(FGAIAircraft * ac, bool firstFlight,
FGAirport * apt, FGAirport* arrival,
@ -580,8 +624,6 @@ bool FGAIFlightPlan::createClimb(FGAIAircraft * ac, bool firstFlight,
SGGeod climb1 = SGGeodesy::direct(cur, course, 10 * SG_NM_TO_METER);
wpt = createInAir(ac, "10000ft climb", climb1, 10000, vClimb);
wpt->setGear_down(true);
wpt->setFlaps_down(true);
pushBackWaypoint(wpt);
SGGeod climb2 = SGGeodesy::direct(cur, course, 20 * SG_NM_TO_METER);
@ -591,8 +633,6 @@ bool FGAIFlightPlan::createClimb(FGAIAircraft * ac, bool firstFlight,
return true;
}
/*******************************************************************
* CreateDescent
* Generate a flight path from the last waypoint of the cruise to
@ -948,13 +988,19 @@ bool FGAIFlightPlan::createLanding(FGAIAircraft * ac, FGAirport * apt,
double glideslopeEntry = -((2000 * SG_FEET_TO_METER) / tan(3.0)) + touchdownDistance;
FGAIWaypoint *wpt = createInAir(ac, "Glideslope begin", rwy->pointOnCenterline(glideslopeEntry),
currElev + 2000, vApproach);
wpt->setGear_down(true);
wpt->setFlaps(1.0f);
wpt->setSpeedBrakes(1.0f);
pushBackWaypoint(wpt);
// deceleration point, 500' above touchdown elevation - slow from approach speed
// to touchdown speed
double decelPoint = -((500 * SG_FEET_TO_METER) / tan(3.0)) + touchdownDistance;
wpt = createInAir(ac, "500' decel", rwy->pointOnCenterline(decelPoint),
currElev + 2000, vTouchdown);
currElev + 500, vTouchdown);
wpt->setGear_down(true);
wpt->setFlaps(1.0f);
wpt->setSpeedBrakes(1.0f);
pushBackWaypoint(wpt);
// compute elevation above the runway start, based on a 3-degree glideslope
@ -962,6 +1008,9 @@ bool FGAIFlightPlan::createLanding(FGAIAircraft * ac, FGAirport * apt,
tan(3.0 * SG_DEGREES_TO_RADIANS) * SG_METER_TO_FEET;
wpt = createInAir(ac, "CrossThreshold", rwy->begin(),
heightAboveRunwayStart + currElev, vTouchdown);
wpt->setGear_down(true);
wpt->setFlaps(1.0f);
wpt->setSpeedBrakes(1.0f);
pushBackWaypoint(wpt);
double rolloutDistance = accelDistance(vTouchdownMetric, vTaxiMetric, decelMetric);
@ -972,7 +1021,10 @@ bool FGAIFlightPlan::createLanding(FGAIAircraft * ac, FGAirport * apt,
double t = ((double) i) / nPoints;
coord = rwy->pointOnCenterline(touchdownDistance + (rolloutDistance * t));
double vel = (vTouchdownMetric * (1.0 - t)) + (vTaxiMetric * t);
wpt = createOnGround(ac, buffer, coord, currElev, vel);
wpt = createOnRunway(ac, buffer, coord, currElev, vel);
wpt->setFlaps(1.0f);
wpt->setSpeedBrakes(1.0f);
wpt->setSpoilers(1.0f);
wpt->setCrossat(currElev);
pushBackWaypoint(wpt);
}
@ -994,7 +1046,10 @@ bool FGAIFlightPlan::createLanding(FGAIAircraft * ac, FGAirport * apt,
}
if (tn) {
wpt = createOnGround(ac, buffer, tn->geod(), currElev, vTaxi);
wpt = createOnRunway(ac, buffer, tn->geod(), currElev, vTaxi);
wpt->setFlaps(1.0f);
wpt->setSpeedBrakes(1.0f);
wpt->setSpoilers(0.0f);
pushBackWaypoint(wpt);
}

View file

@ -21,7 +21,7 @@
#include <src/Main/globals.hxx>
FGAISwiftAircraft::FGAISwiftAircraft(const std::string& callsign, const std::string& modelString) : FGAIBase(otStatic, false)
FGAISwiftAircraft::FGAISwiftAircraft(const std::string& callsign, const std::string& modelString) : FGAIBaseAircraft()
{
std::size_t pos = modelString.find("/Aircraft/"); // Only supporting AI models from FGDATA/AI/Aircraft for now
if(pos != std::string::npos)
@ -67,15 +67,15 @@ double FGAISwiftAircraft::getGroundElevation(const SGGeod& pos) const
void FGAISwiftAircraft::setPlaneSurface(const AircraftSurfaces& surfaces)
{
m_gearNode->setDoubleValue(surfaces.gear);
m_flapsIdentNode->setDoubleValue(surfaces.flaps);
m_spoilerNode->setDoubleValue(surfaces.spoilers);
m_speedBrakeNode->setDoubleValue(surfaces.spoilers);
m_landLightNode->setBoolValue(surfaces.landingLight);
m_taxiLightNode->setBoolValue(surfaces.taxiLight);
m_beaconLightNode->setBoolValue(surfaces.beaconLight);
m_strobeLightNode->setBoolValue(surfaces.strobeLight);
m_navLightNode->setBoolValue(surfaces.navLight);
setGearPos(surfaces.gear);
setFlapsPos(surfaces.flaps);
setSpoilerPos(surfaces.spoilers);
setSpeedBrakePos(surfaces.spoilers);
setBeaconLight(surfaces.beaconLight);
setLandingLight(surfaces.landingLight);
setNavLight(surfaces.navLight);
setStrobeLight(surfaces.strobeLight);
setTaxiLight(surfaces.taxiLight);
}
void FGAISwiftAircraft::setPlaneTransponder(const AircraftTransponder& transponder)
@ -91,17 +91,6 @@ void FGAISwiftAircraft::initProps()
m_transponderCodeNode = _getProps()->getNode("swift/transponder/code", true);
m_transponderCModeNode = _getProps()->getNode("swift/transponder/c-mode", true);
m_transponderIdentNode = _getProps()->getNode("swift/transponder/ident", true);
m_gearNode = _getProps()->getNode("swift/gear/gear-down", true);
m_flapsIdentNode = _getProps()->getNode("swift/flight/flaps", true);
m_spoilerNode = _getProps()->getNode("swift/flight/spoilers", true);
m_speedBrakeNode = _getProps()->getNode("swift/flight/speedbrake", true);
m_landLightNode = _getProps()->getNode("swift/lighting/landing-lights", true);
m_navLightNode = _getProps()->getNode("swift/lighting/nav-lights", true);
m_taxiLightNode = _getProps()->getNode("swift/lighting/taxi-light", true);
m_beaconLightNode = _getProps()->getNode("swift/lighting/beacon", true);
m_strobeLightNode = _getProps()->getNode("swift/lighting/strobe", true);
}
FGAISwiftAircraft::~FGAISwiftAircraft() = default;

View file

@ -21,7 +21,7 @@
#define FLIGHTGEAR_AISWIFTAIRCRAFT_H
#include "AIBase.hxx"
#include "AIBaseAircraft.hxx"
#include <string>
#include <utility>
@ -67,9 +67,7 @@ struct AircraftSurfaces
int lightPattern;
};
class FGAISwiftAircraft : public FGAIBase
class FGAISwiftAircraft : public FGAIBaseAircraft
{
public:
FGAISwiftAircraft(const std::string& callsign, const std::string& modelString);
@ -89,24 +87,6 @@ private:
SGPropertyNode_ptr m_transponderCodeNode;
SGPropertyNode_ptr m_transponderCModeNode;
SGPropertyNode_ptr m_transponderIdentNode;
SGPropertyNode_ptr m_gearNode;
SGPropertyNode_ptr m_flapsIdentNode;
SGPropertyNode_ptr m_spoilerNode;
SGPropertyNode_ptr m_speedBrakeNode;
//SGPropertyNode_ptr m_slatsNode;
//SGPropertyNode_ptr m_wingSweepNode;
//SGPropertyNode_ptr m_thrustNode;
//SGPropertyNode_ptr m_elevatorNode;
//SGPropertyNode_ptr m_rudderNode;
//SGPropertyNode_ptr m_aileronNode;
SGPropertyNode_ptr m_landLightNode;
SGPropertyNode_ptr m_taxiLightNode;
SGPropertyNode_ptr m_beaconLightNode;
SGPropertyNode_ptr m_strobeLightNode;
SGPropertyNode_ptr m_navLightNode;
//SGPropertyNode_ptr m_lightPatternNode;
};

View file

@ -4,6 +4,7 @@ set(SOURCES
AIAircraft.cxx
AIBallistic.cxx
AIBase.cxx
AIBaseAircraft.cxx
AICarrier.cxx
AIEscort.cxx
AIFlightPlan.cxx
@ -28,6 +29,7 @@ set(HEADERS
AIAircraft.hxx
AIBallistic.hxx
AIBase.hxx
AIBaseAircraft.hxx
AICarrier.hxx
AIEscort.hxx
AIFlightPlan.hxx

View file

@ -81,7 +81,7 @@ void FGSidStar::load(SGPath filename) {
wpt->setSpeed (wpt_node->getDoubleValue("ktas", 0));
wpt->setCrossat (wpt_node->getDoubleValue("crossat", -10000));
wpt->setGear_down (wpt_node->getBoolValue("gear-down", false));
wpt->setFlaps_down (wpt_node->getBoolValue("flaps-down", false));
wpt->setFlaps (wpt_node->getBoolValue("flaps-down", false) ? 0.5 : 0.0); // We'll assume all SIDS only require half flaps
wpt->setOn_ground (wpt_node->getBoolValue("on-ground", false));
wpt->setTime_sec (wpt_node->getDoubleValue("time-sec", 0));
wpt->setTime (wpt_node->getStringValue("time", ""));