Merge branch 'jmt/gps' into next
Conflicts: src/Instrumentation/navradio.cxx
This commit is contained in:
commit
ebdeb3eed3
13 changed files with 1798 additions and 48 deletions
|
@ -1828,6 +1828,8 @@
|
||||||
</File>
|
</File>
|
||||||
<File RelativePath="..\..\..\src\GUI\WaypointList.cxx"></File>
|
<File RelativePath="..\..\..\src\GUI\WaypointList.cxx"></File>
|
||||||
<File RelativePath="..\..\..\src\GUI\WaypointList.hxx"></File>
|
<File RelativePath="..\..\..\src\GUI\WaypointList.hxx"></File>
|
||||||
|
<File RelativePath="..\..\..\src\GUI\MapWidget.cxx"></File>
|
||||||
|
<File RelativePath="..\..\..\src\GUI\MapWidget.hxx"></File>
|
||||||
</Filter>
|
</Filter>
|
||||||
<Filter
|
<Filter
|
||||||
Name="Lib_Input"
|
Name="Lib_Input"
|
||||||
|
|
|
@ -2647,6 +2647,8 @@
|
||||||
</File>
|
</File>
|
||||||
<File RelativePath="..\..\..\src\GUI\WaypointList.cxx"></File>
|
<File RelativePath="..\..\..\src\GUI\WaypointList.cxx"></File>
|
||||||
<File RelativePath="..\..\..\src\GUI\WaypointList.hxx"></File>
|
<File RelativePath="..\..\..\src\GUI\WaypointList.hxx"></File>
|
||||||
|
<File RelativePath="..\..\..\src\GUI\MapWidget.cxx"></File>
|
||||||
|
<File RelativePath="..\..\..\src\GUI\MapWidget.hxx"></File>
|
||||||
</Filter>
|
</Filter>
|
||||||
<Filter
|
<Filter
|
||||||
Name="Lib_Input"
|
Name="Lib_Input"
|
||||||
|
|
|
@ -597,6 +597,7 @@ void FGRouteMgr::jumpToIndex(int index)
|
||||||
|
|
||||||
_route->set_current(index);
|
_route->set_current(index);
|
||||||
currentWaypointChanged();
|
currentWaypointChanged();
|
||||||
|
_currentWpt->fireValueChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
void FGRouteMgr::currentWaypointChanged()
|
void FGRouteMgr::currentWaypointChanged()
|
||||||
|
|
|
@ -23,7 +23,8 @@ libGUI_a_SOURCES = \
|
||||||
property_list.cxx property_list.hxx \
|
property_list.cxx property_list.hxx \
|
||||||
layout.cxx layout-props.cxx layout.hxx \
|
layout.cxx layout-props.cxx layout.hxx \
|
||||||
SafeTexFont.cxx SafeTexFont.hxx \
|
SafeTexFont.cxx SafeTexFont.hxx \
|
||||||
WaypointList.cxx WaypointList.hxx
|
WaypointList.cxx WaypointList.hxx \
|
||||||
|
MapWidget.cxx MapWidget.hxx
|
||||||
|
|
||||||
INCLUDES = -I$(top_srcdir) -I$(top_srcdir)/src
|
INCLUDES = -I$(top_srcdir) -I$(top_srcdir)/src
|
||||||
|
|
||||||
|
|
1613
src/GUI/MapWidget.cxx
Normal file
1613
src/GUI/MapWidget.cxx
Normal file
File diff suppressed because it is too large
Load diff
109
src/GUI/MapWidget.hxx
Normal file
109
src/GUI/MapWidget.hxx
Normal file
|
@ -0,0 +1,109 @@
|
||||||
|
#ifndef GUI_MAPWIDGET_HXX
|
||||||
|
#define GUI_MAPWIDGET_HXX
|
||||||
|
|
||||||
|
#include <simgear/compiler.h>
|
||||||
|
#include <simgear/math/SGMath.hxx>
|
||||||
|
#include <simgear/props/props.hxx>
|
||||||
|
|
||||||
|
#include <plib/pu.h>
|
||||||
|
|
||||||
|
#include "dialog.hxx" // for GUI_ID
|
||||||
|
|
||||||
|
// forward decls
|
||||||
|
class FGRouteMgr;
|
||||||
|
class FGRunway;
|
||||||
|
class FGAirport;
|
||||||
|
class FGNavRecord;
|
||||||
|
class FGFix;
|
||||||
|
class MapData;
|
||||||
|
class SGMagVar;
|
||||||
|
|
||||||
|
class MapWidget : public puObject
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
MapWidget(int x, int y, int width, int height);
|
||||||
|
virtual ~MapWidget();
|
||||||
|
|
||||||
|
virtual void setSize(int width, int height);
|
||||||
|
virtual void doHit( int button, int updown, int x, int y ) ;
|
||||||
|
virtual void draw( int dx, int dy ) ;
|
||||||
|
virtual int checkKey(int key, int updown);
|
||||||
|
|
||||||
|
void setProperty(SGPropertyNode_ptr prop);
|
||||||
|
private:
|
||||||
|
void handlePan(int x, int y);
|
||||||
|
|
||||||
|
void pan(const SGVec2d& delta);
|
||||||
|
void zoomIn();
|
||||||
|
void zoomOut();
|
||||||
|
|
||||||
|
void paintAircraftLocation(const SGGeod& aircraftPos);
|
||||||
|
void paintRoute();
|
||||||
|
void paintRuler();
|
||||||
|
|
||||||
|
void drawGPSData();
|
||||||
|
void drawNavRadio(SGPropertyNode_ptr radio);
|
||||||
|
void drawTunedLocalizer(SGPropertyNode_ptr radio);
|
||||||
|
|
||||||
|
void drawLatLonGrid();
|
||||||
|
SGVec2d gridPoint(int ix, int iy);
|
||||||
|
bool drawLineClipped(const SGVec2d& a, const SGVec2d& b);
|
||||||
|
|
||||||
|
void drawAirports();
|
||||||
|
void drawAirport(FGAirport* apt);
|
||||||
|
int scoreAirportRunways(FGAirport* apt);
|
||||||
|
void drawRunwayPre(FGRunway* rwy);
|
||||||
|
void drawRunway(FGRunway* rwy);
|
||||||
|
void drawILS(bool tuned, FGRunway* rwy);
|
||||||
|
|
||||||
|
void drawNavaids();
|
||||||
|
void drawNDB(bool tuned, FGNavRecord* nav);
|
||||||
|
void drawVOR(bool tuned, FGNavRecord* nav);
|
||||||
|
void drawFix(FGFix* fix);
|
||||||
|
|
||||||
|
void drawTraffic();
|
||||||
|
void drawAIAircraft(const SGPropertyNode* model, const SGGeod& pos, double hdg);
|
||||||
|
void drawAIShip(const SGPropertyNode* model, const SGGeod& pos, double hdg);
|
||||||
|
|
||||||
|
void drawData();
|
||||||
|
bool validDataForKey(void* key);
|
||||||
|
MapData* getOrCreateDataForKey(void* key);
|
||||||
|
MapData* createDataForKey(void* key);
|
||||||
|
void setAnchorForKey(void* key, const SGVec2d& anchor);
|
||||||
|
|
||||||
|
SGVec2d project(const SGGeod& geod) const;
|
||||||
|
SGGeod unproject(const SGVec2d& p) const;
|
||||||
|
double currentScale() const;
|
||||||
|
|
||||||
|
void circleAt(const SGVec2d& center, int nSides, double r);
|
||||||
|
void circleAtAlt(const SGVec2d& center, int nSides, double r, double r2);
|
||||||
|
void drawLine(const SGVec2d& p1, const SGVec2d& p2);
|
||||||
|
void drawLegendBox(const SGVec2d& pos, const std::string& t);
|
||||||
|
|
||||||
|
int _width, _height;
|
||||||
|
int _zoom;
|
||||||
|
double _drawRangeNm;
|
||||||
|
double _upHeading; // true heading corresponding to +ve y-axis
|
||||||
|
bool _magneticHeadings;
|
||||||
|
|
||||||
|
SGGeod _projectionCenter;
|
||||||
|
SGGeod _aircraft;
|
||||||
|
SGGeod _clickGeod;
|
||||||
|
SGVec2d _hitLocation;
|
||||||
|
FGRouteMgr* _route;
|
||||||
|
SGPropertyNode_ptr _root;
|
||||||
|
SGPropertyNode_ptr _gps;
|
||||||
|
|
||||||
|
typedef std::map<void*, MapData*> KeyDataMap;
|
||||||
|
KeyDataMap _mapData;
|
||||||
|
std::vector<MapData*> _dataQueue;
|
||||||
|
|
||||||
|
SGMagVar* _magVar;
|
||||||
|
|
||||||
|
typedef std::map<int, SGVec2d> GridPointCache;
|
||||||
|
GridPointCache _gridCache;
|
||||||
|
double _gridSpacing;
|
||||||
|
SGGeod _gridCenter;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // of GUI_MAPWIDGET_HXX
|
|
@ -14,6 +14,7 @@
|
||||||
#include "property_list.hxx"
|
#include "property_list.hxx"
|
||||||
#include "layout.hxx"
|
#include "layout.hxx"
|
||||||
#include "WaypointList.hxx"
|
#include "WaypointList.hxx"
|
||||||
|
#include "MapWidget.hxx"
|
||||||
|
|
||||||
enum format_type { f_INVALID, f_INT, f_LONG, f_FLOAT, f_DOUBLE, f_STRING };
|
enum format_type { f_INVALID, f_INT, f_LONG, f_FLOAT, f_DOUBLE, f_STRING };
|
||||||
static const int FORMAT_BUFSIZE = 255;
|
static const int FORMAT_BUFSIZE = 255;
|
||||||
|
@ -815,7 +816,10 @@ FGDialog::makeObject (SGPropertyNode *props, int parentWidth, int parentHeight)
|
||||||
setupObject(obj, props);
|
setupObject(obj, props);
|
||||||
setColor(obj, props);
|
setColor(obj, props);
|
||||||
return obj;
|
return obj;
|
||||||
|
} else if (type == "map") {
|
||||||
|
MapWidget* mapWidget = new MapWidget(x, y, x + width, y + height);
|
||||||
|
setupObject(mapWidget, props);
|
||||||
|
return mapWidget;
|
||||||
} else if (type == "combo") {
|
} else if (type == "combo") {
|
||||||
fgComboBox *obj = new fgComboBox(x, y, x + width, y + height, props,
|
fgComboBox *obj = new fgComboBox(x, y, x + width, y + height, props,
|
||||||
props->getBoolValue("editable", false));
|
props->getBoolValue("editable", false));
|
||||||
|
@ -953,12 +957,21 @@ FGDialog::setupObject (puObject *object, SGPropertyNode *props)
|
||||||
name = "";
|
name = "";
|
||||||
const char *propname = props->getStringValue("property");
|
const char *propname = props->getStringValue("property");
|
||||||
SGPropertyNode_ptr node = fgGetNode(propname, true);
|
SGPropertyNode_ptr node = fgGetNode(propname, true);
|
||||||
copy_to_pui(node, object);
|
if (type == "map") {
|
||||||
|
// mapWidget binds to a sub-tree of properties, and
|
||||||
|
// ignroes the puValue mechanism, so special case things here
|
||||||
|
MapWidget* mw = static_cast<MapWidget*>(object);
|
||||||
|
mw->setProperty(node);
|
||||||
|
} else {
|
||||||
|
// normal widget, creating PropertyObject
|
||||||
|
copy_to_pui(node, object);
|
||||||
|
PropertyObject *po = new PropertyObject(name, object, node);
|
||||||
|
_propertyObjects.push_back(po);
|
||||||
|
if (props->getBoolValue("live"))
|
||||||
|
_liveObjects.push_back(po);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
PropertyObject *po = new PropertyObject(name, object, node);
|
|
||||||
_propertyObjects.push_back(po);
|
|
||||||
if (props->getBoolValue("live"))
|
|
||||||
_liveObjects.push_back(po);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SGPropertyNode *dest = fgGetNode("/sim/bindings/gui", true);
|
SGPropertyNode *dest = fgGetNode("/sim/bindings/gui", true);
|
||||||
|
|
|
@ -220,7 +220,8 @@ GPS::GPS ( SGPropertyNode *node) :
|
||||||
_num(node->getIntValue("number", 0)),
|
_num(node->getIntValue("number", 0)),
|
||||||
_computeTurnData(false),
|
_computeTurnData(false),
|
||||||
_anticipateTurn(false),
|
_anticipateTurn(false),
|
||||||
_inTurn(false)
|
_inTurn(false),
|
||||||
|
_desiredCourse(0.0)
|
||||||
{
|
{
|
||||||
string branch = "/instrumentation/" + _name;
|
string branch = "/instrumentation/" + _name;
|
||||||
_gpsNode = fgGetNode(branch.c_str(), _num, true );
|
_gpsNode = fgGetNode(branch.c_str(), _num, true );
|
||||||
|
@ -303,6 +304,7 @@ GPS::init ()
|
||||||
fromFlag->alias(wp1_node->getChild("from-flag"));
|
fromFlag->alias(wp1_node->getChild("from-flag"));
|
||||||
|
|
||||||
// autopilot drive properties
|
// autopilot drive properties
|
||||||
|
_apDrivingFlag = fgGetNode("/autopilot/settings/gps-driving-true-heading", true);
|
||||||
_apTrueHeading = fgGetNode("/autopilot/settings/true-heading-deg",true);
|
_apTrueHeading = fgGetNode("/autopilot/settings/true-heading-deg",true);
|
||||||
_apTargetAltitudeFt = fgGetNode("/autopilot/settings/target-altitude-ft", true);
|
_apTargetAltitudeFt = fgGetNode("/autopilot/settings/target-altitude-ft", true);
|
||||||
_apAltitudeLock = fgGetNode("/autopilot/locks/altitude", true);
|
_apAltitudeLock = fgGetNode("/autopilot/locks/altitude", true);
|
||||||
|
@ -958,12 +960,17 @@ void GPS::updateRouteData()
|
||||||
void GPS::driveAutopilot()
|
void GPS::driveAutopilot()
|
||||||
{
|
{
|
||||||
if (!_config.driveAutopilot() || !_realismSimpleGps->getBoolValue()) {
|
if (!_config.driveAutopilot() || !_realismSimpleGps->getBoolValue()) {
|
||||||
|
_apDrivingFlag->setBoolValue(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// compatability feature - allow the route-manager / GPS to drive the
|
// compatability feature - allow the route-manager / GPS to drive the
|
||||||
// generic autopilot heading hold *in leg mode only*
|
// generic autopilot heading hold *in leg mode only*
|
||||||
if (_mode == "leg") {
|
|
||||||
|
bool drive = _mode == "leg";
|
||||||
|
_apDrivingFlag->setBoolValue(drive);
|
||||||
|
|
||||||
|
if (drive) {
|
||||||
// FIXME: we want to set desired track, not heading, here
|
// FIXME: we want to set desired track, not heading, here
|
||||||
_apTrueHeading->setDoubleValue(getWP1Bearing());
|
_apTrueHeading->setDoubleValue(getWP1Bearing());
|
||||||
}
|
}
|
||||||
|
|
|
@ -413,6 +413,7 @@ private:
|
||||||
SGPropertyNode_ptr _realismSimpleGps; ///< should the GPS be simple or realistic?
|
SGPropertyNode_ptr _realismSimpleGps; ///< should the GPS be simple or realistic?
|
||||||
|
|
||||||
// autopilot drive properties
|
// autopilot drive properties
|
||||||
|
SGPropertyNode_ptr _apDrivingFlag;
|
||||||
SGPropertyNode_ptr _apTrueHeading;
|
SGPropertyNode_ptr _apTrueHeading;
|
||||||
SGPropertyNode_ptr _apTargetAltitudeFt;
|
SGPropertyNode_ptr _apTargetAltitudeFt;
|
||||||
SGPropertyNode_ptr _apAltitudeLock;
|
SGPropertyNode_ptr _apAltitudeLock;
|
||||||
|
|
|
@ -891,7 +891,7 @@ void FGNavRadio::search()
|
||||||
} else { // ILS or LOC
|
} else { // ILS or LOC
|
||||||
_gs = globals->get_gslist()->findByFreq(freq, pos);
|
_gs = globals->get_gslist()->findByFreq(freq, pos);
|
||||||
has_gs_node->setBoolValue(_gs != NULL);
|
has_gs_node->setBoolValue(_gs != NULL);
|
||||||
_localizerWidth = localizerWidth(nav);
|
_localizerWidth = nav->localizerWidth();
|
||||||
twist = 0.0;
|
twist = 0.0;
|
||||||
effective_range = nav->get_range();
|
effective_range = nav->get_range();
|
||||||
|
|
||||||
|
@ -941,39 +941,6 @@ void FGNavRadio::search()
|
||||||
id_c4_node->setIntValue( (int)identBuffer[3] );
|
id_c4_node->setIntValue( (int)identBuffer[3] );
|
||||||
}
|
}
|
||||||
|
|
||||||
double FGNavRadio::localizerWidth(FGNavRecord* aLOC)
|
|
||||||
{
|
|
||||||
FGRunway* rwy = aLOC->runway();
|
|
||||||
if (!rwy) {
|
|
||||||
return 6.0; // no runway associated, return default value
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
SGVec3d thresholdCart(SGVec3d::fromGeod(rwy->threshold()));
|
|
||||||
double axisLength = dist(aLOC->cart(), thresholdCart);
|
|
||||||
double landingLength = dist(thresholdCart, SGVec3d::fromGeod(rwy->end()));
|
|
||||||
|
|
||||||
// Reference: http://dcaa.slv.dk:8000/icaodocs/
|
|
||||||
// ICAO standard width at threshold is 210 m = 689 feet = approx 700 feet.
|
|
||||||
// ICAO 3.1.1 half course = DDM = 0.0775
|
|
||||||
// ICAO 3.1.3.7.1 Sensitivity 0.00145 DDM/m at threshold
|
|
||||||
// implies peg-to-peg of 214 m ... we will stick with 210.
|
|
||||||
// ICAO 3.1.3.7.1 "Course sector angle shall not exceed 6 degrees."
|
|
||||||
|
|
||||||
// Very short runway: less than 1200 m (4000 ft) landing length:
|
|
||||||
if (landingLength < 1200.0) {
|
|
||||||
// ICAO fudges localizer sensitivity for very short runways.
|
|
||||||
// This produces a non-monotonic sensitivity-versus length relation.
|
|
||||||
axisLength += 1050.0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Example: very short: San Diego KMYF (Montgomery Field) ILS RWY 28R
|
|
||||||
// Example: short: Tom's River KMJX (Robert J. Miller) ILS RWY 6
|
|
||||||
// Example: very long: Denver KDEN (Denver) ILS RWY 16R
|
|
||||||
double raw_width = 210.0 / axisLength * SGD_RADIANS_TO_DEGREES;
|
|
||||||
return raw_width < 6.0? raw_width : 6.0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void FGNavRadio::audioNavidChanged()
|
void FGNavRadio::audioNavidChanged()
|
||||||
{
|
{
|
||||||
if (_sgr->exists(nav_fx_name)) {
|
if (_sgr->exists(nav_fx_name)) {
|
||||||
|
|
|
@ -191,11 +191,6 @@ class FGNavRadio : public SGSubsystem, public SGPropertyChangeListener
|
||||||
|
|
||||||
void clearOutputs();
|
void clearOutputs();
|
||||||
|
|
||||||
/**
|
|
||||||
* Compute the localizer width in degrees - see implementation for
|
|
||||||
* more information on the relevant standards and formulae.
|
|
||||||
*/
|
|
||||||
double localizerWidth(FGNavRecord* aLOC);
|
|
||||||
FGNavRecord* findPrimaryNavaid(const SGGeod& aPos, double aFreqMHz);
|
FGNavRecord* findPrimaryNavaid(const SGGeod& aPos, double aFreqMHz);
|
||||||
|
|
||||||
/// accessor for tied, read-only 'operable' property
|
/// accessor for tied, read-only 'operable' property
|
||||||
|
|
|
@ -181,6 +181,38 @@ void FGNavRecord::alignLocaliserWithRunway(double aThreshold)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
double FGNavRecord::localizerWidth() const
|
||||||
|
{
|
||||||
|
if (!mRunway) {
|
||||||
|
return 6.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
SGVec3d thresholdCart(SGVec3d::fromGeod(mRunway->threshold()));
|
||||||
|
double axisLength = dist(cart(), thresholdCart);
|
||||||
|
double landingLength = dist(thresholdCart, SGVec3d::fromGeod(mRunway->end()));
|
||||||
|
|
||||||
|
// Reference: http://dcaa.slv.dk:8000/icaodocs/
|
||||||
|
// ICAO standard width at threshold is 210 m = 689 feet = approx 700 feet.
|
||||||
|
// ICAO 3.1.1 half course = DDM = 0.0775
|
||||||
|
// ICAO 3.1.3.7.1 Sensitivity 0.00145 DDM/m at threshold
|
||||||
|
// implies peg-to-peg of 214 m ... we will stick with 210.
|
||||||
|
// ICAO 3.1.3.7.1 "Course sector angle shall not exceed 6 degrees."
|
||||||
|
|
||||||
|
// Very short runway: less than 1200 m (4000 ft) landing length:
|
||||||
|
if (landingLength < 1200.0) {
|
||||||
|
// ICAO fudges localizer sensitivity for very short runways.
|
||||||
|
// This produces a non-monotonic sensitivity-versus length relation.
|
||||||
|
axisLength += 1050.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Example: very short: San Diego KMYF (Montgomery Field) ILS RWY 28R
|
||||||
|
// Example: short: Tom's River KMJX (Robert J. Miller) ILS RWY 6
|
||||||
|
// Example: very long: Denver KDEN (Denver) ILS RWY 16R
|
||||||
|
double raw_width = 210.0 / axisLength * SGD_RADIANS_TO_DEGREES;
|
||||||
|
return raw_width < 6.0? raw_width : 6.0;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
FGTACANRecord::FGTACANRecord(void) :
|
FGTACANRecord::FGTACANRecord(void) :
|
||||||
channel(""),
|
channel(""),
|
||||||
freq(0)
|
freq(0)
|
||||||
|
|
|
@ -96,6 +96,13 @@ public:
|
||||||
* Retrieve the runway this navaid is associated with (for ILS/LOC/GS)
|
* Retrieve the runway this navaid is associated with (for ILS/LOC/GS)
|
||||||
*/
|
*/
|
||||||
FGRunway* runway() const { return mRunway; }
|
FGRunway* runway() const { return mRunway; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* return the localizer width, in degrees
|
||||||
|
* computation is based up ICAO stdandard width at the runway threshold
|
||||||
|
* see implementation for further details.
|
||||||
|
*/
|
||||||
|
double localizerWidth() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
class FGTACANRecord : public SGReferenced {
|
class FGTACANRecord : public SGReferenced {
|
||||||
|
|
Loading…
Reference in a new issue