blob: 3164bed1544f4783c3f52f1833586deb263a3f2d [file] [log] [blame]
James Kuszmauld3f9eb22020-01-12 15:02:07 -08001#include "frc971/zeroing/imu_zeroer.h"
2
3namespace frc971::zeroing {
4
James Kuszmaulddc69702021-03-24 21:55:03 -07005namespace {
6bool DiagStatHasFaults(const ADIS16470DiagStat &diag) {
7 return diag.clock_error() || diag.memory_failure() || diag.sensor_failure() ||
8 diag.standby_mode() || diag.spi_communication_error() ||
James Kuszmaul6d6e1302022-03-12 15:22:48 -08009 diag.flash_memory_update_error() || diag.data_path_overrun() ||
10 diag.checksum_mismatch();
James Kuszmaulddc69702021-03-24 21:55:03 -070011}
12bool ReadingHasFaults(const IMUValues &values) {
13 if (values.has_previous_reading_diag_stat() &&
14 DiagStatHasFaults(*values.previous_reading_diag_stat())) {
15 return true;
16 }
17 if (values.has_self_test_diag_stat() &&
18 DiagStatHasFaults(*values.self_test_diag_stat())) {
19 return true;
20 }
James Kuszmaul6d6e1302022-03-12 15:22:48 -080021 if (values.checksum_failed()) {
22 return true;
23 }
James Kuszmaulddc69702021-03-24 21:55:03 -070024 return false;
25}
26} // namespace
27
James Kuszmauldb85fa32024-03-16 16:55:47 -070028ImuZeroer::ImuZeroer(FaultBehavior fault_behavior, double gyro_max_variation)
29 : fault_behavior_(fault_behavior), gyro_max_variation_(gyro_max_variation) {
James Kuszmauld3f9eb22020-01-12 15:02:07 -080030 gyro_average_.setZero();
31 last_gyro_sample_.setZero();
32 last_accel_sample_.setZero();
33}
34
James Kuszmaulb1e29372020-02-11 16:55:36 -080035bool ImuZeroer::Zeroed() const {
James Kuszmaulddc69702021-03-24 21:55:03 -070036 return num_zeroes_ > kRequiredZeroPoints && !Faulted();
James Kuszmaulb1e29372020-02-11 16:55:36 -080037}
James Kuszmauld3f9eb22020-01-12 15:02:07 -080038
James Kuszmaul6d6e1302022-03-12 15:22:48 -080039bool ImuZeroer::Faulted() const { return reading_faulted_ || zeroing_faulted_; }
James Kuszmauld3f9eb22020-01-12 15:02:07 -080040
James Kuszmaul6d6e1302022-03-12 15:22:48 -080041std::optional<Eigen::Vector3d> ImuZeroer::ZeroedGyro() const {
42 return Faulted() ? std::nullopt
43 : std::make_optional<Eigen::Vector3d>(last_gyro_sample_ -
44 gyro_average_);
James Kuszmauld3f9eb22020-01-12 15:02:07 -080045}
James Kuszmaul6d6e1302022-03-12 15:22:48 -080046
47std::optional<Eigen::Vector3d> ImuZeroer::ZeroedAccel() const {
48 return Faulted() ? std::nullopt
Lee Mracekfddd1372022-10-22 15:58:31 -040049 : std::make_optional<Eigen::Vector3d>(last_accel_sample_);
James Kuszmaulb1e29372020-02-11 16:55:36 -080050}
James Kuszmaul6d6e1302022-03-12 15:22:48 -080051
James Kuszmauld3f9eb22020-01-12 15:02:07 -080052Eigen::Vector3d ImuZeroer::GyroOffset() const { return gyro_average_; }
53
54bool ImuZeroer::GyroZeroReady() const {
James Kuszmaulb1e29372020-02-11 16:55:36 -080055 return gyro_averager_.full() &&
James Kuszmauldb85fa32024-03-16 16:55:47 -070056 gyro_averager_.GetRange() < gyro_max_variation_ &&
James Kuszmaulb1e29372020-02-11 16:55:36 -080057 (last_gyro_sample_.lpNorm<Eigen::Infinity>() <
58 kGyroMaxZeroingMagnitude);
James Kuszmauld3f9eb22020-01-12 15:02:07 -080059}
60
61bool ImuZeroer::AccelZeroReady() const {
62 return accel_averager_.full() &&
63 accel_averager_.GetRange() < kAccelMaxVariation;
64}
65
James Kuszmaulb7f45bb2020-02-26 20:27:48 -080066void ImuZeroer::InsertAndProcessMeasurement(const IMUValues &values) {
James Kuszmaul6d6e1302022-03-12 15:22:48 -080067 if (InsertMeasurement(values)) {
68 ProcessMeasurements();
69 }
James Kuszmaulb7f45bb2020-02-26 20:27:48 -080070}
71
James Kuszmaul6d6e1302022-03-12 15:22:48 -080072bool ImuZeroer::InsertMeasurement(const IMUValues &values) {
James Kuszmaulddc69702021-03-24 21:55:03 -070073 if (ReadingHasFaults(values)) {
James Kuszmaul6d6e1302022-03-12 15:22:48 -080074 reading_faulted_ = true;
75 return false;
76 }
77 if (fault_behavior_ == FaultBehavior::kTemporary) {
78 reading_faulted_ = false;
James Kuszmaulddc69702021-03-24 21:55:03 -070079 }
James Kuszmauld3f9eb22020-01-12 15:02:07 -080080 last_gyro_sample_ << values.gyro_x(), values.gyro_y(), values.gyro_z();
81 gyro_averager_.AddData(last_gyro_sample_);
82 last_accel_sample_ << values.accelerometer_x(), values.accelerometer_y(),
Philipp Schrader790cb542023-07-05 21:06:52 -070083 values.accelerometer_z();
James Kuszmauld3f9eb22020-01-12 15:02:07 -080084 accel_averager_.AddData(last_accel_sample_);
James Kuszmaul6d6e1302022-03-12 15:22:48 -080085 return true;
James Kuszmaulb7f45bb2020-02-26 20:27:48 -080086}
87
88void ImuZeroer::ProcessMeasurements() {
James Kuszmauld3f9eb22020-01-12 15:02:07 -080089 if (GyroZeroReady() && AccelZeroReady()) {
James Kuszmaulb1e29372020-02-11 16:55:36 -080090 ++good_iters_;
James Kuszmaulb7f45bb2020-02-26 20:27:48 -080091 if (good_iters_ > kSamplesToAverage / 40) {
James Kuszmaulb1e29372020-02-11 16:55:36 -080092 const Eigen::Vector3d current_gyro_average = gyro_averager_.GetAverage();
93 constexpr double kAverageUpdateWeight = 0.05;
94 if (num_zeroes_ > 0) {
95 gyro_average_ +=
96 (current_gyro_average - gyro_average_) * kAverageUpdateWeight;
97 } else {
98 gyro_average_ = current_gyro_average;
James Kuszmauld3f9eb22020-01-12 15:02:07 -080099 }
James Kuszmaulb1e29372020-02-11 16:55:36 -0800100 if (num_zeroes_ > 0) {
101 // If we got a new zero and it is substantially different from the
102 // original zero, fault.
103 if ((current_gyro_average - gyro_average_).norm() >
104 kGyroFaultVariation) {
James Kuszmaul6d6e1302022-03-12 15:22:48 -0800105 zeroing_faulted_ = true;
106 } else if (fault_behavior_ == FaultBehavior::kTemporary) {
107 zeroing_faulted_ = false;
James Kuszmaulb1e29372020-02-11 16:55:36 -0800108 }
109 }
110 ++num_zeroes_;
111 gyro_averager_.Reset();
James Kuszmauld3f9eb22020-01-12 15:02:07 -0800112 }
James Kuszmaulb1e29372020-02-11 16:55:36 -0800113 } else {
114 good_iters_ = 0;
James Kuszmauld3f9eb22020-01-12 15:02:07 -0800115 }
116}
117
James Kuszmaulb1e29372020-02-11 16:55:36 -0800118flatbuffers::Offset<control_loops::drivetrain::ImuZeroerState>
119ImuZeroer::PopulateStatus(flatbuffers::FlatBufferBuilder *fbb) const {
120 control_loops::drivetrain::ImuZeroerState::Builder builder(*fbb);
121
122 builder.add_zeroed(Zeroed());
123 builder.add_faulted(Faulted());
124 builder.add_number_of_zeroes(num_zeroes_);
125
126 builder.add_gyro_x_average(GyroOffset().x());
127 builder.add_gyro_y_average(GyroOffset().y());
128 builder.add_gyro_z_average(GyroOffset().z());
129
Lee Mracekfddd1372022-10-22 15:58:31 -0400130 builder.add_accel_x_average(accel_averager_.GetAverage()[0]);
131 builder.add_accel_y_average(accel_averager_.GetAverage()[1]);
132 builder.add_accel_z_average(accel_averager_.GetAverage()[2]);
James Kuszmaul1a398fd2021-06-27 15:15:11 -0700133
James Kuszmaulb1e29372020-02-11 16:55:36 -0800134 return builder.Finish();
135}
136
James Kuszmauld3f9eb22020-01-12 15:02:07 -0800137} // namespace frc971::zeroing