1
0
Fork 0

GPSs uses FlightPlans directly.

This commit is contained in:
James Turner 2013-03-27 20:47:40 +00:00
parent a0cf59d8af
commit e89df85817
13 changed files with 331 additions and 943 deletions

View file

@ -215,13 +215,17 @@ FGRouteMgr::FGRouteMgr() :
input->setStringValue("");
input->addChangeListener(listener);
SGCommandMgr::instance()->addCommand("load-flightplan", commandLoadFlightPlan);
SGCommandMgr::instance()->addCommand("save-flightplan", commandSaveFlightPlan);
SGCommandMgr::instance()->addCommand("activate-flightplan", commandActivateFlightPlan);
SGCommandMgr::instance()->addCommand("clear-flightplan", commandClearFlightPlan);
SGCommandMgr::instance()->addCommand("set-active-waypt", commandSetActiveWaypt);
SGCommandMgr::instance()->addCommand("insert-waypt", commandInsertWaypt);
SGCommandMgr::instance()->addCommand("delete-waypt", commandDeleteWaypt);
SGCommandMgr* cmdMgr = SGCommandMgr::instance();
cmdMgr->addCommand("define-user-waypoint", this, &FGRouteMgr::commandDefineUserWaypoint);
cmdMgr->addCommand("delete-user-waypoint", this, &FGRouteMgr::commandDeleteUserWaypoint);
cmdMgr->addCommand("load-flightplan", commandLoadFlightPlan);
cmdMgr->addCommand("save-flightplan", commandSaveFlightPlan);
cmdMgr->addCommand("activate-flightplan", commandActivateFlightPlan);
cmdMgr->addCommand("clear-flightplan", commandClearFlightPlan);
cmdMgr->addCommand("set-active-waypt", commandSetActiveWaypt);
cmdMgr->addCommand("insert-waypt", commandInsertWaypt);
cmdMgr->addCommand("delete-waypt", commandDeleteWaypt);
}
@ -229,6 +233,10 @@ FGRouteMgr::~FGRouteMgr()
{
input->removeChangeListener(listener);
delete listener;
SGCommandMgr* cmdMgr = SGCommandMgr::instance();
//cmdMgr->removeCommand("define-user-waypoint");
}
@ -306,14 +314,12 @@ void FGRouteMgr::init() {
airborne->setBoolValue(false);
_edited = fgGetNode(RM "signals/edited", true);
_finished = fgGetNode(RM "signals/finished", true);
_flightplanChanged = fgGetNode(RM "signals/flightplan-changed", true);
_currentWpt = fgGetNode(RM "current-wp", true);
_currentWpt->tie(SGRawValueMethods<FGRouteMgr, int>
(*this, &FGRouteMgr::currentIndex, &FGRouteMgr::jumpToIndex));
// temporary distance / eta calculations, for backward-compatability
wp0 = fgGetNode(RM "wp", 0, true);
wp0->getChild("id", 0, true);
wp0->getChild("dist", 0, true);
@ -454,10 +460,6 @@ void FGRouteMgr::update( double dt )
return;
}
if (checkFinished()) {
endOfRoute();
}
// basic course/distance information
SGGeod currentPos = globals->get_aircraft_position();
@ -590,11 +592,6 @@ void FGRouteMgr::waypointsChanged()
{
update_mirror();
_edited->fireValueChanged();
// removing waypoints, deactivate if we hit the end.
if (currentIndex() >= numLegs()) {
endOfRoute();
}
}
// mirror internal route to the property system for inspection by other subsystems
@ -713,63 +710,10 @@ void FGRouteMgr::InputListener::valueChanged(SGPropertyNode *prop)
r++;
if (*r)
mgr->flightPlan()->insertWayptAtIndex(mgr->waypointFromString(r), pos);
} else if (!strcmp(s, "@POSINIT")) {
mgr->initAtPosition();
} else
mgr->flightPlan()->insertWayptAtIndex(mgr->waypointFromString(s), -1);
}
void FGRouteMgr::initAtPosition()
{
if (isRouteActive()) {
return; // don't mess with the active route
}
if (haveUserWaypoints()) {
// user has already defined, loaded or entered a route, again
// don't interfere with it
return;
}
if (airborne->getBoolValue()) {
SG_LOG(SG_AUTOPILOT, SG_INFO, "initAtPosition: airborne, clearing departure info");
_plan->setDeparture((FGAirport*) NULL);
return;
}
// on the ground
SGGeod pos = globals->get_aircraft_position();
if (!_plan->departureAirport()) {
_plan->setDeparture(FGAirport::findClosest(pos, 20.0));
if (!_plan->departureAirport()) {
SG_LOG(SG_AUTOPILOT, SG_INFO, "initAtPosition: couldn't find an airport within 20nm");
return;
}
}
std::string rwy = departure->getStringValue("runway");
FGRunway* r = NULL;
if (!rwy.empty()) {
r = _plan->departureAirport()->getRunwayByIdent(rwy);
} else {
r = _plan->departureAirport()->findBestRunwayForPos(pos);
}
if (!r) {
return;
}
_plan->setDeparture(r);
SG_LOG(SG_AUTOPILOT, SG_INFO, "initAtPosition: starting at "
<< _plan->departureAirport()->ident() << " on runway " << r->ident());
}
bool FGRouteMgr::haveUserWaypoints() const
{
// FIXME
return false;
}
bool FGRouteMgr::activate()
{
if (!_plan) {
@ -798,52 +742,6 @@ void FGRouteMgr::deactivate()
active->setBoolValue(false);
}
void FGRouteMgr::sequence()
{
if (!_plan || !active->getBoolValue()) {
SG_LOG(SG_AUTOPILOT, SG_ALERT, "trying to sequence waypoints with no active route");
return;
}
int nextIndex = _plan->currentIndex() + 1;
if (nextIndex >= _plan->numLegs()) {
SG_LOG(SG_AUTOPILOT, SG_INFO, "sequenced on final leg, deactivating route");
endOfRoute();
return;
}
_plan->setCurrentIndex(nextIndex);
}
void FGRouteMgr::endOfRoute()
{
SG_LOG(SG_AUTOPILOT, SG_INFO, "reached end of active route");
_finished->fireValueChanged();
active->setBoolValue(false);
}
bool FGRouteMgr::checkFinished()
{
if (!_plan) {
return true;
}
bool done = false;
// done if we're stopped on the destination runway
if (_plan->currentLeg() &&
(_plan->currentLeg()->waypoint()->source() == _plan->destinationRunway()))
{
double gs = groundSpeed->getDoubleValue();
done = weightOnWheels->getBoolValue() && (gs < 25);
}
if (done) {
SG_LOG(SG_AUTOPILOT, SG_INFO, "checkFinished: on the ground on destination runway, we're done");
}
return done;
}
void FGRouteMgr::jumpToIndex(int index)
{
if (!_plan) {
@ -1212,3 +1110,37 @@ SGPropertyNode_ptr FGRouteMgr::wayptNodeAtIndex(int index) const
return mirror->getChild("wp", index);
}
bool FGRouteMgr::commandDefineUserWaypoint(const SGPropertyNode* arg)
{
std::string ident = arg->getStringValue("ident");
if (ident.empty()) {
SG_LOG(SG_AUTOPILOT, SG_WARN, "missing ident defining user waypoint");
return false;
}
// check for duplicate idents
FGPositioned::TypeFilter f(FGPositioned::WAYPOINT);
FGPositionedList dups = FGPositioned::findAllWithIdent(ident, &f);
if (!dups.empty()) {
SG_LOG(SG_AUTOPILOT, SG_WARN, "defineUserWaypoint: non-unique waypoint identifier:" << ident);
return false;
}
SGGeod pos(SGGeod::fromDeg(arg->getDoubleValue("longitude-deg"),
arg->getDoubleValue("latitude-deg")));
FGPositioned::createUserWaypoint(ident, pos);
return true;
}
bool FGRouteMgr::commandDeleteUserWaypoint(const SGPropertyNode* arg)
{
std::string ident = arg->getStringValue("ident");
if (ident.empty()) {
SG_LOG(SG_AUTOPILOT, SG_WARN, "missing ident deleting user waypoint");
return false;
}
return FGPositioned::deleteUserWaypoint(ident);
}

View file

@ -90,11 +90,6 @@ public:
*/
void deactivate();
/**
* Step to the next waypoint on the active route
*/
void sequence();
/**
* Set the current waypoint to the specified index.
*/
@ -104,13 +99,11 @@ public:
bool loadRoute(const SGPath& p);
flightgear::WayptRef waypointFromString(const std::string& target);
/**
* Helper command to setup current airport/runway if necessary
*/
void initAtPosition();
private:
bool commandDefineUserWaypoint(const SGPropertyNode* arg);
bool commandDeleteUserWaypoint(const SGPropertyNode* arg);
flightgear::FlightPlan* _plan;
time_t _takeoffTime;
@ -188,23 +181,6 @@ private:
virtual void currentWaypointChanged();
/**
* Check if we've reached the final waypoint.
* Returns true if we have.
*/
bool checkFinished();
/*
* update state when we pass the final waypoint
*/
void endOfRoute();
/**
* Predicate for helping the UI - test if at least one waypoint was
* entered by the user (as opposed to being generated by the route-manager)
*/
bool haveUserWaypoints() const;
// tied getters and setters
const char* getDepartureICAO() const;
const char* getDepartureName() const;

File diff suppressed because it is too large Load diff

View file

@ -15,12 +15,9 @@
#include <simgear/props/tiedpropertylist.hxx>
#include <Navaids/positioned.hxx>
#include <Navaids/FlightPlan.hxx>
#include <Instrumentation/rnav_waypt_controller.hxx>
// forward decls
class SGRoute;
class FGRouteMgr;
class GPSListener;
/**
* Model a GPS radio.
@ -57,10 +54,12 @@ class GPSListener;
* /instrumentation/gps/true-bug-error-deg
* /instrumentation/gps/magnetic-bug-error-deg
*/
class GPS : public SGSubsystem, public flightgear::RNAV
class GPS : public SGSubsystem,
public flightgear::RNAV,
public flightgear::FlightPlan::Delegate
{
public:
GPS (SGPropertyNode *node);
GPS (SGPropertyNode *node, bool defaultGPSMode = false);
GPS ();
virtual ~GPS ();
@ -82,7 +81,6 @@ public:
virtual double overflightArmDistanceM();
private:
friend class GPSListener;
friend class SearchFilter;
/**
@ -142,9 +140,6 @@ private:
// (in seconds)
double _waypointAlertTime;
// minimum runway length to require when filtering
double _minRunwayLengthFt;
// should we require a hard-surfaced runway when filtering?
bool _requireHardSurface;
@ -172,15 +167,8 @@ private:
void updateBasicData(double dt);
void updateTrackingBug();
void updateReferenceNavaid(double dt);
void referenceNavaidSet(const std::string& aNavaid);
void updateRouteData();
void driveAutopilot();
void routeActivated();
void routeManagerSequenced();
void routeEdited();
void routeFinished();
void updateTurn();
void updateOverflight();
@ -195,49 +183,24 @@ private:
/** Update one-shot things when WP1 / leg data change */
void wp1Changed();
// scratch maintenance utilities
void setScratchFromPositioned(FGPositioned* aPos, int aIndex);
void setScratchFromCachedSearchResult();
void setScratchFromRouteWaypoint(int aIndex);
/** Add airport-specific information to a scratch result */
void addAirportToScratch(FGAirport* aAirport);
void clearScratch();
/** Predicate, determine if the lon/lat position in the scratch is
* valid or not. */
bool isScratchPositionValid() const;
FGPositioned::Filter* createFilter(FGPositioned::Type aTy);
/** Search kernel - called each time we step through a result */
void performSearch();
// command handlers
void selectLegMode();
void selectOBSMode();
void selectOBSMode(flightgear::Waypt* waypt);
void directTo();
void loadRouteWaypoint();
void loadNearest();
void search();
void nextResult();
void previousResult();
void defineWaypoint();
void insertWaypointAtIndex(int aIndex);
void removeWaypointAtIndex(int aIndex);
// tied-property getter/setters
void setCommand(const char* aCmd);
const char* getCommand() const { return ""; }
const char* getMode() const { return _mode.c_str(); }
bool getScratchValid() const { return _scratchValid; }
double getScratchDistance() const;
double getScratchMagBearing() const;
double getScratchTrueBearing() const;
bool getScratchHasNext() const;
double getSelectedCourse() const { return _selectedCourse; }
void setSelectedCourse(double crs);
@ -254,9 +217,6 @@ private:
double getGroundspeedKts() const { return _last_speed_kts; }
double getVerticalSpeed() const { return _last_vertical_speed; }
//bool getLegMode() const { return _mode == "leg"; }
//bool getObsMode() const { return _mode == "obs"; }
const char* getWP0Ident() const;
const char* getWP0Name() const;
@ -293,6 +253,16 @@ private:
void tieSGGeodReadOnly(SGPropertyNode* aNode, SGGeod& aRef,
const char* lonStr, const char* latStr, const char* altStr);
// FlightPlan::Delegate
virtual void currentWaypointChanged();
virtual void waypointsChanged();
virtual void cleared();
virtual void endOfFlightPlan();
void sequence();
void routeManagerFlightPlanChanged(SGPropertyNode*);
void routeActivated(SGPropertyNode*);
// members
SGPropertyNode_ptr _gpsNode;
SGPropertyNode_ptr _currentWayptNode;
@ -308,22 +278,13 @@ private:
SGPropertyNode_ptr _magnetic_bug_error_node;
SGPropertyNode_ptr _eastWestVelocity;
SGPropertyNode_ptr _northSouthVelocity;
SGPropertyNode_ptr _ref_navaid_id_node;
SGPropertyNode_ptr _ref_navaid_bearing_node;
SGPropertyNode_ptr _ref_navaid_distance_node;
SGPropertyNode_ptr _ref_navaid_mag_bearing_node;
SGPropertyNode_ptr _ref_navaid_frequency_node;
SGPropertyNode_ptr _ref_navaid_name_node;
SGPropertyNode_ptr _route_active_node;
// SGPropertyNode_ptr _route_active_node;
SGPropertyNode_ptr _route_current_wp_node;
SGPropertyNode_ptr _routeDistanceNm;
SGPropertyNode_ptr _routeETE;
SGPropertyNode_ptr _routeEditedSignal;
SGPropertyNode_ptr _routeFinishedSignal;
SGPropertyNode_ptr _desiredCourseNode;
double _selectedCourse;
double _desiredCourse;
@ -336,15 +297,17 @@ private:
double _lastEWVelocity;
double _lastNSVelocity;
/**
* the instrument manager creates a default instance of us,
* if no explicit GPS is specific in the aircraft's instruments.xml file.
* This allows default route-following to work with the generic autopilot.
* This flat is set in that case, to inform us we're a 'fake' installation,
* and not to worry about electrical power or similar.
*/
bool _defaultGPSMode;
std::string _mode;
GPSListener* _listener;
Config _config;
FGRouteMgr* _routeMgr;
bool _ref_navaid_set;
double _ref_navaid_elapsed;
FGPositionedRef _ref_navaid;
std::string _name;
int _num;
@ -356,17 +319,7 @@ private:
SGGeod _scratchPos;
SGPropertyNode_ptr _scratchNode;
bool _scratchValid;
// search data
int _searchResultIndex;
std::string _searchQuery;
FGPositioned::Type _searchType;
bool _searchExact;
FGPositionedList _searchResults;
bool _searchIsRoute; ///< set if 'search' is actually the current route
bool _searchHasNext; ///< is there a result after this one?
bool _searchNames; ///< set if we're searching names instead of idents
// turn data
bool _computeTurnData; ///< do we need to update the turn data?
bool _anticipateTurn; ///< are we anticipating the next turn or not?
@ -380,18 +333,19 @@ private:
std::auto_ptr<flightgear::WayptController> _wayptController;
SGPropertyNode_ptr _realismSimpleGps; ///< should the GPS be simple or realistic?
flightgear::WayptRef _prevWaypt;
flightgear::WayptRef _currentWaypt;
// autopilot drive properties
SGPropertyNode_ptr _apDrivingFlag;
SGPropertyNode_ptr _apTrueHeading;
SGPropertyNode_ptr _apTargetAltitudeFt;
SGPropertyNode_ptr _apAltitudeLock;
simgear::TiedPropertyList _tiedProperties;
SGSharedPtr<flightgear::FlightPlan> _route;
SGPropertyChangeCallback<GPS> _callbackFlightPlanChanged;
SGPropertyChangeCallback<GPS> _callbackRouteActivated;
};
#endif // __INSTRUMENTS_GPS_HXX

View file

@ -94,7 +94,7 @@ void FGInstrumentMgr::init()
nd->setStringValue("name", "gps");
nd->setIntValue("number", 0);
_instruments.push_back("gps[0]");
set_subsystem("gps[0]", new GPS(nd));
set_subsystem("gps[0]", new GPS(nd, true /* default GPS mode */));
}
// bind() created instruments before init.

View file

@ -265,6 +265,12 @@ int FlightPlan::clearWayptsWithFlag(WayptFlag flag)
}
}
// test if the current leg will be removed
bool currentIsBeingCleared = false;
if (_currentIndex >= 0) {
currentIsBeingCleared = _legs[_currentIndex]->waypoint()->flag(flag);
}
_currentIndex -= count;
// now delete and remove
@ -276,11 +282,18 @@ int FlightPlan::clearWayptsWithFlag(WayptFlag flag)
lockDelegate();
_waypointsChanged = true;
if (count > 0) {
if ((count > 0) || currentIsBeingCleared) {
_currentWaypointChanged = true;
}
_legs.erase(it, _legs.end());
if (_legs.empty()) { // maybe all legs were deleted
if (_delegate) {
_delegate->runCleared();
}
}
unlockDelegate();
return rf.numDeleted();
}
@ -300,6 +313,23 @@ void FlightPlan::setCurrentIndex(int index)
_currentWaypointChanged = true;
unlockDelegate();
}
void FlightPlan::finish()
{
if (_currentIndex == -1) {
return;
}
lockDelegate();
_currentIndex = -1;
_currentWaypointChanged = true;
if (_delegate) {
_delegate->runFinished();
}
unlockDelegate();
}
int FlightPlan::findWayptIndex(const SGGeod& aPos) const
{
@ -1214,5 +1244,11 @@ void FlightPlan::Delegate::runCleared()
if (_inner) _inner->runCleared();
cleared();
}
void FlightPlan::Delegate::runFinished()
{
if (_inner) _inner->runFinished();
endOfFlightPlan();
}
} // of namespace flightgear

View file

@ -104,7 +104,7 @@ public:
virtual void waypointsChanged() { }
virtual void cleared() { }
virtual void currentWaypointChanged() { }
virtual void endOfFlightPlan() { }
protected:
Delegate();
@ -116,6 +116,7 @@ public:
void runWaypointsChanged();
void runCurrentWaypointChanged();
void runCleared();
void runFinished();
friend class FlightPlan;
@ -135,6 +136,8 @@ public:
void setCurrentIndex(int index);
void finish();
Leg* currentLeg() const;
Leg* nextLeg() const;
Leg* previousLeg() const;

View file

@ -1690,10 +1690,12 @@ PositionedID NavDataCache::createPOI(FGPositioned::Type ty, const std::string& i
true /* spatial index */);
}
void NavDataCache::removePOI(FGPositioned::Type ty, const std::string& aIdent)
bool NavDataCache::removePOI(FGPositioned::Type ty, const std::string& aIdent)
{
d->removePositionedWithIdent(ty, aIdent);
// should remove from the live cache too?
return true;
}
void NavDataCache::setAirportMetar(const string& icao, bool hasMetar)

View file

@ -122,7 +122,7 @@ public:
PositionedID createPOI(FGPositioned::Type ty, const std::string& ident, const SGGeod& aPos);
void removePOI(FGPositioned::Type ty, const std::string& aIdent);
bool removePOI(FGPositioned::Type ty, const std::string& aIdent);
void dropGroundnetFor(PositionedID aAirport);

View file

@ -30,6 +30,7 @@
#include <queue>
#include <memory>
#include <boost/foreach.hpp>
#include <boost/algorithm/string/case_conv.hpp>
#include <boost/algorithm/string/predicate.hpp>
@ -85,10 +86,10 @@ FGPositioned::createUserWaypoint(const std::string& aIdent, const SGGeod& aPos)
return cache->loadById(id);
}
void FGPositioned::deleteUserWaypoint(const std::string& aIdent)
bool FGPositioned::deleteUserWaypoint(const std::string& aIdent)
{
NavDataCache* cache = NavDataCache::instance();
cache->removePOI(WAYPOINT, aIdent);
return cache->removePOI(WAYPOINT, aIdent);
}
@ -335,8 +336,8 @@ FGPositionedRef FGPositioned::loadByIdImpl(PositionedID id)
}
FGPositioned::TypeFilter::TypeFilter(Type aTy) :
mMinType(aTy),
mMaxType(aTy)
mMinType(LAST_TYPE),
mMaxType(INVALID)
{
addType(aTy);
}
@ -352,6 +353,23 @@ void FGPositioned::TypeFilter::addType(Type aTy)
mMaxType = std::max(mMaxType, aTy);
}
FGPositioned::TypeFilter
FGPositioned::TypeFilter::fromString(const std::string& aFilterSpec)
{
if (aFilterSpec.empty()) {
throw sg_format_exception("empty filter spec:", aFilterSpec);
}
string_list parts = simgear::strutils::split(aFilterSpec, ",");
TypeFilter f;
BOOST_FOREACH(std::string token, parts) {
f.addType(typeFromName(token));
}
return f;
}
bool
FGPositioned::TypeFilter::pass(FGPositioned* aPos) const
{

View file

@ -163,7 +163,7 @@ public:
class TypeFilter : public Filter
{
public:
TypeFilter(Type aTy);
TypeFilter(Type aTy = INVALID);
virtual bool pass(FGPositioned* aPos) const;
virtual Type minType() const
@ -173,7 +173,10 @@ public:
{ return mMaxType; }
void addType(Type aTy);
static TypeFilter fromString(const std::string& aFilterSpec);
private:
std::vector<Type> types;
Type mMinType, mMaxType;
};
@ -266,7 +269,7 @@ public:
static const char* nameForType(Type aTy);
static FGPositioned* createUserWaypoint(const std::string& aIdent, const SGGeod& aPos);
static void deleteUserWaypoint(const std::string& aIdent);
static bool deleteUserWaypoint(const std::string& aIdent);
protected:
friend class flightgear::NavDataCache;

View file

@ -415,11 +415,11 @@ static const char* airportGhostGetMember(naContext c, void* g, naRef field, naRe
static const char* waypointCommonGetMember(naContext c, Waypt* wpt, const char* fieldName, naRef* out)
{
if (!strcmp(fieldName, "wp_name")) *out = stringToNasal(c, wpt->ident());
if (!strcmp(fieldName, "wp_name") || !strcmp(fieldName, "id")) *out = stringToNasal(c, wpt->ident());
else if (!strcmp(fieldName, "wp_type")) *out = stringToNasal(c, wpt->type());
else if (!strcmp(fieldName, "wp_role")) *out = wayptFlagToNasal(c, wpt->flags());
else if (!strcmp(fieldName, "wp_lat")) *out = naNum(wpt->position().getLatitudeDeg());
else if (!strcmp(fieldName, "wp_lon")) *out = naNum(wpt->position().getLongitudeDeg());
else if (!strcmp(fieldName, "wp_lat") || !strcmp(fieldName, "lat")) *out = naNum(wpt->position().getLatitudeDeg());
else if (!strcmp(fieldName, "wp_lon") || !strcmp(fieldName, "lon")) *out = naNum(wpt->position().getLongitudeDeg());
else if (!strcmp(fieldName, "wp_parent_name")) {
Procedure* proc = dynamic_cast<Procedure*>(wpt->owner());
*out = proc ? stringToNasal(c, proc->ident()) : naNil();
@ -497,6 +497,7 @@ static const char* legGhostGetMember(naContext c, void* g, naRef field, naRef* o
if (!strcmp(fieldName, "parents")) {
*out = naNewVector(c);
naVec_append(*out, fpLegPrototype);
naVec_append(*out, waypointPrototype);
} else if (!strcmp(fieldName, "index")) {
*out = naNum(leg->index());
} else if (!strcmp(fieldName, "alt_cstr")) {
@ -589,6 +590,11 @@ static void flightplanGhostSetMember(naContext c, void* g, naRef field, naRef va
return;
}
if (naIsNil(value)) {
fp->setDeparture(static_cast<FGAirport*>(NULL));
return;
}
naRuntimeError(c, "bad argument type setting departure");
} else if (!strcmp(fieldName, "destination")) {
FGAirport* apt = airportGhost(value);
@ -611,7 +617,7 @@ static void flightplanGhostSetMember(naContext c, void* g, naRef field, naRef va
return;
}
naRuntimeError(c, "bad argument type setting departure");
naRuntimeError(c, "bad argument type setting departure runway");
} else if (!strcmp(fieldName, "destination_runway")) {
FGRunway* rwy = runwayGhost(value);
if (rwy){
@ -619,7 +625,7 @@ static void flightplanGhostSetMember(naContext c, void* g, naRef field, naRef va
return;
}
naRuntimeError(c, "bad argument type setting departure");
naRuntimeError(c, "bad argument type setting destination runway");
} else if (!strcmp(fieldName, "sid")) {
Procedure* proc = procedureGhost(value);
if (proc && (proc->type() == PROCEDURE_SID)) {
@ -1388,6 +1394,21 @@ static naRef f_airport_getApproach(naContext c, naRef me, int argc, naRef* args)
return ghostForProcedure(c, apt->findApproachWithIdent(ident));
}
static naRef f_airport_findBestRunway(naContext c, naRef me, int argc, naRef* args)
{
FGAirport* apt = airportGhost(me);
if (!apt) {
naRuntimeError(c, "findBestRunway called on non-airport object");
}
SGGeod pos;
if (!geodFromArgs(args, 0, argc, pos)) {
naRuntimeError(c, "findBestRunway must be passed a position");
}
return ghostForRunway(c, apt->findBestRunwayForPos(pos));
}
static naRef f_airport_toString(naContext c, naRef me, int argc, naRef* args)
{
FGAirport* apt = airportGhost(me);
@ -1754,13 +1775,17 @@ public:
{
callDelegateMethod("cleared");
}
virtual void endOfFlightPlan()
{
callDelegateMethod("endOfFlightPlan");
}
private:
void callDelegateMethod(const char* method)
{
naRef f;
naMember_cget(_nasal->context(), _instance, method, &f);
if (naIsNil(f)) {
if (naMember_cget(_nasal->context(), _instance, method, &f) == 0) {
return; // no method on the delegate
}
@ -2131,6 +2156,16 @@ static naRef f_flightplan_pathGeod(naContext c, naRef me, int argc, naRef* args)
return result;
}
static naRef f_flightplan_finish(naContext c, naRef me, int argc, naRef* args)
{
FlightPlan* fp = flightplanGhost(me);
if (!fp) {
naRuntimeError(c, "flightplan.finish called on non-flightplan object");
}
fp->finish();
return naNil();
}
static naRef f_leg_setSpeed(naContext c, naRef me, int argc, naRef* args)
{
@ -2376,6 +2411,7 @@ naRef initNasalPositioned(naRef globals, naContext c, naRef gcSave)
hashset(c, airportPrototype, "getSid", naNewFunc(c, naNewCCode(c, f_airport_getSid)));
hashset(c, airportPrototype, "getStar", naNewFunc(c, naNewCCode(c, f_airport_getStar)));
hashset(c, airportPrototype, "getIAP", naNewFunc(c, naNewCCode(c, f_airport_getApproach)));
hashset(c, airportPrototype, "findBestRunwayForPos", naNewFunc(c, naNewCCode(c, f_airport_findBestRunway)));
hashset(c, airportPrototype, "tostring", naNewFunc(c, naNewCCode(c, f_airport_toString)));
flightplanPrototype = naNewHash(c);
@ -2394,6 +2430,7 @@ naRef initNasalPositioned(naRef globals, naContext c, naRef gcSave)
hashset(c, flightplanPrototype, "clearWPType", naNewFunc(c, naNewCCode(c, f_flightplan_clearWPType)));
hashset(c, flightplanPrototype, "clone", naNewFunc(c, naNewCCode(c, f_flightplan_clone)));
hashset(c, flightplanPrototype, "pathGeod", naNewFunc(c, naNewCCode(c, f_flightplan_pathGeod)));
hashset(c, flightplanPrototype, "finish", naNewFunc(c, naNewCCode(c, f_flightplan_finish)));
waypointPrototype = naNewHash(c);
hashset(c, gcSave, "wayptProto", waypointPrototype);

View file

@ -406,8 +406,8 @@ static naRef f_findWithinRange(nasal::CallContext ctx)
static naRef f_findByIdent(nasal::CallContext ctx)
{
std::string prefix = ctx.requireArg<std::string>(0);
FGPositioned::TypeFilter filter(FGPositioned::typeFromName(ctx.getArg<std::string>(1)));
std::string typeSpec = ctx.getArg<std::string>(1);
FGPositioned::TypeFilter filter(FGPositioned::TypeFilter::fromString(typeSpec));
bool exact = ctx.getArg<bool>(2, false);
return ctx.to_nasal( FGPositioned::findAllWithIdent(prefix, &filter, exact) );
@ -416,8 +416,8 @@ static naRef f_findByIdent(nasal::CallContext ctx)
static naRef f_findByName(nasal::CallContext ctx)
{
std::string prefix = ctx.requireArg<std::string>(0);
FGPositioned::TypeFilter filter(FGPositioned::typeFromName(ctx.getArg<std::string>(1)));
std::string typeSpec = ctx.getArg<std::string>(1);
FGPositioned::TypeFilter filter(FGPositioned::TypeFilter::fromString(typeSpec));
return ctx.to_nasal( FGPositioned::findAllWithName(prefix, &filter, false) );
}
@ -501,7 +501,7 @@ naRef initNasalPositioned_cppbind(naRef globalsRef, naContext c, naRef gcSave)
.method("getStar", &FGAirport::findSTARWithIdent)
.method("getIAP", &FGAirport::findApproachWithIdent)
.method("tostring", &FGAirport::toString);
nasal::Hash globals(globalsRef, c),
positioned( globals.createHash("positioned") );