#include <time.h>
#endif
+#include <cstdio>
+
#include <simgear/compiler.h>
#include "route_mgr.hxx"
#include "Navaids/positioned.hxx"
#include <Navaids/waypoint.hxx>
#include <Navaids/procedure.hxx>
-#include "Airports/simple.hxx"
+#include <Navaids/routePath.hxx>
+
+#include "Airports/airport.hxx"
#include "Airports/runways.hxx"
#include <GUI/new_gui.hxx>
#include <GUI/dialog.hxx>
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 = globals->get_commands();
+ 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);
}
{
input->removeChangeListener(listener);
delete listener;
+
+ if (_plan) {
+ _plan->removeDelegate(this);
+ }
+
+ SGCommandMgr* cmdMgr = globals->get_commands();
+ cmdMgr->removeCommand("define-user-waypoint");
+ cmdMgr->removeCommand("delete-user-waypoint");
+ cmdMgr->removeCommand("load-flightplan");
+ cmdMgr->removeCommand("save-flightplan");
+ cmdMgr->removeCommand("activate-flightplan");
+ cmdMgr->removeCommand("clear-flightplan");
+ cmdMgr->removeCommand("set-active-waypt");
+ cmdMgr->removeCommand("insert-waypt");
+ cmdMgr->removeCommand("delete-waypt");
}
departure->tie("name", SGRawValueMethods<FGRouteMgr, const char*>(*this,
&FGRouteMgr::getDepartureName, NULL));
departure->tie("field-elevation-ft", SGRawValueMethods<FGRouteMgr, double>(*this,
- &FGRouteMgr::getDestinationFieldElevation, NULL));
+ &FGRouteMgr::getDepartureFieldElevation, NULL));
departure->getChild("etd", 0, true);
departure->getChild("takeoff-time", 0, true);
&FGRouteMgr::getDestinationFieldElevation, NULL));
destination->getChild("eta", 0, true);
+ destination->getChild("eta-seconds", 0, true);
destination->getChild("touchdown-time", 0, true);
alternate = fgGetNode(RM "alternate", true);
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);
wp0->getChild("eta", 0, true);
+ wp0->getChild("eta-seconds", 0, true);
wp0->getChild("bearing-deg", 0, true);
wp1 = fgGetNode(RM "wp", 1, true);
wp1->getChild("id", 0, true);
wp1->getChild("dist", 0, true);
wp1->getChild("eta", 0, true);
+ wp1->getChild("eta-seconds", 0, true);
wpn = fgGetNode(RM "wp-last", 0, true);
wpn->getChild("dist", 0, true);
wpn->getChild("eta", 0, true);
+ wpn->getChild("eta-seconds", 0, true);
_pathNode = fgGetNode(RM "file-path", 0, true);
}
return true;
}
-FlightPlan* FGRouteMgr::flightPlan() const
+FlightPlanRef FGRouteMgr::flightPlan() const
{
return _plan;
}
-void FGRouteMgr::setFlightPlan(FlightPlan* plan)
+void FGRouteMgr::setFlightPlan(const FlightPlanRef& plan)
{
if (plan == _plan) {
return;
if (_plan) {
_plan->removeDelegate(this);
- delete _plan;
active->setBoolValue(false);
}
return;
}
- if (checkFinished()) {
- endOfRoute();
- }
-
// basic course/distance information
SGGeod currentPos = globals->get_aircraft_position();
return;
}
- double courseDeg;
- double distanceM;
- boost::tie(courseDeg, distanceM) = leg->waypoint()->courseAndDistanceFrom(currentPos);
-
-// update wp0 / wp1 / wp-last
+ // use RoutePath to compute location of active WP
+ RoutePath path(_plan);
+ SGGeod wpPos = path.positionForIndex(_plan->currentIndex());
+ double courseDeg, az2, distanceM;
+ SGGeodesy::inverse(currentPos, wpPos, courseDeg, az2, distanceM);
+
+ // update wp0 / wp1 / wp-last
wp0->setDoubleValue("dist", distanceM * SG_METER_TO_NM);
wp0->setDoubleValue("true-bearing-deg", courseDeg);
courseDeg -= magvar->getDoubleValue(); // expose magnetic bearing
wp0->setDoubleValue("bearing-deg", courseDeg);
- setETAPropertyFromDistance(wp0->getChild("eta"), distanceM);
+ setETAPropertyFromDistance(wp0, distanceM);
double totalPathDistanceNm = _plan->totalDistanceNm();
double totalDistanceRemaining = distanceM * SG_METER_TO_NM; // distance to current waypoint
FlightPlan::Leg* nextLeg = _plan->nextLeg();
if (nextLeg) {
- boost::tie(courseDeg, distanceM) = nextLeg->waypoint()->courseAndDistanceFrom(currentPos);
-
+ wpPos = path.positionForIndex(_plan->currentIndex() + 1);
+ SGGeodesy::inverse(currentPos, wpPos, courseDeg, az2, distanceM);
+
wp1->setDoubleValue("dist", distanceM * SG_METER_TO_NM);
wp1->setDoubleValue("true-bearing-deg", courseDeg);
courseDeg -= magvar->getDoubleValue(); // expose magnetic bearing
wp1->setDoubleValue("bearing-deg", courseDeg);
- setETAPropertyFromDistance(wp1->getChild("eta"), distanceM);
+ setETAPropertyFromDistance(wp1, distanceM);
wp1->setDoubleValue("distance-along-route-nm",
nextLeg->distanceAlongRoute());
wp1->setDoubleValue("remaining-distance-nm",
distanceToGo->setDoubleValue(totalDistanceRemaining);
wpn->setDoubleValue("dist", totalDistanceRemaining);
ete->setDoubleValue(totalDistanceRemaining / gs * 3600.0);
- setETAPropertyFromDistance(wpn->getChild("eta"), totalDistanceRemaining);
+ setETAPropertyFromDistance(wpn, totalDistanceRemaining);
}
void FGRouteMgr::clearRoute()
char eta_str[64];
double eta = aDistance * SG_METER_TO_NM / speed;
+ aProp->getChild("eta-seconds")->setIntValue( eta * 3600 );
if ( eta >= 100.0 ) {
eta = 99.999; // clamp
}
int major = (int)eta,
minor = (int)((eta - (int)eta) * 60.0);
snprintf( eta_str, 64, "%d:%02d", major, minor );
- aProp->setStringValue( eta_str );
+ aProp->getChild("eta")->setStringValue( eta_str );
}
void FGRouteMgr::removeLegAtIndex(int aIndex)
{
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
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) {
return false;
}
- _plan->setCurrentIndex(0);
+ _plan->activate();
active->setBoolValue(true);
SG_LOG(SG_AUTOPILOT, SG_INFO, "route-manager, activate route ok");
return true;
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) {
void FGRouteMgr::setDepartureRunway(const char* aIdent)
{
+ if (!_plan) {
+ return;
+ }
+
FGAirport* apt = _plan->departureAirport();
if (!apt || (aIdent == NULL)) {
_plan->setDeparture(apt);
void FGRouteMgr::setDepartureICAO(const char* aIdent)
{
+ if (!_plan) {
+ return;
+ }
+
if ((aIdent == NULL) || (strlen(aIdent) < 4)) {
_plan->setDeparture((FGAirport*) NULL);
} else {
void FGRouteMgr::setSID(const char* aIdent)
{
+ if (!_plan) {
+ return;
+ }
+
FGAirport* apt = _plan->departureAirport();
if (!apt || (aIdent == NULL)) {
_plan->setSID((flightgear::SID*) NULL);
void FGRouteMgr::setDestinationICAO(const char* aIdent)
{
+ if (!_plan) {
+ return;
+ }
+
if ((aIdent == NULL) || (strlen(aIdent) < 4)) {
_plan->setDestination((FGAirport*) NULL);
} else {
void FGRouteMgr::setDestinationRunway(const char* aIdent)
{
+ if (!_plan) {
+ return;
+ }
+
FGAirport* apt = _plan->destinationAirport();
if (!apt || (aIdent == NULL)) {
_plan->setDestination(apt);
void FGRouteMgr::setApproach(const char* aIdent)
{
+ if (!_plan) {
+ return;
+ }
+
FGAirport* apt = _plan->destinationAirport();
if (!strcmp(aIdent, "DEFAULT")) {
double enrouteCourse = -1.0;
void FGRouteMgr::setSTAR(const char* aIdent)
{
+ if (!_plan) {
+ return;
+ }
+
FGAirport* apt = _plan->destinationAirport();
if (!apt || (aIdent == NULL)) {
_plan->setSTAR((STAR*) NULL);
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);
+}
+