blob: c0831e8b9f6912c2af3eb525232e2bb31ebf1af9 [file] [log] [blame]
#include "frc971/zeroing/pulse_index.h"
#include <cmath>
#include <limits>
#include "glog/logging.h"
namespace frc971 {
namespace zeroing {
void PulseIndexZeroingEstimator::Reset() {
max_index_position_ = ::std::numeric_limits<double>::lowest();
min_index_position_ = ::std::numeric_limits<double>::max();
offset_ = 0;
last_used_index_pulse_count_ = 0;
zeroed_ = false;
error_ = false;
}
void PulseIndexZeroingEstimator::StoreIndexPulseMaxAndMin(
const IndexPosition &info) {
// If we have a new index pulse.
if (last_used_index_pulse_count_ != info.index_pulses()) {
// If the latest pulses's position is outside the range we've currently
// seen, record it appropriately.
if (info.latched_encoder() > max_index_position_) {
max_index_position_ = info.latched_encoder();
}
if (info.latched_encoder() < min_index_position_) {
min_index_position_ = info.latched_encoder();
}
last_used_index_pulse_count_ = info.index_pulses();
}
}
int PulseIndexZeroingEstimator::IndexPulseCount() const {
if (min_index_position_ > max_index_position_) {
// This condition means we haven't seen a pulse yet.
return 0;
}
// Calculate the number of pulses encountered so far.
return 1 + static_cast<int>(
::std::round((max_index_position_ - min_index_position_) /
constants_.index_difference));
}
void PulseIndexZeroingEstimator::UpdateEstimate(const IndexPosition &info) {
StoreIndexPulseMaxAndMin(info);
const int index_pulse_count = IndexPulseCount();
if (index_pulse_count > constants_.index_pulse_count) {
if (!error_) {
VLOG(1) << "Got more index pulses than expected. Got "
<< index_pulse_count << " expected "
<< constants_.index_pulse_count;
error_ = true;
}
}
// TODO(austin): Detect if the encoder or index pulse is unplugged.
// TODO(austin): Detect missing counts.
if (index_pulse_count == constants_.index_pulse_count && !zeroed_) {
offset_ = constants_.measured_index_position -
constants_.known_index_pulse * constants_.index_difference -
min_index_position_;
zeroed_ = true;
} else if (zeroed_ && !error_) {
// Detect whether the index pulse is somewhere other than where we expect
// it to be. First we compute the position of the most recent index pulse.
double index_pulse_distance =
info.latched_encoder() + offset_ - constants_.measured_index_position;
// Second we compute the position of the index pulse in terms of
// the index difference. I.e. if this index pulse is two pulses away from
// the index pulse that we know about then this number should be positive
// or negative two.
double relative_distance =
index_pulse_distance / constants_.index_difference;
// Now we compute how far away the measured index pulse is from the
// expected index pulse.
double error = relative_distance - ::std::round(relative_distance);
// This lets us check if the index pulse is within an acceptable error
// margin of where we expected it to be.
if (::std::abs(error) > constants_.allowable_encoder_error) {
VLOG(1)
<< "Encoder ticks out of range since last index pulse. known index "
"pulse: "
<< constants_.measured_index_position << ", expected index pulse: "
<< round(relative_distance) * constants_.index_difference +
constants_.measured_index_position
<< ", actual index pulse: " << info.latched_encoder() + offset_
<< ", "
"allowable error: "
<< constants_.allowable_encoder_error * constants_.index_difference;
error_ = true;
}
}
position_ = info.encoder() + offset_;
}
flatbuffers::Offset<PulseIndexZeroingEstimator::State>
PulseIndexZeroingEstimator::GetEstimatorState(
flatbuffers::FlatBufferBuilder *fbb) const {
State::Builder builder(*fbb);
builder.add_error(error_);
builder.add_zeroed(zeroed_);
builder.add_position(position_);
builder.add_min_index_position(min_index_position_);
builder.add_max_index_position(max_index_position_);
builder.add_index_pulses_seen(IndexPulseCount());
return builder.Finish();
}
} // namespace zeroing
} // namespace frc971