1
0
Fork 0

Time: The sun solver has been generalised to to handle any solar system body.

The functions fgSunPositionGST() and fgTimeSecondsUntilSunAngle() have been
renamed to fgBodyPositionGST() and fgBodyPositionGST() respectively, and both
require a new char argument specifying the body of interest.  This allows the
position of all solar system bodies to be calculated from the aircraft frame of
reference.
This commit is contained in:
Edward d'Auvergne 2015-12-11 23:55:22 +01:00
parent 0ba2e8708e
commit 6e62228c1d
4 changed files with 56 additions and 50 deletions

View file

@ -363,19 +363,19 @@ void TimeManager::setTimeOffset(const std::string& offset_type, long int offset)
if ( offset_type == "real" ) {
warp = 0;
} else if ( offset_type == "dawn" ) {
warp = fgTimeSecondsUntilSunAngle( cur_time, loc, 90.0, true );
warp = fgTimeSecondsUntilBodyAngle( cur_time, loc, 90.0, true, "sun" );
} else if ( offset_type == "morning" ) {
warp = fgTimeSecondsUntilSunAngle( cur_time, loc, 75.0, true );
warp = fgTimeSecondsUntilBodyAngle( cur_time, loc, 75.0, true, "sun" );
} else if ( offset_type == "noon" ) {
warp = fgTimeSecondsUntilSunAngle( cur_time, loc, 0.0, true );
warp = fgTimeSecondsUntilBodyAngle( cur_time, loc, 0.0, true, "sun" );
} else if ( offset_type == "afternoon" ) {
warp = fgTimeSecondsUntilSunAngle( cur_time, loc, 75.0, false );
warp = fgTimeSecondsUntilBodyAngle( cur_time, loc, 75.0, false, "sun" );
} else if ( offset_type == "dusk" ) {
warp = fgTimeSecondsUntilSunAngle( cur_time, loc, 90.0, false );
warp = fgTimeSecondsUntilBodyAngle( cur_time, loc, 90.0, false, "sun" );
} else if ( offset_type == "evening" ) {
warp = fgTimeSecondsUntilSunAngle( cur_time, loc, 100.0, false );
warp = fgTimeSecondsUntilBodyAngle( cur_time, loc, 100.0, false, "sun" );
} else if ( offset_type == "midnight" ) {
warp = fgTimeSecondsUntilSunAngle( cur_time, loc, 180.0, false );
warp = fgTimeSecondsUntilBodyAngle( cur_time, loc, 180.0, false, "sun" );
} else if ( offset_type == "system-offset" ) {
warp = offset;
orig_warp = 0;

View file

@ -1,6 +1,7 @@
/*
* bodysolver.cxx - given a location on earth and a time of day/date,
* find the number of seconds to various sun positions.
* find the number of seconds to various solar system body
* positions.
*
* Written by Curtis Olson, started September 2003.
*
@ -46,21 +47,22 @@ static const time_t step_secs = 60;
/* given a particular time expressed in side real time at prime
* meridian (GST), compute position on the earth (lat, lon) such that
* sun is directly overhead. (lat, lon are reported in radians */
* solar system body is directly overhead. (lat, lon are reported in
* radians) */
void fgSunPositionGST(double gst, double *lon, double *lat) {
void fgBodyPositionGST(double gst, double *lon, double *lat, const char *body) {
/* time_t ssue; seconds since unix epoch */
/* double *lat; (return) latitude */
/* double *lon; (return) longitude */
double tmp;
SGPropertyNode* sun = fgGetNode("/ephemeris/sun");
assert(sun);
double xs = sun->getDoubleValue("xs");
//double ys = sun->getDoubleValue("ys");
double ye = sun->getDoubleValue("ye");
double ze = sun->getDoubleValue("ze");
SGPropertyNode* body_node = fgGetNode("/ephemeris/" + std::string(body));
assert(body_node);
double xs = body_node->getDoubleValue("xs");
//double ys = body_node->getDoubleValue("ys");
double ye = body_node->getDoubleValue("ye");
double ze = body_node->getDoubleValue("ze");
double ra = atan2(ye, xs);
double dec = atan2(ze, sqrt(xs * xs + ye * ye));
@ -73,52 +75,53 @@ void fgSunPositionGST(double gst, double *lon, double *lat) {
*lat = dec;
}
static double sun_angle( const SGTime &t, const SGVec3d& world_up) {
SG_LOG( SG_EVENT, SG_DEBUG, " Updating Sun position" );
static double body_angle( const SGTime &t, const SGVec3d& world_up, const char* body) {
SG_LOG( SG_EVENT, SG_DEBUG, " Updating " << body << " position" );
SG_LOG( SG_EVENT, SG_DEBUG, " Gst = " << t.getGst() );
double sun_lon, sun_gc_lat;
fgSunPositionGST( t.getGst(), &sun_lon, &sun_gc_lat );
SGVec3d sunpos = SGVec3d::fromGeoc(SGGeoc::fromRadM(sun_lon, sun_gc_lat,
double lon, gc_lat;
fgBodyPositionGST( t.getGst(), &lon, &gc_lat, body );
SGVec3d bodypos = SGVec3d::fromGeoc(SGGeoc::fromRadM(lon, gc_lat,
SGGeodesy::EQURAD));
SG_LOG( SG_EVENT, SG_DEBUG, " t.cur_time = " << t.get_cur_time() );
SG_LOG( SG_EVENT, SG_DEBUG,
" Sun Geocentric lat = " << sun_gc_lat );
" " << body << " geocentric lat = " << gc_lat );
// calculate the sun's relative angle to local up
// calculate the body's relative angle to local up
SGVec3d nup = normalize(world_up);
SGVec3d nsun = normalize(sunpos);
SGVec3d nbody = normalize(bodypos);
// cout << "nup = " << nup[0] << "," << nup[1] << ","
// << nup[2] << endl;
// cout << "nsun = " << nsun[0] << "," << nsun[1] << ","
// << nsun[2] << endl;
// cout << "nbody = " << nbody[0] << "," << nbody[1] << ","
// << nbody[2] << endl;
double sun_angle = acos( dot( nup, nsun ) );
double body_angle = acos( dot( nup, nbody ) );
double signedPI = (sun_angle < 0.0) ? -SGD_PI : SGD_PI;
sun_angle = fmod(sun_angle+signedPI, SGD_2PI) - signedPI;
double signedPI = (body_angle < 0.0) ? -SGD_PI : SGD_PI;
body_angle = fmod(body_angle+signedPI, SGD_2PI) - signedPI;
double sun_angle_deg = sun_angle * SG_RADIANS_TO_DEGREES;
SG_LOG( SG_EVENT, SG_DEBUG, "sun angle relative to current location = "
<< sun_angle_deg );
double body_angle_deg = body_angle * SG_RADIANS_TO_DEGREES;
SG_LOG( SG_EVENT, SG_DEBUG, body << " angle relative to current location = "
<< body_angle_deg );
return sun_angle_deg;
return body_angle_deg;
}
/**
* Given the current unix time in seconds, calculate seconds to the
* specified sun angle (relative to straight up.) Also specify if we
* want the angle while the sun is ascending or descending. For
* specified body angle (relative to straight up.) Also specify if we
* want the angle while the body is ascending or descending. For
* instance noon is when the sun angle is 0 (or the closest it can
* get.) Dusk is when the sun angle is 90 and descending. Dawn is
* when the sun angle is 90 and ascending.
*/
time_t fgTimeSecondsUntilSunAngle( time_t cur_time,
time_t fgTimeSecondsUntilBodyAngle( time_t cur_time,
const SGGeod& loc,
double target_angle_deg,
bool ascending )
bool ascending,
const char *body )
{
SGVec3d world_up = SGVec3d::fromGeod(loc);
SGTime t = SGTime( loc, SGPath(), 0 );
@ -132,7 +135,7 @@ time_t fgTimeSecondsUntilSunAngle( time_t cur_time,
secs += step_secs )
{
t.update( loc, secs, 0 );
double angle_deg = sun_angle( t, world_up );
double angle_deg = body_angle( t, world_up, body );
double diff = fabs( angle_deg - target_angle_deg );
if ( diff < best_diff ) {
if ( last_angle <= 180.0 && ascending

View file

@ -1,6 +1,7 @@
/*
* bodysolver.hxx - given a location on earth and a time of day/date,
* find the number of seconds to various sun positions.
* find the number of seconds to various solar system body
* positions.
*
* Written by Curtis Olson, started September 2003.
*
@ -24,8 +25,8 @@
*/
#ifndef _SUNSOLVER_HXX
#define _SUNSOLVER_HXX
#ifndef _BODYSOLVER_HXX
#define _BODYSOLVER_HXX
#ifndef __cplusplus
@ -40,23 +41,25 @@ class SGGeod;
/**
* Given the current unix time in seconds, calculate seconds to the
* specified sun angle (relative to straight up.) Also specify if we
* want the angle while the sun is ascending or descending. For
* instance noon is when the sun angle is 0 (or the closest it can
* specified solar system body angle (relative to straight up.) Also
* specify if we want the angle while the body is ascending or descending.
* For instance noon is when the sun angle is 0 (or the closest it can
* get.) Dusk is when the sun angle is 90 and descending. Dawn is
* when the sun angle is 90 and ascending.
*/
time_t fgTimeSecondsUntilSunAngle( time_t cur_time,
time_t fgTimeSecondsUntilBodyAngle( time_t cur_time,
const SGGeod& loc,
double target_angle_deg,
bool ascending );
bool ascending,
const char *body );
/**
* given a particular time expressed in side real time at prime
* meridian (GST), compute position on the earth (lat, lon) such that
* sun is directly overhead. (lat, lon are reported in radians
* solar system body is directly overhead. (lat, lon are reported in
* radians)
*/
void fgSunPositionGST(double gst, double *lon, double *lat);
void fgBodyPositionGST(double gst, double *lon, double *lat, const char *body);
#endif /* _SUNSOLVER_HXX */
#endif /* _BODYSOLVER_HXX */

View file

@ -392,7 +392,7 @@ void FGLight::updateSunPos()
{
SGTime *t = globals->get_time_params();
fgSunPositionGST(t->getGst(), &_sun_lon, &_sun_lat);
fgBodyPositionGST(t->getGst(), &_sun_lon, &_sun_lat, "sun");
// It might seem that sun_gc_lat needs to be converted to geodetic
// latitude here, but it doesn't. The sun latitude is the latitude