RocketPy icon indicating copy to clipboard operation
RocketPy copied to clipboard

ENH: Sensors

Open MateusStano opened this issue 1 year ago • 6 comments

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.md has been updated (if relevant)

Description

This PR tackles issue #273 and builds on top of #580

Added:

  • Sensors abstract class
  • Accelerometer class
  • Gyroscope class
  • Sensors are included in the Flight simulation loop. Having any amount of sensors in the simulated rocket will add only one additional call to u_dot per simulation step. Sensors only work time_overshoot=False
  • add_sensor method in rocket class that receives the sensor and its position and saves them in a Component object
  • __and__ operator for elementwise multiplication between Vector objects
  • euler_to_quaternions function in tools.py for conversion from euler angles to quaternions
  • transformation_euler_angles static method in the Matrix class 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 Components class for speed purposes
  • Parachute triggerfunc can now receive a list of sensors as its last argument
  • Controller controller_function can now receive a list of sensors as its last argument

Sensors Architecture

  • Sensors have their orientation and noise information saved in itself. When added to the rocket, a position must be given
  • Each type of sensor has its own measure method that characterizes the sensor. The measure function receives (t, state, state_derivative, *args). *args refers to the specific input required by the sensor. Different types of sensors will receive different *args.
  • At each call of the measure method, the sensor's reading is saved in the measured_data attribute. This means that the state of the sensor changes throughout the simulation.

Notes

  • I created a notebook called sensors_testing.ipynb for 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 z axis of the Calisto flight. Seems to be related to errors in the derivation of the motor's mass_dot. This does not happen when the old udot is used. We should fix this soon
  • Useful links:

Breaking change

  • [ ] Yes
  • [x] No

MateusStano avatar Apr 02 '24 16:04 MateusStano

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.

Files Patch % Lines
rocketpy/plots/rocket_plots.py 30.43% 16 Missing :warning:
rocketpy/sensors/sensors.py 87.35% 11 Missing :warning:
rocketpy/simulation/flight.py 91.79% 11 Missing :warning:
rocketpy/control/controller.py 75.00% 3 Missing :warning:
rocketpy/mathutils/vector_matrix.py 90.90% 2 Missing :warning:
rocketpy/prints/sensors_prints.py 98.14% 1 Missing :warning:
rocketpy/rocket/components.py 85.71% 1 Missing :warning:
rocketpy/rocket/rocket.py 90.00% 1 Missing :warning:
rocketpy/sensors/accelerometer.py 98.48% 1 Missing :warning:
rocketpy/sensors/gyroscope.py 98.55% 1 Missing :warning:
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.

codecov[bot] avatar Apr 02 '24 17:04 codecov[bot]

I forgot to comment in the review:

  • There must be a warning in the Flight class if a Rocket has AirBrakes and overshootable is True. The same apply for Controllers.

phmbressan avatar Apr 04 '24 23:04 phmbressan

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:

  1. If the same sensor instance was added twice to a rocket the measured_data would have intercalated data
  2. 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_rockets property, which maps how many times that Sensors instance has been added to a rocket. This lets us deal with repeatedly added sensors
  • Reset Sensors.measured_data every 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_data are cached into a property in the Flight class called sensor_data. sensor_data sensor 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_data is a list in the form [(t1, ax1, ay1, az1), (t2, ax2, ay2, az3), ...]
  • Flight.sensors_data is 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_data is a list in the form [[(t1, ax1, ay1, az1), (t2, ax2, ay2, az3), ...], [(t1, ax1, ay1, az1), (t2, ax2, ay2, az3), ...]]
  • Flight.sensors_data is 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

MateusStano avatar May 01 '24 18:05 MateusStano

This is awesome!

image

Gui-FernandesBR avatar May 05 '24 07:05 Gui-FernandesBR

@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.

Gui-FernandesBR avatar May 15 '24 03:05 Gui-FernandesBR

Seems like we have an inverted direction somewhere: image

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

MateusStano avatar May 16 '24 15:05 MateusStano

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

MateusStano avatar May 21 '24 20:05 MateusStano