James Kuszmaul | d3f9eb2 | 2020-01-12 15:02:07 -0800 | [diff] [blame] | 1 | #ifndef FRC971_ZEROING_IMU_ZEROER_H_ |
| 2 | #define FRC971_ZEROING_IMU_ZEROER_H_ |
| 3 | |
James Kuszmaul | 6d6e130 | 2022-03-12 15:22:48 -0800 | [diff] [blame] | 4 | #include <optional> |
| 5 | |
James Kuszmaul | b1e2937 | 2020-02-11 16:55:36 -0800 | [diff] [blame] | 6 | #include "frc971/control_loops/drivetrain/drivetrain_status_generated.h" |
James Kuszmaul | d3f9eb2 | 2020-01-12 15:02:07 -0800 | [diff] [blame] | 7 | #include "frc971/wpilib/imu_generated.h" |
| 8 | #include "frc971/zeroing/averager.h" |
| 9 | |
| 10 | namespace frc971::zeroing { |
| 11 | |
| 12 | // This class handles processing IMU measurements and zeroing them once it is |
| 13 | // able to do so. |
| 14 | class ImuZeroer { |
| 15 | public: |
James Kuszmaul | 30aca50 | 2020-01-19 15:05:33 -0800 | [diff] [blame] | 16 | // Average 0.5 seconds of data (assuming 2kHz sampling rate). |
James Kuszmaul | 3e1bb27 | 2020-01-17 18:38:19 -0800 | [diff] [blame] | 17 | // TODO(james): Make the gyro zero in a constant amount of time, rather than a |
| 18 | // constant number of samples... |
James Kuszmaul | 30aca50 | 2020-01-19 15:05:33 -0800 | [diff] [blame] | 19 | // TODO(james): Run average and GetRange calculations over every sample on |
| 20 | // every timestep, to provide consistent timing. |
James Kuszmaul | 0a98140 | 2021-10-09 21:00:34 -0700 | [diff] [blame] | 21 | static constexpr size_t kSamplesToAverage = 200; |
James Kuszmaul | b1e2937 | 2020-02-11 16:55:36 -0800 | [diff] [blame] | 22 | static constexpr size_t kRequiredZeroPoints = 10; |
James Kuszmaul | d3f9eb2 | 2020-01-12 15:02:07 -0800 | [diff] [blame] | 23 | |
James Kuszmaul | 6d6e130 | 2022-03-12 15:22:48 -0800 | [diff] [blame] | 24 | enum class FaultBehavior { |
| 25 | // When we encounter a fault, latch and stay in an errored state |
| 26 | // indefinitely. |
| 27 | kLatch, |
| 28 | // When we encounter a fault, don't process the reading and return nullopt |
| 29 | // for all measurements. |
| 30 | kTemporary |
| 31 | }; |
| 32 | |
| 33 | explicit ImuZeroer(FaultBehavior fault_behavior = FaultBehavior::kLatch); |
James Kuszmaul | d3f9eb2 | 2020-01-12 15:02:07 -0800 | [diff] [blame] | 34 | bool Zeroed() const; |
| 35 | bool Faulted() const; |
James Kuszmaul | 6d6e130 | 2022-03-12 15:22:48 -0800 | [diff] [blame] | 36 | bool InsertMeasurement(const IMUValues &values); |
James Kuszmaul | b7f45bb | 2020-02-26 20:27:48 -0800 | [diff] [blame] | 37 | // PErforms the heavier-duty processing for managing zeroing. |
| 38 | void ProcessMeasurements(); |
| 39 | void InsertAndProcessMeasurement(const IMUValues &values); |
James Kuszmaul | d3f9eb2 | 2020-01-12 15:02:07 -0800 | [diff] [blame] | 40 | Eigen::Vector3d GyroOffset() const; |
James Kuszmaul | 6d6e130 | 2022-03-12 15:22:48 -0800 | [diff] [blame] | 41 | std::optional<Eigen::Vector3d> ZeroedGyro() const; |
| 42 | std::optional<Eigen::Vector3d> ZeroedAccel() const; |
James Kuszmaul | b1e2937 | 2020-02-11 16:55:36 -0800 | [diff] [blame] | 43 | |
| 44 | flatbuffers::Offset<control_loops::drivetrain::ImuZeroerState> PopulateStatus( |
| 45 | flatbuffers::FlatBufferBuilder *fbb) const; |
| 46 | |
James Kuszmaul | d3f9eb2 | 2020-01-12 15:02:07 -0800 | [diff] [blame] | 47 | private: |
| 48 | // Max variation (difference between the maximum and minimum value) in a |
| 49 | // kSamplesToAverage range before we allow using the samples for zeroing. |
| 50 | // These values are currently based on looking at results from the ADIS16448. |
Philipp Schrader | 790cb54 | 2023-07-05 21:06:52 -0700 | [diff] [blame^] | 51 | static constexpr double kGyroMaxVariation = 0.02; // rad / sec |
James Kuszmaul | b1e2937 | 2020-02-11 16:55:36 -0800 | [diff] [blame] | 52 | // Maximum magnitude we allow the gyro zero to have--this is used to prevent |
| 53 | // us from zeroing the gyro if we just happen to be spinning at a very |
| 54 | // consistent non-zero rate. Currently this is only plausible in simulation. |
| 55 | static constexpr double kGyroMaxZeroingMagnitude = 0.1; // rad / sec |
James Kuszmaul | d3f9eb2 | 2020-01-12 15:02:07 -0800 | [diff] [blame] | 56 | // Max variation in the range before we consider the accelerometer readings to |
| 57 | // be steady. |
Philipp Schrader | 790cb54 | 2023-07-05 21:06:52 -0700 | [diff] [blame^] | 58 | static constexpr double kAccelMaxVariation = 0.05; // g's |
James Kuszmaul | d3f9eb2 | 2020-01-12 15:02:07 -0800 | [diff] [blame] | 59 | // If we ever are able to rezero and get a zero that is more than |
| 60 | // kGyroFaultVariation away from the original zeroing, fault. |
James Kuszmaul | ad2f8db | 2021-10-24 17:02:57 -0700 | [diff] [blame] | 61 | static constexpr double kGyroFaultVariation = 0.05; // rad / sec |
James Kuszmaul | d3f9eb2 | 2020-01-12 15:02:07 -0800 | [diff] [blame] | 62 | |
| 63 | bool GyroZeroReady() const; |
| 64 | bool AccelZeroReady() const; |
| 65 | |
| 66 | Averager<double, kSamplesToAverage, 3> gyro_averager_; |
| 67 | // Averager for the accelerometer readings--we don't currently actually |
| 68 | // average the readings, but we do check that the accelerometer readings have |
| 69 | // stayed roughly constant during the calibration period. |
| 70 | Averager<double, kSamplesToAverage, 3> accel_averager_; |
| 71 | // The average zero position of the gyro. |
| 72 | Eigen::Vector3d gyro_average_; |
| 73 | Eigen::Vector3d last_gyro_sample_; |
| 74 | Eigen::Vector3d last_accel_sample_; |
James Kuszmaul | 6d6e130 | 2022-03-12 15:22:48 -0800 | [diff] [blame] | 75 | |
| 76 | const FaultBehavior fault_behavior_; |
| 77 | bool reading_faulted_ = false; |
| 78 | bool zeroing_faulted_ = false; |
| 79 | |
James Kuszmaul | b1e2937 | 2020-02-11 16:55:36 -0800 | [diff] [blame] | 80 | size_t good_iters_ = 0; |
| 81 | size_t num_zeroes_ = 0; |
James Kuszmaul | d3f9eb2 | 2020-01-12 15:02:07 -0800 | [diff] [blame] | 82 | }; |
| 83 | |
| 84 | } // namespace frc971::zeroing |
| 85 | #endif // FRC971_ZEROING_IMU_ZEROER_H_ |