Date: 2/16/20224
This document includes notes that were created while making and running the simple_gravity_spacecraft script and analysis
Requirements
Create a script in C++ that propagates a spacecraft orbit for 5400 seconds Use "Spacecraft" construct Log the simulation time, spacecraft position, and spacecraft velocity Have orbital parameters: semimajor axis(a)=6714000 meters, eccentricity(e)=0.1, inclination(i)=40 degrees, RAAN=10 degrees, argument of periapsis(w)=10 degrees, true anomaly(f)=30 degrees
Script:
The main function takes in two arguments. argc (argument count) is an integer that stores how many arguments were taken in. argv (argument vector) is an array of pointers to arrays of character objects that contain the input arguments.
The first section of our code establishes our simulation executive. This is a class that handles the scheduling, manages the frames, houses the search function, and functions for logging and integration. The search function is why each new object has a string as an input. The parseargs function interperets the command line inputs. Then we set the simulation speed and an end time for our simulation. Creating this executive also automatically establishes a root frame that is at the origin.
We then create our planet object by inputting our simulation executive and a name which, by convention, should be the same as the object name. In this case we want to establish Earth as our central body. We then want to 'place' this planet at the origin of the root frame which is done in the next line. We then set our frames' parents, joints, and angular speed by running Earth.setupFrames(). By default the gravitational parameter is the gravitational parameter of Earth but for clarity we will specify this quantity in units of m3/s2.
The next section in our code creates an object of the spacecraft class. This class has a constructor, which is a function that is run when the class is created to establish basic properties of the object in our class. In our case the constructor takes in two arguments, the simulation executive and the name of the spacecraft. For this example our spacecraft object is named sc. When this object is created it also establishes a body axis. We then want to establish that our spacecraft object, sc, is orbiting around our planet object, Earth. To do this we use a function called config from planet that takes in a planet. //why does this take in a memory address.// We then "setup objects" which establishes our point mass gravity model and our "frame state sensor model". This is what establishes our spacecraft as the target frame and the planet as the reference frame which we will use later to find position and velocity. Next, we setupFrames just like we did for the planet which sets our frames' parents, joints, and angular speed. We also setupSignals which links our gravity model to the frame state sensor. Lastly, we need to initialize our spacecrafts position and velocity. We do this using initializeFromOrbitElements with the elements given in the requirments. We must convert the given orbit elements to degrees by multiplying by a constant called DEG2RAD that has the value of pi/180. This is done to speed up the code by avoiding unecessary division, provide clarity of the purpose of the calculation, and provide an easy way to change the value across all of its instances if needed. It is crucial that initializeFromOrbitElements is run after we set up our frames, objects, and signals.
Next we will create a way to record the "state" of our spacecraft. This includes the velocity and position at each time step. Using the CsvLogger we can create a file that contains these values. To do this we must include "logging/CsvLogger.h". The CsvLogger constructor takes in the simulation executive and the model name. We can then add parameters for time, velocity, and position. Note that the time and posistion are in terms of the planet inertial frame. Additionally the velocity vector is derived with respect to the planet inertial frame.
Finally we startup and run the executive.
Analysis:
Now that we have the data we need saved in a csv file. The next step is to create a file called analysis where we will make two figures. One will contain the position in each axis as a function of time (plots overlaid). The other is a 3D graph of the position in X, Y, Z. The choice was made to create this analysis in Python to gain better understanding as well as the already established visual creation method.
The first step is to import the csv file that we just created. To do this we need a python utility called pandas. Next, we create a document to house our graphs and give it a title as well as some author information using the AutoDocPy class.
Next we create our 3D spacecraft position plot. In a variable called cfg we assign the plot title as well as axes titles. We also define our data to be graphed as the x, y, and z posistions. To do this we assign the three elements of our previously logged spacecraft position vector to x, y, and z respectively. Note that the index starts at 0 so the first three elements look like df['sc_inrtl_position_0'], df['sc_inrtl_position_1'], and df['sc_inrtl_position_2']. We then create the 3D graph using Plot3D. This takes in one argument that is the cfg variable we just created. Next, we create the header that will be displayed above the graph in the documents and isert the graph as a .fig. A similar process was used to create the 2D plots of position and velocity components vs time except we have to input time and use Plot2d.
Running the code:
The information in "/workspaces/modelspace/docs/buildinfo/commands.adoc" was very helpful with how to compile and run the code. First we navigate to "/workspaces/modelspace/build/" and run "cmake .." this creates/edits the make files. These files tell the code what do include and in what order to buld the code. Then run "make" this builds the code. This method of compilation is helpful because it makes it easier to compile complicated systems of files that have a lot of dependencies. Additionally, "make" only recompiles things that have changed instead of recompiling every file when you only edit a few. This is saves a lot of time when troubleshooting code. Once we have run "make" the executible files have been made. To run our C++ script we run the command "./cpp/scripts/tutorials/simple_gravity_spacecraft/tutorials_simple_gravity_spacecraft_script.o". The csv file that we created is saved in "/workspaces/modelspace/build/results/sc_states.csv". To run the analysis code we navigate to the location of our analysis code "/workspaces/modelspace/python/scripts/tutorials/simple_gravity_spacecraft/analysis.py" and run the command "python3 analysis.py". This creates our figures and adoc in the same directory as the analysis script.
Thats everything now go look at the pretty graphs!
Problems I fixed:
I was getting an error that either the spacecraft or planet frames was a null pointer. To fix this I used sc.setupObjects() and Earth.setupObjects(). This established the frames in the format needed for the logging. After I fixed the first error, I was getting an error that said that the Planet and Spacecraft did not share the same parent frame. To fix this I used sc.setupFrames() and Earth.setupFrames(). This established the executive frame as the parent frame for both.