C++ Project: Orbital Mechanics
C++ Project: Orbital Mechanics
C++ Project: Orbital Mechanics
Introduction
Travel through the solar system can be a dangerous and expensive venture. After
the tremendous amount of fuel/energy expended in simply reaching escape
velocity, there must be remaining fuel for further orientation and to break out of a
stable Earth orbit. This facet and other obstructions are oft cited as reasons to turn
away from space travel, despite its numerous economic, scientific, and social
benefits. Fortunately, there are methods that make covering these vast distances
relatively cheap. One of these cost-effective solutions is known as a Hohmann
transfer orbit. With the correct alignment between Earth and the destination, and
two properly timed burns, a spacecraft can be made to coast across with very little
fuel expenditure.
Summary
Blank lines 30
Comment lines 25
Total 305
55 variables
The program that I have built is a calculator for a highly simplified Hohmann
transfer orbit . It assumes that gravitational effects between the destination planet
and the spacecraft are null, and depends only upon the mutual attraction of Sol as
its gravitational pivot point.
I used the project as an opportunity to implement the different techniques we have
covered in the class. I was able to construct and use variables of different data
types, constants, control structures, I/O manipulation, functions, and Boolean
operators. Furthermore, I used single and two dimensional arrays to hold the dozens
of values that had to be accounted for the rocket motor, destinations, and
propellant types. I used files to store some of the data read into these arrays, such
as the specifications for the different motors.
I ran into problems with choosing the correct data types for my distance functions.
Because I had used such large numbers initially, and had passed these values to
more than one function, the variables became infinite when pushed into lower order
variable data types. In implementing arrays I had to learn the best way to organize
the data, and find efficient techniques to calling these values when needed.
In completion I realize that I should have taken acceleration due to gravitational
effects into account as their absence resulted in unrealistic outcomes. For instance,
to reach the gas giants my program insists that megatons of liquid hydrogen/liquid
oxygen propellant would be necessary to move achieve the delta v necessary to
complete a transfer. However, the Voyager spacecraft were able to achieve much
greater delta v requirements by using the gravity wells of planets to slingshot to
incredible speeds
Psuedocode
Prototype of menu, planets, and equation functions
Begin main function
Introduction
Declare loop variable
Do
Declare choice and mass variables
Call drive function
Prompt user for rerun
Get answer
While prompt is y or Y
End main
Begin drive
Prompt user for mass
Get mass
Display options of drives
Get drive choice
Call switch function and pass choice into it
case 5: call Jupiter function and pass mass, isp, and fuel type
case 6: call Saturn function and pass mass, isp, and fuel type
case 7: call Uranus function and pass mass, isp, and fuel type
case 8: call Neptune function and pass mass, isp, and fuel type
case 9: call Pluto function and pass mass, isp, and fuel type
case 10: call kuiper function and pass mass, isp, and fuel type
default: tell user it is an invalid option
End destination
Begin Mercury
Declare aphelion, perihelion , name.
Call and pass these values to the Hohmann function alongside mass, isp, and
fuel
Do this routine for each corresponding destination up to kuiper
End Mercury
Begin Hohmann
Call variables passed from one of the destination functions, name, mass,
aphelion, and perihelion
Declare and initialize constants for mass of sun, orbital radius of earth, and
Pi
Declare variables for text, the final, initial, and total delta v, mu, units of time,
units of length, units of mass, and transit time
If called aphelion and perihelion are mutually greater than earth orbit
Calculate delta vs using method 1 for both aphelion and perihelion
then the total
Else
Calculate delta vs using method 2 for both aphelion and perihelion
then the total
Calculate the transit times for both aphelion and perihelion in months
If the transit time for either is > 12
Initialize time unit as years
Flowchart
References
www.cpluplus.com
Program
#include <cstdlib>
#include <iostream>
#include <cmath>
#include <iomanip>
#include <fstream>
#include <cstring>
using namespace std;
//Function prototypes
void drive();
void specs(int, int, float);
void destination(long double, float, string);
void mercury(float, float, string);
void venus(float, float, string);
void mars(float, float, string);
void asteroid(float, float, string);
void jupiter(float, float, string);
void saturn(float, float, string);
void uranus(float, float, string);
void neptune(float, float, string);
void pluto(float, float, string);
void kuiper(float, float, string);
void hohmann(long double, float, float, float, string, string);
float propellant(float, float, float);
int main() {
//Program intro, decided it was unnecessary to loop this far back
cout<<"This program will calculate the change in velocity necessary to complete
a"<<endl;
cout<<"Hohmann transfer, an orbit considered 'cheap'in terms of delta-V
budget."<<endl;
cout<<"It will also compute the transit time of the transfer, and the
fuel/oxidizer ."<<endl;
cout<<"required to complete the journey."<<endl;
cout<<"The initial location is Earth orbit, and the destination is assumed to be
aligned."<<endl;
cout<<"on the same orbital plane."<<endl;
cout<<"\n";
char prompt_answer;
//Beginning to program 'run' loop
do{
//calling menu function
drive();
cout<<"\n";
//Prompt user for rerun
cout<<"Press 'y' or 'Y' to run again"<<endl;
cin>>prompt_answer;
}while(prompt_answer=='y'||prompt_answer=='Y');
}
//menu function that is called to display fuel and destination choices each of
void drive(){
int schoice, engine, fuel;
float shell_mass;
cout<<"Please input the mass of your spacecraft in metric tons"<<endl;
cout<<"(For reference the shuttle orbiter was 2,041 metric tons, while"<<endl;
cout<<"the Voyager satellites were each .72 of a metric ton.)"<<endl;
cin>>shell_mass;
cout<<"\n";
cout<<"Choose a drive for the spacecraft"<<endl;
cout<<" Manufacturer
Impulse(sec)"<<endl;
Engine
cout<<"1) Space-X
cout<<"2) Aerojet
Merlin-1c
LR-87
Fuel
LOX/RP1
LOX/LH2
RD-180
SSME/RS-25
4.45e3
7.33e3
LOX/RP1
LOX/LH2
342.0"<<endl;
290.0"<<endl;
4.15e6
2.28e3
VASIMR
LH2
LH2
5
3.36e5
5000.0"<<endl;
cin>>schoice;
cout<<"\n";
switch(schoice){
case 1: specs(engine=0, fuel=0, shell_mass);break;
case 2: specs(engine=1, fuel=1, shell_mass);break;
case 3: specs(engine=2, fuel=0, shell_mass);break;
case 4: specs(engine=3, fuel=1, shell_mass);break;
case 5: specs(engine=4, fuel=2, shell_mass);break;
case 6: specs(engine=5, fuel=2, shell_mass);break;
default :
cout<<"That is not a valid choice of drive"<<endl;break;
}
cout<<" \n";
}//initialize the spacecraft specifications from the values passed from the drive
function
void specs(int e, int f, float sm){
const int ROWS=2, COLS=6;
long double engine_mass, dry_mass, isp, motor[ROWS][COLS];
string fuels[3];
ifstream input;
input.open("engine.txt");
if(input.fail()){
//cout<<"Input file opening failed . \n";
}//fill motor array from file
for(int row=0;row<ROWS;row++){
int col=0;
input>>motor[row][col];
/*if(row==1){
cout<<"isp ="<<motor[row][col]<<endl;
}else
cout<<"mass ="<<motor[row][col]<<endl;*/
for(col=1;col<COLS;col++){
input>>motor[row][col];
/*if(row==1){
cout<<"isp ="<<motor[row][col]<<endl;
}else
cout<<"mass ="<<motor[row][col]<<endl;*/
}
}
input.close();
input.open("fuel.txt");
if(input.fail()){
cout<<"Input file opening failed . \n";
}//fill fuel array from file
for(int row=0;row<3;row++){
input>>fuels[row];
//cout<<"fuel ="<<fuels[row]<<endl;
}
input.close();
string fuel=fuels[f];
engine_mass=motor[0][e];//cout<<"engine mass ="<<engine_mass<<endl;
isp=motor[1][e];//cout<<"specific impulse ="<<isp<<endl;
dry_mass=engine_mass+sm;//cout<<"dry mass ="<<dry_mass<<endl;
cout<<"The mass of your spacecraft is now "<<dry_mass<<" metric
tons"<<endl;
destination(dry_mass,isp,fuel);
}
void destination(long double m, float i, string f ){
int dchoice;
cout<<"\n";
cout<<"Choose a destination by entering its corresponding number"<<endl;
cout<<"1) Mercury"<<endl;
cout<<"2) Venus"<<endl;
cout<<"3) Mars"<<endl;
cout<<"4) Asteroid Belt"<<endl;
cout<<"5) Jupiter"<<endl;
cout<<"6) Saturn"<<endl;
cout<<"7) Uranus"<<endl;
cout<<"8) Neptune"<<endl;
cout<<"9) Pluto"<<endl;
cout<<"10) Kuiper Belt"<<endl;
cout<<"\n";
cin>>dchoice;
switch(dchoice){
case 1: mercury(m,i,f);break;
case 2: venus(m,i,f);break;
case 3: mars(m,i,f);break;
case 4: asteroid(m,i,f);break;
case 5: jupiter(m,i,f);break;
case 6: saturn(m,i,f);break;
case 7: uranus(m,i,f);break;
case 8: neptune(m,i,f);break;
case 9: pluto(m,i,f);break;
float aphelion=7.3e12;
float perihelion=4.4e12;
string name= "Pluto";
hohmann(aphelion, perihelion, isp, mass, name, fuel);
}
void kuiper(float mass, float isp, string fuel){
float aphelion= 7.48e12;
float perihelion=4.49e12;
string name= "Kuiper Belt";
hohmann(aphelion, perihelion, isp, mass, name, fuel);
}
void hohmann(long double r1, float r2, float i, float m, string n, string f ){
//declare and initialize constants, variables
float const M_SUN=1.9e30, R_EARTH=1.5e11,
C_GRAVITY=6.7e-11,PI=4*atan(1);
long double dv1, dv2, dv3, dv4, dvtot_ap, dvtot_pe, transit_ap=0, transit_pe=0,
mu, ap_prop_mass, pe_prop_mass;
string time_unit=" months", distance_unit=" meters", mass_unit=" tons";
m*=10e3;
//Calculate the initial, final, and total delta vee's for aphelion & perihelion
mu=C_GRAVITY*(M_SUN+m);
//Sort which equation to use based on values initialized for orbital radii
if(R_EARTH<r1&&R_EARTH<r2){
dv1=sqrt(mu/R_EARTH)*(sqrt((2.0*r1)/(R_EARTH+r1))-1.0);
dv2=sqrt(mu/r1)*(1.0-sqrt((2.0*r1)/(R_EARTH+r1)));
dvtot_ap=dv1+dv2;//d-vee total at farthest distance
dv3=sqrt(mu/R_EARTH)*(sqrt((2.0*r2)/(R_EARTH+r2))-1.0);
dv4=sqrt(mu/r2)*(1.0-sqrt((2.0*r2)/(R_EARTH+r2)));
dv3=sqrt(mu/r2)*(sqrt((2.0*R_EARTH)/(R_EARTH+r2))-1.0);
dv4=sqrt(mu/R_EARTH)*(1.0-sqrt((2.0*R_EARTH)/(R_EARTH+r2)));
dvtot_pe=dv3+dv4;//d-vee total at shortest distance
}
//Calculate the time to reach destination
transit_ap=PI*sqrt((pow((R_EARTH+r1),3))/(8*mu))/2592000;//convert to
//months from seconds
transit_pe=PI*sqrt((pow((R_EARTH+r2),3))/(8*mu))/2592000;
ap_prop_mass=propellant(dvtot_ap,m,i);
pe_prop_mass=propellant(dvtot_pe,m,i);
if(ap_prop_mass>=10e9){
ap_prop_mass/=10e9;
mass_unit=" gigatons";
}
if(pe_prop_mass>=10e9){
pe_prop_mass/=10e9;
mass_unit=" gigatons";
}
if(ap_prop_mass>=10e6){
ap_prop_mass/=10e6;
mass_unit=" megatons";
}
if(pe_prop_mass>=10e6){
pe_prop_mass/=10e6;
mass_unit=" megatons";
}
if(ap_prop_mass>=10e3){
ap_prop_mass/=10e3;
mass_unit=" kilotons";
}
if(pe_prop_mass>=10e3){
pe_prop_mass/=10e3;
mass_unit=" kilotons";
}
//Output results
cout<<"The total delta-V necessary when " <<n<<" is at aphelion is "<<
setprecision(3)<<dvtot_ap<<setprecision(3)<<distance_unit<<"/sec"<<endl;
//convert distance to kilometers
cout<<"With the drive configuration it would require
"<<setprecision(3)<<ap_prop_mass<<mass_unit<<" of "<<f<<endl;
cout<<"At this distance it will take "<<transit_ap<<time_unit<<endl;
cout<<"\n";
cout<<"The total delta-V necessary when " <<n<<" is at perihelion is "<<
setprecision(3)<<dvtot_pe<<setprecision(3)<<distance_unit<<"/sec"<<endl;
cout<<"With the drive configuration it would require
"<<setprecision(3)<<pe_prop_mass<<mass_unit<<" of "<<f<<endl;
cout<<"At this distance it will take "<<transit_pe<<time_unit<<endl;
}
float propellant(float d_vel, float m, float i){
const float G0=9.81;//acceleration due to earth in meters/sec
const float E=2.71828;//base of natural log
long double vel_exh, mass_propel;
vel_exh=i*G0;//exhaust velocity = specific impulse*acceleration due to earths
gravity
//cout<<"exhaust velocity ="<<vel_exh<<"meters/sec"<<endl;
mass_propel=m/(pow(E,(d_vel/vel_exh))-1);//mass of propellant = dry mass/
(e^(dVee/exhaust velocity)-1) in kilograms
return mass_propel/1000;//propellant mass in tons pass this value back to
hohmann
}