blob: a9b1045b2f49b4e95d55a668f0397b1d9657bf54 [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() ||
9 diag.flash_memory_update_error() || diag.data_path_overrun();
10}
11bool ReadingHasFaults(const IMUValues &values) {
12 if (values.has_previous_reading_diag_stat() &&
13 DiagStatHasFaults(*values.previous_reading_diag_stat())) {
14 return true;
15 }
16 if (values.has_self_test_diag_stat() &&
17 DiagStatHasFaults(*values.self_test_diag_stat())) {
18 return true;
19 }
20 return false;
21}
22} // namespace
23
James Kuszmauld3f9eb22020-01-12 15:02:07 -080024ImuZeroer::ImuZeroer() {
25 gyro_average_.setZero();
James Kuszmaulb1e29372020-02-11 16:55:36 -080026 accel_average_.setZero();
James Kuszmauld3f9eb22020-01-12 15:02:07 -080027 last_gyro_sample_.setZero();
28 last_accel_sample_.setZero();
29}
30
James Kuszmaulb1e29372020-02-11 16:55:36 -080031bool ImuZeroer::Zeroed() const {
James Kuszmaulddc69702021-03-24 21:55:03 -070032 return num_zeroes_ > kRequiredZeroPoints && !Faulted();
James Kuszmaulb1e29372020-02-11 16:55:36 -080033}
James Kuszmauld3f9eb22020-01-12 15:02:07 -080034
35bool ImuZeroer::Faulted() const { return faulted_; }
36
37Eigen::Vector3d ImuZeroer::ZeroedGyro() const {
38 return last_gyro_sample_ - gyro_average_;
39}
James Kuszmaulb1e29372020-02-11 16:55:36 -080040Eigen::Vector3d ImuZeroer::ZeroedAccel() const {
41 return last_accel_sample_ - accel_average_;
42}
James Kuszmauld3f9eb22020-01-12 15:02:07 -080043Eigen::Vector3d ImuZeroer::GyroOffset() const { return gyro_average_; }
44
45bool ImuZeroer::GyroZeroReady() const {
James Kuszmaulb1e29372020-02-11 16:55:36 -080046 return gyro_averager_.full() &&
47 gyro_averager_.GetRange() < kGyroMaxVariation &&
48 (last_gyro_sample_.lpNorm<Eigen::Infinity>() <
49 kGyroMaxZeroingMagnitude);
James Kuszmauld3f9eb22020-01-12 15:02:07 -080050}
51
52bool ImuZeroer::AccelZeroReady() const {
53 return accel_averager_.full() &&
54 accel_averager_.GetRange() < kAccelMaxVariation;
55}
56
James Kuszmaulb7f45bb2020-02-26 20:27:48 -080057void ImuZeroer::InsertAndProcessMeasurement(const IMUValues &values) {
58 InsertMeasurement(values);
59 ProcessMeasurements();
60}
61
62void ImuZeroer::InsertMeasurement(const IMUValues &values) {
James Kuszmaulddc69702021-03-24 21:55:03 -070063 if (ReadingHasFaults(values)) {
64 faulted_ = true;
65 return;
66 }
James Kuszmauld3f9eb22020-01-12 15:02:07 -080067 last_gyro_sample_ << values.gyro_x(), values.gyro_y(), values.gyro_z();
68 gyro_averager_.AddData(last_gyro_sample_);
69 last_accel_sample_ << values.accelerometer_x(), values.accelerometer_y(),
70 values.accelerometer_z();
71 accel_averager_.AddData(last_accel_sample_);
James Kuszmaulb7f45bb2020-02-26 20:27:48 -080072}
73
74void ImuZeroer::ProcessMeasurements() {
James Kuszmauld3f9eb22020-01-12 15:02:07 -080075 if (GyroZeroReady() && AccelZeroReady()) {
James Kuszmaulb1e29372020-02-11 16:55:36 -080076 ++good_iters_;
James Kuszmaulb7f45bb2020-02-26 20:27:48 -080077 if (good_iters_ > kSamplesToAverage / 40) {
James Kuszmaulb1e29372020-02-11 16:55:36 -080078 const Eigen::Vector3d current_gyro_average = gyro_averager_.GetAverage();
79 constexpr double kAverageUpdateWeight = 0.05;
80 if (num_zeroes_ > 0) {
81 gyro_average_ +=
82 (current_gyro_average - gyro_average_) * kAverageUpdateWeight;
83 } else {
84 gyro_average_ = current_gyro_average;
James Kuszmauld3f9eb22020-01-12 15:02:07 -080085 }
James Kuszmaulb1e29372020-02-11 16:55:36 -080086 if (num_zeroes_ > 0) {
87 // If we got a new zero and it is substantially different from the
88 // original zero, fault.
89 if ((current_gyro_average - gyro_average_).norm() >
90 kGyroFaultVariation) {
91 faulted_ = true;
92 }
93 }
94 ++num_zeroes_;
95 gyro_averager_.Reset();
James Kuszmauld3f9eb22020-01-12 15:02:07 -080096 }
James Kuszmaulb1e29372020-02-11 16:55:36 -080097 } else {
98 good_iters_ = 0;
James Kuszmauld3f9eb22020-01-12 15:02:07 -080099 }
100}
101
James Kuszmaulb1e29372020-02-11 16:55:36 -0800102flatbuffers::Offset<control_loops::drivetrain::ImuZeroerState>
103ImuZeroer::PopulateStatus(flatbuffers::FlatBufferBuilder *fbb) const {
104 control_loops::drivetrain::ImuZeroerState::Builder builder(*fbb);
105
106 builder.add_zeroed(Zeroed());
107 builder.add_faulted(Faulted());
108 builder.add_number_of_zeroes(num_zeroes_);
109
110 builder.add_gyro_x_average(GyroOffset().x());
111 builder.add_gyro_y_average(GyroOffset().y());
112 builder.add_gyro_z_average(GyroOffset().z());
113
James Kuszmaul1a398fd2021-06-27 15:15:11 -0700114 builder.add_accel_x_average(accel_average_.x());
115 builder.add_accel_y_average(accel_average_.y());
116 builder.add_accel_z_average(accel_average_.z());
117
James Kuszmaulb1e29372020-02-11 16:55:36 -0800118 return builder.Finish();
119}
120
James Kuszmauld3f9eb22020-01-12 15:02:07 -0800121} // namespace frc971::zeroing