FlightGear next
gps.hxx
Go to the documentation of this file.
1/*
2 * SPDX-License-Identifier: CC0-1.0
3 *
4 * gps.hxx - distance-measuring equipment.
5 * Written by David Megginson, started 2003.
6 *
7 * This file is in the Public Domain and comes with no warranty.
8*/
9
10#pragma once
11
12#include <cassert>
13#include <memory>
14
15#include <simgear/props/props.hxx>
16#include <simgear/structure/subsystem_mgr.hxx>
17#include <simgear/props/tiedpropertylist.hxx>
18
22
23#define FG_210_COMPAT 1
24
60class GPS : public SGSubsystem,
61 public flightgear::RNAV,
63{
64public:
65 GPS (SGPropertyNode *node, bool defaultGPSMode = false);
66 GPS ();
67 virtual ~GPS();
68
69 // SGSubsystem interface
70 void init() override;
71 void reinit() override;
72 void bind() override;
73 void unbind() override;
74 void update (double delta_time_sec) override;
75 void shutdown() override;
76
77 // Subsystem identification.
78 static const char* staticSubsystemClassId() { return "gps"; }
79
80 // RNAV interface
81 SGGeod position() override;
82 double trackDeg() override;
83 double groundSpeedKts() override;
84 double vspeedFPM() override;
85 double magvarDeg() override;
86 double selectedMagCourse() override;
87 double overflightDistanceM() override;
88 double overflightArmDistanceM() override;
89 double overflightArmAngleDeg() override;
90 bool canFlyBy() const override;
91 double maxFlyByTurnAngleDeg() const override;
92
93 std::optional<LegData> previousLegData() override;
94
95 std::optional<double> nextLegTrack() override;
96
97 double turnRadiusNm(double groundSpeedKnots) override;
98private:
99 friend class SearchFilter;
100
101 void setFlyByMaxTurnAngle(double maxAngle);
102
106 class Config
107 {
108 public:
109 Config();
110
111 void bind(GPS* aOwner, SGPropertyNode* aCfg);
112
113 bool turnAnticipationEnabled() const { return _enableTurnAnticipation; }
114
119 double turnRateDegSec() const { return _turnRate; }
120
124 double overflightDistanceNm() const { return _overflightDistance; }
130 double overflightArmDistanceNm() const { return _overflightArmDistance; }
134 double overflightArmAngleDeg() const { return _overflightArmAngle; }
135
139 double waypointAlertTime() const { return _waypointAlertTime; }
140
141 bool requireHardSurface() const { return _requireHardSurface; }
142
143 bool cdiDeflectionIsAngular() const { return (_cdiMaxDeflectionNm <= 0.0); }
144
145 double cdiDeflectionLinearPeg() const
146 {
147 assert(_cdiMaxDeflectionNm > 0.0);
148 return _cdiMaxDeflectionNm;
149 }
150
151 bool driveAutopilot() const { return _driveAutopilot; }
152
153 bool courseSelectable() const { return _courseSelectable; }
154
162 bool followLegTrackToFix() const { return _followLegTrackToFix; }
163
164
165 bool delegateDoesSequencing() const { return _delegateSequencing; }
166
167 double maxFlyByTurnAngleDeg() const { return _maxFlyByTurnAngle; }
168
169 void setMaxFlyByTurnAngle(double deg)
170 {
171 _maxFlyByTurnAngle = deg;
172 }
173
174 private:
175 bool _enableTurnAnticipation;
176
177 // desired turn rate in degrees per second
178 double _turnRate;
179
180 // distance from waypoint to arm overflight sequencing (in nm)
181 double _overflightDistance;
182
183 // distance from waypoint to arm overflight sequencing (in nm)
184 double _overflightArmDistance;
185
186 //abs angle from course to waypoint to arm overflight sequencing (in deg)
187 double _overflightArmAngle;
188
189 // time before reaching a waypoint to trigger annunciator light/sound
190 // (in seconds)
191 double _waypointAlertTime;
192
193 // should we require a hard-surfaced runway when filtering?
194 bool _requireHardSurface;
195
196 double _cdiMaxDeflectionNm;
197
198 // should we drive the autopilot directly or not?
199 bool _driveAutopilot;
200
201 // is selected-course-deg read to set desired-course or not?
202 bool _courseSelectable;
203
204 // do we fly direct to fixes, or follow the leg track closely?
205 bool _followLegTrackToFix;
206
207 // do we handle waypoint sequencing ourselves, or let the delegate do it?
208 // default is we do it, for backwards compatability
209 bool _delegateSequencing = false;
210
211 double _maxFlyByTurnAngle = 90.0;
212 };
213
214 class SearchFilter : public FGPositioned::Filter
215 {
216 public:
217 virtual bool pass(FGPositioned* aPos) const;
218
219 virtual FGPositioned::Type minType() const;
220 virtual FGPositioned::Type maxType() const;
221 };
222
224 void clearOutput();
225
226 void updateBasicData(double dt);
227
228 void updateTrackingBug();
229 void updateRouteData();
230 void driveAutopilot();
231
233 void wp1Changed();
234
235 void clearScratch();
236
239 bool isScratchPositionValid() const;
240 FGPositionedRef positionedFromScratch() const;
241
242#if FG_210_COMPAT
243 void setScratchFromPositioned(FGPositioned* aPos, int aIndex);
244 void setScratchFromCachedSearchResult();
245 void setScratchFromRouteWaypoint(int aIndex);
246
248 void addAirportToScratch(FGAirport* aAirport);
249
250 FGPositioned::Filter* createFilter(FGPositioned::Type aTy);
251
253 void performSearch();
254
255 // command handlers
256 void loadRouteWaypoint();
257 void loadNearest();
258 void search();
259 void nextResult();
260 void previousResult();
261 void defineWaypoint();
262 void insertWaypointAtIndex(int aIndex);
263 void removeWaypointAtIndex(int aIndex);
264 void commandExitHold();
265
266 // tied-property getter/setters
267 double getScratchDistance() const;
268 double getScratchMagBearing() const;
269 double getScratchTrueBearing() const;
270 bool getScratchHasNext() const;
271
272#endif
273
274 // command handlers
275 void selectLegMode();
276 void selectOBSMode(flightgear::Waypt* waypt);
277 void directTo();
278
279 // tied-property getter/setters
280 void setCommand(const char* aCmd);
281 const char* getCommand() const { return ""; }
282
283 const char* getMode() const { return _mode.c_str(); }
284 bool getScratchValid() const { return _scratchValid; }
285
286 double getSelectedCourse() const { return _selectedCourse; }
287 void setSelectedCourse(double crs);
288 double getDesiredCourse() const { return _desiredCourse; }
289
290 double getCDIDeflection() const;
291
292 double getLegDistance() const;
293 double getLegCourse() const;
294 double getLegMagCourse() const;
295
296 double getTrueTrack() const { return _last_true_track; }
297 double getMagTrack() const;
298 double getGroundspeedKts() const { return _last_speed_kts; }
299 double getVerticalSpeed() const { return _last_vertical_speed; }
300
301 const char* getWP0Ident() const;
302 const char* getWP0Name() const;
303
304 bool getWP1IValid() const;
305 const char* getWP1Ident() const;
306 const char* getWP1Name() const;
307
308 double getWP1Distance() const;
309 double getWP1TTW() const;
310 const char* getWP1TTWString() const;
311 double getWP1Bearing() const;
312 double getWP1MagBearing() const;
313 double getWP1CourseDeviation() const;
314 double getWP1CourseErrorNm() const;
315 bool getWP1ToFlag() const;
316 bool getWP1FromFlag() const;
317
318 // true-bearing-error and mag-bearing-error
319
320 double computeTurnRadiusNm(double aGroundSpeedKts) const;
321
325 template <typename T>
326 void tie(SGPropertyNode* aNode, const char* aRelPath, const SGRawValue<T>& aRawValue)
327 {
328 _tiedProperties.Tie(aNode->getNode(aRelPath, true), aRawValue);
329 }
330
332 void tieSGGeod(SGPropertyNode* aNode, SGGeod& aRef,
333 const char* lonStr, const char* latStr, const char* altStr);
334
336 void tieSGGeodReadOnly(SGPropertyNode* aNode, SGGeod& aRef,
337 const char* lonStr, const char* latStr, const char* altStr);
338
339 void updateCurrentWpNode(const SGGeod& p);
340
341// FlightPlan::Delegate
342 void currentWaypointChanged() override;
343 void waypointsChanged() override;
344 void cleared() override;
345 void endOfFlightPlan() override;
346
347 void doSequence();
348 void routeManagerFlightPlanChanged(SGPropertyNode*);
349 void routeActivated(SGPropertyNode*);
350
351// members
352 SGPropertyNode_ptr _gpsNode;
353 SGPropertyNode_ptr _currentWayptNode;
354 SGPropertyNode_ptr _currentWpLatNode,
355 _currentWpLonNode, _currentWpAltNode;
356
357 SGPropertyNode_ptr _magvar_node;
358 SGPropertyNode_ptr _serviceable_node;
359 SGPropertyNode_ptr _electrical_node;
360 SGPropertyNode_ptr _tracking_bug_node;
361 SGPropertyNode_ptr _raim_node;
362
363 SGPropertyNode_ptr _odometer_node;
364 SGPropertyNode_ptr _trip_odometer_node;
365 SGPropertyNode_ptr _true_bug_error_node;
366 SGPropertyNode_ptr _magnetic_bug_error_node;
367 SGPropertyNode_ptr _eastWestVelocity;
368 SGPropertyNode_ptr _northSouthVelocity;
369
370 // SGPropertyNode_ptr _route_active_node;
371 SGPropertyNode_ptr _route_current_wp_node;
372 SGPropertyNode_ptr _routeDistanceNm;
373 SGPropertyNode_ptr _routeETE;
374 SGPropertyNode_ptr _desiredCourseNode;
375
376 double _selectedCourse;
377 double _desiredCourse;
378
379 bool _dataValid;
380 SGGeod _last_pos;
381 bool _lastPosValid;
382 double _last_speed_kts;
383 double _last_true_track;
384 double _last_vertical_speed;
385 double _lastEWVelocity;
386 double _lastNSVelocity;
387
395 bool _defaultGPSMode;
396
397 std::string _mode;
398 Config _config;
399 std::string _name;
400 int _num;
401
402 SGGeod _wp0_position;
403 SGGeod _indicated_pos;
404 double _legDistanceNm;
405
406 // scratch data
407 SGGeod _scratchPos;
408 SGPropertyNode_ptr _scratchNode;
409 bool _scratchValid;
410#if FG_210_COMPAT
411 // search data
412 int _searchResultIndex;
413 std::string _searchQuery;
414 FGPositioned::Type _searchType;
415 bool _searchExact;
416 FGPositionedList _searchResults;
417 bool _searchIsRoute;
418 bool _searchHasNext;
419 bool _searchNames;
420#endif
421
422 std::optional<RNAV::LegData> _wp0Data;
423
424 std::unique_ptr<flightgear::WayptController> _wayptController;
425
426 flightgear::WayptRef _prevWaypt;
427 flightgear::WayptRef _currentWaypt;
428
429 // autopilot drive properties
430 SGPropertyNode_ptr _apDrivingFlag;
431 SGPropertyNode_ptr _apTrueHeading;
432
433 simgear::TiedPropertyList _tiedProperties;
434
436
437 SGPropertyChangeCallback<GPS> _callbackFlightPlanChanged;
438 SGPropertyChangeCallback<GPS> _callbackRouteActivated;
439};
#define p(x)
SGSharedPtr< FGPositioned > FGPositionedRef
Definition airways.hxx:30
void unbind() override
Definition gps.cxx:280
std::optional< double > nextLegTrack() override
Definition gps.cxx:500
double magvarDeg() override
Magnetic variation at current position.
Definition gps.cxx:470
double maxFlyByTurnAngleDeg() const override
maximum angle in degrees where flyBy is permitted.
Definition gps.cxx:495
double trackDeg() override
True track in degrees.
Definition gps.cxx:455
double vspeedFPM() override
Vertical speed in ft/minute.
Definition gps.cxx:465
double selectedMagCourse() override
device selected course (eg, from autopilot / MCP / OBS) in degrees
Definition gps.cxx:490
double groundSpeedKts() override
Ground speed (along the track) in knots.
Definition gps.cxx:460
std::optional< LegData > previousLegData() override
device leg previous waypoint position(eg, from route manager)
Definition gps.cxx:509
void shutdown() override
Definition gps.cxx:387
SGGeod position() override
Definition gps.cxx:446
static const char * staticSubsystemClassId()
Definition gps.hxx:78
void init() override
Definition gps.cxx:137
bool canFlyBy() const override
Definition gps.cxx:536
void reinit() override
Definition gps.cxx:182
void bind() override
Definition gps.cxx:188
double overflightArmAngleDeg() override
angle for overflight sequencing.
Definition gps.cxx:485
void update(double delta_time_sec) override
Definition gps.cxx:320
double overflightArmDistanceM() override
minimum distance to a waypoint for overflight sequencing.
Definition gps.cxx:480
GPS(SGPropertyNode *node, bool defaultGPSMode=false)
Definition gps.cxx:104
double overflightDistanceM() override
minimum distance to switch next waypoint.
Definition gps.cxx:475
virtual ~GPS()
Definition gps.cxx:132
Abstract RNAV interface, for devices which implement an RNAV system - INS / GPS / FMS.
double turnRadiusNm()
compute turn radius based on current ground-speed
SGSharedPtr< FlightPlan > FlightPlanRef
SGSharedPtr< Waypt > WayptRef
std::vector< FGPositionedRef > FGPositionedList