#include "Matrix.h"
#include "Rotation.h"
#include "Attitude.h"
#include "Orbit.h"
#include "CombinedNumericPropagator.h"
#include "RungeKuttaIntegrator.h"
#include "orbitmodels/TwoBodyDynamics.h"
#include "EarthCentralBody.h"
#include "OrbitState.h"
#include "AttitudeState.h"
#include "orbitstaterep/PositionVelocity.h"
#include "orbitframes/OrbitFrameIJK.h"
#include "Plot.h"
using namespace O_SESSAME;
NumericPropagator* SetupPropagator();
Environment* SetupEnvironment();
Orbit* SetupOrbit();
Attitude* SetupAttitude();
void myOrbitStateConvFunc(const Matrix &_meshPoint, OrbitState &_convertedOrbitState);
void myAttitudeStateConvFunc(const Matrix &_meshPoint, AttitudeState &_convertedAttitudeState);
int main()
{
cout << "Calling SetupOrbit()" << endl;
Orbit* myOrbit = SetupOrbit();
cout << "Calling SetupAttitude()" << endl;
Attitude* myAttitude = SetupAttitude();
cout << "Calling SetupPropagator()" << endl;
NumericPropagator* myPropagator = SetupPropagator();
myOrbit->SetPropagator(myPropagator);
myAttitude->SetPropagator(myPropagator);
cout << "Calling SetupEnvironment()" << endl;
Environment* myEnvironment = SetupEnvironment();
myOrbit->SetEnvironment(myEnvironment);
myAttitude->SetEnvironment(myEnvironment);
double numOrbits = 1/10.0;
cout << "Number of Orbits: " << flush;
vector<ssfTime> integrationTimes;
ssfTime begin(0);
ssfTime end(begin + 92*60*numOrbits);
integrationTimes.push_back(begin);
integrationTimes.push_back(end);
cout << "PropTime = " << begin.GetSeconds() << " s -> " << end.GetSeconds() << " s" << endl;
cout << "Orbit State: " << ~myOrbit->GetStateObject().GetState() << endl;
cout << "Attitude State: " << ~myAttitude->GetStateObject().GetState() << endl;
tick();
myPropagator->Propagate(integrationTimes, myOrbit->GetStateObject().GetState(), myAttitude->GetStateObject().GetState());
ssfSeconds calcTime = tock();
cout << "finished propagating in " << calcTime << " seconds." << endl;
for (int ii = 0; ii < 2 ; ++ii)
{
integrationTimes[0] = integrationTimes[1];
integrationTimes[1] = integrationTimes[0] + 92*60*numOrbits;
cout << integrationTimes[0] << " -> " << integrationTimes[1] << endl;
myPropagator->Propagate(integrationTimes, myOrbit->GetStateObject().GetState(), myAttitude->GetStateObject().GetState());
}
Matrix orbitHistory = myOrbit->GetHistory().GetHistory();
Matrix orbitPlotting = orbitHistory(_,_(MatrixIndexBase+1,MatrixIndexBase+3));
Matrix attitudeHistory = myAttitude->GetHistory().GetHistory();
Matrix attitudePlotting = attitudeHistory(_,_(MatrixIndexBase,MatrixIndexBase+4));
Plot3D(orbitPlotting);
Plot2D(attitudePlotting);
ofstream ofile;
ofile.open("OrbitHistory.dat");
ofile << myOrbit->GetHistory().GetHistory();
ofile.close();
ofile.open("AttitudeHistory.dat");
ofile << myAttitude->GetHistory().GetHistory();
ofile.close();
return 0;
}
Vector GravityForceFunction(const ssfTime &_currentTime, const OrbitState &_currentOrbitState, const AttitudeState &_currentAttitudeState, const EnvFuncParamaterType &_parameterList)
{
static Vector Forces(3);
static Vector Position(3); Position(_) = _currentOrbitState.GetState()(_(VectorIndexBase,VectorIndexBase+2));
Forces = -398600.441 / pow(norm2(Position),3) * Position;
return Forces;
}
Vector DragForceFunction(const ssfTime &_currentTime, const OrbitState &_currentOrbitState, const AttitudeState &_currentAttitudeState, const EnvFuncParamaterType &_parameterList)
{
static Vector Forces(3);
double BC = *(reinterpret_cast<double*>(_parameterList[0]));
static Vector Vrel(3); Vrel(_) = _currentOrbitState.GetState()(_(VectorIndexBase+3,VectorIndexBase+5));
double Vrel_mag = norm2(Vrel);
double rho = *(reinterpret_cast<double*>(_parameterList[1]));
Forces = -1/2 * rho / BC * pow(Vrel_mag,2) * Vrel / Vrel_mag;
return Forces;
}
Environment* SetupEnvironment()
{
Environment* pEarthEnv = new Environment;
EarthCentralBody *pCBEarth = new EarthCentralBody;
pEarthEnv->SetCentralBody(pCBEarth);
cout << "Filling Parameters" << endl;
EnvFunction TwoBodyGravity(&GravityForceFunction);
pEarthEnv->AddForceFunction(TwoBodyGravity);
EnvFunction DragForce(&DragForceFunction);
double *BC = new double(200);
DragForce.AddParameter(reinterpret_cast<void*>(BC), 1);
double *rho = new double(1.13 * pow(static_cast<double>(10), static_cast<double>(-12)));
DragForce.AddParameter(reinterpret_cast<void*>(rho), 2);
pEarthEnv->AddForceFunction(DragForce);
cout << "Finished Setting up Earth Environment" << endl;
return pEarthEnv;
}
NumericPropagator* SetupPropagator()
{
CombinedNumericPropagator* myProp = new CombinedNumericPropagator;
RungeKuttaIntegrator* orbitIntegrator = new RungeKuttaIntegrator;
RungeKuttaIntegrator* attitudeIntegrator = new RungeKuttaIntegrator;
orbitIntegrator->SetNumSteps(100);
myProp->SetOrbitIntegrator(orbitIntegrator);
attitudeIntegrator->SetNumSteps(1000);
myProp->SetAttitudeIntegrator(attitudeIntegrator);
myProp->SetOrbitStateConversion(&myOrbitStateConvFunc);
myProp->SetAttitudeStateConversion(&myAttitudeStateConvFunc);
return myProp;
}
void myOrbitStateConvFunc(const Matrix &_meshPoint, OrbitState &_convertedOrbitState)
{
static Vector tempVector(_meshPoint[MatrixColsIndex].getIndexBound() - 1);
tempVector(_) = ~_meshPoint(_,_(MatrixIndexBase+1, _meshPoint[MatrixColsIndex].getIndexBound()));
_convertedOrbitState.SetState(tempVector);
return;
}
Orbit* SetupOrbit()
{
Orbit* myOrbit = new Orbit;
OrbitState myOrbitState;
myOrbitState.SetStateRepresentation(new PositionVelocity);
myOrbitState.SetOrbitFrame(new OrbitFrameIJK);
Vector initPV(6);
initPV(VectorIndexBase+0) = -5776.6;
initPV(VectorIndexBase+1) = -157;
initPV(VectorIndexBase+2) = 3496.9;
initPV(VectorIndexBase+3) = -2.595;
initPV(VectorIndexBase+4) = -5.651;
initPV(VectorIndexBase+5) = -4.513;
myOrbitState.SetState(initPV);
myOrbit->SetStateObject(myOrbitState);
myOrbit->SetDynamicsEq(&TwoBodyDynamics);
Matrix Parameters(1,1);
Parameters(MatrixIndexBase,MatrixIndexBase) = 398600.441;
myOrbit->SetParameters(Parameters);
return myOrbit;
}
void myAttitudeStateConvFunc(const Matrix &_meshPoint, AttitudeState &_convertedAttitudeState)
{
static Vector tempQ(4); tempQ(_) = ~_meshPoint(_,_(2, 5));
static Vector tempVector(3); tempVector(_) = ~_meshPoint(1, _(6, 8));
_convertedAttitudeState.SetState(Rotation(Quaternion(tempQ)), tempVector);
return;
}
static Vector AttituteDynamics(const ssfTime &_time, const Vector& _integratingState, Orbit *_Orbit, Attitude *_Attitude, const Matrix &_parameters, const Functor &_forceFunctorPtr)
{
static Vector stateDot(7);
static Matrix bMOI(3,3);
static Matrix qtemp(4,3);
static Matrix Tmoment(3,1);
static Vector qIn(4);
static Vector wIn(3);
qIn = _integratingState(_(VectorIndexBase,VectorIndexBase + 3));
wIn = _integratingState(_(VectorIndexBase + 4,VectorIndexBase + 6));
qIn /= norm2(qIn);
qtemp(_(VectorIndexBase+0,VectorIndexBase+2),_(VectorIndexBase+0,VectorIndexBase+2)) = skew(qIn(_(VectorIndexBase+0,VectorIndexBase+2))) + qIn(VectorIndexBase+3) * eye(3);
qtemp(VectorIndexBase+3, _(VectorIndexBase+0,VectorIndexBase+2)) = -(~qIn(_(VectorIndexBase+0,VectorIndexBase+2)));
qtemp(_,MatrixIndexBase) = 0.5 * qtemp * wIn;
bMOI = _parameters(_(MatrixIndexBase+0,MatrixIndexBase+2),_(MatrixIndexBase+0,MatrixIndexBase+2));
Tmoment(_,_) = (_forceFunctorPtr.Call(_time, _Orbit->GetStateObject(), _Attitude->GetStateObject()))(_);
Tmoment = (bMOI.inverse() * (Tmoment - skew(wIn) * (bMOI * wIn)));
stateDot(_(VectorIndexBase,VectorIndexBase + 3)) = qtemp(_,MatrixIndexBase);
stateDot(_(VectorIndexBase + 4,VectorIndexBase + 6)) = Tmoment(_,MatrixIndexBase);
return stateDot;
}
Attitude* SetupAttitude()
{
Attitude* myAttitude = new Attitude;
AttitudeState myAttitudeState;
myAttitudeState.SetRotation(Rotation(Quaternion(0,0,0,1)));
Vector initAngVelVector(3);
initAngVelVector(1) = 0.1;
myAttitudeState.SetAngularVelocity(initAngVelVector);
myAttitude->SetStateObject(myAttitudeState);
myAttitude->SetDynamicsEq(&AttituteDynamics);
myAttitude->SetParameters(eye(3));
return myAttitude;
}