blob: 6bc2d0ea499f618111625205e06959adfcefbefc [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 Kuszmaul6d6e1302022-03-12 15:22:48 -080028ImuZeroer::ImuZeroer(FaultBehavior fault_behavior)
29 : fault_behavior_(fault_behavior) {
James Kuszmauld3f9eb22020-01-12 15:02:07 -080030 gyro_average_.setZero();
James Kuszmaulb1e29372020-02-11 16:55:36 -080031 accel_average_.setZero();
James Kuszmauld3f9eb22020-01-12 15:02:07 -080032 last_gyro_sample_.setZero();
33 last_accel_sample_.setZero();
34}
35
James Kuszmaulb1e29372020-02-11 16:55:36 -080036bool ImuZeroer::Zeroed() const {
James Kuszmaulddc69702021-03-24 21:55:03 -070037 return num_zeroes_ > kRequiredZeroPoints && !Faulted();
James Kuszmaulb1e29372020-02-11 16:55:36 -080038}
James Kuszmauld3f9eb22020-01-12 15:02:07 -080039
James Kuszmaul6d6e1302022-03-12 15:22:48 -080040bool ImuZeroer::Faulted() const { return reading_faulted_ || zeroing_faulted_; }
James Kuszmauld3f9eb22020-01-12 15:02:07 -080041
James Kuszmaul6d6e1302022-03-12 15:22:48 -080042std::optional<Eigen::Vector3d> ImuZeroer::ZeroedGyro() const {
43 return Faulted() ? std::nullopt
44 : std::make_optional<Eigen::Vector3d>(last_gyro_sample_ -
45 gyro_average_);
James Kuszmauld3f9eb22020-01-12 15:02:07 -080046}
James Kuszmaul6d6e1302022-03-12 15:22:48 -080047
48std::optional<Eigen::Vector3d> ImuZeroer::ZeroedAccel() const {
49 return Faulted() ? std::nullopt
50 : std::make_optional<Eigen::Vector3d>(last_accel_sample_ -
51 accel_average_);
James Kuszmaulb1e29372020-02-11 16:55:36 -080052}
James Kuszmaul6d6e1302022-03-12 15:22:48 -080053
James Kuszmauld3f9eb22020-01-12 15:02:07 -080054Eigen::Vector3d ImuZeroer::GyroOffset() const { return gyro_average_; }
55
56bool ImuZeroer::GyroZeroReady() const {
James Kuszmaulb1e29372020-02-11 16:55:36 -080057 return gyro_averager_.full() &&
58 gyro_averager_.GetRange() < kGyroMaxVariation &&
59 (last_gyro_sample_.lpNorm<Eigen::Infinity>() <
60 kGyroMaxZeroingMagnitude);
James Kuszmauld3f9eb22020-01-12 15:02:07 -080061}
62
63bool ImuZeroer::AccelZeroReady() const {
64 return accel_averager_.full() &&
65 accel_averager_.GetRange() < kAccelMaxVariation;
66}
67
James Kuszmaulb7f45bb2020-02-26 20:27:48 -080068void ImuZeroer::InsertAndProcessMeasurement(const IMUValues &values) {
James Kuszmaul6d6e1302022-03-12 15:22:48 -080069 if (InsertMeasurement(values)) {
70 ProcessMeasurements();
71 }
James Kuszmaulb7f45bb2020-02-26 20:27:48 -080072}
73
James Kuszmaul6d6e1302022-03-12 15:22:48 -080074bool ImuZeroer::InsertMeasurement(const IMUValues &values) {
James Kuszmaulddc69702021-03-24 21:55:03 -070075 if (ReadingHasFaults(values)) {
James Kuszmaul6d6e1302022-03-12 15:22:48 -080076 reading_faulted_ = true;
77 return false;
78 }
79 if (fault_behavior_ == FaultBehavior::kTemporary) {
80 reading_faulted_ = false;
James Kuszmaulddc69702021-03-24 21:55:03 -070081 }
James Kuszmauld3f9eb22020-01-12 15:02:07 -080082 last_gyro_sample_ << values.gyro_x(), values.gyro_y(), values.gyro_z();
83 gyro_averager_.AddData(last_gyro_sample_);
84 last_accel_sample_ << values.accelerometer_x(), values.accelerometer_y(),
85 values.accelerometer_z();
86 accel_averager_.AddData(last_accel_sample_);
James Kuszmaul6d6e1302022-03-12 15:22:48 -080087 return true;
James Kuszmaulb7f45bb2020-02-26 20:27:48 -080088}
89
90void ImuZeroer::ProcessMeasurements() {
James Kuszmauld3f9eb22020-01-12 15:02:07 -080091 if (GyroZeroReady() && AccelZeroReady()) {
James Kuszmaulb1e29372020-02-11 16:55:36 -080092 ++good_iters_;
James Kuszmaulb7f45bb2020-02-26 20:27:48 -080093 if (good_iters_ > kSamplesToAverage / 40) {
James Kuszmaulb1e29372020-02-11 16:55:36 -080094 const Eigen::Vector3d current_gyro_average = gyro_averager_.GetAverage();
95 constexpr double kAverageUpdateWeight = 0.05;
96 if (num_zeroes_ > 0) {
97 gyro_average_ +=
98 (current_gyro_average - gyro_average_) * kAverageUpdateWeight;
99 } else {
100 gyro_average_ = current_gyro_average;
James Kuszmauld3f9eb22020-01-12 15:02:07 -0800101 }
James Kuszmaulb1e29372020-02-11 16:55:36 -0800102 if (num_zeroes_ > 0) {
103 // If we got a new zero and it is substantially different from the
104 // original zero, fault.
105 if ((current_gyro_average - gyro_average_).norm() >
106 kGyroFaultVariation) {
James Kuszmaul6d6e1302022-03-12 15:22:48 -0800107 zeroing_faulted_ = true;
108 } else if (fault_behavior_ == FaultBehavior::kTemporary) {
109 zeroing_faulted_ = false;
James Kuszmaulb1e29372020-02-11 16:55:36 -0800110 }
111 }
112 ++num_zeroes_;
113 gyro_averager_.Reset();
James Kuszmauld3f9eb22020-01-12 15:02:07 -0800114 }
James Kuszmaulb1e29372020-02-11 16:55:36 -0800115 } else {
116 good_iters_ = 0;
James Kuszmauld3f9eb22020-01-12 15:02:07 -0800117 }
118}
119
James Kuszmaulb1e29372020-02-11 16:55:36 -0800120flatbuffers::Offset<control_loops::drivetrain::ImuZeroerState>
121ImuZeroer::PopulateStatus(flatbuffers::FlatBufferBuilder *fbb) const {
122 control_loops::drivetrain::ImuZeroerState::Builder builder(*fbb);
123
124 builder.add_zeroed(Zeroed());
125 builder.add_faulted(Faulted());
126 builder.add_number_of_zeroes(num_zeroes_);
127
128 builder.add_gyro_x_average(GyroOffset().x());
129 builder.add_gyro_y_average(GyroOffset().y());
130 builder.add_gyro_z_average(GyroOffset().z());
131
James Kuszmaul1a398fd2021-06-27 15:15:11 -0700132 builder.add_accel_x_average(accel_average_.x());
133 builder.add_accel_y_average(accel_average_.y());
134 builder.add_accel_z_average(accel_average_.z());
135
James Kuszmaulb1e29372020-02-11 16:55:36 -0800136 return builder.Finish();
137}
138
James Kuszmauld3f9eb22020-01-12 15:02:07 -0800139} // namespace frc971::zeroing