Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rewrite DutyCycleEncoder and AnalogEncoder #6398

Merged
merged 33 commits into from
May 24, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
7c248d3
Deprecate AbsoluteEncoder classes, Replace DCE with DutyCyclePotentio…
ThadHouse Feb 25, 2024
d048b86
Keep with AnalogEncoder and DutyCycleEncoder
ThadHouse Feb 26, 2024
797eb84
Add inversion
ThadHouse Feb 26, 2024
5a4d3fd
Fix up example
ThadHouse Feb 29, 2024
dd2332d
Fixup C++
ThadHouse Feb 29, 2024
1e02bbb
Fix unused variable
ThadHouse Mar 2, 2024
d33ba3c
Add rollover support
ThadHouse Mar 2, 2024
85adf21
Formatting fixes
github-actions[bot] Mar 2, 2024
413b945
Analog Encoder Destructor
ThadHouse Mar 3, 2024
bdceac9
Docs
ThadHouse Mar 3, 2024
88298ee
Docs and format
ThadHouse Mar 3, 2024
cff871a
More format
ThadHouse Mar 3, 2024
ed0c807
Formatting
ThadHouse Mar 3, 2024
b5e681c
Format
ThadHouse Mar 3, 2024
0c6b352
Completely remove rollover
ThadHouse Mar 8, 2024
0889fec
Deprecate AbsoluteEncoder classes, Replace DCE with DutyCyclePotentio…
ThadHouse Feb 25, 2024
2ee6216
Keep with AnalogEncoder and DutyCycleEncoder
ThadHouse Feb 26, 2024
0c4b9c7
Add inversion
ThadHouse Feb 26, 2024
85469db
Fix up example
ThadHouse Feb 29, 2024
071b62c
Fixup C++
ThadHouse Feb 29, 2024
f48c093
Fix unused variable
ThadHouse Mar 2, 2024
a9a353f
Add rollover support
ThadHouse Mar 2, 2024
1d71776
Formatting fixes
github-actions[bot] Mar 2, 2024
e9a0339
Analog Encoder Destructor
ThadHouse Mar 3, 2024
45da00d
Docs
ThadHouse Mar 3, 2024
202a9e8
Docs and format
ThadHouse Mar 3, 2024
8d9c427
More format
ThadHouse Mar 3, 2024
af23048
Formatting
ThadHouse Mar 3, 2024
3622c01
Format
ThadHouse Mar 3, 2024
0b1e8a8
Completely remove rollover
ThadHouse Mar 8, 2024
879c396
Merge branch 'absencoderreplace' of https://github.com/thadhouse/allw…
ThadHouse Apr 29, 2024
07e4f0f
Merge remote-tracking branch 'wpilibsuite/main' into absencoderreplace
ThadHouse May 5, 2024
ee36569
Merge remote-tracking branch 'wpilibsuite/main' into absencoderreplace
ThadHouse May 13, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
147 changes: 67 additions & 80 deletions wpilibc/src/main/native/cpp/AnalogEncoder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,130 +8,117 @@
#include <wpi/sendable/SendableBuilder.h>

#include "frc/AnalogInput.h"
#include "frc/Counter.h"
#include "frc/Errors.h"
#include "frc/MathUtil.h"
#include "frc/RobotController.h"

using namespace frc;

AnalogEncoder::~AnalogEncoder() {}

AnalogEncoder::AnalogEncoder(int channel)
: AnalogEncoder(std::make_shared<AnalogInput>(channel)) {}

AnalogEncoder::AnalogEncoder(AnalogInput& analogInput)
: m_analogInput{&analogInput, wpi::NullDeleter<AnalogInput>{}},
m_analogTrigger{m_analogInput.get()},
m_counter{} {
Init();
: m_analogInput{&analogInput, wpi::NullDeleter<AnalogInput>{}} {
Init(1.0, 0.0);
}

AnalogEncoder::AnalogEncoder(AnalogInput* analogInput)
: m_analogInput{analogInput, wpi::NullDeleter<AnalogInput>{}},
m_analogTrigger{m_analogInput.get()},
m_counter{} {
Init();
: m_analogInput{analogInput, wpi::NullDeleter<AnalogInput>{}} {
Init(1.0, 0.0);
}

AnalogEncoder::AnalogEncoder(std::shared_ptr<AnalogInput> analogInput)
: m_analogInput{std::move(analogInput)},
m_analogTrigger{m_analogInput.get()},
m_counter{} {
Init();
: m_analogInput{std::move(analogInput)} {
Init(1.0, 0.0);
}

void AnalogEncoder::Init() {
m_simDevice = hal::SimDevice{"AnalogEncoder", m_analogInput->GetChannel()};
AnalogEncoder::AnalogEncoder(int channel, double fullRange, double expectedZero)
: AnalogEncoder(std::make_shared<AnalogInput>(channel), fullRange,
expectedZero) {}

if (m_simDevice) {
m_simPosition = m_simDevice.CreateDouble("Position", false, 0.0);
m_simAbsolutePosition =
m_simDevice.CreateDouble("absPosition", hal::SimDevice::kInput, 0.0);
}

m_analogTrigger.SetLimitsVoltage(1.25, 3.75);
m_counter.SetUpSource(
m_analogTrigger.CreateOutput(AnalogTriggerType::kRisingPulse));
m_counter.SetDownSource(
m_analogTrigger.CreateOutput(AnalogTriggerType::kFallingPulse));
AnalogEncoder::AnalogEncoder(AnalogInput& analogInput, double fullRange,
double expectedZero)
: m_analogInput{&analogInput, wpi::NullDeleter<AnalogInput>{}} {
Init(fullRange, expectedZero);
}

wpi::SendableRegistry::AddLW(this, "DutyCycle Encoder",
m_analogInput->GetChannel());
AnalogEncoder::AnalogEncoder(AnalogInput* analogInput, double fullRange,
double expectedZero)
: m_analogInput{analogInput, wpi::NullDeleter<AnalogInput>{}} {
Init(fullRange, expectedZero);
}

static bool DoubleEquals(double a, double b) {
constexpr double epsilon = 0.00001;
return std::abs(a - b) < epsilon;
AnalogEncoder::AnalogEncoder(std::shared_ptr<AnalogInput> analogInput,
double fullRange, double expectedZero)
: m_analogInput{std::move(analogInput)} {
Init(fullRange, expectedZero);
}

units::turn_t AnalogEncoder::Get() const {
if (m_simPosition) {
return units::turn_t{m_simPosition.Get()};
}
void AnalogEncoder::Init(double fullRange, double expectedZero) {
m_simDevice = hal::SimDevice{"AnalogEncoder", m_analogInput->GetChannel()};

// As the values are not atomic, keep trying until we get 2 reads of the same
// value If we don't within 10 attempts, error
for (int i = 0; i < 10; i++) {
auto counter = m_counter.Get();
auto pos = m_analogInput->GetVoltage();
auto counter2 = m_counter.Get();
auto pos2 = m_analogInput->GetVoltage();
if (counter == counter2 && DoubleEquals(pos, pos2)) {
pos = pos / frc::RobotController::GetVoltage5V();
units::turn_t turns{counter + pos - m_positionOffset};
m_lastPosition = turns;
return turns;
}
if (m_simDevice) {
m_simPosition = m_simDevice.CreateDouble("Position", false, 0.0);
}

FRC_ReportError(
warn::Warning,
"Failed to read Analog Encoder. Potential Speed Overrun. Returning last "
"value");
return m_lastPosition;
m_fullRange = fullRange;
m_expectedZero = expectedZero;

wpi::SendableRegistry::AddLW(this, "Analog Encoder",
m_analogInput->GetChannel());
}

double AnalogEncoder::GetAbsolutePosition() const {
if (m_simAbsolutePosition) {
return m_simAbsolutePosition.Get();
double AnalogEncoder::Get() const {
if (m_simPosition) {
return m_simPosition.Get();
}

return m_analogInput->GetVoltage() / frc::RobotController::GetVoltage5V();
}
double analog = m_analogInput->GetVoltage();
double pos = analog / RobotController::GetVoltage5V();

double AnalogEncoder::GetPositionOffset() const {
return m_positionOffset;
}
// Map sensor range if range isn't full
pos = MapSensorRange(pos);

void AnalogEncoder::SetPositionOffset(double offset) {
m_positionOffset = std::clamp(offset, 0.0, 1.0);
}

void AnalogEncoder::SetDistancePerRotation(double distancePerRotation) {
m_distancePerRotation = distancePerRotation;
}
// Compute full range and offset
pos = pos * m_fullRange - m_expectedZero;

double AnalogEncoder::GetDistancePerRotation() const {
return m_distancePerRotation;
// Map from 0 - Full Range
double result = InputModulus(pos, 0.0, m_fullRange);
// Invert if necessary
if (m_isInverted) {
return m_fullRange - result;
}
return result;
}

double AnalogEncoder::GetDistance() const {
return Get().value() * GetDistancePerRotation();
void AnalogEncoder::SetVoltagePercentageRange(double min, double max) {
m_sensorMin = std::clamp(min, 0.0, 1.0);
m_sensorMax = std::clamp(max, 0.0, 1.0);
}

void AnalogEncoder::Reset() {
m_counter.Reset();
m_positionOffset =
m_analogInput->GetVoltage() / frc::RobotController::GetVoltage5V();
void AnalogEncoder::SetInverted(bool inverted) {
m_isInverted = inverted;
}

int AnalogEncoder::GetChannel() const {
return m_analogInput->GetChannel();
}

double AnalogEncoder::MapSensorRange(double pos) const {
if (pos < m_sensorMin) {
pos = m_sensorMin;
}
if (pos > m_sensorMax) {
pos = m_sensorMax;
}
pos = (pos - m_sensorMin) / (m_sensorMax - m_sensorMin);
return pos;
}

void AnalogEncoder::InitSendable(wpi::SendableBuilder& builder) {
builder.SetSmartDashboardType("AbsoluteEncoder");
builder.AddDoubleProperty(
"Distance", [this] { return this->GetDistance(); }, nullptr);
builder.AddDoubleProperty(
"Distance Per Rotation",
[this] { return this->GetDistancePerRotation(); }, nullptr);
"Position", [this] { return this->Get(); }, nullptr);
}
Loading
Loading