void main( int argc, char **argv) { double state_vect2[6], jd = atof( argv[3]); const int home_planet = atoi( argv[1]), planet_no = atoi( argv[2]); double dist = 0., pvsun[6]; int i, pass, center = 12; void *p; char *filename; if( argc > 4) center = atoi( argv[4]); printf( "Year approx %.3lf\n", 2000. + (jd - 2451545.) / 365.25); filename = "d:\\guide_b\\jpl_eph\\sub_de.406"; p = jpl_init_ephemeris( filename, NULL, NULL); if( !p) { printf( "JPL data not loaded\n"); exit( -1); } jpl_pleph( p, jd, center, home_planet, state_vect2, 1); printf( "Observer state vector:\n"); show_state_vector( state_vect2); // for( i = 0; i < 3; i++) // pvsun[i] = jpl_get_pvsun( p)[i]; for( pass = 0; pass < 4; pass++) { double state_vect[6], ang; char buff[30]; jpl_pleph( p, jd - dist * AU_IN_KM / (SPEED_OF_LIGHT * 86400.), center, planet_no, state_vect, 1); if( pass == 3) { for( i = 0; i < 3; i++) pvsun[i] = state_vect[i] + jpl_get_pvsun( p)[i]; // pvsun[i] += state_vect[i]; printf( "%.11lf %.11lf %.11lf\n", pvsun[0], pvsun[1], pvsun[2]); printf( "Dist to sun: %.11lf\n", vector_length( pvsun)); } for( i = 0; i < 6; i++) state_vect[i] -= state_vect2[i]; dist = vector_length( state_vect); show_state_vector( state_vect); ang = atan2( state_vect[1], state_vect[0]) * 12. / PI; format_base_sixty( buff, ang + 12.); buff[15] = '\0'; printf( "%s ", buff + 1); /* skip leading '+' */ ang = -asin( state_vect[2] / dist) * 180. / PI; format_base_sixty( buff, ang); buff[14] = '\0'; printf( "%s %.11lf (%.3lf km)\n", buff, dist, dist * AU_IN_KM); } jpl_close_ephemeris( p); }
bool GetDe431Coor(const double jde, const int planet_id, double * xyz, const int centralBody_id) { if(initDone) { // This may return some error code! int jplresult=jpl_pleph(ephem, jde, planet_id, centralBody_id, tempXYZ, 0); switch (jplresult) { case 0: // all OK. break; case JPL_EPH_OUTSIDE_RANGE: qDebug() << "GetDe431Coor: JPL_EPH_OUTSIDE_RANGE at jde" << jde << "for planet" << planet_id; return false; break; case JPL_EPH_READ_ERROR: qDebug() << "GetDe431Coor: JPL_EPH_READ_ERROR at jde" << jde << "for planet" << planet_id; return false; break; case JPL_EPH_QUANTITY_NOT_IN_EPHEMERIS: qDebug() << "GetDe431Coor: JPL_EPH_QUANTITY_NOT_IN_EPHEMERIS at jde" << jde << "for planet" << planet_id; return false; break; case JPL_EPH_INVALID_INDEX: qDebug() << "GetDe431Coor: JPL_EPH_INVALID_INDEX at jde" << jde << "for planet" << planet_id; return false; break; case JPL_EPH_FSEEK_ERROR: qDebug() << "GetDe431Coor: JPL_EPH_FSEEK_ERROR at jde" << jde << "for planet" << planet_id; return false; break; default: // Should never happen... qDebug() << "GetDe431Coor: unknown error" << jplresult << "at jde" << jde << "for planet" << planet_id; return false; break; } tempICRF = Vec3d(tempXYZ[0], tempXYZ[1], tempXYZ[2]); tempECL = StelCore::matJ2000ToVsop87 * tempICRF; xyz[0] = tempECL[0]; xyz[1] = tempECL[1]; xyz[2] = tempECL[2]; return true; } return false; }
int Ephem_step(const double JD, unsigned char select_bodies[JPL_NUMDEFS], unsigned int origin, double (*statevec)[JPL_NUMDEFS][6]) { /* FIXME: (Rody Oldenhuis) put this in global struct or something */ #define AU (149597870.700) #define SECONDS_PER_DAY (86400.0) int err_code = 0; unsigned int i = 0u, j = 0u; /* Compute relevant ephemeris */ for (i=0u; i<JPL_NUMDEFS && err_code==0; ++i) { if (select_bodies[i]) { err_code = jpl_pleph(ephem, JD, i+1u, origin, (*statevec)[i], 1); /* Convert units from AU to km, and AU/day to km/s */ for (j=0u; j<3u; ++j) (*statevec)[i][j] *= AU; for (j=3u; j<6u; ++j) (*statevec)[i][j] *= AU/SECONDS_PER_DAY; } else { for (j=0u; j<6u; ++j) (*statevec)[i][j] = 0.0; } } /* error condition */ if (err_code != 0) { /* Output error, and explicitly assign all-zero output values */ for (i=0u; i<JPL_NUMDEFS; ++i) for (j=0u; j<6u; ++j) (*statevec)[i][j] = 0.0; } return err_code; }
static void get_rectang( void *jpleph, double *loc, double t_c, int planet_no) { if( !planet_no) loc[0] = loc[1] = loc[2] = 0.; else { double tloc[6]; // static int count = 100; // if( count) // { // count--; // printf( "t: %.5lf pl %d: ", t_c, planet_no); // } jpl_pleph( jpleph, t_c * 36525. + 2451545., planet_no, 11, tloc, 0); // if( count) // { // count--; // printf( "got it\n"); // } memcpy( loc, tloc, 3 * sizeof( double)); } }
int main( const int argc, const char **argv) { char nams[JPL_MAX_N_CONSTANTS][6], buff[102]; double vals[JPL_MAX_N_CONSTANTS]; double max_err_found[10][6]; int line, n_failures[10]; size_t i, j; unsigned n_constants, n_columns; int output_frequency = 100; const char *ephfile_name = argv[1]; double start_jd, end_jd; double roundoff_error = 0.; bool report_all_errors = false; bool pause_on_errors = true; FILE *testfile; clock_t timer; void *ephem; const char *test_file_name = NULL; #if defined( __GNUC__) && !defined( __MINGW32__) const char path_separator = '/'; #else const char path_separator = '\\'; #endif const char *error_messages[7] = { "Result outside acceptable error tolerance", "Outside date range", "Read error", "Quantity not in index", "? Obsolete error; shouldn't happen", "Invalid index", "Seek error" }; const int n_errors = sizeof( error_messages) / sizeof( error_messages[0]); /***** Write a fingerprint to the screen. ***********************************/ setvbuf( stdout, NULL, _IONBF, 0); puts("\n JPL test-ephemeris program (v.1.2)\n" " C version translated from the original JPL FORTRAN code.\n"); if( argc < 2) error_exit( -1); for( i = 0; i < 10; i++) for( j = 0; j < 6; j++) max_err_found[i][j] = 0.; for( i = 2; i < (size_t)argc; i++) if( argv[i][0] == '-') switch( argv[i][1]) { case 'a': case 'A': report_all_errors = true; break; case 'f': case 'F': output_frequency = atoi( argv[i] + 2); break; case 'n': case 'N': pause_on_errors = false; break; case 't': case 'T': test_file_name = argv[i] + 2; break; default: printf( "Unrecognized option '%s'\n", argv[i]); error_exit( -2); break; } /****** Print the ephemeris constants. **************************************/ ephem = jpl_init_ephemeris( ephfile_name, nams, vals); if( !ephem) { printf( "Ephemeris file '%s' not loaded\n", ephfile_name); printf( "Error code: %d\n", jpl_init_error_code( )); error_exit( -2); } else printf( "Ephemeris initialized\n"); n_constants = (unsigned)jpl_get_long( ephem, JPL_EPHEM_N_CONSTANTS); printf( "%u constants\n", n_constants); if( n_constants > JPL_MAX_N_CONSTANTS) n_constants = JPL_MAX_N_CONSTANTS; start_jd = jpl_get_double( ephem, JPL_EPHEM_START_JD), end_jd = jpl_get_double( ephem, JPL_EPHEM_END_JD), printf("%.9f %.9f %.9f\n", start_jd, end_jd, jpl_get_double( ephem, JPL_EPHEM_STEP)); n_columns = (n_constants + 1) / 2; for( i = 0; i < (size_t)n_columns; i++) { printf("%.6s %24.16E",nams[i],vals[i]); if( i + n_columns < n_constants) printf(" %.6s %24.16E",nams[i + n_columns],vals[i + n_columns]); printf( "\n"); } printf( "emrat = %.15f AU = %.5f\n", jpl_get_double( ephem, JPL_EPHEM_EARTH_MOON_RATIO), jpl_get_double( ephem, JPL_EPHEM_AU_IN_KM)); /****** Skip the test points file header comments. *************************/ if( test_file_name) strcpy( buff, test_file_name); else { const char *extension; strcpy( buff, ephfile_name); for( i = strlen( buff); i && buff[i - 1] != path_separator; i--) ; strcpy( buff + i, "testpo"); extension = strchr( ephfile_name + i, '.'); if( extension) strcat( buff + i, extension); else sprintf( buff + strlen( buff), ".%3ld", jpl_get_long( ephem, JPL_EPHEM_EPHEMERIS_VERSION)); } testfile = fopen( buff, "r"); if( !testfile) { printf( "Test data file '%s' not found\n", buff); error_exit( -3); } while( fgets( buff, 100, testfile) && memcmp( buff, "EOT", 3)) ; puts(" LINE JED t# c# x# --- JPL value --- " "--- user value -- -- difference --"); line=0; timer = clock( ); for( i = 0; i < 10; i++) n_failures[i] = 0; while( fgets( buff, 100, testfile) != NULL) { int err_code, ntarg, nctr, ncoord; double del, et; double r[6], xi, xi_computed; bool fatal_error = false, report_this_error = false; /***** Read a value from the test case; Skip if not within the time-range of the present version of the ephemeris. */ line++; if( sscanf( buff + 15," %lf %d %d %d %lf", &et, &ntarg, &nctr, &ncoord, &xi) != 5) { printf( "Failure to parse line %d:\n%s\n", line, buff); fatal_error = true; } else { err_code = jpl_pleph(ephem, et, ntarg, nctr, r, 1); if( err_code > 0 || err_code < -n_errors) { printf( "Internal error: unknown error code %d\n", err_code); fatal_error = true; } else if( !roundoff_error) { char *tptr = strchr( buff + 30, '.'); assert( tptr); tptr++; roundoff_error = .5; while( *tptr >= '0' && *tptr <= '9') { tptr++; roundoff_error /= 10.; } } } if( fatal_error) { printf( "\nThis error shouldn't happen, ever. It indicates a bug\n"); printf( "that should be fixed.\n"); printf( "Please contact [email protected] and report this.\n"); return( -1); } xi_computed = r[ncoord - 1]; del = fabs( xi_computed - xi); if( err_code) { n_failures[-err_code]++; if( n_failures[-err_code] == 1 || report_all_errors) report_this_error = true; } else { const double tolerance = max_accepted_error( ntarg, ncoord) + fabs( xi) * 1e-14 + roundoff_error; const unsigned idx = (ntarg <= 13 ? 0 : ntarg - 13); if( max_err_found[idx][ncoord - 1] < del - tolerance) max_err_found[idx][ncoord - 1] = del - tolerance; if( del > tolerance) { n_failures[0]++; if( n_failures[-err_code] == 1 || report_all_errors) { report_this_error = true; printf( "***** warning : next difference >= tolerance *****\n"); printf( "%s", buff); } } } if( (!err_code && !(line % output_frequency)) || report_this_error) printf("%4d %10.1f %2d %2d %2d %25.20f %25.20f %22.20f\n", line,et,ntarg,nctr,ncoord,xi, xi_computed, xi_computed - xi); if( report_this_error) { printf( "Error message: '%s'\n", error_messages[-err_code]); if( err_code == JPL_EPH_OUTSIDE_RANGE) { const double J2000 = 2451545.; printf( "WARNING: The test file tests items outside the range\n"); printf( "of this ephemeris!\n"); printf( "The input ephemeris file covers years from %.1f to %.1f.\n", 2000. + (start_jd - J2000) / 365.25, 2000. + (end_jd - J2000) / 365.25); printf( "The test is for the year %.1f\n", 2000. + (et - J2000) / 365.25); printf( "It's common for DE files to be built that cover a subset of the\n"); printf( "range of the original ephemerides, so this may not be an error.\n"); } if( !report_all_errors) { printf( " Further errors of this type won't be shown, but you'll get a count\n"); printf( " of how many are found. (Use the '-a' switch to report all errors.)\n"); } if( pause_on_errors) { printf( " Hit any key:\n"); getchar( ); } } } for( i = 0; i < 10; i++) for( j = 0; j < 6; j++) if( max_err_found[i][j]) printf( "%d %d %.8e %c\n", (int)i, (int)j + 1, max_err_found[i][j], (max_err_found[i][j] > 0.) ? '*' : ' '); printf( "%d lines read and tested in %.3f seconds\n", line, (double)( clock( ) - timer) / (double)CLOCKS_PER_SEC); for( i = 0; i < (size_t)n_errors; i++) if( n_failures[i]) printf( "%d lines failed with error code %d ('%s').\n", n_failures[i], -(int)i, error_messages[i]); fclose( testfile); jpl_close_ephemeris( ephem); return( 0); }
static int planet_posn_raw( int planet_no, const double jd, double *vect_2000) { static void *ps_1996_data[10]; const int jpl_center = 11; /* default to heliocentric */ int i, rval = 0; static const char *jpl_filename = NULL; static void *jpl_eph = NULL; const int bc405_start = 100; const int calc_vel = (planet_no & PLANET_POSN_VELOCITY_FLAG) ? 1 : 0; planet_no &= ~PLANET_POSN_VELOCITY_FLAG; if( !planet_no) /* the sun */ { vect_2000[0] = vect_2000[1] = vect_2000[2] = 0.; if( !jd && jpl_eph) /* return version data: */ { vect_2000[0] = (double)jpl_get_long( jpl_eph, JPL_EPHEM_EPHEMERIS_VERSION); vect_2000[1] = jpl_get_double( jpl_eph, JPL_EPHEM_START_JD); vect_2000[2] = jpl_get_double( jpl_eph, JPL_EPHEM_END_JD); } return( 0); } if( planet_no >= bc405_start && planet_no < bc405_start + 300) { double temp_loc[4]; rval = asteroid_position_raw( planet_no - bc405_start, jd, temp_loc); if( debug_level > 8) debug_printf( "JD %f, minor planet %d: (%f %f %f)\n", jd, planet_no, temp_loc[0], temp_loc[1], temp_loc[2]); memcpy( vect_2000, temp_loc, 3 * sizeof( double)); return( rval); } if( !jpl_filename) { FILE *ifile; #if defined (_WIN32) || defined( __WATCOMC__) jpl_filename = get_environment_ptr( "JPL_FILENAME"); #else jpl_filename = get_environment_ptr( "LINUX_JPL_FILENAME"); #endif if( *jpl_filename) jpl_eph = jpl_init_ephemeris( jpl_filename, NULL, NULL); if( !jpl_eph) if( (ifile = fopen_ext( "jpl_eph.txt", "fcrb")) != NULL) { char buff[100]; while( !jpl_eph && fgets_trimmed( buff, sizeof( buff), ifile)) if( *buff && *buff != ';') { jpl_eph = jpl_init_ephemeris( buff, NULL, NULL); if( !jpl_eph) { char tname[255]; make_config_dir_name( tname, buff); jpl_eph = jpl_init_ephemeris( tname, NULL, NULL); } } if( debug_level) debug_printf( "Ephemeris file %s\n", buff); fclose( ifile); } if( debug_level && jpl_eph) { debug_printf( "\nEphemeris time span years %.3f to %.3f\n", (jpl_get_double( jpl_eph, JPL_EPHEM_START_JD) - J0) / 365.25, (jpl_get_double( jpl_eph, JPL_EPHEM_END_JD) - J0) / 365.25); debug_printf( "Ephemeris version %ld\n", jpl_get_long( jpl_eph, JPL_EPHEM_EPHEMERIS_VERSION)); debug_printf( "Kernel size %ld, record size %ld, swap_bytes %ld\n", jpl_get_long( jpl_eph, JPL_EPHEM_KERNEL_SIZE), jpl_get_long( jpl_eph, JPL_EPHEM_KERNEL_RECORD_SIZE), jpl_get_long( jpl_eph, JPL_EPHEM_KERNEL_SWAP_BYTES)); debug_printf( "ncon = %ld AU=%f emrat = %f\n", jpl_get_long( jpl_eph, JPL_EPHEM_N_CONSTANTS), jpl_get_double( jpl_eph, JPL_EPHEM_AU_IN_KM), jpl_get_double( jpl_eph, JPL_EPHEM_EARTH_MOON_RATIO)); } } if( jpl_eph) { double state[6]; /* DE gives both posn & velocity */ int failure_code; if( planet_no < 0) /* flag to unload everything */ { jpl_close_ephemeris( jpl_eph); jpl_eph = NULL; jpl_filename = NULL; return( 0); } else if( planet_no == 10) failure_code = jpl_pleph( jpl_eph, jd, 10, 3, state, calc_vel); else failure_code = jpl_pleph( jpl_eph, jd, (planet_no == 3) ? 13 : planet_no, jpl_center, state, calc_vel); if( !failure_code) /* we're done */ { if( debug_level > 8) debug_printf( "JD %f, planet %d: (%f %f %f)\n", jd, planet_no, state[0], state[1], state[2]); equatorial_to_ecliptic( state); memcpy( vect_2000, state + calc_vel, 3 * sizeof( double)); return( 0); } else if( debug_level) debug_printf( "Failed: JD %f, planet %d, code %d\n", jd, planet_no, failure_code); } if( planet_no == 10) /* the moon */ { double tloc[4]; if( !compute_elp_xyz( NULL, (jd - J2000) / 36525., 0., tloc)) for( i = 0; i < 3; i++) vect_2000[i] = tloc[i] / AU_IN_KM; else { static int first_time = 1; rval = -3; if( first_time) generic_message_box( get_find_orb_text( 2019), "o"); first_time = 0; compute_rough_planet_loc( (jd - J2000) / 36525., 10, vect_2000); } return( rval); } if( planet_no < 0) /* flag to unload everything */ { for( i = 0; i < 10; i++) if( ps_1996_data[i]) { unload_ps1996_series( ps_1996_data[i]); ps_1996_data[i] = NULL; } return( 0); } if( !ps_1996_data[planet_no]) ps_1996_data[planet_no] = load_ps1996_series( NULL, jd, planet_no); if( !ps_1996_data[planet_no]) rval = -1; else if( get_ps1996_position( jd, ps_1996_data[planet_no], vect_2000, 0)) { unload_ps1996_series( ps_1996_data[planet_no]); ps_1996_data[planet_no] = load_ps1996_series( NULL, jd, planet_no); if( !ps_1996_data[planet_no]) rval = -2; else if( get_ps1996_position( jd, ps_1996_data[planet_no], vect_2000, 0)) rval = -3; } if( !rval) equatorial_to_ecliptic( vect_2000); else { static int first_time = 1; if( first_time) { generic_message_box( get_find_orb_text( 2020), "o"); debug_printf( "Loading ps_1996: rval %d, planet %d, JD %f\n", rval, planet_no, jd); } first_time = 0; if( planet_no > 0 && planet_no < 9) compute_rough_planet_loc( (jd - J2000) / 36525., planet_no, vect_2000); } return( rval); }