trick/trick_source/sim_services/Integrator/unittest/ISat.cpp
2015-02-26 09:02:31 -06:00

214 lines
6.7 KiB
C++

#include "Integrator.hh"
#include <math.h>
#include <iostream>
// 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);
}