1
0
mirror of https://gitlab.com/lander-team/lander-cpp.git synced 2025-06-16 15:17:23 +00:00

Compare commits

...

78 Commits
PID ... main

Author SHA1 Message Date
7a523bab6d Merge branch '36-move-init_loadcells-to-teensy-h' into 'main'
Resolve "Move init_loadCells() to teensy.h"

Closes #36

See merge request lander-team/lander-cpp!28
2021-11-22 19:55:20 +00:00
Brendan McGeeney
9442884d44 Resolve "Move init_loadCells() to teensy.h" 2021-11-22 19:55:19 +00:00
Brendan McGeeney
8054e26857 Merge branch '36-move-init_loadcells-to-teensy-h' into 'main'
Resolve "Move init_loadCells() to teensy.h"

Closes #36

See merge request lander-team/lander-cpp!26
2021-11-15 03:39:27 +00:00
bpmcgeeney
6a4437614e added read_lc declaration back in main.cpp 2021-11-14 20:34:47 -07:00
bpmcgeeney
503bf40c5b Moved init_loadCells() to teensy.h 2021-11-14 20:31:17 -07:00
Brendan McGeeney
f7acf25479 Merge branch '31-avionics-integration-test' into 'main'
Resolve "Avionics Integration Test"

Closes #31

See merge request lander-team/lander-cpp!25
2021-11-15 00:21:42 +00:00
62d8a37517 Merge branch '31-avionics-integration-test' of gitlab.com:lander-team/lander-cpp into 31-avionics-integration-test 2021-11-14 17:13:56 -07:00
8528b028e5 keep platforms the same 2021-11-14 17:13:49 -07:00
bpmcgeeney
5a99508761 More robust gimbal test function, delay based on step size of Sim 2021-11-14 17:10:58 -07:00
bpmcgeeney
e6f7e4c160 Formal build for Avionics Integration Test 2021-11-14 16:41:25 -07:00
bpmcgeeney
82e43b1fe8 Added test gimbal function 2021-11-14 14:23:28 -07:00
bpmcgeeney
8fa9dba55e Integrated servos, just neefds to be slowed down now 2021-11-14 13:59:51 -07:00
d487d6d30a should make sure code compiles before pushing 2021-11-14 10:33:16 -07:00
0f3e267af8 organized main 2021-11-14 10:32:04 -07:00
812f62f22a load cell integration 2021-11-13 14:48:12 -07:00
Matthew Robinaugh
c05bbb6845 Merge branch '31-avionics-integration-test' of gitlab.com:lander-team/lander-cpp into 31-avionics-integration-test 2021-11-13 11:32:49 -07:00
Matthew Robinaugh
717bb92678 Update lc values to be calibrated and vector math 2021-11-13 11:32:42 -07:00
47e8042a57 cleaned write2csv 2021-11-13 11:25:44 -07:00
b9c2e7fb35 now reading from load cells each loop 2021-11-13 11:17:44 -07:00
069ab2a9e4 extra code 2021-11-12 15:54:34 -07:00
554f0fdc53 Merge branch '31-avionics-integration-test' of gitlab.com:lander-team/lander-cpp into 31-avionics-integration-test 2021-11-12 15:52:26 -07:00
a6dcb6863f added load cells to csv 2021-11-12 15:47:27 -07:00
Matthew Robinaugh
f32bf60c72 Merge branch '31-avionics-integration-test' of gitlab.com:lander-team/lander-cpp into 31-avionics-integration-test 2021-11-12 15:34:28 -07:00
289f2e7a43 Merge branch '31-avionics-integration-test' into 'main'
Print Timing Info

See merge request lander-team/lander-cpp!24
2021-11-12 22:23:30 +00:00
Brendan McGeeney
4594c87fe6 Print Timing Info 2021-11-12 22:23:30 +00:00
bpmcgeeney
03c5b6d16f printing timing info 2021-11-12 15:05:03 -07:00
e9d8063604 Merge branch '22-make-function-to-turn-test-stand-load-cells-into-thrust-vector' into 'main'
Resolve "Make function to turn test stand load cells into thrust vector"

Closes #22

See merge request lander-team/lander-cpp!17
2021-11-12 20:51:20 +00:00
175c5a0b41 initialize loadTotal 2021-11-12 13:50:26 -07:00
f7c34b6c8c Merge branch 'main' into '22-make-function-to-turn-test-stand-load-cells-into-thrust-vector'
# Conflicts:
#   .vscode/extensions.json
#   include/teensy.h
#   src/main.cpp
2021-11-12 20:46:35 +00:00
2a0426334d load cells dont run on native 2021-11-12 13:38:06 -07:00
4ef7619217 compiling 😆 2021-11-12 13:35:06 -07:00
Brendan McGeeney
8ec17dd820 Merge branch '27-fix-simulation-on-teensy' into 'main'
Resolve "Fix SImulation on Teensy"

Closes #27

See merge request lander-team/lander-cpp!23
2021-11-12 19:26:58 +00:00
Brendan McGeeney
1e4ee942e2 Merge branch 'main' into '27-fix-simulation-on-teensy'
# Conflicts:
#   src/main.cpp
2021-11-12 19:23:05 +00:00
bpmcgeeney
0058af9667 Fixed differences between native and teensy, added getThrust() function to clean up thrustInfo() 2021-11-11 21:58:57 -07:00
Matthew Robinaugh
01cf0966f2 Initialize load cell values 2021-11-10 14:42:57 -07:00
f0577a8fce outfile now has more precision 2021-11-10 14:42:47 -07:00
Matthew Robinaugh
1ec624cc55 Update to load cell calibration and initialize lc 2021-11-10 14:36:31 -07:00
Matthew Robinaugh
541d7f4281 Added Struct for load cells 2021-11-08 15:37:56 -07:00
bpmcgeeney
87fb8f8621 fixed, gonna make some more changes to make sure we're utilizing our whole burn 2021-11-08 14:43:52 -07:00
851edaa361 Merge branch '26-simulation-abort-indication' into 'main'
Resolve "Simulation Abort Indication"

Closes #26

See merge request lander-team/lander-cpp!22
2021-11-08 21:05:00 +00:00
7cffb33ff1 donezo 2021-11-08 13:54:12 -07:00
Brendan McGeeney
fe1a5b9bc0 Merge branch '28-increment-file-name-on-sd-card' into 'main'
Resolve "Increment File Name on SD Card"

Closes #28

See merge request lander-team/lander-cpp!21
2021-11-08 20:37:19 +00:00
4f44788038 no longer angry 2021-11-08 13:31:49 -07:00
bpmcgeeney
cce451f069 its angry 2021-11-08 11:19:06 -07:00
Brendan McGeeney
995d856d08 Merge branch '15-integrate-with-sd-card' into 'main'
Resolve "Integrate with SD Card"

Closes #15

See merge request lander-team/lander-cpp!20
2021-11-05 21:00:43 +00:00
bpmcgeeney
9bce55f7af fixed time duration display 2021-11-05 13:58:27 -07:00
Matthew Robinaugh
3eb9369371 Fixed Linux build error 2021-11-05 13:32:15 -07:00
48c1059c0a fixed outVector size and removed teensy 2021-11-05 06:04:30 -07:00
bpmcgeeney
897b5c1d7d outvector struct now only created when building native 2021-11-04 21:56:39 -07:00
bpmcgeeney
a305b9599e Now printing entire sim to simOut.csv on SD card 2021-11-04 21:24:55 -07:00
bpmcgeeney
c06693e6aa added back delay at the end of the sim 2021-11-04 17:51:52 -07:00
bpmcgeeney
05663a5ac7 fixed file open error, it works! 2021-11-04 17:41:20 -07:00
bpmcgeeney
cce72b9114 Initial test function, still needs to be run on teensy to verify 2021-11-04 15:56:55 -07:00
15b3cf04fd Merge branch 'make-teensy-compile' into 'main'
Make teensy compile

See merge request lander-team/lander-cpp!19
2021-11-04 19:46:10 +00:00
b9ccfd110e Make teensy compile 2021-11-04 19:46:10 +00:00
ce4cbff8bd ignore files managed by PIO 2021-11-03 20:02:35 -07:00
c0bd8128fe Merge branch 'platformio-stuff' into 'main'
Platformio stuff

See merge request lander-team/lander-cpp!18
2021-11-04 02:58:49 +00:00
5abdc75c81 Platformio stuff 2021-11-04 02:58:49 +00:00
0d3c0a9d1c Merge branch 'loadCellCalibrate' into 'main'
Load cell calibrate

See merge request lander-team/lander-cpp!16
2021-11-03 22:44:24 +00:00
a129221588 Load cell calibrate 2021-11-03 22:44:23 +00:00
50dd49481a Merge branch '25-separate-native-and-teensy-code' into 'main'
Resolve "Separate native and teensy code"

Closes #25

See merge request lander-team/lander-cpp!14
2021-11-03 22:33:10 +00:00
66590a33fe Resolve "Separate native and teensy code" 2021-11-03 22:33:10 +00:00
ad602ca834 Only build Julia plots for main since they take forever. 2021-11-03 19:31:48 +00:00
Matthew Robinaugh
326b5592f6 Added -wall to tasks.json 2021-11-02 18:24:51 -07:00
378c6d8014 Merge branch 'main' of gitlab.com:lander-team/lander-cpp 2021-10-20 13:43:44 -07:00
656ce8ed8d fix being able to build from any file 2021-10-20 13:43:40 -07:00
30cef521c0 fix units 2021-10-19 17:50:18 +00:00
1746f670a9 Merge branch '21-prettier-plots' into 'main'
Resolve "prettier plots"

Closes #21

See merge request lander-team/lander-cpp!10
2021-10-19 16:29:04 +00:00
c73fc0fd7c Resolve "prettier plots" 2021-10-19 16:29:04 +00:00
bpmcgeeney
cebccecf2b Fixed logging errors 2021-10-18 15:22:40 -07:00
c3f3c34c5b remove columns in csv header !9 2021-10-15 14:37:03 -07:00
a7de8b71a3 Merge branch 'main' of gitlab.com:lander-team/lander-cpp 2021-10-15 14:31:46 -07:00
64a50b97e0 change to new delim !9 2021-10-15 14:31:41 -07:00
Brendan McGeeney
d28fe808dd Merge branch '20-not-writing-csv-data-for-every-column' into 'main'
Resolve "Not writing CSV data for every column"

Closes #20

See merge request lander-team/lander-cpp!9
2021-10-15 20:07:43 +00:00
bpmcgeeney
2f4a9044ef Added thrust logging, deleted deriv column along with spaces in csv file 2021-10-15 13:04:46 -07:00
Brendan McGeeney
016ddc1261 Merge branch '11-servos-need-a-rate-limitation' into 'main'
Resolve "Servos need a rate limitation"

Closes #11

See merge request lander-team/lander-cpp!8
2021-10-15 19:49:45 +00:00
bpmcgeeney
b0a94c663d Servo rate limiting implemented with a new limit function 2021-10-15 12:44:37 -07:00
bpmcgeeney
59345992db Adding back PID gains since they didn't survive the merge for some reason 2021-10-14 18:25:33 -07:00
20 changed files with 1967 additions and 340 deletions

6
.gitignore vendored
View File

@ -2,3 +2,9 @@
*.csv
output
public
.pio
.vscode/.browse.c_cpp.db*
.vscode/c_cpp_properties.json
.vscode/launch.json
.vscode/ipch

View File

@ -13,14 +13,14 @@ build:
stage: build
script:
- mkdir public
- g++ ./src/main.cpp -I include -o ./public/sim.out
- g++ ./src/main.cpp -I include -o ./public/sim.out -D NATIVE -Wall
- ./public/sim.out
- mv simOut.csv public
artifacts:
paths:
- public
plots:
pythonplots:
# stage: build
image: python:3.9-buster
dependencies:
@ -32,11 +32,27 @@ plots:
paths:
- public
juliaplots:
image: julia:1.7
dependencies:
- build
script:
- apt-get update
- apt-get install -y unzip
- julia -e 'using Pkg; Pkg.activate("./juliaHelpers/"); Pkg.instantiate()'
- julia --project=./juliaHelpers ./juliaHelpers/simplot.jl
artifacts:
paths:
- public
only:
- main
pages:
stage: deploy
dependencies:
- build
- plots
- pythonplots
- juliaplots
script:
- ""
artifacts:

View File

@ -1,22 +0,0 @@
{
"configurations": [
{
"name": "Win32",
"includePath": [
"${workspaceFolder}/**",
"${workspaceFolder}/include"
],
"defines": [
"_DEBUG",
"UNICODE",
"_UNICODE"
],
"windowsSdkVersion": "10.0.18362.0",
"compilerPath": "C:\\Program Files (x86)\\Microsoft Visual Studio\\2019\\Community\\VC\\Tools\\MSVC\\14.25.28610\\bin\\Hostx64\\x64\\cl.exe",
"cStandard": "c17",
"cppStandard": "c++17",
"intelliSenseMode": "windows-msvc-x64"
}
],
"version": 4
}

View File

@ -1,7 +1,10 @@
{
// See http://go.microsoft.com/fwlink/?LinkId=827846
// for the documentation about the extensions.json format
"recommendations": [
"ms-vscode.cpptools",
"wayou.vscode-todo-highlight",
"usernamehw.errorlens"
"platformio.platformio-ide",
"usernamehw.errorlens",
"wayou.vscode-todo-highlight"
]
}

29
.vscode/launch.json vendored
View File

@ -1,29 +0,0 @@
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"name": "g++ - Build and debug simulation",
"type": "cppdbg",
"request": "launch",
"program": "${workspaceFolder}/main.exe",
"args": [],
"stopAtEntry": false,
"cwd": "${fileDirname}",
"environment": [],
"externalConsole": false,
"MIMode": "gdb",
"miDebuggerPath": "gdb.exe",
"setupCommands": [
{
"description": "Enable pretty-printing for gdb",
"text": "-enable-pretty-printing",
"ignoreFailures": true
}
],
"preLaunchTask": "buildSim"
}
]
}

View File

@ -42,7 +42,11 @@
"vector": "cpp",
"cctype": "cpp",
"sstream": "cpp",
"string": "cpp"
"string": "cpp",
"chrono": "cpp",
"ratio": "cpp",
"thread": "cpp",
"string_view": "cpp"
},
"C_Cpp.clang_format_fallbackStyle": "LLVM",
"editor.formatOnSave": true,

5
.vscode/tasks.json vendored
View File

@ -2,7 +2,7 @@
"version": "2.0.0",
"tasks": [
{
"type": "cppbuild",
"type": "process",
"label": "buildSim",
"command": "g++",
"args": [
@ -11,7 +11,8 @@
"-o",
"${workspaceFolder}/main.exe",
"-I",
"${workspaceFolder}/include"
"${workspaceFolder}/include",
"-Wall"
],
"options": {
"cwd": "${fileDirname}"

View File

@ -29,8 +29,12 @@ Download the raw CSV: https://lander-team.gitlab.io/lander-cpp/simOut.csv
Download Linux Binaries: https://lander-team.gitlab.io/lander-cpp/sim.out
![Accel-Vel-Alt vs Time](https://lander-team.gitlab.io/lander-cpp/AVA.png)
### Plots
![Euler Angles vs Time](https://lander-team.gitlab.io/lander-cpp/Angles.png)
Click on the images for interactive versions.
![Servo Position vs Time](https://lander-team.gitlab.io/lander-cpp/Servos.png)
<a href="https://lander-team.gitlab.io/lander-cpp/plot1.html" rel="Accel-Vel-ALt">![Accel-Vel-ALt](https://lander-team.gitlab.io/lander-cpp/plot1.svg)</a>
<a href="https://lander-team.gitlab.io/lander-cpp/plot2.html" rel="Euler Angles vs Time">![Euler Angles vs Time](https://lander-team.gitlab.io/lander-cpp/plot2.svg)</a>
<a href="https://lander-team.gitlab.io/lander-cpp/plot3.html" rel="Servo Position vs Time">![Servo Position vs Time](https://lander-team.gitlab.io/lander-cpp/plot3.svg)</a>

View File

@ -20,25 +20,76 @@ struct Vehicle {
double burntime;
double burnVelocity;
double thrust, burnElapsed, burnStart;
bool thrustFiring = false;
int thrustFiring = 0; // 0: Pre-burn, 1: Mid-burn, 2: Post-burn
double PIDx, PIDy, Fx, Fy, Fz;
double PIDx, PIDy, Fx, Fy, Fz, F;
double momentX, momentY, momentZ;
double I11, I22, I33;
double I11dot, I22dot, I33dot;
int maxServo;
double maxServo;
double maxServoRate;
double xServoDegs, yServoDegs;
double xServoDegsDot, yServoDegsDot;
double Kp, Ki, Kd;
double yError, yPrevError;
double pError, pPrevError;
double i_yError, i_pError = 0;
double i_yError, i_pError = 0.0;
double d_yError, d_pError;
double simTime;
int stepSize;
double stepSize;
double stepDuration;
double time = 0.0;
double lc0, lc1, lc2, lc3 = 0.0;
double lc0_processed, lc1_processed, lc2_processed, lc3_processed = 0.0;
};
void init_Vehicle(Vehicle &State) {
// PID Gains
State.Kp = -6.8699;
State.Ki = 0.0;
State.Kd = -0.775;
// Initial Velocity
State.vx = 0.0; // [m/s]
State.vy = 0.0; // [m/s]
State.vz = 0.0; // [m/s]
// Initial YPR
State.yaw = 45.0 * M_PI / 180.0; // [rad]
State.pitch = 45.0 * M_PI / 180.0; // [rad]
State.roll = 0.0 * M_PI / 180.0; // [rad]
// Initial YPRdot
State.yawdot = 1.0 * M_PI / 180.0; // [rad/s]
State.pitchdot = -1.0 * M_PI / 180.0; // [rad/s]
State.rolldot = 0.0 * M_PI / 180.0; // [rad/s]
// Servo Limitation
State.maxServo = 7.0; // [degs]
State.maxServoRate = 360.0; // [degs/sec]
// Vehicle Properties
State.massInitial = 1.2; // [kg]
State.vehicleHeight = 0.5318; // [m]
State.vehicleRadius = 0.05105; // [m]
State.momentArm = 0.145; // [m]
// Sim Step Size
State.stepSize = 5.0; // [ms]
// Other Properties
State.massPropellant = 0.06; // [kg]
State.massBurnout = State.massInitial - State.massPropellant; // [kg]
State.burntime = 3.45 - 0.148; // [s]
State.mdot = State.massPropellant / State.burntime; // [kg/s]
State.mass = State.massInitial; // [kg]
State.burnElapsed = 2000; // [s]
}
#endif

129
include/native.h Normal file
View File

@ -0,0 +1,129 @@
#include "Vehicle.h"
#include <iostream>
void thrustInfo(struct Vehicle &);
void processTVC(struct Vehicle &);
void write2CSV(struct outVector &, struct Vehicle &);
void printSimResults(struct Vehicle &);
void thrustInfo(Vehicle &State) {
if ((std::abs(State.burnVelocity + State.vz) < 1.03) &&
(State.thrustFiring == 0)) {
// Start burn
State.burnStart = State.time;
State.burnElapsed = 0.0;
State.thrustFiring = 1;
getThrust(State);
} else if (State.thrustFiring == 1) {
State.burnElapsed = (State.time - State.burnStart) / 1000.0;
State.mass = State.massInitial - (State.mdot * State.burnElapsed);
getThrust(State);
} else {
State.thrust = 0.0;
}
}
void processTVC(Vehicle &State) {
// Vector math to aqcuire thrust vector components
State.Fx = State.thrust * sin(State.xServoDegs * (M_PI / 180));
State.Fy = State.thrust * sin(State.yServoDegs * (M_PI / 180));
State.Fz = sqrt(pow(State.thrust, 2) - pow(State.Fx, 2) - pow(State.Fy, 2)) +
(State.mass * g);
// Calculate moment created by Fx and Fy
State.momentX = State.Fx * State.momentArm;
State.momentY = State.Fy * State.momentArm;
State.momentZ = 0;
}
void write2CSV(outVector &stateVector, Vehicle &State) {
// Deleting any previous output file
if (remove("simOut.csv") != 0)
perror("No file deletion necessary");
else
puts("Previous output file successfully deleted");
// Define and open output file "simOut.csv"
std::fstream outfile;
outfile.open("simOut.csv", std::ios::app);
// Output file header. These are the variables that we output - useful for
// debugging
outfile << "t,x,y,z,vx,vy,vz,ax,ay,az,yaw,pitch,roll,yawdot,pitchdot,rolldot,"
"Servo1,Servo2,thrustFiring,PIDx,PIDy,thrust"
<< std::endl;
// writing to output file
for (int i = 0; i < State.time; i += State.stepSize) {
outfile << i << ", ";
outfile << stateVector.x[i] << ",";
outfile << stateVector.y[i] << ",";
outfile << stateVector.z[i] << ",";
outfile << stateVector.vx[i] << ",";
outfile << stateVector.vy[i] << ",";
outfile << stateVector.vz[i] << ",";
outfile << stateVector.ax[i] << ",";
outfile << stateVector.ay[i] << ",";
outfile << stateVector.az[i] << ",";
outfile << stateVector.yaw[i] * 180 / M_PI << ",";
outfile << stateVector.pitch[i] * 180 / M_PI << ",";
outfile << stateVector.roll[i] * 180 / M_PI << ",";
outfile << stateVector.yawdot[i] * 180 / M_PI << ",";
outfile << stateVector.pitchdot[i] * 180 / M_PI << ",";
outfile << stateVector.rolldot[i] * 180 / M_PI << ",";
outfile << stateVector.servo1[i] << ",";
outfile << stateVector.servo2[i] << ",";
outfile << stateVector.thrustFiring[i] << ",";
outfile << stateVector.PIDx[i] << ",";
outfile << stateVector.PIDy[i] << ",";
outfile << stateVector.thrust[i] << std::endl;
}
outfile.close();
std::cout << "simOut.csv created successfully.\n" << std::endl;
}
void printSimResults(Vehicle &State) {
State.yaw = State.yaw * 180 / M_PI;
State.pitch = State.pitch * 180 / M_PI;
State.roll = State.roll * 180 / M_PI;
double landing_angle =
pow(State.yaw * State.yaw + State.pitch * State.pitch, .5);
double landing_velocity =
pow(State.vx * State.vx + State.vy * State.vy + State.vz * State.vz, .5);
if (landing_angle < 5.0) {
std::cout << "Landing Angle < 5.0 degrees | PASS | ";
} else {
std::cout << "Landing Angle < 5.0 degrees | FAIL | ";
}
std::cout << "Final Angles: [" << State.yaw << ", " << State.pitch << "]"
<< std::endl;
if (landing_velocity < 1.0) {
std::cout << "Landing Velocity < 1.0 m/s | PASS | ";
} else {
std::cout << "Landing Velocity < 1.0 m/s | FAIL | ";
}
std::cout << "Final Velocity: [" << State.vx << ", " << State.vy << ", "
<< State.vz << "]" << std::endl;
std::cout << std::endl << "Simulation Complete\n" << std::endl;
}

View File

@ -4,7 +4,7 @@
#define OUTVECTOR_H
struct outVector {
int length = 100000; // current sim runs ~5000 steps, x2 just in case
int length = 10000; // current sim runs ~5000 steps, x2 just in case
std::vector<double> x = std::vector<double>(length, 0.0);
std::vector<double> y = std::vector<double>(length, 0.0);
@ -33,6 +33,8 @@ struct outVector {
std::vector<double> PIDx = std::vector<double>(length, 0.0);
std::vector<double> PIDy = std::vector<double>(length, 0.0);
std::vector<double> thrust = std::vector<double>(length, 0.0);
};
#endif

View File

@ -4,74 +4,23 @@
#include <iostream>
void burnStartTimeCalc(struct Vehicle &);
void thrustSelection(struct Vehicle &, int t);
void pidController(struct Vehicle &, struct Vehicle &);
void TVC(struct Vehicle &);
void vehicleDynamics(struct Vehicle &, struct Vehicle &, int t);
void state2vec(struct Vehicle &, struct Vehicle &, struct outVector &, int t);
void write2CSV(struct outVector &, struct Vehicle &);
double derivative(double x2, double x1, double dt);
double integral(double x2, double x1, double dt);
void TVC(struct Vehicle &, struct Vehicle &);
void vehicleDynamics(struct Vehicle &, struct Vehicle &);
void state2vec(struct Vehicle &, struct Vehicle &, struct outVector &);
double derivative(double current, double previous, double step);
double integral(double currentChange, double prevValue, double dt);
double limit(double value, double upr, double lwr);
void getThrust(struct Vehicle &);
// Any parameters that are constants should be declared here instead of buried
// in code
// Any parameters that are constants should be declared here instead of
// buried in code
double const dt = 0.01;
double const g = -9.81;
bool sim(struct Vehicle &State, struct Vehicle &PrevState) {
outVector stateVector;
// Determine when to burn
burnStartTimeCalc(State);
int t = 0;
// Start Sim
do {
vehicleDynamics(State, PrevState, t);
thrustSelection(State, t);
pidController(State, PrevState);
TVC(State);
state2vec(State, PrevState, stateVector, t);
t += State.stepSize;
} while ((State.z > 0.0) || (State.thrust > 0.1));
write2CSV(stateVector, State);
bool pass = 1;
double landing_angle =
pow(State.yaw * State.yaw + State.pitch * State.pitch, .5);
double landing_velocity =
pow(State.vx * State.vx + State.vy * State.vy + State.vz * State.vz, .5);
if (landing_angle < 5.0) {
std::cout << " Landing Angle < 5° | PASS | ";
} else {
std::cout << " Landing Angle < 5° | FAIL | ";
pass = pass * 0;
}
std::cout << "Final Angles: [" << State.yaw << ", " << State.pitch << "]"
<< std::endl;
if (landing_velocity < 5.0) {
std::cout << "Landing Velocity < 5 m/s | PASS | ";
} else {
std::cout << "Landing Velocity < 5 m/s | FAIL | ";
pass = pass * 0;
}
std::cout << "Final Velocity: [" << State.vx << ", " << State.vy << ", "
<< State.vz << "]" << std::endl;
return pass;
}
void burnStartTimeCalc(Vehicle &State) {
double velocity = State.vz;
double h = 0;
double h = 0.0;
double mass, thrust;
@ -88,37 +37,40 @@ void burnStartTimeCalc(Vehicle &State) {
else if ((i > 3.382) && (i < 3.46))
thrust = -195.78 * i + 675.11;
else
thrust = 0.0;
velocity = (((thrust / mass) + g) * dt) + velocity;
h = velocity * dt + h;
h = (((thrust / mass) + g) * dt) + h;
}
State.z = h + (pow(velocity, 2) / (2 * -g)); // starting height
State.z = h + (pow(velocity, 2) / (2.0 * -g)); // starting height
State.z = 19.05;
State.burnVelocity = velocity; // terminal velocity
double burnStartTime = State.burnVelocity / -g;
State.simTime = (State.burntime + burnStartTime) * 1000;
State.simTime = (State.burntime + burnStartTime) * 1000.0;
}
void vehicleDynamics(Vehicle &State, Vehicle &PrevState, int t) {
void vehicleDynamics(Vehicle &State, Vehicle &PrevState) {
// Moment of Inertia
State.I11 = State.mass * ((1 / 12) * pow(State.vehicleHeight, 2) +
pow(State.vehicleRadius, 2) / 4);
State.I22 = State.mass * ((1 / 12) * pow(State.vehicleHeight, 2) +
pow(State.vehicleRadius, 2) / 4);
State.I11 = State.mass * ((1 / 12.0) * pow(State.vehicleHeight, 2) +
pow(State.vehicleRadius, 2) / 4.0);
State.I22 = State.mass * ((1 / 12.0) * pow(State.vehicleHeight, 2) +
pow(State.vehicleRadius, 2) / 4.0);
State.I33 = State.mass * 0.5 * pow(State.vehicleRadius, 2);
// Idot
if (t < 0.1) {
State.I11dot = 0;
State.I22dot = 0;
State.I33dot = 0;
if (State.time < 0.1) {
State.I11dot = 0.0;
State.I22dot = 0.0;
State.I33dot = 0.0;
State.x = 0;
State.y = 0;
State.x = 0.0;
State.y = 0.0;
State.ax = 0;
State.ay = 0;
State.ax = 0.0;
State.ay = 0.0;
State.az = State.Fz / State.massInitial;
} else {
@ -178,45 +130,6 @@ void vehicleDynamics(Vehicle &State, Vehicle &PrevState, int t) {
}
}
void thrustSelection(Vehicle &State, int t) {
if (State.burnElapsed != 2000) {
// determine where in the thrust curve we're at based on elapsed burn time
// as well as current mass
State.burnElapsed = (t - State.burnStart) / 1000;
State.mass = State.massInitial - (State.mdot * State.burnElapsed);
}
else if (abs(State.burnVelocity + State.vz) < 0.001) {
// Start burn
State.burnStart = t;
State.burnElapsed = 0;
}
else
State.burnElapsed = 2000; // arbitrary number to ensure we don't burn
if ((State.burnElapsed > 0.147) && (State.burnElapsed < 0.420)) {
State.thrustFiring = true;
State.thrust = 65.165 * State.burnElapsed - 2.3921;
} else if ((State.burnElapsed > 0.419) && (State.burnElapsed < 3.383))
State.thrust = 0.8932 * pow(State.burnElapsed, 6) -
11.609 * pow(State.burnElapsed, 5) +
60.739 * pow(State.burnElapsed, 4) -
162.99 * pow(State.burnElapsed, 3) +
235.6 * pow(State.burnElapsed, 2) -
174.43 * State.burnElapsed + 67.17;
else if ((State.burnElapsed > 3.382) && (State.burnElapsed < 3.46))
State.thrust = -195.78 * State.burnElapsed - 675.11;
if (State.burnElapsed > 3.45) {
State.thrustFiring = false;
State.thrust = 0;
}
}
void pidController(Vehicle &State, struct Vehicle &PrevState) {
// Make sure we start reacting when we start burning
if (State.thrust > 0.01) {
@ -233,7 +146,6 @@ void pidController(Vehicle &State, struct Vehicle &PrevState) {
State.d_pError = derivative(State.pError, PrevState.pError, State.stepSize);
// TVC block properly
State.PIDx = (State.Kp * State.yError + State.Ki * State.i_yError +
State.Kd * State.d_yError) /
State.momentArm;
@ -242,69 +154,58 @@ void pidController(Vehicle &State, struct Vehicle &PrevState) {
State.momentArm;
} else {
State.PIDx = 0;
State.PIDy = 0;
State.PIDx = 0.0;
State.PIDy = 0.0;
}
// PID Force limiter X
if (State.PIDx > State.thrust)
State.PIDx = State.thrust;
else if (State.PIDx < -1 * State.thrust)
State.PIDx = -1 * State.thrust;
// PID Force limiter Y
if (State.PIDy > State.thrust)
State.PIDy = State.thrust;
else if (State.PIDy < -1 * State.thrust)
State.PIDy = -1 * State.thrust;
// PID Force Limiter
State.PIDx = limit(State.PIDx, State.thrust, -State.thrust);
State.PIDy = limit(State.PIDy, State.thrust, -State.thrust);
}
void TVC(Vehicle &State) {
void TVC(Vehicle &State, Vehicle &PrevState) {
if (State.thrust < 0.1) {
// Define forces and moments for t = 0
State.Fx = 0;
State.Fy = 0;
State.Fx = 0.0;
State.Fy = 0.0;
State.Fz = g * State.massInitial;
State.momentX = 0;
State.momentY = 0;
State.momentZ = 0;
State.momentX = 0.0;
State.momentY = 0.0;
State.momentZ = 0.0;
} else {
// Convert servo position to degrees for comparison to max allowable
State.xServoDegs = (180 / M_PI) * asin(State.PIDx / State.thrust);
State.xServoDegs = (180.0 / M_PI) * asin(State.PIDx / State.thrust);
State.yServoDegs = (180.0 / M_PI) * asin(State.PIDy / State.thrust);
// Servo position limiter
if (State.xServoDegs > State.maxServo)
State.xServoDegs = State.maxServo;
else if (State.xServoDegs < -1 * State.maxServo)
State.xServoDegs = -1 * State.maxServo;
// Limit Servo Position
State.xServoDegs = limit(State.xServoDegs, State.maxServo, -State.maxServo);
State.yServoDegs = limit(State.yServoDegs, State.maxServo, -State.maxServo);
// Convert servo position to degrees for comparison to max allowable
State.yServoDegs = (180 / M_PI) * asin(State.PIDy / State.thrust);
// Servo Rate
State.xServoDegsDot =
derivative(State.xServoDegs, PrevState.xServoDegs, State.stepSize);
State.yServoDegsDot =
derivative(State.yServoDegs, PrevState.yServoDegs, State.stepSize);
// Servo position limiter
if (State.yServoDegs > State.maxServo)
State.yServoDegs = State.maxServo;
else if (State.yServoDegs < -1 * State.maxServo)
State.yServoDegs = -1 * State.maxServo;
// Limit Servo Rate
State.xServoDegsDot =
limit(State.xServoDegsDot, State.maxServoRate, -State.maxServoRate);
State.yServoDegsDot =
limit(State.yServoDegsDot, State.maxServoRate, -State.maxServoRate);
// Vector math to aqcuire thrust vector components
State.Fx = State.thrust * sin(State.xServoDegs * (M_PI / 180));
State.Fy = State.thrust * sin(State.yServoDegs * (M_PI / 180));
State.Fz =
sqrt(pow(State.thrust, 2) - pow(State.Fx, 2) - pow(State.Fy, 2)) +
(State.mass * g);
// Calculate moment created by Fx and Fy
State.momentX = State.Fx * State.momentArm;
State.momentY = State.Fy * State.momentArm;
State.momentZ = 0;
// Back to Degrees
State.xServoDegs =
integral(State.xServoDegsDot, PrevState.xServoDegs, State.stepSize);
State.yServoDegs =
integral(State.yServoDegsDot, PrevState.yServoDegs, State.stepSize);
}
}
void state2vec(Vehicle &State, Vehicle &PrevState, outVector &stateVector,
int t) {
void state2vec(Vehicle &State, Vehicle &PrevState, outVector &stateVector) {
int t = State.time;
stateVector.x[t] = State.x;
stateVector.y[t] = State.y;
stateVector.z[t] = State.z;
@ -333,71 +234,47 @@ void state2vec(Vehicle &State, Vehicle &PrevState, outVector &stateVector,
stateVector.PIDx[t] = State.PIDx;
stateVector.PIDy[t] = State.PIDy;
// Set "prev" values for next timestep
PrevState = State;
}
void write2CSV(outVector &stateVector, Vehicle &State) {
// Deleting any previous output file
if (remove("simOut.csv") != 0)
perror("No file deletion necessary");
else
puts("Previous output file successfully deleted");
// Define and open output file "simOut.csv"
std::fstream outfile;
outfile.open("simOut.csv", std::ios::app);
// Output file header. These are the variables that we output - useful for
// debugging
outfile << "t, x, y, z, vx, vy, vz, ax, ay, az, yaw, pitch, roll, yawdot, "
"pitchdot, rolldot, Servo1, Servo2, thrustFiring, PIDx, PIDy, "
"thrust, deriv"
<< std::endl;
// writing to output file
for (int t = 0; t < State.simTime; t += State.stepSize) {
outfile << t << ", ";
outfile << stateVector.x[t] << ", ";
outfile << stateVector.y[t] << ", ";
outfile << stateVector.z[t] << ", ";
outfile << stateVector.vx[t] << ", ";
outfile << stateVector.vy[t] << ", ";
outfile << stateVector.vz[t] << ", ";
outfile << stateVector.ax[t] << ", ";
outfile << stateVector.ay[t] << ", ";
outfile << stateVector.az[t] << ", ";
outfile << stateVector.yaw[t] * 180 / M_PI << ", ";
outfile << stateVector.pitch[t] * 180 / M_PI << ", ";
outfile << stateVector.roll[t] * 180 / M_PI << ", ";
outfile << stateVector.yawdot[t] * 180 / M_PI << ", ";
outfile << stateVector.pitchdot[t] * 180 / M_PI << ", ";
outfile << stateVector.rolldot[t] * 180 / M_PI << ", ";
outfile << stateVector.servo1[t] << ", ";
outfile << stateVector.servo2[t] << ", ";
outfile << stateVector.thrustFiring[t] << ", ";
outfile << stateVector.PIDx[t] << ", ";
outfile << stateVector.PIDy[t] << std::endl;
}
outfile.close();
std::cout << "simOut.csv created successfully.\n" << std::endl;
stateVector.thrust[t] = State.thrust;
}
double derivative(double current, double previous, double step) {
double dxdt = (current - previous) / (step / 1000);
double dxdt = (current - previous) / (step / 1000.0);
return dxdt;
}
double integral(double currentChange, double prevValue, double dt) {
return (currentChange * dt / 1000) + prevValue;
return (currentChange * dt / 1000.0) + prevValue;
}
double limit(double value, double upr, double lwr) {
if (value > upr)
value = upr;
else if (value < lwr)
value = lwr;
else
value = value;
return value;
}
void getThrust(Vehicle &State) {
if ((State.burnElapsed > 0.147) && (State.burnElapsed < 0.420)) {
State.thrust = 65.165 * State.burnElapsed - 2.3921;
} else if ((State.burnElapsed > 0.419) && (State.burnElapsed < 3.383))
State.thrust = 0.8932 * pow(State.burnElapsed, 6.0) -
11.609 * pow(State.burnElapsed, 5.0) +
60.739 * pow(State.burnElapsed, 4.0) -
162.99 * pow(State.burnElapsed, 3.0) +
235.6 * pow(State.burnElapsed, 2.0) -
174.43 * State.burnElapsed + 67.17;
else if ((State.burnElapsed > 3.382) && (State.burnElapsed < 3.46)) {
State.thrust = -195.78 * State.burnElapsed + 675.11;
}
if (State.burnElapsed > 3.45) {
State.thrustFiring = 2;
State.thrust = 0.0;
}
}

398
include/teensy.h Normal file
View File

@ -0,0 +1,398 @@
#include "Vehicle.h"
#include <Arduino.h>
#include <HX711.h>
#include <PWMServo.h>
#include <SD.h>
#include <SPI.h>
void testGimbal(class PWMServo &, class PWMServo &);
void initLoadCells(struct Vehicle &);
void initFile();
void thrustInfo(struct Vehicle &);
void processTVC(struct Vehicle &, class PWMServo &, class PWMServo &);
void write2CSV(struct Vehicle &);
void printSimResults(struct Vehicle &);
void teensyAbort();
double loadCellFilter(double current, double previous);
// Load cell stuff
HX711 lc0;
HX711 lc1;
HX711 lc2;
HX711 lc3;
void read_lc0();
void read_lc1();
void read_lc2();
void read_lc3();
const int lc_clock = 23;
const int pin_lc0 = 14;
const int pin_lc1 = 15;
const int pin_lc2 = 19;
const int pin_lc3 = 20;
const int pin_igniter = 7;
double lcGain0 = -98.32;
double lcGain1 = -97.59;
double lcGain2 = -100.51;
double lcGain3 = -118.65;
// SD card stuff
const int chipSelect = BUILTIN_SDCARD;
File dataFile;
void testGimbal(PWMServo &servo1, PWMServo &servo2) {
int servoTest = 90;
servo1.write(servoTest);
servo2.write(servoTest);
// Servo 1 Test
for (servoTest = 0; servoTest < 7; servoTest += 1) {
servo1.write(90 + servoTest);
delay(30);
}
for (servoTest = 7; servoTest >= 1; servoTest -= 1) {
servo1.write(90 + servoTest);
delay(30);
}
delay(1000);
// Servo 2 Test
for (servoTest = 0; servoTest < 7; servoTest += 1) {
servo2.write(90 + servoTest);
delay(30);
}
for (servoTest = 7; servoTest >= 1; servoTest -= 1) {
servo2.write(90 + servoTest);
delay(30);
}
delay(1000);
// Servo 1 & 2 Test
for (servoTest = 0; servoTest < 7; servoTest += 1) {
servo1.write(90 + servoTest);
servo2.write(90 + servoTest);
delay(30);
}
for (servoTest = 7; servoTest >= 1; servoTest -= 1) {
servo1.write(90 + servoTest);
servo2.write(90 + servoTest);
delay(30);
}
delay(30);
// BRING IN YAW AND PITCH CONVERSION FROM TVC TEST
servo1.write(90);
servo2.write(90);
}
void initLoadCells(Vehicle &State) {
// Configure clock pin with high impedance to protect
// pin (if this doesn't work, change to OUTPUT)
pinMode(lc_clock, INPUT);
// Configure load cell data pins as inputs
pinMode(pin_lc0, INPUT);
pinMode(pin_lc1, INPUT);
pinMode(pin_lc2, INPUT);
pinMode(pin_lc3, INPUT);
lc0.begin(pin_lc0, lc_clock);
lc1.begin(pin_lc1, lc_clock);
lc2.begin(pin_lc2, lc_clock);
lc3.begin(pin_lc3, lc_clock);
Serial.print("Calibrating");
lc0.set_scale();
lc1.set_scale();
lc2.set_scale();
lc3.set_scale();
lc0.tare(50);
Serial.print(".");
lc1.tare(50);
Serial.print(".");
lc2.tare(50);
Serial.println(".");
lc3.tare(50);
// Attach ISRs to load cell data pins to read data when available
attachInterrupt(digitalPinToInterrupt(pin_lc0), read_lc0, LOW);
attachInterrupt(digitalPinToInterrupt(pin_lc1), read_lc1, LOW);
attachInterrupt(digitalPinToInterrupt(pin_lc2), read_lc2, LOW);
attachInterrupt(digitalPinToInterrupt(pin_lc3), read_lc3, LOW);
Serial.println("Load Cells Initialized");
// Initializes State variables
State.lc0 = 9.81 * 0.001 * lc0.get_value() / lcGain0;
State.lc1 = 9.81 * 0.001 * lc1.get_value() / lcGain1;
State.lc2 = 9.81 * 0.001 * lc2.get_value() / lcGain2;
State.lc3 = 9.81 * 0.001 * lc3.get_value() / lcGain3;
}
void initFile() {
Serial.print("Initializing SD card...");
// see if the card is present and can be initialized:
if (!SD.begin(chipSelect)) {
Serial.println("Card failed, or not present. \n\nABORTING SIMULATION");
teensyAbort();
}
Serial.println("Card initialized.");
int i = 1;
const char *fileName;
if (SD.exists("simOut.csv")) {
while (i > 0.0) {
fileName = ("simOut_" + String(i) + ".csv").c_str();
if (!SD.exists(fileName)) {
// Open simOut_i.csv
dataFile = SD.open(fileName, FILE_WRITE);
if (dataFile) {
Serial.println("File successfully opened!");
} else {
// if the file didn't open, print an error:
Serial.println("Error opening output file. \n\nABORTING SIMULATION");
teensyAbort();
}
i = 0.0;
} else {
i++;
}
}
} else {
// Open simOut.csv
dataFile = SD.open("simOut.csv", FILE_WRITE);
if (dataFile) {
Serial.println("File successfully opened!");
} else {
// if the file didn't open, print an error:
Serial.println("Error opening output file. \n\nABORTING SIMULATION");
teensyAbort();
}
}
// File Header
dataFile.println(
"t,x,y,z,vx,vy,vz,ax,ay,az,yaw,pitch,roll,yawdot,pitchdot,rolldot,"
"Servo1,Servo2,thrustFiring,thrust,simResponse,lc0,lc1,lc2,lc3,lc0_"
"processed,lc1_processed,"
"lc2_processed,lc3_processed");
}
void thrustInfo(Vehicle &State) {
if ((abs(State.burnVelocity + State.vz) < 1.03) &&
(State.thrustFiring == 0)) {
// Start burn
State.burnStart = State.time;
State.burnElapsed = 0.0;
analogWrite(pin_igniter, 256);
State.thrustFiring = 1;
getThrust(State);
} else if (State.thrustFiring == 1) {
State.burnElapsed = (State.time - State.burnStart) / 1000.0;
State.mass = State.massInitial - (State.mdot * State.burnElapsed);
getThrust(State);
double r = 3.0;
double R = 5.0;
// Vector math to aqcuire thrust vector components
// PLACEHOLDER PLACEHOLDERPLACEHOLDER PLACEHOLDERPLACEHOLDER
// PLACEHOLDERPLACEHOLDER PLACEHOLDERPLACEHOLDER PLACEHOLDER
State.thrust = State.lc0_processed + State.lc1_processed +
State.lc2_processed + State.lc3_processed;
State.Fx = (State.lc1_processed - State.lc2_processed) * r / R;
State.Fy = (State.lc0_processed - State.lc3_processed) * r / R;
State.Fz =
sqrt(pow(State.thrust, 2) - pow(State.Fx, 2) - pow(State.Fy, 2)) +
(state.mass * g);
} else {
State.thrust = 0.0;
}
}
void processTVC(Vehicle &State, PWMServo &servo1, PWMServo &servo2) {
State.Fx = State.thrust * sin(State.xServoDegs * (M_PI / 180.0));
State.Fy = State.thrust * sin(State.yServoDegs * (M_PI / 180.0));
State.Fz = sqrt(pow(State.thrust, 2) - pow(State.Fx, 2) - pow(State.Fy, 2)) +
(State.mass * g);
// Calculate moment created by Fx and Fy
State.momentX = State.Fx * State.momentArm;
State.momentY = State.Fy * State.momentArm;
State.momentZ = 0.0;
State.F = sqrt(pow(State.Fx, 2) + pow(State.Fy, 2) + pow(State.Fz, 2));
servo1.write(90 + State.xServoDegs);
servo2.write(90 + State.yServoDegs);
}
void write2CSV(Vehicle &State) {
dataFile.print(String(State.time, 5));
dataFile.print(",");
dataFile.print(String(State.x, 5));
dataFile.print(",");
dataFile.print(String(State.y, 5));
dataFile.print(",");
dataFile.print(String(State.z, 5));
dataFile.print(",");
dataFile.print(String(State.vx, 5));
dataFile.print(",");
dataFile.print(String(State.vy, 5));
dataFile.print(",");
dataFile.print(String(State.vz, 5));
dataFile.print(",");
dataFile.print(String(State.ax, 5));
dataFile.print(",");
dataFile.print(String(State.ay, 5));
dataFile.print(",");
dataFile.print(String(State.az, 5));
dataFile.print(",");
dataFile.print(String(State.yaw * 180.0 / M_PI, 5));
dataFile.print(",");
dataFile.print(String(State.pitch * 180.0 / M_PI, 5));
dataFile.print(",");
dataFile.print(String(State.roll * 180.0 / M_PI, 5));
dataFile.print(",");
dataFile.print(String(State.yawdot * 180.0 / M_PI, 5));
dataFile.print(",");
dataFile.print(String(State.pitchdot * 180.0 / M_PI, 5));
dataFile.print(",");
dataFile.print(String(State.rolldot * 180.0 / M_PI, 5));
dataFile.print(",");
dataFile.print(String(State.xServoDegs, 5));
dataFile.print(",");
dataFile.print(String(State.yServoDegs, 5));
dataFile.print(",");
dataFile.print(String(State.thrustFiring, 5));
dataFile.print(",");
dataFile.print(String(State.thrust, 5));
dataFile.print(",");
dataFile.print(String(State.stepDuration, 5));
dataFile.print(",");
dataFile.print(String(State.lc0, 5));
dataFile.print(",");
dataFile.print(String(State.lc1, 5));
dataFile.print(",");
dataFile.print(String(State.lc2, 5));
dataFile.print(",");
dataFile.print(String(State.lc3, 5));
dataFile.print(",");
dataFile.print(String(State.lc0_processed, 5));
dataFile.print(",");
dataFile.print(String(State.lc1_processed, 5));
dataFile.print(",");
dataFile.print(String(State.lc2_processed, 5));
dataFile.print(",");
dataFile.print(String(State.lc3_processed, 5));
dataFile.print("\n");
}
void printSimResults(Vehicle &State) {
State.yaw = State.yaw * 180.0 / M_PI;
State.pitch = State.pitch * 180.0 / M_PI;
State.roll = State.roll * 180.0 / M_PI;
double landing_angle =
pow(State.yaw * State.yaw + State.pitch * State.pitch, .5);
double landing_velocity =
pow(State.vx * State.vx + State.vy * State.vy + State.vz * State.vz, .5);
if (landing_angle < 5.0) {
Serial.print("Landing Angle < 5.0 degrees | PASS | ");
} else {
Serial.print("Landing Angle < 5.0 degrees | FAIL | ");
}
Serial.print("Final Angles: [" + String(State.yaw) + ", " +
String(State.pitch) + "]\n");
if (landing_velocity < 1.0) {
Serial.print("Landing Velocity < 1.0 m/s | PASS | ");
} else {
Serial.print("Landing Velocity < 1.0 m/s | FAIL | ");
}
Serial.print("Final Velocity: [" + String(State.vx) + ", " +
String(State.vy) + ", " + String(State.vz) + "]\n");
Serial.print("\nSimulation Complete\n");
}
void closeFile() {
// close the file:
dataFile.close();
Serial.println("File closed\n");
}
void teensyAbort() {
while (1) {
digitalWrite(BUILTIN_LED, HIGH);
delay(1000);
digitalWrite(BUILTIN_LED, LOW);
delay(1000);
}
}
// ISRs to print data to serial monitor
void read_lc0() {
State.lc0 = lc0.get_value();
State.lc0_processed = 0.00981 * State.lc0 / lcGain0;
State.lc0_processed =
loadCellFilter(State.lc0_processed, PrevState.lc0_processed);
PrevState.lc0_processed = State.lc0_processed;
}
void read_lc1() {
State.lc1 = lc1.get_value();
State.lc1_processed = 0.00981 * State.lc1 / lcGain1;
State.lc1_processed =
loadCellFilter(State.lc1_processed, PrevState.lc1_processed);
PrevState.lc1_processed = State.lc1_processed;
}
void read_lc2() {
State.lc2 = lc2.get_value();
State.lc2_processed = 0.00981 * State.lc2 / lcGain2;
State.lc2_processed =
loadCellFilter(State.lc2_processed, PrevState.lc2_processed);
PrevState.lc2_processed = State.lc2_processed;
}
void read_lc3() {
State.lc3 = lc3.get_value();
State.lc3_processed = 0.00981 * State.lc3 / lcGain3;
State.lc3_processed =
loadCellFilter(State.lc3_processed, PrevState.lc3_processed);
PrevState.lc3_processed = State.lc3_processed;
}
double loadCellFilter(double current, double previous) {
if (abs(current - previous > 60.0)) {
return previous;
} else {
return current;
}
}

1033
juliaHelpers/Manifest.toml Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,5 @@
[deps]
CSV = "336ed68f-0bac-5ca0-87d4-7b16caf5d00b"
DataFrames = "a93c6f00-e57d-5684-b7b6-d8193f3e46c0"
PlotlyJS = "f0f68f2c-4968-5e81-91da-67840de0976a"
Plots = "91a5bcdd-55d7-5caf-9e0b-520d859cae80"

45
juliaHelpers/simplot.jl Normal file
View File

@ -0,0 +1,45 @@
using Plots
using CSV
using DataFrames
theme(:juno)
plotlyjs()
df = CSV.File("./public/simOut.csv") |> DataFrame
# df = CSV.File("./simOut.csv") |> DataFrame
println(describe(df))
p1 = let
a = plot(df.t, [df.ax df.ay df.az], labels = ["" "" ""], title = "Acceleration", ylabel = "m/s^2")
v = plot(df.t, df.vx .* df.vx .+ df.vy .* df.vy .+ df.vz .* df.vz .|> sqrt, labels = "Total Velocity", title = "Total Velocity", ylabel = "m/s", linecolor = "orchid")
x = plot(df.t, df.z, labels = "Altitude", title = "Altitude", ylabel = "m", xlabel = "time (ms)", linecolor = "chartreuse")
plot(a, v, x, layout = (3, 1), legend = :outertopright)
end
p2 = let
ypr = plot(df.t, [df.yaw df.pitch df.roll], label = ["Yaw" "Pitch" "Roll"], ylabel = "Euler Angles (degree)", title = "Vehicle Deflection")
ω = plot(df.t, [df.yawdot df.pitchdot df.rolldot], label = ["" "" ""], ylabel = "Angular Velocity (deg/s)", title = "Vehicle Deflection", xlabel = "time (ms)")
plot(ypr, ω, layout = (2, 1))
end
p3 = plot(df.t, [df.Servo1 df.Servo2], label = ["Yaw" "Pitch"], ylabel = "Servo Position (degree)", xlabel = "time (ms)", title = "Servo Positions")
global i = 1
theme(:ggplot2)
for p in [p1 p2 p3]
savefig(p, "./public/plot$i.svg")
savefig(p, "./public/plot$i.html")
savefig(p, "./public/plot$i.png")
global i = i + 1
end

View File

@ -30,6 +30,7 @@ Servo2 = T(:, 18);
PIDx = T(:, 20);
PIDy = T(:, 21);
thrust = T(:, 22);
% Acceleration
subplot(3, 1, 1)
plot(t, az)
@ -51,7 +52,6 @@ title('Altitude vs Time')
xlabel('Time (s)')
ylabel('Altitude (m)')
ylim([0 z(1)+5])
saveas(gcf,'outputs/Accel-Vel-Alt vs Time.png')
figure(2)
@ -75,7 +75,6 @@ plot(t, rolldot)
title('Angular Velocity vs Time')
xlabel('Time (ms)')
ylabel('Angular Velocity (deg/s)')
saveas(gcf,'outputs/Euler Angles vs Time.png')
legend("yawdot", "pitchdot", "rolldot")
figure(3)
@ -93,4 +92,12 @@ plot(t, Servo2)
title('Servo 2 Position vs Time')
xlabel('Time (ms)')
ylabel('Servo 2 Position (rad)')
saveas(gcf,'outputs/Servo Position vs Time.png')
figure(4)
% Servo 1 Position
plot(t, thrust)
title('Thrust vs Time')
xlabel('Time (ms)')
ylabel('Thrust (N)')

20
platformio.ini Normal file
View File

@ -0,0 +1,20 @@
; PlatformIO Project Configuration File
;
; Build options: build flags, source filter
; Upload options: custom upload port, speed and extra flags
; Library options: dependencies, extra library storages
; Advanced options: extra scripting
;
; Please visit documentation for the other options and examples
; https://docs.platformio.org/page/projectconf.html
[env:NATIVE]
platform = native
build_flags = -std=c++11 -Wall -O1 -D NATIVE
[env:teensy41]
platform = teensy
board = teensy41
framework = arduino
build_flags = -std=c++11 -Wall -O1 -D TEENSY
lib_deps = bogde/HX711@^0.7.4

View File

@ -4,7 +4,7 @@ import pandas as pd
plt.style.use("ggplot")
df = pd.read_csv("./public/simOut.csv", delimiter=", ")
df = pd.read_csv("./public/simOut.csv")
# Acceleration

View File

@ -1,5 +1,4 @@
#define M_PI 3.14159265359
#if defined(_WIN32) || defined(NATIVE)
#include <cmath>
#include <fstream>
#include <iostream>
@ -7,56 +6,134 @@
#include <stdio.h>
#include <string>
#include <vector>
#elif defined(TEENSY)
#include <Arduino.h>
#endif
#define M_PI 3.14159265359
#include "Vehicle.h"
#include "sim.h"
bool sim(struct Vehicle &);
int main() {
Vehicle State;
Vehicle PrevState;
// Initial Velocity
State.vx = 0; // [m/s]
State.vy = 0; // [m/s]
State.vz = 0; // [m/s]
#if defined(TEENSY)
// Initial YPR
State.yaw = 10 * M_PI / 180; // [rad]
State.pitch = 5 * M_PI / 180; // [rad]
State.roll = 0 * M_PI / 180; // [rad]
int BUILTIN_LED = 13;
unsigned long last, initTime;
// Initial YPRdot
State.yawdot = 1 * M_PI / 180; // [rad/s]
State.pitchdot = -1 * M_PI / 180; // [rad/s]
State.rolldot = 0 * M_PI / 180; // [rad/s]
#include "teensy.h"
#include <HX711.h>
#include <PWMServo.h>
// Servo Limitation
State.maxServo = 15; // [degs]
PWMServo servo1;
PWMServo servo2;
// Vehicle Properties
State.massInitial = 1.2; // [kg]
State.vehicleHeight = 0.5318; // [m]
State.vehicleRadius = 0.05105; // [m]
State.momentArm = 0.145; // [m]
const int pin_servo1 = 33;
const int pin_servo2 = 29;
const int pin_igniter = 7;
// Sim Step Size
State.stepSize = 1; // [ms]
int servoPos = 90; // variable to store the servo position;
// Other Properties
State.massPropellant = 0.06; // [kg]
State.massBurnout = State.massInitial - State.massPropellant; // [kg]
State.burntime = 3.45 - 0.148; // [s]
State.mdot = State.massPropellant / State.burntime; // [kg/s]
State.mass = State.massInitial; // [kg]
State.burnElapsed = 2000; // [s]
PrevState.thrust = 0; // [N]
void setup() {
Serial.begin(9600);
bool outcome = sim(State, PrevState);
delay(5000);
Serial.println("Simulation Countdown:");
for (int i = 0; i < 10; i++) {
Serial.println(10 - i);
delay(1000);
}
initLoadCells(State);
init_Vehicle(State);
servo1.attach(pin_servo1);
servo2.attach(pin_servo2);
testGimbal(servo1, servo2);
Serial.println("Servos Tested");
delay(3000);
Serial.println("Simulated Vehicle Initalized");
// Determine when to burn
analogWrite(pin_igniter, 0);
burnStartTimeCalc(State);
Serial.println("Starting Height Calculated");
initFile();
// PLACE BUTTON HERE---------------------------------------------
initTime = micros();
}
void loop() {
last = micros();
vehicleDynamics(State, PrevState);
thrustInfo(State);
pidController(State, PrevState);
TVC(State, PrevState);
processTVC(State, servo1, servo2);
write2CSV(State);
// Set previous values for next timestep
PrevState = State;
State.time += State.stepSize;
if ((State.z < 0.0) && (State.thrustFiring == 2)) {
analogWrite(pin_igniter, 0);
Serial.println("Run duration:" + String((micros() - initTime) / 1000000.0) +
" seconds");
printSimResults(State);
closeFile();
delay(3000);
Serial.println("SUCCESS");
Serial.println("Exiting Sim");
teensyAbort();
}
State.stepDuration = micros() - last;
delayMicroseconds((1000.0 * State.stepSize) - State.stepDuration);
}
#endif
#if defined(_WIN32) || defined(NATIVE)
#include "native.h"
outVector stateVector;
int main() {
init_Vehicle(State);
// Determine when to burn
burnStartTimeCalc(State);
do {
vehicleDynamics(State, PrevState);
thrustInfo(State);
pidController(State, PrevState);
TVC(State, PrevState);
processTVC(State);
state2vec(State, PrevState, stateVector);
// Set "prev" values for next timestep
PrevState = State;
State.time += State.stepSize;
if ((State.z < 0.0) && (State.thrustFiring == 2)) {
write2CSV(stateVector, State);
printSimResults(State);
init_Vehicle(State);
}
} while ((State.z > 0.0) || (State.thrustFiring != 2));
std::cout << std::endl << "Simulation Complete 🚀" << std::endl;
// ^^^
// 50% chance this makes Mattys linux crash
return 0;
}
#endif