1
0
Fork 0

Use ground-network to improve MP start location.

Search for the closest ground-net node near but /not/ on, the requested
runway. This works fairly well, although for some airports the selected
node is surprisingly far from the runway.
This commit is contained in:
James Turner 2016-11-13 22:20:40 +01:00
parent 1c4656512a
commit eaf779deb2
3 changed files with 39 additions and 18 deletions

View file

@ -36,6 +36,9 @@
#include <simgear/scene/util/OsgMath.hxx>
#include <simgear/structure/exception.hxx>
#include <simgear/timing/timestamp.hxx>
#include <simgear/math/SGLineSegment.hxx>
#include <simgear/math/SGGeometryFwd.hxx>
#include <simgear/math/SGIntersect.hxx>
#include <Airports/airport.hxx>
#include <Airports/runways.hxx>
@ -222,18 +225,28 @@ FGTaxiNodeRef FGGroundNetwork::findNearestNode(const SGGeod & aGeod) const
return result;
}
FGTaxiNodeRef FGGroundNetwork::findNearestNodeOffRunway(const SGGeod& aGeod) const
FGTaxiNodeRef FGGroundNetwork::findNearestNodeOffRunway(const SGGeod& aGeod, FGRunway* rwy, double marginM) const
{
SGVec3d cartPos = SGVec3d::fromGeod(aGeod);
auto node = std::min_element(m_nodes.begin(), m_nodes.end(),
[cartPos](const FGTaxiNodeRef& a, const FGTaxiNodeRef& b)
{
double aDist = a->getIsOnRunway() ? DBL_MAX : distSqr(cartPos, a->cart());
double bDist = b->getIsOnRunway() ? DBL_MAX : distSqr(cartPos, b->cart());
return aDist < bDist;
});
FGTaxiNodeVector nodes;
const SGLineSegmentd runwayLine(rwy->cart(), SGVec3d::fromGeod(rwy->end()));
const double marginMSqr = marginM * marginM;
const SGVec3d cartPos = SGVec3d::fromGeod(aGeod);
if (node == m_nodes.end()) {
std::copy_if(m_nodes.begin(), m_nodes.end(), std::back_inserter(nodes),
[runwayLine, cartPos, marginMSqr] (const FGTaxiNodeRef& a)
{
if (a->getIsOnRunway()) return false;
return (distSqr(runwayLine, a->cart()) >= marginMSqr);
});
// find closest of matching nodes
auto node = std::min_element(nodes.begin(), nodes.end(),
[cartPos](const FGTaxiNodeRef& a, const FGTaxiNodeRef& b)
{ return distSqr(cartPos, a->cart()) < distSqr(cartPos, b->cart()); });
if (node == nodes.end()) {
return FGTaxiNodeRef();
}

View file

@ -249,7 +249,7 @@ public:
FGTaxiNodeRef findNearestNode(const SGGeod& aGeod) const;
FGTaxiNodeRef findNearestNodeOnRunway(const SGGeod& aGeod, FGRunway* aRunway = NULL) const;
FGTaxiNodeRef findNearestNodeOffRunway(const SGGeod& aGeod) const;
FGTaxiNodeRef findNearestNodeOffRunway(const SGGeod& aGeod, FGRunway* aRunway, double distanceM) const;
FGTaxiSegment *findSegment(unsigned int idx) const;

View file

@ -36,6 +36,7 @@
#include <Airports/runways.hxx>
#include <Airports/airport.hxx>
#include <Airports/dynamics.hxx>
#include <Airports/groundnetwork.hxx>
#include <AIModel/AIManager.hxx>
#include <GUI/MessageBox.hxx>
@ -166,21 +167,28 @@ boost::tuple<SGGeod, double> runwayStartPos(FGRunwayRef runway)
{
fgSetString("/sim/atc/runway", runway->ident().c_str());
double offsetNm = fgGetDouble("/sim/presets/offset-distance-nm");
double startOffset = fgGetDouble("/sim/airport/runways/start-offset-m", 5.0);
SGGeod pos = runway->pointOnCenterline(startOffset);
if (isMPEnabled() && (fabs(offsetNm) <0.1)) {
SG_LOG( SG_GENERAL, SG_WARN, "Requested to start on " << runway->airport()->ident() << "/" <<
runway->ident() << ", MP is enabled so computing hold short position to avoid runway incursion");
// set this so multiplayer.nas can inform the user
fgSetBool("/sim/presets/avoided-mp-runway", true);
FGGroundNetwork* groundNet = runway->airport()->groundNetwork();
// add a margin, try to keep the entire aeroplane comfortable off the
// runway.
double margin = startOffset + (runway->widthM() * 1.5);
FGTaxiNodeRef taxiNode = groundNet ? groundNet->findNearestNodeOffRunway(pos, runway, margin) : 0;
if (taxiNode) {
// set this so multiplayer.nas can inform the user
fgSetBool("/sim/presets/avoided-mp-runway", true);
return boost::make_tuple(taxiNode->geod(), SGGeodesy::courseDeg(taxiNode->geod(), pos));
}
double width = runway->widthM();
double offset = fgGetDouble("/sim/airport/runways/start-offset-m", 5.0) + width;
SGGeod pos = runway->pointOffCenterline(width * 0.5, -offset);
return boost::make_tuple(pos, runway->headingDeg() + 90.0);
// if we couldn't find a suitable taxi-node, give up. Guessing a position
// causes too much pain (starting in the water or similar bad things)
}
SGGeod pos = runway->pointOnCenterline(fgGetDouble("/sim/airport/runways/start-offset-m", 5.0));
return boost::make_tuple(pos, runway->headingDeg());
}