ENH: Sensors
Pull request type
- [x] Code changes (bugfix, features)
Checklist
- [x] Tests for the changes have been added (if needed)
- [x] Docs have been reviewed and added / updated
- [x] Lint (
black rocketpy/ tests/) has passed locally - [x] All tests (
pytest tests -m slow --runslow) have passed locally - [x]
CHANGELOG.mdhas been updated (if relevant)
Description
This PR tackles issue #273 and builds on top of #580
Added:
Sensorsabstract classAccelerometerclassGyroscopeclassSensorsare included in theFlightsimulation loop. Having any amount of sensors in the simulated rocket will add only one additional call tou_dotper simulation step. Sensors only worktime_overshoot=Falseadd_sensormethod in rocket class that receives the sensor and its position and saves them in aComponentobject__and__operator for elementwise multiplication betweenVectorobjectseuler_to_quaternionsfunction intools.pyfor conversion from euler angles to quaternionstransformation_euler_anglesstatic method in theMatrixclass for construction of a rotation matrix from euler angles- Sensors representation in the rocket drawing by their position and normal vector, given a choice of plane for the drawing
- Small refactor of
Componentsclass for speed purposes - Parachute
triggerfunccan now receive a list of sensors as its last argument - Controller
controller_functioncan now receive a list of sensors as its last argument
Sensors Architecture
Sensorshave theirorientationand noise information saved in itself. When added to the rocket, a position must be given- Each type of sensor has its own
measuremethod that characterizes the sensor. Themeasurefunction receives(t, state, state_derivative, *args).*argsrefers to the specific input required by the sensor. Different types of sensors will receive different*args. - At each call of the
measuremethod, the sensor's reading is saved in themeasured_dataattribute. This means that the state of the sensor changes throughout the simulation.
Notes
- I created a notebook called
sensors_testing.ipynbfor testing the current sensor implementation. It does not need to be reviewed - The modulus of all axes of an accelerometer/gyroscope without noise placed in the rocket's center of dry mass should be the same as the flight's acceleration/rotation modulus. This is tested in
test_ideal_sensors. The tolerance in this test is limited by numerical errors in the calculation of the rotation matrix from the quaternions. This is probably causing inaccuracies in the simulation. We should fix this soon - At time 3.9s there is a dissonant acceleration value in the
zaxis of theCalistoflight. Seems to be related to errors in the derivation of the motor'smass_dot. This does not happen when the old udot is used. We should fix this soon - Useful links:
- accelerometer point of measure translation
- noise models 1 and 2
- rotations 1 and 2
Breaking change
- [ ] Yes
- [x] No
Codecov Report
Attention: Patch coverage is 90.80460% with 48 lines in your changes are missing coverage. Please review.
Please upload report for BASE (
enh/sensors-impl@fbeff2c). Learn more about missing BASE report.
Additional details and impacted files
@@ Coverage Diff @@
## enh/sensors-impl #583 +/- ##
===================================================
Coverage ? 73.78%
===================================================
Files ? 64
Lines ? 10049
Branches ? 0
===================================================
Hits ? 7415
Misses ? 2634
Partials ? 0
:umbrella: View full report in Codecov by Sentry.
:loudspeaker: Have feedback on the report? Share it here.
I forgot to comment in the review:
- There must be a warning in the
Flightclass if aRockethasAirBrakesandovershootableisTrue. The same apply forControllers.
Hey! So I have changed the way the sensors readings. The initial implementation had the measurements saved in the sensor object being used, this caused the following problems:
- If the same sensor instance was added twice to a rocket the
measured_datawould have intercalated data - Running several Flight simulations with a rocket with the same sensors instances would just keep appending data to
measured_data
However, the measured_data attribute was an useful way to get previous sensor readings inside the controller function. My solution was to save the data both in the Flight class and in the Sensors. In the Flight the sensors reading are saved as a dict, while in the Sensors its saved as a list. This grants versatility to the code.
To do this I had to:
- Create the
Sensors._attatched_rocketsproperty, which maps how many times thatSensorsinstance has been added to a rocket. This lets us deal with repeatedly added sensors - Reset
Sensors.measured_dataevery simulation. This means that a sensor object will only have data of one simulation max. This could be changed to have several simulations but I see no use for that. - At the end of a simulation, the sensors
measured_dataare cached into a property in theFlightclass calledsensor_data.sensor_datasensor data is a dict that maps each sensor to its reading list
So the final structure is of the saved attributes is as follows:
Given an Accelerometer that is added once to the rocket. We have that its:
.measured_datais a list in the form[(t1, ax1, ay1, az1), (t2, ax2, ay2, az3), ...]Flight.sensors_datais a dict in the form{Accelerometer : [(t1, ax1, ay1, az1), (t2, ax2, ay2, az3), ...]}
If there is an Accelerometer that is added twice to the rocket. We have that its:
.measured_datais a list in the form[[(t1, ax1, ay1, az1), (t2, ax2, ay2, az3), ...], [(t1, ax1, ay1, az1), (t2, ax2, ay2, az3), ...]]Flight.sensors_datais a dict in the form{Accelerometer : {1 : [(t1, ax1, ay1, az1), (t2, ax2, ay2, az3), ...]}, 2: [(t1, ax1, ay1, az1), (t2, ax2, ay2, az3), ...]} }
However, we could also have the Flight.sensors_data be {Accelerometer : [[(t1, ax1, ay1, az1), (t2, ax2, ay2, az3), ...], [(t1, ax1, ay1, az1), (t2, ax2, ay2, az3), ...]] } in this last case. Any opinions on this?
@Gui-FernandesBR @phmbressan This is ready for a new review
This is awesome!
@MateusStano , tomorrow I will invest some time to test the jupyter notebook and search for any bug. In the mean time, there are still a few conversations opened, would you mind addressing them?
This is a already too large PR (70 commits), feel free to write down some TODOs in the code if you think something is not crucial, just let us know please.
Btw the head branch seems to be outdated with respect to the develop branch.
Seems like we have an inverted direction somewhere:
This result is supposed to be right because the noisy gyroscope is upside down. Please check the orientation and see if it makes any sense
Also I did not care so much about the new jupyter notebook, I think it is there as a fast testing option only, right?
Yes, its just for testing right now
I'll go ahead and merge this then
