Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement Apogee Prediction #47

Merged
merged 142 commits into from
Nov 1, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
142 commits
Select commit Hold shift + click to select a range
6d38ae5
added quaternion and gyro rotation
wlsanderson Oct 9, 2024
058f1d2
Very rough speed calculations
wlsanderson Oct 9, 2024
2ef8edf
made the linter happy hopefully
wlsanderson Oct 9, 2024
721d707
made tests for rotations
wlsanderson Oct 13, 2024
fbd3de2
Merge remote-tracking branch 'origin/main' into apogee-pred
wlsanderson Oct 16, 2024
e7c9909
made first draft of apogee prediction
wlsanderson Oct 16, 2024
bd5208b
made unit tests
wlsanderson Oct 17, 2024
9693fea
Merge remote-tracking branch 'origin/main' into apogee-pred
wlsanderson Oct 17, 2024
6f93812
integration test
wlsanderson Oct 17, 2024
b2c0aaf
works except for the math
wlsanderson Oct 18, 2024
1982bbd
csv fix, working thru quaternion rotation fixes
wlsanderson Oct 19, 2024
9e593c0
small changes, calculating rotated speed is broken
wlsanderson Oct 19, 2024
fb8d87c
Merge main and fix conflicts
harshil21 Oct 21, 2024
4bbc474
Ruff fixes
harshil21 Oct 21, 2024
269d5ac
Add apogee property, dep in pyproject, some renaming
harshil21 Oct 21, 2024
6b89e4a
Merge branch 'main' into apogee-pred
harshil21 Oct 21, 2024
9ccff77
Update mock sim display and disable warning
harshil21 Oct 21, 2024
8c59d4f
Add new velocity calculation to display
harshil21 Oct 21, 2024
0622211
Ruff fixes
harshil21 Oct 21, 2024
6345b3e
fixed velocity, disabled motor burnout state change failsafe
wlsanderson Oct 22, 2024
d41692d
apogee-calc fixes
wlsanderson Oct 22, 2024
3e3dacc
WIP: time_diff calc caching
harshil21 Oct 22, 2024
2f5a0ed
WIP: time_diff calc caching
harshil21 Oct 22, 2024
7363cb7
Cleaned up time differences
JacksonElia Oct 22, 2024
e8ef992
WIP: Refactoring data processor and multiprocessing
harshil21 Oct 22, 2024
18dcc80
Got rid of old speed
JacksonElia Oct 22, 2024
c554443
Got rid of old speed
JacksonElia Oct 22, 2024
8e5b1e8
Got rid of old speed
JacksonElia Oct 22, 2024
0ac977c
WIP: Rotate calc array for processed_data_packets
harshil21 Oct 22, 2024
8af9bbf
merge and fix conflicts
wlsanderson Oct 22, 2024
2783ca2
gravity-vector
wlsanderson Oct 22, 2024
ee79cad
WIP: Get processed data packets ready for ApogeePredictor class multi…
harshil21 Oct 23, 2024
dd95ee1
Worked on multi processing a bit
JacksonElia Oct 23, 2024
0a434ce
Made method static
JacksonElia Oct 23, 2024
c4b666f
Changes before I have to go to class
JacksonElia Oct 23, 2024
9d43193
added launch data with gyro and comp accel
wlsanderson Oct 24, 2024
fa3a9f0
Made some more progress on converting to multi processing
JacksonElia Oct 24, 2024
b2e230d
Merge remote-tracking branch 'origin/apogee-pred' into apogee-pred
JacksonElia Oct 24, 2024
e71e3f6
fixed csv
wlsanderson Oct 24, 2024
4e8832d
actually fixed csv
wlsanderson Oct 24, 2024
3ec8de9
Changed to vertical accelerations
JacksonElia Oct 24, 2024
c3fd91f
Changes before harshil
JacksonElia Oct 24, 2024
7c33cd8
november launch data
wlsanderson Oct 24, 2024
a10787d
WIP: Work on apogee multiprocessing
harshil21 Oct 24, 2024
3c3adcc
cum_trapz
wlsanderson Oct 25, 2024
8e53d67
fixing apogee integrals
wlsanderson Oct 25, 2024
4b2e61f
changes in apogee pred and state.py
harshil21 Oct 25, 2024
e74f3ca
gravity vector changes
wlsanderson Oct 25, 2024
6ddc084
WIP: mock sim works again! without apogee pred
harshil21 Oct 25, 2024
e4b1b05
gravity vector part 2
wlsanderson Oct 25, 2024
9576a05
gravity vector part 3
wlsanderson Oct 25, 2024
83468fc
comments and changed trap sum to cum sum
wlsanderson Oct 25, 2024
48955e6
WIP: Mock sim actually works but apogee takes a while to converge and…
harshil21 Oct 25, 2024
2aa3d14
Comment out a print statement
harshil21 Oct 25, 2024
2b0d956
Change gravity constant for testing purposes
harshil21 Oct 25, 2024
f9b9473
Change curve_fit_initial back to original for testing purposes
harshil21 Oct 25, 2024
5e68f38
Cleaned up data processor without breaking anything
JacksonElia Oct 25, 2024
e7c2661
Finished cleaning up data processor
JacksonElia Oct 25, 2024
b919da1
Moved apogee predictor to main
JacksonElia Oct 25, 2024
3ac0feb
Finally fix wrong predicted apogee
harshil21 Oct 25, 2024
1097f51
Ruff fixes
harshil21 Oct 25, 2024
98bdf2b
Add apogee process to display
harshil21 Oct 25, 2024
6d4f8a6
Bring back self argument for ApogeePred class
harshil21 Oct 25, 2024
bc97846
Speed -> Velocity renaming
harshil21 Oct 25, 2024
de5c144
Add predicted apogee and vertical accel to logger
harshil21 Oct 25, 2024
95d3d5b
gravity orientation fixes, and changed mock to purple nurple
wlsanderson Oct 25, 2024
4b715f4
reversed default direction of acceleration
wlsanderson Oct 25, 2024
57b87f7
fixed comments
wlsanderson Oct 25, 2024
32a8084
gravity and quaternions in datasets
wlsanderson Oct 26, 2024
9fb18cb
Merge pull request #56 from NCSU-High-Powered-Rocketry-Club/gravity-fix
JacksonElia Oct 26, 2024
44d1518
Did some more clean up for data_processor
JacksonElia Oct 27, 2024
8968d8a
Added some tests
JacksonElia Oct 27, 2024
93908c7
Added np testing
JacksonElia Oct 27, 2024
6e40e46
Fixed a bug
JacksonElia Oct 27, 2024
bf084b5
Fixed incorrect checking for None
JacksonElia Oct 27, 2024
93d6123
Merge main and fix conflicts
harshil21 Oct 27, 2024
0b97267
Fix conflict in csv file
harshil21 Oct 27, 2024
1d12830
ruff fixes
harshil21 Oct 27, 2024
2096474
Got tests passing for data_processor
JacksonElia Oct 27, 2024
be69a33
Ruff
JacksonElia Oct 27, 2024
329a57e
Update airbrakes/data_handling/data_processor.py
JacksonElia Oct 27, 2024
73b94bb
Improved init test
JacksonElia Oct 27, 2024
c60efe1
Added quat tests
JacksonElia Oct 27, 2024
7881a95
Ruff
JacksonElia Oct 27, 2024
5fe88c2
Merge main and fix conflicts
harshil21 Oct 27, 2024
db7d496
Fix mock sim path
harshil21 Oct 27, 2024
ccc9ac0
mock is good to go
JacksonElia Oct 27, 2024
ed2e713
additional refactoring
JacksonElia Oct 27, 2024
a2e2fb4
Update tests/test_data_processor.py
harshil21 Oct 27, 2024
72a9bf2
Merge pull request #62 from NCSU-High-Powered-Rocketry-Club/more-tests
JacksonElia Oct 27, 2024
56a591f
new imu testing data
wlsanderson Oct 28, 2024
c1697cb
I deleted everything and it works
wlsanderson Oct 29, 2024
24b1e8b
ruff + comments
wlsanderson Oct 29, 2024
10baab8
multiplying acceleration by -1
wlsanderson Oct 29, 2024
63ab741
ruff
wlsanderson Oct 29, 2024
166fcc2
changed rotation list format, fixed tests
wlsanderson Oct 29, 2024
d87c159
Merge pull request #64 from NCSU-High-Powered-Rocketry-Club/rotation-…
JacksonElia Oct 29, 2024
fb3c2d2
Fixed a couple tests
JacksonElia Oct 29, 2024
d970c80
Fixed even more tests!
JacksonElia Oct 29, 2024
386447d
apogee pred test
wlsanderson Oct 29, 2024
2010af8
I'm tired of tests
JacksonElia Oct 29, 2024
d4c4b7c
ap-tests
wlsanderson Oct 29, 2024
7e30a88
More apogee prediction tests
harshil21 Oct 29, 2024
078ec79
Merge main and fix conflicts
harshil21 Oct 30, 2024
eb8c118
Merge branch 'apogee-pred' into apogee-pred-tests
harshil21 Oct 30, 2024
77e382d
Fix airbrakes.update tests
harshil21 Oct 30, 2024
afa3f5b
More asserts
harshil21 Oct 30, 2024
b97d705
Work on tests a bit
harshil21 Oct 30, 2024
5a3efbc
apogee integration test
wlsanderson Oct 30, 2024
bbea55f
Ruff fixes
harshil21 Oct 30, 2024
32e4a8f
Get all tests working except Integration
harshil21 Oct 30, 2024
10ff95e
Some test_data_processor clean up
harshil21 Oct 30, 2024
568f298
test fix for windows
wlsanderson Oct 30, 2024
1644918
event fix
wlsanderson Oct 30, 2024
bf04dea
Integration test passes
harshil21 Oct 30, 2024
6b34fec
Review: Change apogee pred frequency
harshil21 Oct 30, 2024
2c17f1d
Update tests/test_apogee_predictor.py
harshil21 Oct 30, 2024
ee6dace
Merge pull request #67 from NCSU-High-Powered-Rocketry-Club/apogee-pr…
JacksonElia Oct 30, 2024
5d101a3
Merge branch 'main' into apogee-pred
harshil21 Oct 30, 2024
389b67f
Fix Standby spelling
JacksonElia Oct 30, 2024
0e0f56e
Clean up
JacksonElia Oct 30, 2024
3071417
Use scipy for calculating rotated accelerations
harshil21 Oct 30, 2024
7132ee7
Update airbrakes/data_handling/data_processor.py
JacksonElia Oct 31, 2024
664da75
Tiny performance improvement, about 19%
harshil21 Oct 31, 2024
3d75260
Did pr changes and fixed failing actions
JacksonElia Oct 31, 2024
a818bce
Added the motor burn fallback condition back in
JacksonElia Oct 31, 2024
2317b38
Fix unit tests
JacksonElia Oct 31, 2024
5a15912
Fixed ruff and some tests
JacksonElia Oct 31, 2024
961af1a
Fixed ruff and some tests
JacksonElia Oct 31, 2024
91f743f
fixed comment
wlsanderson Oct 31, 2024
e5ee93b
added imu_data readme
wlsanderson Oct 31, 2024
403cbd4
test_airbrakes fixed tests
wlsanderson Oct 31, 2024
638302e
ruff
wlsanderson Oct 31, 2024
715ca8f
fixed state tests?
wlsanderson Oct 31, 2024
5383b77
Merge pull request #69 from NCSU-High-Powered-Rocketry-Club/apogee-pr…
JacksonElia Oct 31, 2024
59fbb95
Fix all tests again
harshil21 Oct 31, 2024
438f927
Review: Test for sending duplicated data to apogee pred
harshil21 Nov 1, 2024
aad38c6
Ruff
harshil21 Nov 1, 2024
ce78429
state test
wlsanderson Nov 1, 2024
ee98ead
Changes to state motor burn and tests
harshil21 Nov 1, 2024
fc25b4a
ruff fixes
harshil21 Nov 1, 2024
0aefa09
Update architecture diagram
harshil21 Nov 1, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 8 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ _A video of our air brakes extending and retracting_
As per the finite state machine design pattern, we have a context class which links everything together. Every loop, the context:

1. **Gets data from the IMU**
2. **Processes the data** in the Data Processor (calculates speed, averages, maximums, etc.)
2. **Processes the data** in the Data Processor (calculates velocity, averages, maximums, etc.)
3. **Updates the current state** with the processed data
4. **Controls the servo extension** based on the current state's instructions (e.g., extends air brakes to slow down the rocket)
5. **Logs all data** from the IMU, Data Processor, Servo, and States
Expand All @@ -37,6 +37,7 @@ flowchart TD
Airbrakes --> Update[update]:::bubble
%% IMU Data Packet Flow
IMUDataPacket --> Update
Apogee_Predictor --> Update

%% States as individual nodes
State((State)):::circular
Expand All @@ -59,18 +60,20 @@ flowchart TD
%% Connections with Labels
Airbrakes ---|Child Process| Logger((Logger)):::circular
Airbrakes ---|Child Process| IMU((IMU)):::circular
Airbrakes ---|Child Process| Apogee_Predictor((Apogee Predictor)):::circular
IMU((IMU)):::circular ---|Fetch Packets| IMUDataPacket[(IMU Data Packet)]:::outputSquare

%% IMU Data Processing
IMUDataPacket --> IMUDataProcessor[IMU Data Processor]:::circular
%%IMUDataProcessor --> ProcessedData[(Processed Data Packet)]:::outputSquare
IMUDataProcessor --> Speed[(Speed)]:::outputSquare
IMUDataProcessor --> Velocity[(Velocity)]:::outputSquare
IMUDataProcessor --> Altitude[(Altitude)]:::outputSquare
IMUDataProcessor --> Rotated_Accel[(Rotated Acceleration)]:::outputSquare

Speed --> ProcessedData[(Processed Data Packet)]:::outputSquare
Velocity --> ProcessedData[(Processed Data Packet)]:::outputSquare
Altitude --> ProcessedData[(Processed Data Packet)]:::outputSquare
Rotated_Accel --> ProcessedData[(Processed Data Packet)]:::outputSquare

ProcessedData[(Processed Data Packet)]:::outputSquare --> Update
ProcessedData[(Processed Data Packet)]:::outputSquare --> Update

%% Logging Mechanism
Logger --> LogFunction[log]:::bubble
Expand Down
70 changes: 55 additions & 15 deletions airbrakes/airbrakes.py
Original file line number Diff line number Diff line change
@@ -1,19 +1,20 @@
"""Module which provides a high level interface to the air brakes system on the rocket."""

from collections import deque
from typing import TYPE_CHECKING

from airbrakes.data_handling.apogee_predictor import ApogeePredictor
from airbrakes.data_handling.data_processor import IMUDataProcessor
from airbrakes.data_handling.imu_data_packet import EstimatedDataPacket
from airbrakes.data_handling.logger import Logger
from airbrakes.hardware.imu import IMU, IMUDataPacket
from airbrakes.hardware.imu import IMU
from airbrakes.hardware.servo import Servo
from airbrakes.state import StandByState, State
from airbrakes.state import StandbyState, State
from constants import ServoExtension

if TYPE_CHECKING:
from collections import deque

from airbrakes.data_handling.processed_data_packet import ProcessedDataPacket
from airbrakes.hardware.imu import IMUDataPacket


class AirbrakesContext:
Expand All @@ -25,42 +26,59 @@ class AirbrakesContext:
"""

__slots__ = (
"apogee_predictor",
"current_extension",
"data_processor",
"est_data_packets",
"imu",
"imu_data_packets",
"logger",
"processed_data_packets",
"servo",
"shutdown_requested",
"state",
)

def __init__(self, servo: Servo, imu: IMU, logger: Logger, data_processor: IMUDataProcessor) -> None:
def __init__(
self,
servo: Servo,
imu: IMU,
logger: Logger,
data_processor: IMUDataProcessor,
apogee_predictor: ApogeePredictor,
) -> None:
"""
Initializes the airbrakes context with the specified hardware objects, logger, and data processor. The state
machine starts in the StandByState, which is the initial state of the airbrakes system.
machine starts in the StandbyState, which is the initial state of the airbrakes system.
:param servo: The servo object that controls the extension of the airbrakes. This can be a real servo or a mock
servo.
:param imu: The IMU object that reads data from the rocket's IMU. This can be a real IMU or a mock IMU.
:param logger: The logger object that logs data to a CSV file.
:param data_processor: The data processor object that processes IMU data on a higher level.
:param apogee_predictor: The apogee predictor object that predicts the apogee of the rocket.
"""
self.servo = servo
self.imu = imu
self.logger = logger
self.data_processor = data_processor
self.apogee_predictor = apogee_predictor

# Placeholder for the current airbrake extension until they are set
self.current_extension: ServoExtension = ServoExtension.MIN_EXTENSION

self.state: State = StandByState(self)
# The rocket starts in the StandbyState
self.state: State = StandbyState(self)
self.shutdown_requested = False
self.imu_data_packets: deque[IMUDataPacket] = deque()
self.processed_data_packets: deque[ProcessedDataPacket] = deque()
self.est_data_packets: list[EstimatedDataPacket] = []

def start(self) -> None:
"""
Starts the IMU and logger processes. This is called before the main while loop starts.
"""
self.imu.start()
self.logger.start()
self.apogee_predictor.start()

def stop(self) -> None:
"""
Expand All @@ -72,6 +90,7 @@ def stop(self) -> None:
self.retract_airbrakes()
self.imu.stop()
self.logger.stop()
self.apogee_predictor.stop()
self.shutdown_requested = True

def update(self) -> None:
Expand All @@ -84,32 +103,42 @@ def update(self) -> None:
# *may* not be the most recent data. But we want continuous data for state, apogee,
# and logging purposes, so we don't need to worry about that, as long as we're not too
# behind on processing
imu_data_packets: deque[IMUDataPacket] = self.imu.get_imu_data_packets()
self.imu_data_packets = self.imu.get_imu_data_packets()

# This should never happen, but if it does, we want to not error out and wait for packets
if not imu_data_packets:
if not self.imu_data_packets:
return

# Split the data packets into estimated and raw data packets for use in processing and logging
est_data_packets = [
self.est_data_packets = [
data_packet
for data_packet in imu_data_packets.copy()
for data_packet in self.imu_data_packets.copy()
if isinstance(data_packet, EstimatedDataPacket)
# The copy() above is critical to ensure the data here is not modified by the data processor
]

# Update the processed data with the new data packets. We only care about EstimatedDataPackets
self.data_processor.update(est_data_packets)
self.data_processor.update(self.est_data_packets)

# Get the processed data packets from the data processor, this will have the same length as the number of
# EstimatedDataPackets in data_packets
processed_data_packets: deque[ProcessedDataPacket] = self.data_processor.get_processed_data_packets()
self.processed_data_packets = self.data_processor.get_processed_data_packets()

# Update the state machine based on the latest processed data
self.state.update()

# Logs the current state, extension, IMU data, and processed data
self.logger.log(self.state.name[0], self.current_extension.value, imu_data_packets, processed_data_packets)
self.logger.log(
self.state.name,
self.current_extension.value,
self.imu_data_packets,
self.processed_data_packets,
self.apogee_predictor.apogee,
)
# CAUTION: You would need to copy() self.processed_data_packets in the log line above
# if you want to reference it anywhere else after update(), because it would be modified
# by the logger. e.g. in tests. For tests, the workaround would be to monkeypatch
# the log() method to not modify the processed_data_packets.

def extend_airbrakes(self) -> None:
"""
Expand All @@ -124,3 +153,14 @@ def retract_airbrakes(self) -> None:
"""
self.servo.set_retracted()
self.current_extension = ServoExtension.MIN_EXTENSION

def predict_apogee(self) -> None:
"""
Predicts the apogee of the rocket based on the current processed data. This
should only be called in the coast state, before we start controlling the airbrakes.
"""
# We have to only only run this for estimated data packets, otherwise we send duplicate
# data to the predictor (because for a raw data packet, we still have the 'old' processed_data_packets)
# This would result in a very slow convergence and inaccurate predictions.
if self.est_data_packets:
self.apogee_predictor.update(self.processed_data_packets)
Loading