[wpilib] Rewrite DutyCycleEncoder and AnalogEncoder (#6398)

This commit is contained in:
Thad House
2024-05-24 11:53:56 -07:00
committed by GitHub
parent 294c9946ae
commit d05c7c125b
18 changed files with 638 additions and 883 deletions

View File

@@ -8,13 +8,9 @@
#include <hal/SimDevice.h>
#include <hal/Types.h>
#include <units/angle.h>
#include <wpi/sendable/Sendable.h>
#include <wpi/sendable/SendableHelper.h>
#include "frc/AnalogTrigger.h"
#include "frc/Counter.h"
namespace frc {
class AnalogInput;
@@ -27,6 +23,8 @@ class AnalogEncoder : public wpi::Sendable,
/**
* Construct a new AnalogEncoder attached to a specific AnalogIn channel.
*
* <p>This has a fullRange of 1 and an expectedZero of 0.
*
* @param channel the analog input channel to attach to
*/
explicit AnalogEncoder(int channel);
@@ -34,6 +32,8 @@ class AnalogEncoder : public wpi::Sendable,
/**
* Construct a new AnalogEncoder attached to a specific AnalogInput.
*
* <p>This has a fullRange of 1 and an expectedZero of 0.
*
* @param analogInput the analog input to attach to
*/
explicit AnalogEncoder(AnalogInput& analogInput);
@@ -41,6 +41,8 @@ class AnalogEncoder : public wpi::Sendable,
/**
* Construct a new AnalogEncoder attached to a specific AnalogInput.
*
* <p>This has a fullRange of 1 and an expectedZero of 0.
*
* @param analogInput the analog input to attach to
*/
explicit AnalogEncoder(AnalogInput* analogInput);
@@ -48,90 +50,79 @@ class AnalogEncoder : public wpi::Sendable,
/**
* Construct a new AnalogEncoder attached to a specific AnalogInput.
*
* <p>This has a fullRange of 1 and an expectedZero of 0.
*
* @param analogInput the analog input to attach to
*/
explicit AnalogEncoder(std::shared_ptr<AnalogInput> analogInput);
~AnalogEncoder() override = default;
/**
* Construct a new AnalogEncoder attached to a specific AnalogIn channel.
*
* @param channel the analog input channel to attach to
* @param fullRange the value to report at maximum travel
* @param expectedZero the reading where you would expect a 0 from get()
*/
AnalogEncoder(int channel, double fullRange, double expectedZero);
/**
* Construct a new AnalogEncoder attached to a specific AnalogInput.
*
* @param analogInput the analog input to attach to
* @param fullRange the value to report at maximum travel
* @param expectedZero the reading where you would expect a 0 from get()
*/
AnalogEncoder(AnalogInput& analogInput, double fullRange,
double expectedZero);
/**
* Construct a new AnalogEncoder attached to a specific AnalogInput.
*
* @param analogInput the analog input to attach to
* @param fullRange the value to report at maximum travel
* @param expectedZero the reading where you would expect a 0 from get()
*/
AnalogEncoder(AnalogInput* analogInput, double fullRange,
double expectedZero);
/**
* Construct a new AnalogEncoder attached to a specific AnalogInput.
*
* @param analogInput the analog input to attach to
* @param fullRange the value to report at maximum travel
* @param expectedZero the reading where you would expect a 0 from get()
*/
AnalogEncoder(std::shared_ptr<AnalogInput> analogInput, double fullRange,
double expectedZero);
~AnalogEncoder() override;
AnalogEncoder(AnalogEncoder&&) = default;
AnalogEncoder& operator=(AnalogEncoder&&) = default;
/**
* Reset the Encoder distance to zero.
* Get the encoder value.
*
* @return the encoder value scaled by the full range input
*/
void Reset();
double Get() const;
/**
* Get the encoder value since the last reset.
* Set the encoder voltage percentage range. Analog sensors are not always
* fully stable at the end of their travel ranges. Shrinking this range down
* can help mitigate issues with that.
*
* This is reported in rotations since the last reset.
*
* @return the encoder value in rotations
* @param min minimum voltage percentage (0-1 range)
* @param max maximum voltage percentage (0-1 range)
*/
units::turn_t Get() const;
void SetVoltagePercentageRange(double min, double max);
/**
* Get the absolute position of the analog encoder.
* Set if this encoder is inverted.
*
* <p>GetAbsolutePosition() - GetPositionOffset() will give an encoder
* absolute position relative to the last reset. This could potentially be
* negative, which needs to be accounted for.
*
* <p>This will not account for rollovers, and will always be just the raw
* absolute position.
*
* @return the absolute position
* @param inverted true to invert the encoder, false otherwise
*/
double GetAbsolutePosition() const;
/**
* Get the offset of position relative to the last reset.
*
* GetAbsolutePosition() - GetPositionOffset() will give an encoder absolute
* position relative to the last reset. This could potentially be negative,
* which needs to be accounted for.
*
* @return the position offset
*/
double GetPositionOffset() const;
/**
* Set the position offset.
*
* <p>This must be in the range of 0-1.
*
* @param offset the offset
*/
void SetPositionOffset(double offset);
/**
* Set the distance per rotation of the encoder. This sets the multiplier used
* to determine the distance driven based on the rotation value from the
* encoder. Set this value based on the how far the mechanism travels in 1
* rotation of the encoder, and factor in gearing reductions following the
* encoder shaft. This distance can be in any units you like, linear or
* angular.
*
* @param distancePerRotation the distance per rotation of the encoder
*/
void SetDistancePerRotation(double distancePerRotation);
/**
* Get the distance per rotation for this encoder.
*
* @return The scale factor that will be used to convert rotation to useful
* units.
*/
double GetDistancePerRotation() const;
/**
* Get the distance the sensor has driven since the last reset as scaled by
* the value from SetDistancePerRotation.
*
* @return The distance driven since the last reset
*/
double GetDistance() const;
void SetInverted(bool inverted);
/**
* Get the channel number.
@@ -143,17 +134,17 @@ class AnalogEncoder : public wpi::Sendable,
void InitSendable(wpi::SendableBuilder& builder) override;
private:
void Init();
void Init(double fullRange, double expectedZero);
double MapSensorRange(double pos) const;
std::shared_ptr<AnalogInput> m_analogInput;
AnalogTrigger m_analogTrigger;
Counter m_counter;
double m_positionOffset = 0;
double m_distancePerRotation = 1.0;
mutable units::turn_t m_lastPosition{0.0};
double m_fullRange;
double m_expectedZero;
double m_sensorMin{0.0};
double m_sensorMax{1.0};
bool m_isInverted{false};
hal::SimDevice m_simDevice;
hal::SimDouble m_simPosition;
hal::SimDouble m_simAbsolutePosition;
};
} // namespace frc

View File

@@ -8,13 +8,11 @@
#include <hal/SimDevice.h>
#include <hal/Types.h>
#include <units/angle.h>
#include <units/frequency.h>
#include <units/time.h>
#include <wpi/sendable/Sendable.h>
#include <wpi/sendable/SendableHelper.h>
#include "frc/AnalogTrigger.h"
#include "frc/Counter.h"
namespace frc {
class DutyCycle;
class DigitalSource;
@@ -30,6 +28,8 @@ class DutyCycleEncoder : public wpi::Sendable,
/**
* Construct a new DutyCycleEncoder on a specific channel.
*
* <p>This has a fullRange of 1 and an expectedZero of 0.
*
* @param channel the channel to attach to
*/
explicit DutyCycleEncoder(int channel);
@@ -37,6 +37,8 @@ class DutyCycleEncoder : public wpi::Sendable,
/**
* Construct a new DutyCycleEncoder attached to an existing DutyCycle object.
*
* <p>This has a fullRange of 1 and an expectedZero of 0.
*
* @param dutyCycle the duty cycle to attach to
*/
explicit DutyCycleEncoder(DutyCycle& dutyCycle);
@@ -44,6 +46,8 @@ class DutyCycleEncoder : public wpi::Sendable,
/**
* Construct a new DutyCycleEncoder attached to an existing DutyCycle object.
*
* <p>This has a fullRange of 1 and an expectedZero of 0.
*
* @param dutyCycle the duty cycle to attach to
*/
explicit DutyCycleEncoder(DutyCycle* dutyCycle);
@@ -51,6 +55,8 @@ class DutyCycleEncoder : public wpi::Sendable,
/**
* Construct a new DutyCycleEncoder attached to an existing DutyCycle object.
*
* <p>This has a fullRange of 1 and an expectedZero of 0.
*
* @param dutyCycle the duty cycle to attach to
*/
explicit DutyCycleEncoder(std::shared_ptr<DutyCycle> dutyCycle);
@@ -58,6 +64,8 @@ class DutyCycleEncoder : public wpi::Sendable,
/**
* Construct a new DutyCycleEncoder attached to a DigitalSource object.
*
* <p>This has a fullRange of 1 and an expectedZero of 0.
*
* @param digitalSource the digital source to attach to
*/
explicit DutyCycleEncoder(DigitalSource& digitalSource);
@@ -65,6 +73,8 @@ class DutyCycleEncoder : public wpi::Sendable,
/**
* Construct a new DutyCycleEncoder attached to a DigitalSource object.
*
* <p>This has a fullRange of 1 and an expectedZero of 0.
*
* @param digitalSource the digital source to attach to
*/
explicit DutyCycleEncoder(DigitalSource* digitalSource);
@@ -72,10 +82,79 @@ class DutyCycleEncoder : public wpi::Sendable,
/**
* Construct a new DutyCycleEncoder attached to a DigitalSource object.
*
* <p>This has a fullRange of 1 and an expectedZero of 0.
*
* @param digitalSource the digital source to attach to
*/
explicit DutyCycleEncoder(std::shared_ptr<DigitalSource> digitalSource);
/**
* Construct a new DutyCycleEncoder on a specific channel.
*
* @param channel the channel to attach to
* @param fullRange the value to report at maximum travel
* @param expectedZero the reading where you would expect a 0 from get()
*/
DutyCycleEncoder(int channel, double fullRange, double expectedZero);
/**
* Construct a new DutyCycleEncoder attached to an existing DutyCycle object.
*
* @param dutyCycle the duty cycle to attach to
* @param fullRange the value to report at maximum travel
* @param expectedZero the reading where you would expect a 0 from get()
*/
DutyCycleEncoder(DutyCycle& dutyCycle, double fullRange, double expectedZero);
/**
* Construct a new DutyCycleEncoder attached to an existing DutyCycle object.
*
* @param dutyCycle the duty cycle to attach to
* @param fullRange the value to report at maximum travel
* @param expectedZero the reading where you would expect a 0 from get()
*/
DutyCycleEncoder(DutyCycle* dutyCycle, double fullRange, double expectedZero);
/**
* Construct a new DutyCycleEncoder attached to an existing DutyCycle object.
*
* @param dutyCycle the duty cycle to attach to
* @param fullRange the value to report at maximum travel
* @param expectedZero the reading where you would expect a 0 from get()
*/
DutyCycleEncoder(std::shared_ptr<DutyCycle> dutyCycle, double fullRange,
double expectedZero);
/**
* Construct a new DutyCycleEncoder attached to a DigitalSource object.
*
* @param digitalSource the digital source to attach to
* @param fullRange the value to report at maximum travel
* @param expectedZero the reading where you would expect a 0 from get()
*/
DutyCycleEncoder(DigitalSource& digitalSource, double fullRange,
double expectedZero);
/**
* Construct a new DutyCycleEncoder attached to a DigitalSource object.
*
* @param digitalSource the digital source to attach to
* @param fullRange the value to report at maximum travel
* @param expectedZero the reading where you would expect a 0 from get()
*/
DutyCycleEncoder(DigitalSource* digitalSource, double fullRange,
double expectedZero);
/**
* Construct a new DutyCycleEncoder attached to a DigitalSource object.
*
* @param digitalSource the digital source to attach to
* @param fullRange the value to report at maximum travel
* @param expectedZero the reading where you would expect a 0 from get()
*/
DutyCycleEncoder(std::shared_ptr<DigitalSource> digitalSource,
double fullRange, double expectedZero);
~DutyCycleEncoder() override = default;
DutyCycleEncoder(DutyCycleEncoder&&) = default;
@@ -108,52 +187,11 @@ class DutyCycleEncoder : public wpi::Sendable,
void SetConnectedFrequencyThreshold(int frequency);
/**
* Reset the Encoder distance to zero.
* Get the encoder value.
*
* @return the encoder value scaled by the full range input
*/
void Reset();
/**
* Get the encoder value since the last reset.
*
* This is reported in rotations since the last reset.
*
* @return the encoder value in rotations
*/
units::turn_t Get() const;
/**
* Get the absolute position of the duty cycle encoder encoder.
*
* <p>GetAbsolutePosition() - GetPositionOffset() will give an encoder
* absolute position relative to the last reset. This could potentially be
* negative, which needs to be accounted for.
*
* <p>This will not account for rollovers, and will always be just the raw
* absolute position.
*
* @return the absolute position
*/
double GetAbsolutePosition() const;
/**
* Get the offset of position relative to the last reset.
*
* GetAbsolutePosition() - GetPositionOffset() will give an encoder absolute
* position relative to the last reset. This could potentially be negative,
* which needs to be accounted for.
*
* @return the position offset
*/
double GetPositionOffset() const;
/**
* Set the position offset.
*
* <p>This must be in the range of 0-1.
*
* @param offset the offset
*/
void SetPositionOffset(double offset);
double Get() const;
/**
* Set the encoder duty cycle range. As the encoder needs to maintain a duty
@@ -171,32 +209,24 @@ class DutyCycleEncoder : public wpi::Sendable,
void SetDutyCycleRange(double min, double max);
/**
* Set the distance per rotation of the encoder. This sets the multiplier used
* to determine the distance driven based on the rotation value from the
* encoder. Set this value based on the how far the mechanism travels in 1
* rotation of the encoder, and factor in gearing reductions following the
* encoder shaft. This distance can be in any units you like, linear or
* angular.
* Sets the assumed frequency of the connected device.
*
* @param distancePerRotation the distance per rotation of the encoder
* <p>By default, the DutyCycle engine has to compute the frequency of the
* input signal. This can result in both delayed readings and jumpy readings.
* To solve this, you can pass the expected frequency of the sensor to this
* function. This will use that frequency to compute the DutyCycle percentage,
* rather than the computed frequency.
*
* @param frequency the assumed frequency of the sensor
*/
void SetDistancePerRotation(double distancePerRotation);
void SetAssumedFrequency(units::hertz_t frequency);
/**
* Get the distance per rotation for this encoder.
* Set if this encoder is inverted.
*
* @return The scale factor that will be used to convert rotation to useful
* units.
* @param inverted true to invert the encoder, false otherwise
*/
double GetDistancePerRotation() const;
/**
* Get the distance the sensor has driven since the last reset as scaled by
* the value from SetDistancePerRotation.
*
* @return The distance driven since the last reset
*/
double GetDistance() const;
void SetInverted(bool inverted);
/**
* Get the FPGA index for the DutyCycleEncoder.
@@ -215,23 +245,20 @@ class DutyCycleEncoder : public wpi::Sendable,
void InitSendable(wpi::SendableBuilder& builder) override;
private:
void Init();
void Init(double fullRange, double expectedZero);
double MapSensorRange(double pos) const;
std::shared_ptr<DutyCycle> m_dutyCycle;
std::unique_ptr<AnalogTrigger> m_analogTrigger;
std::unique_ptr<Counter> m_counter;
int m_frequencyThreshold = 100;
double m_positionOffset = 0;
double m_distancePerRotation = 1.0;
mutable units::turn_t m_lastPosition{0.0};
double m_sensorMin = 0;
double m_sensorMax = 1;
double m_fullRange;
double m_expectedZero;
units::second_t m_period{0_s};
double m_sensorMin{0.0};
double m_sensorMax{1.0};
bool m_isInverted{false};
hal::SimDevice m_simDevice;
hal::SimDouble m_simPosition;
hal::SimDouble m_simAbsolutePosition;
hal::SimDouble m_simDistancePerRotation;
hal::SimBoolean m_simIsConnected;
};
} // namespace frc

View File

@@ -28,28 +28,16 @@ class AnalogEncoderSim {
explicit AnalogEncoderSim(const AnalogEncoder& encoder);
/**
* Set the position using an Rotation2d.
* Set the position.
*
* @param angle The angle.
* @param value The position.
*/
void SetPosition(Rotation2d angle);
/**
* Set the position of the encoder.
*
* @param turns The position.
*/
void SetTurns(units::turn_t turns);
void Set(double value);
/**
* Get the simulated position.
*/
units::turn_t GetTurns();
/**
* Get the position as a Rotation2d.
*/
Rotation2d GetPosition();
double Get();
private:
hal::SimDouble m_positionSim;

View File

@@ -33,55 +33,18 @@ class DutyCycleEncoderSim {
explicit DutyCycleEncoderSim(int channel);
/**
* Get the position in turns.
* Get the position.
*
* @return The position.
*/
double Get();
/**
* Set the position in turns.
* Set the position.
*
* @param turns The position.
* @param value The position.
*/
void Set(units::turn_t turns);
/**
* Get the distance.
*
* @return The distance.
*/
double GetDistance();
/**
* Set the distance.
*
* @param distance The distance.
*/
void SetDistance(double distance);
/**
* Get the absolute position.
*
* @return The absolute position
*/
double GetAbsolutePosition();
/**
* Set the absolute position.
*
* @param position The absolute position
*/
void SetAbsolutePosition(double position);
/**
* Get the distance per rotation for this encoder.
*
* @return The scale factor that will be used to convert rotation to useful
* units.
*/
double GetDistancePerRotation();
void Set(double value);
/**
* Get if the encoder is connected.
@@ -99,8 +62,6 @@ class DutyCycleEncoderSim {
private:
hal::SimDouble m_simPosition;
hal::SimDouble m_simDistancePerRotation;
hal::SimDouble m_simAbsolutePosition;
hal::SimBoolean m_simIsConnected;
};