00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034 #include "space/rotating_body.hpp"
00035 #include "space/astronomy.hpp"
00036 #include "data/broker.hpp"
00037 #include "math/quaternion.hpp"
00038 #include "math/units.hpp"
00039
00040 #include <cmath>
00041
00042 using namespace gsgl;
00043 using namespace gsgl::data;
00044 using namespace gsgl::math;
00045 using namespace gsgl::scenegraph;
00046 using namespace gsgl::physics;
00047
00048 namespace periapsis
00049 {
00050
00051 namespace space
00052 {
00053
00054 void body_rotator::calc_orientation_aux(double alpha, double delta, double W, transform & orientation)
00055 {
00056
00057 alpha *= math::DEG2RAD;
00058 delta *= math::DEG2RAD;
00059 W *= math::DEG2RAD;
00060
00061
00062 gsgl::real_t rot_angle = static_cast<gsgl::real_t>(PI_OVER_2 + alpha + W);
00063 quaternion rotation(vector::Z_AXIS, rot_angle);
00064
00065 gsgl::real_t inc_angle = static_cast<gsgl::real_t>( PI_OVER_2 - delta );
00066
00067 double axis_angle = PI_OVER_2 + alpha;
00068 gsgl::real_t axis_x = static_cast<gsgl::real_t>( ::cos(axis_angle) );
00069 gsgl::real_t axis_y = static_cast<gsgl::real_t>( ::sin(axis_angle) );
00070
00071 quaternion inclination(vector(axis_x, axis_y, 0), inc_angle);
00072 quaternion oq = inclination * rotation;
00073
00074 orientation = EQUATORIAL_WRT_ECLIPTIC * transform(oq);
00075 }
00076
00077
00078 void body_rotator::calc_angular_velocity_aux(double ang_diff, double d, const transform & orientation, vector & angular_velocity)
00079 {
00080
00081
00082
00083 double mag = (ang_diff / d) * (math::DEG2RAD / math::units::SECONDS_PER_DAY);
00084 vector axis = orientation * vector::Z_AXIS;
00085
00086 angular_velocity = axis * static_cast<gsgl::real_t>(mag);
00087 }
00088
00089
00090
00091
00092 struct major_planet_rec
00093 {
00094 wchar_t *name;
00095 double alpha_zero, alpha_rate;
00096 double delta_zero, delta_rate;
00097 double w_zero, w_rate, w_sin_term;
00098 double n_zero, n_rate;
00099 };
00100
00101 static major_planet_rec major_planet_data[] =
00102 {
00103 { L"Sol", 286.13, 0.0, 63.87, 0.0, 84.10, 14.1844000, 0.0, 0.0, 0.0 },
00104 { L"Mercury", 281.01, -0.033, 61.45, -0.005, 329.548, 6.1385025, 0.0, 0.0, 0.0 },
00105 { L"Venus", 272.76, 0.0, 67.16, 0.0, 160.20, -1.4813688, 0.0, 0.0, 0.0 },
00106 { L"Earth", 0.00, -0.641, 90.00, -0.557, 190.147, 360.9856235, 0.0, 0.0, 0.0 },
00107 { L"Mars", 317.68143, -0.1061, 52.88650, -0.0609, 176.630, 350.89198226, 0.0, 0.0, 0.0 },
00108 { L"Jupiter", 268.05, -0.009, 64.49, 0.003, 284.95, 870.5366420, 0.0, 0.0, 0.0 },
00109 { L"Saturn", 40.589, -0.036, 83.537, -0.004, 38.90, 810.7939024, 0.0, 0.0, 0.0 },
00110 { L"Uranus", 257.311, 0.0, -15.175, 0.0, 203.81, -501.1600928, 0.0, 0.0, 0.0 },
00111 { L"Neptune", 299.36, 0.70, 43.46, -0.51, 253.18, 536.3128492, -0.48, 357.85, 52.316 },
00112 { L"Pluto", 313.02, 0.0, 9.09, 0.0, 236.77, -56.3623195, 0.0, 0.0, 0.0 },
00113
00114 { 0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 }
00115
00116 };
00117
00118
00119 class major_planet_rotator
00120 : public body_rotator
00121 {
00122 const major_planet_rec *data;
00123 public:
00124 major_planet_rotator(const major_planet_rec *data) : body_rotator(), data(data) {}
00125
00126 virtual void calc_orientation(double jdn, transform & orientation, vector & angular_velocity);
00127 };
00128
00129
00130 void major_planet_rotator::calc_orientation(double jdn, transform & orientation, vector & angular_velocity)
00131 {
00132 double d = jdn - J2000;
00133 double T = (d / 36525.0);
00134
00135 double alpha, delta, W, ang_diff;
00136
00137 if (data->n_zero != 0.0 || data->n_rate != 0.0)
00138 {
00139 double N = data->n_zero + data->n_rate * T;
00140 N *= math::DEG2RAD;
00141
00142 alpha = data->alpha_zero + data->alpha_rate * ::sin(N);
00143 delta = data->delta_zero + data->delta_rate * ::cos(N);
00144 W = data->w_zero + (ang_diff = data->w_rate * d + data->w_sin_term * ::sin(N));
00145 }
00146 else
00147 {
00148 alpha = data->alpha_zero + data->alpha_rate * T;
00149 delta = data->delta_zero + data->delta_rate * T;
00150 W = data->w_zero + (ang_diff = data->w_rate * d);
00151 }
00152
00153 calc_orientation_aux(alpha, delta, W, orientation);
00154 calc_angular_velocity_aux(ang_diff, d, orientation, angular_velocity);
00155 }
00156
00157
00158
00159
00160
00161 namespace rotator
00162 {
00163
00164 namespace sol
00165 {
00166
00167 class sol : public major_planet_rotator
00168 {
00169 public:
00170 sol(const config_record &) : major_planet_rotator(&major_planet_data[0]) {}
00171
00172 BROKER_DECLARE_CREATOR(periapsis::space::rotator::sol::sol);
00173 };
00174
00175 BROKER_DEFINE_CREATOR(periapsis::space::rotator::sol::sol);
00176
00177 }
00178
00179
00180 namespace mercury
00181 {
00182
00183 class mercury : public major_planet_rotator
00184 {
00185 public:
00186 mercury(const config_record &) : major_planet_rotator(&major_planet_data[1]) {}
00187
00188 BROKER_DECLARE_CREATOR(periapsis::space::rotator::mercury::mercury);
00189 };
00190
00191 BROKER_DEFINE_CREATOR(periapsis::space::rotator::mercury::mercury);
00192
00193 }
00194
00195
00196 namespace venus
00197 {
00198
00199 class venus : public major_planet_rotator
00200 {
00201 public:
00202 venus(const config_record &) : major_planet_rotator(&major_planet_data[2]) {}
00203
00204 BROKER_DECLARE_CREATOR(periapsis::space::rotator::venus::venus);
00205 };
00206
00207 BROKER_DEFINE_CREATOR(periapsis::space::rotator::venus::venus);
00208
00209 }
00210
00211
00212 namespace earth
00213 {
00214
00215 class earth : public major_planet_rotator
00216 {
00217 public:
00218 earth(const config_record &) : major_planet_rotator(&major_planet_data[3]) {}
00219
00220 BROKER_DECLARE_CREATOR(periapsis::space::rotator::earth::earth);
00221 };
00222
00223 BROKER_DEFINE_CREATOR(periapsis::space::rotator::earth::earth);
00224
00225
00226 class moon : public body_rotator
00227 {
00228 public:
00229 moon(const config_record &) : body_rotator() {}
00230
00231 virtual void calc_orientation(double jdn, transform & orientation, vector & angular_velocity)
00232 {
00233 double d = jdn - J2000;
00234 double T = (d / 36525.0);
00235
00236 double alpha, delta, W, ang_diff;
00237
00238 double E1 = 125.045 - 0.0529921*d; E1 *= math::DEG2RAD;
00239 double E2 = 250.089 - 0.1059842*d; E2 *= math::DEG2RAD;
00240 double E3 = 260.008 + 13.0120009*d; E3 *= math::DEG2RAD;
00241 double E4 = 176.625 + 13.3407154*d; E4 *= math::DEG2RAD;
00242 double E5 = 357.529 + 0.9856003*d; E5 *= math::DEG2RAD;
00243 double E6 = 311.589 + 26.4057084*d; E6 *= math::DEG2RAD;
00244 double E7 = 134.963 + 13.0649930*d; E7 *= math::DEG2RAD;
00245 double E8 = 276.617 + 0.3287146*d; E8 *= math::DEG2RAD;
00246 double E9 = 34.226 + 1.7484877*d; E9 *= math::DEG2RAD;
00247 double E10 = 15.134 - 0.1589763*d; E10 *= math::DEG2RAD;
00248 double E11 = 119.743 + 0.0036096*d; E11 *= math::DEG2RAD;
00249 double E12 = 239.961 + 0.1643573*d; E12 *= math::DEG2RAD;
00250 double E13 = 25.053 + 12.9590088*d; E13 *= math::DEG2RAD;
00251
00252 alpha = 269.9949 + 0.0031*T - 3.8787*::sin(E1) - 0.1204*::sin(E2)
00253 + 0.0700*::sin(E3) - 0.0172*::sin(E4) + 0.0072*::sin(E6)
00254 - 0.0052*::sin(E10) + 0.0043*::sin(E13);
00255
00256 delta = 66.5392 + 0.0130*T + 1.5419*::cos(E1) + 0.0239*::cos(E2)
00257 - 0.0278*::cos(E3) + 0.0068*::cos(E4) - 0.0029*::cos(E6)
00258 + 0.0009*::cos(E7) + 0.0008*::cos(E10) - 0.0009*::cos(E13);
00259
00260 W = 38.3213 + (ang_diff = 13.17635815*d - 1.4e-12*d*d + 3.5610*::sin(E1)
00261 + 0.1208*::sin(E2) - 0.0642*::sin(E3) + 0.0158*::sin(E4)
00262 + 0.0252*::sin(E5) - 0.0066*::sin(E6) - 0.0047*::sin(E7)
00263 - 0.0046*::sin(E8) + 0.0028*::sin(E9) + 0.0052*::sin(E10)
00264 + 0.0040*::sin(E11) + 0.0019*::sin(E12) - 0.0044*::sin(E13));
00265
00266 calc_orientation_aux(alpha, delta, W, orientation);
00267 calc_angular_velocity_aux(ang_diff, d, orientation, angular_velocity);
00268 }
00269
00270 BROKER_DECLARE_CREATOR(periapsis::space::rotator::earth::moon);
00271 };
00272
00273 BROKER_DEFINE_CREATOR(periapsis::space::rotator::earth::moon);
00274
00275 }
00276
00277
00278 namespace mars
00279 {
00280
00281 class mars : public major_planet_rotator
00282 {
00283 public:
00284 mars(const config_record &) : major_planet_rotator(&major_planet_data[4]) {}
00285
00286 BROKER_DECLARE_CREATOR(periapsis::space::rotator::mars::mars);
00287 };
00288
00289 BROKER_DEFINE_CREATOR(periapsis::space::rotator::mars::mars);
00290
00291
00292
00293
00294 class mars_rotator : public body_rotator
00295 {
00296 public:
00297 mars_rotator() : body_rotator() {}
00298
00299 protected:
00300 double d, T;
00301 double M1, M2, M3;
00302 double alpha, delta, W;
00303
00304 void calc_orientation_pre(double jdn)
00305 {
00306 d = jdn - J2000;
00307 T = d / 36525.0;
00308
00309 M1 = 169.51 - 0.4357640*d; M1 *= math::DEG2RAD;
00310 M2 = 192.93 + 1128.4096700*d + 8.864*T*T; M2 *= math::DEG2RAD;
00311 M3 = 53.47 - 0.0181510*d; M3 *= math::DEG2RAD;
00312 }
00313 };
00314
00315
00316 class phobos : public mars_rotator
00317 {
00318 public:
00319 phobos(const config_record &) : mars_rotator() {}
00320
00321 virtual void calc_orientation(double jdn, transform & orientation, vector & angular_velocity)
00322 {
00323 double ang_diff;
00324 calc_orientation_pre(jdn);
00325
00326 alpha = 317.68 - 0.108*T + 1.79*::sin(M1);
00327 delta = 52.90 - 0.061*T - 1.08*::cos(M1);
00328 W = 35.06 + (ang_diff = 1128.8445850*d + 8.864*T*T - 1.42*::sin(M1) - 0.78*::sin(M2));
00329
00330 calc_orientation_aux(alpha, delta, W, orientation);
00331 calc_angular_velocity_aux(ang_diff, d, orientation, angular_velocity);
00332 }
00333
00334 BROKER_DECLARE_CREATOR(periapsis::space::rotator::mars::phobos);
00335 };
00336
00337 BROKER_DEFINE_CREATOR(periapsis::space::rotator::mars::phobos);
00338
00339
00340 class deimos : public mars_rotator
00341 {
00342 public:
00343 deimos(const config_record &) : mars_rotator() {}
00344
00345 virtual void calc_orientation(double jdn, transform & orientation, vector & angular_velocity)
00346 {
00347 double ang_diff;
00348 calc_orientation_pre(jdn);
00349
00350 alpha = 316.65 - 0.108*T + 2.98*::sin(M3);
00351 delta = 53.52 - 0.061*T - 1.78*::cos(M3);
00352 W = 79.41 + (ang_diff = 285.1618970*d - 0.520*T*T - 2.58*::sin(M3) + 0.19*::cos(M3));
00353
00354 calc_orientation_aux(alpha, delta, W, orientation);
00355 calc_angular_velocity_aux(ang_diff, d, orientation, angular_velocity);
00356 }
00357
00358 BROKER_DECLARE_CREATOR(periapsis::space::rotator::mars::deimos);
00359 };
00360
00361 BROKER_DEFINE_CREATOR(periapsis::space::rotator::mars::deimos);
00362
00363 }
00364
00365
00366 namespace jupiter
00367 {
00368
00369 class jupiter : public major_planet_rotator
00370 {
00371 public:
00372 jupiter(const config_record &) : major_planet_rotator(&major_planet_data[5]) {}
00373
00374 BROKER_DECLARE_CREATOR(periapsis::space::rotator::jupiter::jupiter);
00375 };
00376
00377 BROKER_DEFINE_CREATOR(periapsis::space::rotator::jupiter::jupiter);
00378
00379
00380
00381 class jupiter_rotator : public body_rotator
00382 {
00383 public:
00384 jupiter_rotator() : body_rotator() {}
00385
00386 protected:
00387 double d, T, alpha, delta, W;
00388 double J1, J2, J3, J4, J5, J6, J7, J8;
00389
00390 void calc_orientation_pre(double jdn)
00391 {
00392 d = jdn - J2000;
00393 T = d / 36525.0;
00394
00395 J1 = 73.32 + 91472.9 * T; J1 *= math::DEG2RAD;
00396 J2 = 24.62 + 45137.2 * T; J2 *= math::DEG2RAD;
00397 J3 = 283.90 + 4850.7 * T; J3 *= math::DEG2RAD;
00398 J4 = 355.80 + 1191.3 * T; J4 *= math::DEG2RAD;
00399 J5 = 119.90 + 262.1 * T; J5 *= math::DEG2RAD;
00400 J6 = 229.80 + 64.3 * T; J6 *= math::DEG2RAD;
00401 J7 = 352.35 + 2382.6 * T; J7 *= math::DEG2RAD;
00402 J8 = 113.35 + 6070.0 * T; J8 *= math::DEG2RAD;
00403 }
00404 };
00405
00406
00407 class io : public jupiter_rotator
00408 {
00409 public:
00410 io(const config_record &) : jupiter_rotator() {}
00411
00412 virtual void calc_orientation(double jdn, transform & orientation, vector & angular_velocity)
00413 {
00414 double ang_diff;
00415 calc_orientation_pre(jdn);
00416
00417 alpha = 268.05 - 0.009*T + 0.094*::sin(J3) + 0.024*::sin(J4);
00418 delta = 64.50 + 0.003*T + 0.040*::cos(J3) + 0.011*::cos(J4);
00419 W = 200.39 + (ang_diff = 203.4889538*d - 0.085*::sin(J3) - 0.022*::sin(J4));
00420
00421 calc_orientation_aux(alpha, delta, W, orientation);
00422 calc_angular_velocity_aux(ang_diff, d, orientation, angular_velocity);
00423 }
00424
00425 BROKER_DECLARE_CREATOR(periapsis::space::rotator::jupiter::io);
00426 };
00427
00428 BROKER_DEFINE_CREATOR(periapsis::space::rotator::jupiter::io);
00429
00430
00431 class europa : public jupiter_rotator
00432 {
00433 public:
00434 europa(const config_record &) : jupiter_rotator() {}
00435
00436 virtual void calc_orientation(double jdn, transform & orientation, vector & angular_velocity)
00437 {
00438 double ang_diff;
00439 calc_orientation_pre(jdn);
00440
00441 alpha = 268.08 - 0.009*T + 1.086*::sin(J4) + 0.060*::sin(J5) + 0.015*::sin(J6) + 0.009*::sin(J7);
00442 delta = 64.51 + 0.003*T + 0.468*::cos(J4) + 0.026*::cos(J5) + 0.007*::cos(J6) + 0.002*::cos(J7);
00443 W = 36.022 + (ang_diff = 101.3747235*d - 0.980*::sin(J4) - 0.054*::sin(J5) - 0.014*::sin(J6) - 0.008*::sin(J7));
00444
00445 calc_orientation_aux(alpha, delta, W, orientation);
00446 calc_angular_velocity_aux(ang_diff, d, orientation, angular_velocity);
00447 }
00448
00449 BROKER_DECLARE_CREATOR(periapsis::space::rotator::jupiter::europa);
00450 };
00451
00452 BROKER_DEFINE_CREATOR(periapsis::space::rotator::jupiter::europa);
00453
00454
00455 class ganymede : public jupiter_rotator
00456 {
00457 public:
00458 ganymede(const config_record &) : jupiter_rotator() {}
00459
00460 virtual void calc_orientation(double jdn, transform & orientation, vector & angular_velocity)
00461 {
00462 double ang_diff;
00463 calc_orientation_pre(jdn);
00464
00465 alpha = 268.20 - 0.009*T - 0.037*::sin(J4) + 0.431*::sin(J5) + 0.091*::sin(J6);
00466 delta = 64.57 + 0.003*T - 0.016*::cos(J4) + 0.186*::cos(J5) + 0.039*::cos(J6);
00467 W = 44.064 + (ang_diff = 50.3176081*d + 0.033*::sin(J4) - 0.389*::sin(J5) - 0.082*::sin(J6));
00468
00469 calc_orientation_aux(alpha, delta, W, orientation);
00470 calc_angular_velocity_aux(ang_diff, d, orientation, angular_velocity);
00471 }
00472
00473
00474 BROKER_DECLARE_CREATOR(periapsis::space::rotator::jupiter::ganymede);
00475 };
00476
00477 BROKER_DEFINE_CREATOR(periapsis::space::rotator::jupiter::ganymede);
00478
00479
00480 class callisto : public jupiter_rotator
00481 {
00482 public:
00483 callisto(const config_record &) : jupiter_rotator() {}
00484
00485 virtual void calc_orientation(double jdn, transform & orientation, vector & angular_velocity)
00486 {
00487 double ang_diff;
00488 calc_orientation_pre(jdn);
00489
00490 alpha = 268.72 - 0.009*T - 0.068*::sin(J5) + 0.590*::sin(J6) + 0.010*::sin(J8);
00491 delta = 64.83 + 0.003*T - 0.029*::cos(J5) + 0.254*::cos(J6) - 0.004*::cos(J8);
00492 W = 259.51 + (ang_diff = 21.5710715*d + 0.061*::sin(J5) - 0.533*::sin(J6) - 0.009*::sin(J8));
00493
00494 calc_orientation_aux(alpha, delta, W, orientation);
00495 calc_angular_velocity_aux(ang_diff, d, orientation, angular_velocity);
00496 }
00497
00498 BROKER_DECLARE_CREATOR(periapsis::space::rotator::jupiter::callisto);
00499 };
00500
00501 BROKER_DEFINE_CREATOR(periapsis::space::rotator::jupiter::callisto);
00502
00503 }
00504
00505
00506 namespace saturn
00507 {
00508
00509 class saturn : public major_planet_rotator
00510 {
00511 public:
00512 saturn(const config_record &)
00513 : major_planet_rotator(&major_planet_data[6])
00514 {}
00515
00516 BROKER_DECLARE_CREATOR(periapsis::space::rotator::saturn::saturn);
00517 };
00518
00519 BROKER_DEFINE_CREATOR(periapsis::space::rotator::saturn::saturn);
00520
00521 }
00522
00523
00524 namespace uranus
00525 {
00526
00527 class uranus : public major_planet_rotator
00528 {
00529 public:
00530 uranus(const config_record &)
00531 : major_planet_rotator(&major_planet_data[7])
00532 {}
00533
00534 BROKER_DECLARE_CREATOR(periapsis::space::rotator::uranus::uranus);
00535 };
00536
00537 BROKER_DEFINE_CREATOR(periapsis::space::rotator::uranus::uranus);
00538 }
00539
00540
00541 namespace neptune
00542 {
00543
00544 class neptune : public major_planet_rotator
00545 {
00546 public:
00547 neptune(const config_record &)
00548 : major_planet_rotator(&major_planet_data[8])
00549 {}
00550
00551 BROKER_DECLARE_CREATOR(periapsis::space::rotator::neptune::neptune);
00552 };
00553
00554 BROKER_DEFINE_CREATOR(periapsis::space::rotator::neptune::neptune);
00555 }
00556
00557
00558 namespace pluto
00559 {
00560 }
00561
00562
00563 }
00564
00565
00566
00567
00568 rotating_body::rotating_body(const gsgl::string & name, gsgl::scenegraph::node *parent, body_rotator *rotator)
00569 : physics_frame(name, parent), rotator(rotator)
00570 {
00571 }
00572
00573
00574 rotating_body::~rotating_body()
00575 {
00576 delete rotator;
00577 }
00578
00579
00580
00581
00582
00583 void rotating_body::init(context *c)
00584 {
00585 if (rotator)
00586 rotator->calc_orientation(c->julian_cur, get_orientation(), get_angular_velocity());
00587
00588 assert(get_linear_velocity().mag() == 0);
00589 }
00590
00591
00592 void rotating_body::update(context *c)
00593 {
00594 if (rotator)
00595 rotator->calc_orientation(c->julian_cur, get_orientation(), get_angular_velocity());
00596
00597 assert(get_linear_velocity().mag() == 0);
00598 }
00599
00600
00601 }
00602
00603 }