From 3ab197a0006f9a9ec8afbb84b6e236a7e9aa1b66 Mon Sep 17 00:00:00 2001 From: Richard Harrison Date: Mon, 19 Apr 2021 18:04:47 +0200 Subject: [PATCH] Active Tower improvements. Previous commit removed the logic that sets the tower position and altitude; this commit fixes this. Also added limits and default for tower altitude because there are a lot of towers that are at the same altitude as the airport; this is clearly a lack of data. Also there are some towers that are ludicrously high (e.g. KLSV). This commit defines a reasonable minimum and maximum values for tower altitude; together with a default altitude which will be added to the airport elevation when the tower altitude is outside of these ranges (above airpot altitude). --------------- I used the following queries can against the navdata cache to figure out what sensible values were: to locate overly tall towers select a.type, a.ident, a.name, (p.elev_m - a.elev_m) from positioned as p inner join positioned as a on a.octree_node = p.octree_node where p.type=22 and a.type=1 and abs(p.elev_m - a.elev_m) > 100 to locate towers at ground level: select a.type, a.ident, a.name, (p.elev_m - a.elev_m) from positioned as p inner join positioned as a on a.octree_node = p.octree_node where p.type=22 and a.type=1 and abs(p.elev_m - a.elev_m) < 0.1 to calculate the average tower height select avg(p.elev_m - a.elev_m) from positioned as p inner join positioned as a on a.octree_node = p.octree_node where p.type=22 and a.type=1 and abs(p.elev_m - a.elev_m) --- src/Environment/environment_mgr.cxx | 62 ++++++++++++++++++++++------- src/Environment/environment_mgr.hxx | 4 ++ 2 files changed, 51 insertions(+), 15 deletions(-) diff --git a/src/Environment/environment_mgr.cxx b/src/Environment/environment_mgr.cxx index 6628b83ec..b68002be4 100644 --- a/src/Environment/environment_mgr.cxx +++ b/src/Environment/environment_mgr.cxx @@ -86,6 +86,9 @@ void FG3DCloudsListener::valueChanged( SGPropertyNode * node ) FGEnvironmentMgr::FGEnvironmentMgr () : _environment(new FGEnvironment()), + _multiplayerListener(nullptr), + nearestAirport(nullptr), + nearestCarrier(nullptr), _sky(globals->get_renderer()->getSky()) { fgClouds = new FGClouds; @@ -99,6 +102,9 @@ FGEnvironmentMgr::FGEnvironmentMgr () : set_subsystem("ridgelift", new FGRidgeLift); set_subsystem("magvar", new FGMagVarManager); + max_tower_height_feet = fgGetDouble("/sim/airport/max-tower-height-ft", 70); + min_tower_height_feet = fgGetDouble("/sim/airport/min-tower-height-ft", 6); + default_tower_height_feet = fgGetDouble("default-tower-height-ft", 30); } FGEnvironmentMgr::~FGEnvironmentMgr () @@ -339,11 +345,26 @@ void FGEnvironmentMgr::updateClosestAirport() fgSetString("/sim/airport/closest-airport-id", nearestAirport->ident().c_str()); } - if (nearestAirport->hasTower()) + if (nearestAirport->hasTower()) { nearestTowerPosition = nearestAirport->getTowerLocation(); - else + SG_LOG(SG_ENVIRONMENT, SG_DEBUG, "airport-id=" << nearestAirport->getId() << " tower_pos=" << nearestTowerPosition); + } + else { nearestTowerPosition = nearestAirport->geod(); - + SG_LOG(SG_ENVIRONMENT, SG_DEBUG, "no tower for airport-id=" << nearestAirport->getId()); + } + //Ensure that the tower isn't at ground level by adding a nominal amount + //TODO: (fix the data so that too short or too tall towers aren't present in the data) + auto towerAirpotDistance = abs(nearestTowerPosition.getElevationFt() - nearestAirport->geod().getElevationFt()); + if (towerAirpotDistance < min_tower_height_feet) { + nearestTowerPosition.setElevationFt(nearestTowerPosition.getElevationFt() + default_tower_height_feet); + SG_LOG(SG_ENVIRONMENT, SG_DEBUG, "Tower altitude adjusted because it was at below minimum height above ground (" << min_tower_height_feet << "feet) for airport " << nearestAirport->getId()); + } + else if (towerAirpotDistance > max_tower_height_feet) { + nearestTowerPosition.setElevationFt(nearestTowerPosition.getElevationFt() + default_tower_height_feet); + SG_LOG(SG_ENVIRONMENT, SG_DEBUG, "Tower altitude adjusted because it was taller than the permitted maximum of (" << max_tower_height_feet << "feet) for airport " << nearestAirport->getId()); + } + // nearestIdent = nearestAirport->ident(); nearestTowerPositionValid = true; @@ -373,21 +394,18 @@ void FGEnvironmentMgr::updateClosestAirport() nearestCarrier = nullptr; } - if (nearestCarrier != nullptr) { + // figure out if the carrier's tower is closer + if (!nearestTowerPositionValid || (nearestCarrier != nullptr && nctn->GetDistanceMeters() < towerDistance)) { SGGeod carrierGeod(*nctn->GetPosition()); + nearestIdent = nctn->GetCarrierIdent(); + nearestTowerPositionValid = true; - // figure out if the carrier's tower is closer - if (!nearestTowerPositionValid || nctn->GetDistanceMeters() < towerDistance) { - nearestTowerPosition = carrierGeod; - nearestIdent = nctn->GetCarrierIdent(); - nearestTowerPositionValid = true; + // + // these will be used to determine and update the tower position + towerViewPositionLatDegNode = nctn->GetViewPositionLatNode(); + towerViewPositionLonDegNode = nctn->GetViewPositionLonNode(); + towerViewPositionAltFtNode = nctn->GetViewPositionAltNode(); - // - // these will be used to determine and update the tower position - towerViewPositionLatDegNode = nctn->GetViewPositionLatNode(); - towerViewPositionLonDegNode = nctn->GetViewPositionLonNode(); - towerViewPositionAltFtNode = nctn->GetViewPositionAltNode(); - } // although the carrier is moving - these values can afford to be 10 seconds old so we don't need to // update them. fgSetDouble("/sim/airport/nearest-carrier-latitude-deg", nctn->GetPosition()->getLatitudeDeg()); @@ -395,6 +413,20 @@ void FGEnvironmentMgr::updateClosestAirport() fgSetDouble("/sim/airport/nearest-carrier-altitude-ft", nctn->GetPosition()->getElevationFt()); fgSetDouble("/sim/airport/nearest-carrier-deck-height", nctn->GetDeckheight()); } + else { + if (nearestAirport != nullptr) { + std::string path = ViewPropertyEvaluator::getStringValue("(/sim/view[(/sim/current-view/view-number-raw)]/config/root)/sim/tower/"); + fgSetString(path + "airport-id", nearestAirport->getId()); + + fgSetDouble(path + "latitude-deg", nearestTowerPosition.getLatitudeDeg()); + fgSetDouble(path + "longitude-deg", nearestTowerPosition.getLongitudeDeg()); + fgSetDouble(path + "altitude-ft", nearestTowerPosition.getElevationFt()); + } + else { + SG_LOG(SG_ENVIRONMENT, SG_DEBUG, "FGEnvironmentMgr::update: No airport or carrier within 100NM range of current multiplayer aircraft"); + } + } + if (fgGetString("/sim/airport/nearest-tower-ident") != nearestIdent) { SG_LOG(SG_ENVIRONMENT, SG_ALERT, "Nearest airport tower now " << nearestIdent); diff --git a/src/Environment/environment_mgr.hxx b/src/Environment/environment_mgr.hxx index bb6f417c5..4467d20e0 100644 --- a/src/Environment/environment_mgr.hxx +++ b/src/Environment/environment_mgr.hxx @@ -99,6 +99,10 @@ private: FGEnvironment * _environment = nullptr; // always the same, for now FGClouds *fgClouds = nullptr; bool _cloudLayersDirty = true; + int max_tower_height_feet; + int min_tower_height_feet; + int default_tower_height_feet; + simgear::TiedPropertyList _tiedProperties; SGPropertyChangeListener * _3dCloudsEnableListener; FGEnvironmentMgrMultiplayerListener * _multiplayerListener;