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:
parent
1c4656512a
commit
eaf779deb2
3 changed files with 39 additions and 18 deletions
src
|
@ -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();
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue