The track is computed between two subsequent settings of the geodetic position and represents the true track.
Also the _set_Latitude() and _set_Longitude() methods were removed. Use _set_Geodetic_Position(lat,lon) instead.
_set_V_calibrated_kts( kts );
_set_V_ground_speed( kts );
- SGGeod pos = SGGeod::fromDegM(get_Longitude(), get_Latitude(), get_Altitude());
+ SGGeod pos = getPosition();
// update (lon/lat) position
SGGeod pos2;
double az2;
geo_direct_wgs_84 ( pos, heading * SGD_RADIANS_TO_DEGREES,
dist, pos2, &az2 );
- _set_Longitude( pos2.getLongitudeRad() );
- _set_Latitude( pos2.getLatitudeRad() );
+ _set_Geodetic_Position( pos2.getLatitudeRad(), pos2.getLongitudeRad(), pos.getElevationFt() );
double sl_radius, lat_geoc;
sgGeodToGeoc( get_Latitude(), get_Altitude(), &sl_radius, &lat_geoc );
get_Psi() * SGD_RADIANS_TO_DEGREES,
dist, &lat2, &lon2, &az2 );
- _set_Longitude( lon2 * SGD_DEGREES_TO_RADIANS );
- _set_Latitude( lat2 * SGD_DEGREES_TO_RADIANS );
+ _set_Geodetic_Position( lat2 * SGD_DEGREES_TO_RADIANS, lon2 * SGD_DEGREES_TO_RADIANS );
}
// cout << "lon error = " << fabs(end.x()*SGD_RADIANS_TO_DEGREES - lon2)
get_Psi() * SGD_RADIANS_TO_DEGREES,
dist, &lat2, &lon2, &az2 );
- _set_Longitude( lon2 * SGD_DEGREES_TO_RADIANS );
- _set_Latitude( lat2 * SGD_DEGREES_TO_RADIANS );
+ _set_Geodetic_Position( lat2 * SGD_DEGREES_TO_RADIANS, lon2 * SGD_DEGREES_TO_RADIANS );
}
// cout << "lon error = " << fabs(end.x()*SGD_RADIANS_TO_DEGREES - lon2)
&FGInterface::get_Psi_deg,
&FGInterface::set_Psi_deg);
fgSetArchivable("/orientation/heading-deg");
+ fgTie("/orientation/track-deg", this,
+ &FGInterface::get_Track);
// Body-axis "euler rates" (rotation speed, but in a funny
// representation).
fgUntie("/orientation/roll-deg");
fgUntie("/orientation/pitch-deg");
fgUntie("/orientation/heading-deg");
+ fgUntie("/orientation/track-deg");
fgUntie("/orientation/roll-rate-degps");
fgUntie("/orientation/pitch-rate-degps");
fgUntie("/orientation/yaw-rate-degps");
void FGInterface::_updatePositionM(const SGVec3d& cartPos)
{
+ TrackComputer tracker( track, geodetic_position_v );
cartesian_position_v = cartPos;
geodetic_position_v = SGGeod::fromCart(cartesian_position_v);
geocentric_position_v = SGGeoc::fromCart(cartesian_position_v);
void FGInterface::_updatePosition(const SGGeod& geod)
{
+ TrackComputer tracker( track, geodetic_position_v );
geodetic_position_v = geod;
cartesian_position_v = SGVec3d::fromGeod(geodetic_position_v);
geocentric_position_v = SGGeoc::fromCart(cartesian_position_v);
void FGInterface::_updatePosition(const SGGeoc& geoc)
{
+ TrackComputer tracker( track, geodetic_position_v );
geocentric_position_v = geoc;
cartesian_position_v = SGVec3d::fromGeoc(geocentric_position_v);
geodetic_position_v = SGGeod::fromCart(cartesian_position_v);
using std::vector;
using std::string;
+/**
+ * A little helper class to update the track if
+ * the position has changed. In the constructor,
+ * create a copy of the current position and store
+ * references to the position object and the track
+ * variable to update.
+ * The destructor, called at TrackComputer's end of
+ * life/visibility, computes the track if the
+ * position has changed.
+ */
+class TrackComputer {
+public:
+ inline TrackComputer( double & track, const SGGeod & position ) :
+ _track( track ),
+ _position( position ),
+ _prevPosition( position ) {
+ }
+
+ inline ~TrackComputer() {
+ if( _prevPosition == _position ) return;
+ _track = SGGeodesy::courseDeg( _prevPosition, _position );
+ }
+private:
+ double & _track;
+ const SGGeod & _position;
+ const SGGeod _prevPosition;
+};
+
// This is based heavily on LaRCsim/ls_generic.h
class FGInterface : public SGSubsystem {
double runway_altitude;
double climb_rate; // in feet per second
double altitude_agl;
+ double track;
double daux[16]; // auxilliary doubles
float faux[16]; // auxilliary floats
geocentric_position_v.setLongitudeRad(lon);
geocentric_position_v.setRadiusFt(rad);
}
+/* Don't call _set_L[at|ong]itude() directly, use _set_Geodetic_Position() instead.
+ These methods can't update the track.
+ *
inline void _set_Latitude(double lat) {
geodetic_position_v.setLatitudeRad(lat);
}
inline void _set_Longitude(double lon) {
geodetic_position_v.setLongitudeRad(lon);
}
+*/
inline void _set_Altitude(double altitude) {
geodetic_position_v.setElevationFt(altitude);
}
inline void _set_Altitude_AGL(double agl) {
altitude_agl = agl;
}
+ inline void _set_Geodetic_Position( double lat, double lon ) {
+ _set_Geodetic_Position( lat, lon, geodetic_position_v.getElevationFt());
+ }
inline void _set_Geodetic_Position( double lat, double lon, double alt ) {
+ TrackComputer tracker( track, geodetic_position_v );
geodetic_position_v.setLatitudeRad(lat);
geodetic_position_v.setLongitudeRad(lon);
geodetic_position_v.setElevationFt(alt);
return geodetic_position_v.getElevationFt();
}
inline double get_Altitude_AGL(void) const { return altitude_agl; }
+ inline double get_Track(void) const { return track; }
inline double get_Latitude_deg () const {
return geodetic_position_v.getLatitudeDeg();