#include "Integrator.hh" #include #include // This is from matrix_macros.h in Trick. /* matrix times vector : prod[i] = mat[i][j] * vect[i] */ #define MxV( prod , mat , vect ) { \ prod[0] = mat[0][0] * vect[0] + mat[0][1] * vect[1] + mat[0][2] * vect[2] ; \ prod[1] = mat[1][0] * vect[0] + mat[1][1] * vect[1] + mat[1][2] * vect[2] ; \ prod[2] = mat[2][0] * vect[0] + mat[2][1] * vect[1] + mat[2][2] * vect[2] ; \ } // GRAVITATIONAL_CONSTANT (Nm2/kg2) #define GRAVITATIONAL_CONSTANT 6.67e-11 // LUNAR_MASS (kg) #define LUNAR_MASS 7.36e22 // LUNAR RADIUS (m) #define LUNAR_RADIUS 1737400.0 #define RADIANS_PER_DEGREE 0.0174532925 typedef struct { double mass; double pos[3]; double vel[3]; double acc[3]; } SATELLITE; typedef struct { double radius; double mass; } PLANET; typedef struct { double semi_major_axis; /* (m) */ double eccentricity; /* (--) */ double inclination; /* (r) */ double argument_of_perigee; /* (r) */ double right_ascension; /* (r) */ double true_anomaly; /* (r) */ } ORBITAL_ELEMENTS; void calc_gravity( SATELLITE * S, PLANET * P, double * G ) { double distance; double pos_hat[3]; double g_force_mag; // Calculate Gravitational Force distance = sqrt( S->pos[0] * S->pos[0] + S->pos[1] * S->pos[1] + S->pos[2] * S->pos[2] ); pos_hat[0] = S->pos[0] / distance ; pos_hat[1] = S->pos[1] / distance ; pos_hat[2] = S->pos[2] / distance ; g_force_mag = ( GRAVITATIONAL_CONSTANT * P->mass * S->mass ) / ( distance * distance ) ; G[0] = g_force_mag * - pos_hat[0] ; G[1] = g_force_mag * - pos_hat[1] ; G[2] = g_force_mag * - pos_hat[2] ; } // // Reference: ISS SIGI Attitude Processor Orbit Equations EG2/Rodolfo Gonzalez 20 Aug 2003 void orb_elem_to_intl( ORBITAL_ELEMENTS * O, /* IN */ PLANET * P, /* IN */ double * R_intl, /* OUT */ double * V_intl ) { /* OUT */ double ra, wp, in ; double M_pci_perif[3][3]; /* Perifocal --> Inertial transform */ double semi_latus_rectum; double r_magnitude; double r_perifocal[3]; double v_perifocal[3]; double v_mag; semi_latus_rectum = O->semi_major_axis * ( 1.0 - O->eccentricity * O->eccentricity ); r_magnitude = semi_latus_rectum / (1.0 + O->eccentricity * cos( O->true_anomaly )); r_perifocal[0] = r_magnitude * cos( O->true_anomaly); r_perifocal[1] = r_magnitude * sin( O->true_anomaly); r_perifocal[2] = 0; v_mag = sqrt( GRAVITATIONAL_CONSTANT * P->mass / semi_latus_rectum); v_perifocal[0] = v_mag * (-sin(O->true_anomaly)); v_perifocal[1] = v_mag * (O->eccentricity + cos(O->true_anomaly)); v_perifocal[2] = 0; ra = O->right_ascension; wp = O->argument_of_perigee; in = O->inclination; M_pci_perif[0][0] = cos(ra)*cos(wp) - sin(ra)*cos(in)*sin(wp) ; M_pci_perif[0][1] = -cos(ra)*sin(wp) - sin(ra)*cos(in)*cos(wp) ; M_pci_perif[0][2] = sin(ra)*sin(in); M_pci_perif[1][0] = sin(ra)*cos(wp) + cos(ra)*cos(in)*sin(wp) ; M_pci_perif[1][1] = -sin(ra)*sin(wp) + cos(ra)*cos(in)*cos(wp) ; M_pci_perif[1][2] = -cos(ra)*sin(in) ; M_pci_perif[2][0] = sin(in)*sin(wp) ; M_pci_perif[2][1] = sin(in)*cos(wp) ; M_pci_perif[2][2] = cos(in) ; MxV( R_intl , M_pci_perif , r_perifocal) ; MxV( V_intl , M_pci_perif , v_perifocal) ; } void deriv(SATELLITE *S, PLANET *P) { double gforce[3]; calc_gravity(S, P, gforce ); S->acc[0] = gforce[0] / S->mass ; S->acc[1] = gforce[1] / S->mass ; S->acc[2] = gforce[2] / S->mass ; } int main(int argc, const char* argv[]) { SATELLITE satellite; PLANET planet; ORBITAL_ELEMENTS orbital_elements; long tick = 0; double seconds_per_tick = 1.0; double sim_time = 0.0; // Initialization satellite.mass = 100; planet.mass = LUNAR_MASS; planet.radius = LUNAR_RADIUS; orbital_elements.semi_major_axis = 2000000; // meters orbital_elements.eccentricity = 0.2; orbital_elements.inclination = 5.0 * RADIANS_PER_DEGREE; orbital_elements.argument_of_perigee = 0.0; orbital_elements.right_ascension = 0.0; // radians orbital_elements.true_anomaly = 0.0; // radians orb_elem_to_intl( &orbital_elements, &planet, satellite.pos, satellite.vel); Trick::Integrator *I = getIntegrator( Euler, 6, 1.0); do { // sim loop sim_time = tick * seconds_per_tick ; std::cout << "sim_time = " << sim_time << std::endl; do { // Integration Loop I->time = sim_time; std::cout << "step #" << I->intermediate_step << std::endl; std::cout.flush(); std::cout << "deriv ..."; std::cout.flush(); deriv( &satellite, &planet); std::cout << "done." << std::endl; std::cout.flush(); std::cout << "loading state ..."; std::cout.flush(); I->state[0] = satellite.pos[0]; I->state[1] = satellite.pos[1]; I->state[2] = satellite.pos[2]; I->state[3] = satellite.vel[0]; I->state[4] = satellite.vel[1]; I->state[5] = satellite.vel[2]; std::cout << "done." << std::endl; std::cout.flush(); std::cout << "loading state deriv ..."; std::cout.flush(); I->deriv[I->intermediate_step][0] = satellite.vel[0]; I->deriv[I->intermediate_step][1] = satellite.vel[1]; I->deriv[I->intermediate_step][2] = satellite.vel[2]; I->deriv[I->intermediate_step][3] = satellite.acc[0]; I->deriv[I->intermediate_step][4] = satellite.acc[1]; I->deriv[I->intermediate_step][5] = satellite.acc[2]; std::cout << "done." << std::endl; std::cout.flush(); std::cout << "integrate" << std::endl; std::cout.flush(); I->integrate(); std::cout << "done." << std::endl; std::cout.flush(); satellite.pos[0] = I->state_ws[I->intermediate_step][0]; satellite.pos[1] = I->state_ws[I->intermediate_step][1]; satellite.pos[2] = I->state_ws[I->intermediate_step][2]; satellite.vel[0] = I->state_ws[I->intermediate_step][3]; satellite.vel[1] = I->state_ws[I->intermediate_step][4]; satellite.vel[2] = I->state_ws[I->intermediate_step][5]; } while ( I->intermediate_step); std::cout << "(" << satellite.pos[0] <<","<< satellite.pos[1] <<","<< satellite.pos[2] << ")" << std::endl; tick++; } while (sim_time < 10.0); }