Moved C++ comments from source files to headers (#1111)

Also sorted functions in C++ sources to match order in related headers.
This commit is contained in:
Tyler Veness
2018-05-31 20:47:15 -07:00
committed by Peter Johnson
parent d9971a705a
commit 8c680a26f8
234 changed files with 9936 additions and 9309 deletions

View File

@@ -33,6 +33,13 @@ class ADXL345_I2C : public ErrorBase,
double ZAxis;
};
/**
* Constructs the ADXL345 Accelerometer over I2C.
*
* @param port The I2C port the accelerometer is attached to
* @param range The range (+ or -) that the accelerometer will measure
* @param deviceAddress The I2C address of the accelerometer (0x1D or 0x53)
*/
explicit ADXL345_I2C(I2C::Port port, Range range = kRange_2G,
int deviceAddress = kAddress);
~ADXL345_I2C() override = default;
@@ -46,7 +53,20 @@ class ADXL345_I2C : public ErrorBase,
double GetY() override;
double GetZ() override;
/**
* Get the acceleration of one axis in Gs.
*
* @param axis The axis to read from.
* @return Acceleration of the ADXL345 in Gs.
*/
virtual double GetAcceleration(Axes axis);
/**
* Get the acceleration of all axes in Gs.
*
* @return An object containing the acceleration measured on each axis of the
* ADXL345 in Gs.
*/
virtual AllAxes GetAccelerations();
void InitSendable(SendableBuilder& builder) override;

View File

@@ -32,7 +32,14 @@ class ADXL345_SPI : public ErrorBase,
double ZAxis;
};
/**
* Constructor.
*
* @param port The SPI port the accelerometer is attached to
* @param range The range (+ or -) that the accelerometer will measure
*/
explicit ADXL345_SPI(SPI::Port port, Range range = kRange_2G);
~ADXL345_SPI() override = default;
ADXL345_SPI(const ADXL345_SPI&) = delete;
@@ -44,7 +51,20 @@ class ADXL345_SPI : public ErrorBase,
double GetY() override;
double GetZ() override;
/**
* Get the acceleration of one axis in Gs.
*
* @param axis The axis to read from.
* @return Acceleration of the ADXL345 in Gs.
*/
virtual double GetAcceleration(Axes axis);
/**
* Get the acceleration of all axes in Gs.
*
* @return An object containing the acceleration measured on each axis of the
* ADXL345 in Gs.
*/
virtual AllAxes GetAccelerations();
void InitSendable(SendableBuilder& builder) override;

View File

@@ -29,8 +29,21 @@ class ADXL362 : public ErrorBase, public SendableBase, public Accelerometer {
};
public:
/**
* Constructor. Uses the onboard CS1.
*
* @param range The range (+ or -) that the accelerometer will measure.
*/
explicit ADXL362(Range range = kRange_2G);
/**
* Constructor.
*
* @param port The SPI port the accelerometer is attached to
* @param range The range (+ or -) that the accelerometer will measure.
*/
explicit ADXL362(SPI::Port port, Range range = kRange_2G);
virtual ~ADXL362() = default;
ADXL362(const ADXL362&) = delete;
@@ -42,7 +55,20 @@ class ADXL362 : public ErrorBase, public SendableBase, public Accelerometer {
double GetY() override;
double GetZ() override;
/**
* Get the acceleration of one axis in Gs.
*
* @param axis The axis to read from.
* @return Acceleration of the ADXL362 in Gs.
*/
virtual double GetAcceleration(Axes axis);
/**
* Get the acceleration of all axes in Gs.
*
* @return An object containing the acceleration measured on each axis of the
* ADXL362 in Gs.
*/
virtual AllAxes GetAccelerations();
void InitSendable(SendableBuilder& builder) override;

View File

@@ -28,13 +28,64 @@ namespace frc {
*/
class ADXRS450_Gyro : public GyroBase {
public:
/**
* Gyro constructor on onboard CS0.
*/
ADXRS450_Gyro();
/**
* Gyro constructor on the specified SPI port.
*
* @param port The SPI port the gyro is attached to.
*/
explicit ADXRS450_Gyro(SPI::Port port);
virtual ~ADXRS450_Gyro() = default;
/**
* Return the actual angle in degrees that the robot is currently facing.
*
* The angle is based on the current accumulator value corrected by the
* oversampling rate, the gyro type and the A/D calibration values.
* The angle is continuous, that is it will continue from 360->361 degrees.
* This allows algorithms that wouldn't want to see a discontinuity in the
* gyro output as it sweeps from 360 to 0 on the second time around.
*
* @return the current heading of the robot in degrees. This heading is based
* on integration of the returned rate from the gyro.
*/
double GetAngle() const override;
/**
* Return the rate of rotation of the gyro
*
* The rate is based on the most recent reading of the gyro analog value
*
* @return the current rate in degrees per second
*/
double GetRate() const override;
/**
* Reset the gyro.
*
* Resets the gyro to a heading of zero. This can be used if there is
* significant drift in the gyro and it needs to be recalibrated after it has
* been running.
*/
void Reset() override;
/**
* Initialize the gyro.
*
* Calibrate the gyro by running for a number of samples and computing the
* center value. Then use the center value as the Accumulator center value for
* subsequent measurements.
*
* It's important to make sure that the robot is not moving while the
* centering calculations are in progress, this is typically done when the
* robot is first turned on while it's sitting at rest before the competition
* starts.
*/
void Calibrate() override;
private:

View File

@@ -27,19 +27,85 @@ class AnalogAccelerometer : public ErrorBase,
public SendableBase,
public PIDSource {
public:
/**
* Create a new instance of an accelerometer.
*
* The constructor allocates desired analog input.
*
* @param channel The channel number for the analog input the accelerometer is
* connected to
*/
explicit AnalogAccelerometer(int channel);
/**
* Create a new instance of Accelerometer from an existing AnalogInput.
*
* Make a new instance of accelerometer given an AnalogInput. This is
* particularly useful if the port is going to be read as an analog channel as
* well as through the Accelerometer class.
*
* @param channel The existing AnalogInput object for the analog input the
* accelerometer is connected to
*/
explicit AnalogAccelerometer(AnalogInput* channel);
/**
* Create a new instance of Accelerometer from an existing AnalogInput.
*
* Make a new instance of accelerometer given an AnalogInput. This is
* particularly useful if the port is going to be read as an analog channel as
* well as through the Accelerometer class.
*
* @param channel The existing AnalogInput object for the analog input the
* accelerometer is connected to
*/
explicit AnalogAccelerometer(std::shared_ptr<AnalogInput> channel);
~AnalogAccelerometer() override = default;
/**
* Return the acceleration in Gs.
*
* The acceleration is returned units of Gs.
*
* @return The current acceleration of the sensor in Gs.
*/
double GetAcceleration() const;
/**
* Set the accelerometer sensitivity.
*
* This sets the sensitivity of the accelerometer used for calculating the
* acceleration. The sensitivity varies by accelerometer model. There are
* constants defined for various models.
*
* @param sensitivity The sensitivity of accelerometer in Volts per G.
*/
void SetSensitivity(double sensitivity);
/**
* Set the voltage that corresponds to 0 G.
*
* The zero G voltage varies by accelerometer model. There are constants
* defined for various models.
*
* @param zero The zero G voltage.
*/
void SetZero(double zero);
/**
* Get the Acceleration for the PID Source parent.
*
* @return The current acceleration in Gs.
*/
double PIDGet() override;
void InitSendable(SendableBuilder& builder) override;
private:
/**
* Common function for initializing the accelerometer.
*/
void InitAccelerometer();
std::shared_ptr<AnalogInput> m_analogInput;

View File

@@ -38,21 +38,147 @@ class AnalogGyro : public GyroBase {
static constexpr double kCalibrationSampleTime = 5.0;
static constexpr double kDefaultVoltsPerDegreePerSecond = 0.007;
/**
* Gyro constructor using the Analog Input channel number.
*
* @param channel The analog channel the gyro is connected to. Gyros can only
* be used on on-board Analog Inputs 0-1.
*/
explicit AnalogGyro(int channel);
/**
* Gyro constructor with a precreated AnalogInput object.
*
* Use this constructor when the analog channel needs to be shared.
* This object will not clean up the AnalogInput object when using this
* constructor.
*
* Gyros can only be used on on-board channels 0-1.
*
* @param channel A pointer to the AnalogInput object that the gyro is
* connected to.
*/
explicit AnalogGyro(AnalogInput* channel);
/**
* Gyro constructor with a precreated AnalogInput object.
*
* Use this constructor when the analog channel needs to be shared.
* This object will not clean up the AnalogInput object when using this
* constructor.
*
* @param channel A pointer to the AnalogInput object that the gyro is
* connected to.
*/
explicit AnalogGyro(std::shared_ptr<AnalogInput> channel);
/**
* Gyro constructor using the Analog Input channel number with parameters for
* presetting the center and offset values. Bypasses calibration.
*
* @param channel The analog channel the gyro is connected to. Gyros can only
* be used on on-board Analog Inputs 0-1.
* @param center Preset uncalibrated value to use as the accumulator center
* value.
* @param offset Preset uncalibrated value to use as the gyro offset.
*/
AnalogGyro(int channel, int center, double offset);
/**
* Gyro constructor with a precreated AnalogInput object and calibrated
* parameters.
*
* Use this constructor when the analog channel needs to be shared.
* This object will not clean up the AnalogInput object when using this
* constructor.
*
* @param channel A pointer to the AnalogInput object that the gyro is
* connected to.
* @param center Preset uncalibrated value to use as the accumulator center
* value.
* @param offset Preset uncalibrated value to use as the gyro offset.
*/
AnalogGyro(std::shared_ptr<AnalogInput> channel, int center, double offset);
virtual ~AnalogGyro();
/**
* Return the actual angle in degrees that the robot is currently facing.
*
* The angle is based on the current accumulator value corrected by the
* oversampling rate, the gyro type and the A/D calibration values. The angle
* is continuous, that is it will continue from 360->361 degrees. This allows
* algorithms that wouldn't want to see a discontinuity in the gyro output as
* it sweeps from 360 to 0 on the second time around.
*
* @return The current heading of the robot in degrees. This heading is based
* on integration of the returned rate from the gyro.
*/
double GetAngle() const override;
/**
* Return the rate of rotation of the gyro
*
* The rate is based on the most recent reading of the gyro analog value
*
* @return the current rate in degrees per second
*/
double GetRate() const override;
/**
* Return the gyro center value. If run after calibration,
* the center value can be used as a preset later.
*
* @return the current center value
*/
virtual int GetCenter() const;
/**
* Return the gyro offset value. If run after calibration,
* the offset value can be used as a preset later.
*
* @return the current offset value
*/
virtual double GetOffset() const;
/**
* Set the gyro sensitivity.
*
* This takes the number of volts/degree/second sensitivity of the gyro and
* uses it in subsequent calculations to allow the code to work with multiple
* gyros. This value is typically found in the gyro datasheet.
*
* @param voltsPerDegreePerSecond The sensitivity in Volts/degree/second
*/
void SetSensitivity(double voltsPerDegreePerSecond);
/**
* Set the size of the neutral zone.
*
* Any voltage from the gyro less than this amount from the center is
* considered stationary. Setting a deadband will decrease the amount of
* drift when the gyro isn't rotating, but will make it less accurate.
*
* @param volts The size of the deadband in volts
*/
void SetDeadband(double volts);
/**
* Reset the gyro.
*
* Resets the gyro to a heading of zero. This can be used if there is
* significant drift in the gyro and it needs to be recalibrated after it has
* been running.
*/
void Reset() override;
/**
* Initialize the gyro.
*
* Calibration is handled by Calibrate().
*/
virtual void InitGyro();
void Calibrate() override;
protected:

View File

@@ -38,38 +38,243 @@ class AnalogInput : public ErrorBase, public SendableBase, public PIDSource {
static constexpr int kAccumulatorNumChannels = 2;
static constexpr int kAccumulatorChannels[kAccumulatorNumChannels] = {0, 1};
/**
* Construct an analog input.
*
* @param channel The channel number on the roboRIO to represent. 0-3 are
* on-board 4-7 are on the MXP port.
*/
explicit AnalogInput(int channel);
~AnalogInput() override;
/**
* Get a sample straight from this channel.
*
* The sample is a 12-bit value representing the 0V to 5V range of the A/D
* converter in the module. The units are in A/D converter codes. Use
* GetVoltage() to get the analog value in calibrated units.
*
* @return A sample straight from this channel.
*/
int GetValue() const;
/**
* Get a sample from the output of the oversample and average engine for this
* channel.
*
* The sample is 12-bit + the bits configured in SetOversampleBits().
* The value configured in SetAverageBits() will cause this value to be
* averaged 2**bits number of samples.
*
* This is not a sliding window. The sample will not change until
* 2**(OversampleBits + AverageBits) samples have been acquired from the
* module on this channel.
*
* Use GetAverageVoltage() to get the analog value in calibrated units.
*
* @return A sample from the oversample and average engine for this channel.
*/
int GetAverageValue() const;
/**
* Get a scaled sample straight from this channel.
*
* The value is scaled to units of Volts using the calibrated scaling data
* from GetLSBWeight() and GetOffset().
*
* @return A scaled sample straight from this channel.
*/
double GetVoltage() const;
/**
* Get a scaled sample from the output of the oversample and average engine
* for this channel.
*
* The value is scaled to units of Volts using the calibrated scaling data
* from GetLSBWeight() and GetOffset().
*
* Using oversampling will cause this value to be higher resolution, but it
* will update more slowly.
*
* Using averaging will cause this value to be more stable, but it will update
* more slowly.
*
* @return A scaled sample from the output of the oversample and average
* engine for this channel.
*/
double GetAverageVoltage() const;
/**
* Get the channel number.
*
* @return The channel number.
*/
int GetChannel() const;
/**
* Set the number of averaging bits.
*
* This sets the number of averaging bits. The actual number of averaged
* samples is 2^bits.
*
* Use averaging to improve the stability of your measurement at the expense
* of sampling rate. The averaging is done automatically in the FPGA.
*
* @param bits Number of bits of averaging.
*/
void SetAverageBits(int bits);
/**
* Get the number of averaging bits previously configured.
*
* This gets the number of averaging bits from the FPGA. The actual number of
* averaged samples is 2^bits. The averaging is done automatically in the
* FPGA.
*
* @return Number of bits of averaging previously configured.
*/
int GetAverageBits() const;
/**
* Set the number of oversample bits.
*
* This sets the number of oversample bits. The actual number of oversampled
* values is 2^bits. Use oversampling to improve the resolution of your
* measurements at the expense of sampling rate. The oversampling is done
* automatically in the FPGA.
*
* @param bits Number of bits of oversampling.
*/
void SetOversampleBits(int bits);
/**
* Get the number of oversample bits previously configured.
*
* This gets the number of oversample bits from the FPGA. The actual number of
* oversampled values is 2^bits. The oversampling is done automatically in the
* FPGA.
*
* @return Number of bits of oversampling previously configured.
*/
int GetOversampleBits() const;
/**
* Get the factory scaling least significant bit weight constant.
*
* Volts = ((LSB_Weight * 1e-9) * raw) - (Offset * 1e-9)
*
* @return Least significant bit weight.
*/
int GetLSBWeight() const;
/**
* Get the factory scaling offset constant.
*
* Volts = ((LSB_Weight * 1e-9) * raw) - (Offset * 1e-9)
*
* @return Offset constant.
*/
int GetOffset() const;
/**
* Is the channel attached to an accumulator.
*
* @return The analog input is attached to an accumulator.
*/
bool IsAccumulatorChannel() const;
/**
* Initialize the accumulator.
*/
void InitAccumulator();
/**
* Set an initial value for the accumulator.
*
* This will be added to all values returned to the user.
*
* @param initialValue The value that the accumulator should start from when
* reset.
*/
void SetAccumulatorInitialValue(int64_t value);
/**
* Resets the accumulator to the initial value.
*/
void ResetAccumulator();
/**
* Set the center value of the accumulator.
*
* The center value is subtracted from each A/D value before it is added to
* the accumulator. This is used for the center value of devices like gyros
* and accelerometers to take the device offset into account when integrating.
*
* This center value is based on the output of the oversampled and averaged
* source from the accumulator channel. Because of this, any non-zero
* oversample bits will affect the size of the value for this field.
*/
void SetAccumulatorCenter(int center);
/**
* Set the accumulator's deadband.
*/
void SetAccumulatorDeadband(int deadband);
/**
* Read the accumulated value.
*
* Read the value that has been accumulating.
* The accumulator is attached after the oversample and average engine.
*
* @return The 64-bit value accumulated since the last Reset().
*/
int64_t GetAccumulatorValue() const;
/**
* Read the number of accumulated values.
*
* Read the count of the accumulated values since the accumulator was last
* Reset().
*
* @return The number of times samples from the channel were accumulated.
*/
int64_t GetAccumulatorCount() const;
/**
* Read the accumulated value and the number of accumulated values atomically.
*
* This function reads the value and count from the FPGA atomically.
* This can be used for averaging.
*
* @param value Reference to the 64-bit accumulated output.
* @param count Reference to the number of accumulation cycles.
*/
void GetAccumulatorOutput(int64_t& value, int64_t& count) const;
/**
* Set the sample rate per channel for all analog channels.
*
* The maximum rate is 500kS/s divided by the number of channels in use.
* This is 62500 samples/s per channel.
*
* @param samplesPerSecond The number of samples per second.
*/
static void SetSampleRate(double samplesPerSecond);
/**
* Get the current sample rate for all channels
*
* @return Sample rate.
*/
static double GetSampleRate();
/**
* Get the Average value for the PID Source base object.
*
* @return The average voltage.
*/
double PIDGet() override;
void InitSendable(SendableBuilder& builder) override;

View File

@@ -19,11 +19,34 @@ namespace frc {
*/
class AnalogOutput : public ErrorBase, public SendableBase {
public:
/**
* Construct an analog output on the given channel.
*
* All analog outputs are located on the MXP port.
*
* @param channel The channel number on the roboRIO to represent.
*/
explicit AnalogOutput(int channel);
~AnalogOutput() override;
/**
* Set the value of the analog output.
*
* @param voltage The output value in Volts, from 0.0 to +5.0
*/
void SetVoltage(double voltage);
/**
* Get the voltage of the analog output
*
* @return The value in Volts, from 0.0 to +5.0
*/
double GetVoltage() const;
/**
* Get the channel of this AnalogOutput.
*/
int GetChannel();
void InitSendable(SendableBuilder& builder) override;

View File

@@ -27,7 +27,7 @@ class AnalogPotentiometer : public ErrorBase,
public Potentiometer {
public:
/**
* AnalogPotentiometer constructor.
* Construct an Analog Potentiometer object from a channel number.
*
* Use the fullRange and offset values so that the output produces meaningful
* values. I.E: you have a 270 degree potentiometer and you want the output to
@@ -38,18 +38,57 @@ class AnalogPotentiometer : public ErrorBase,
* This will calculate the result from the fullRange times the fraction of the
* supply voltage, plus the offset.
*
* @param channel The analog channel this potentiometer is plugged into.
* @param fullRange The scaling to multiply the voltage by to get a meaningful
* unit.
* @param offset The offset to add to the scaled value for controlling the
* zero value.
* @param channel The channel number on the roboRIO to represent. 0-3 are
* on-board 4-7 are on the MXP port.
* @param fullRange The angular value (in desired units) representing the full
* 0-5V range of the input.
* @param offset The angular value (in desired units) representing the
* angular output at 0V.
*/
explicit AnalogPotentiometer(int channel, double fullRange = 1.0,
double offset = 0.0);
/**
* Construct an Analog Potentiometer object from an existing Analog Input
* pointer.
*
* Use the fullRange and offset values so that the output produces meaningful
* values. I.E: you have a 270 degree potentiometer and you want the output to
* be degrees with the halfway point as 0 degrees. The fullRange value is
* 270.0 degrees and the offset is -135.0 since the halfway point after
* scaling is 135 degrees.
*
* This will calculate the result from the fullRange times the fraction of the
* supply voltage, plus the offset.
*
* @param channel The existing Analog Input pointer
* @param fullRange The angular value (in desired units) representing the full
* 0-5V range of the input.
* @param offset The angular value (in desired units) representing the
* angular output at 0V.
*/
explicit AnalogPotentiometer(AnalogInput* input, double fullRange = 1.0,
double offset = 0.0);
/**
* Construct an Analog Potentiometer object from an existing Analog Input
* pointer.
*
* Use the fullRange and offset values so that the output produces meaningful
* values. I.E: you have a 270 degree potentiometer and you want the output to
* be degrees with the halfway point as 0 degrees. The fullRange value is
* 270.0 degrees and the offset is -135.0 since the halfway point after
* scaling is 135 degrees.
*
* This will calculate the result from the fullRange times the fraction of the
* supply voltage, plus the offset.
*
* @param channel The existing Analog Input pointer
* @param fullRange The angular value (in desired units) representing the full
* 0-5V range of the input.
* @param offset The angular value (in desired units) representing the
* angular output at 0V.
*/
explicit AnalogPotentiometer(std::shared_ptr<AnalogInput> input,
double fullRange = 1.0, double offset = 0.0);
@@ -58,7 +97,8 @@ class AnalogPotentiometer : public ErrorBase,
/**
* Get the current reading of the potentiomer.
*
* @return The current position of the potentiometer.
* @return The current position of the potentiometer (in the units used for
* fullRange and offset).
*/
double Get() const override;

View File

@@ -23,17 +23,109 @@ class AnalogTrigger : public ErrorBase, public SendableBase {
friend class AnalogTriggerOutput;
public:
/**
* Constructor for an analog trigger given a channel number.
*
* @param channel The channel number on the roboRIO to represent. 0-3 are
* on-board 4-7 are on the MXP port.
*/
explicit AnalogTrigger(int channel);
/**
* Construct an analog trigger given an analog input.
*
* This should be used in the case of sharing an analog channel between the
* trigger and an analog input object.
*
* @param channel The pointer to the existing AnalogInput object
*/
explicit AnalogTrigger(AnalogInput* channel);
~AnalogTrigger() override;
/**
* Set the upper and lower limits of the analog trigger.
*
* The limits are given as floating point voltage values.
*
* @param lower The lower limit of the trigger in Volts.
* @param upper The upper limit of the trigger in Volts.
*/
void SetLimitsVoltage(double lower, double upper);
/**
* Set the upper and lower limits of the analog trigger.
*
* The limits are given in ADC codes. If oversampling is used, the units must
* be scaled appropriately.
*
* @param lower The lower limit of the trigger in ADC codes (12-bit values).
* @param upper The upper limit of the trigger in ADC codes (12-bit values).
*/
void SetLimitsRaw(int lower, int upper);
/**
* Configure the analog trigger to use the averaged vs. raw values.
*
* If the value is true, then the averaged value is selected for the analog
* trigger, otherwise the immediate value is used.
*
* @param useAveragedValue If true, use the Averaged value, otherwise use the
* instantaneous reading
*/
void SetAveraged(bool useAveragedValue);
/**
* Configure the analog trigger to use a filtered value.
*
* The analog trigger will operate with a 3 point average rejection filter.
* This is designed to help with 360 degree pot applications for the period
* where the pot crosses through zero.
*
* @param useFilteredValue If true, use the 3 point rejection filter,
* otherwise use the unfiltered value
*/
void SetFiltered(bool useFilteredValue);
/**
* Return the index of the analog trigger.
*
* This is the FPGA index of this analog trigger instance.
*
* @return The index of the analog trigger.
*/
int GetIndex() const;
/**
* Return the InWindow output of the analog trigger.
*
* True if the analog input is between the upper and lower limits.
*
* @return True if the analog input is between the upper and lower limits.
*/
bool GetInWindow();
/**
* Return the TriggerState output of the analog trigger.
*
* True if above upper limit.
* False if below lower limit.
* If in Hysteresis, maintain previous state.
*
* @return True if above upper limit. False if below lower limit. If in
* Hysteresis, maintain previous state.
*/
bool GetTriggerState();
/**
* Creates an AnalogTriggerOutput object.
*
* Gets an output object that can be used for routing. Caller is responsible
* for deleting the AnalogTriggerOutput object.
*
* @param type An enum of the type of output object to create.
* @return A pointer to a new AnalogTriggerOutput object.
*/
std::shared_ptr<AnalogTriggerOutput> CreateOutput(
AnalogTriggerType type) const;

View File

@@ -51,17 +51,49 @@ class AnalogTriggerOutput : public DigitalSource {
public:
~AnalogTriggerOutput() override;
/**
* Get the state of the analog trigger output.
*
* @return The state of the analog trigger output.
*/
bool Get() const;
// DigitalSource interface
/**
* @return The HAL Handle to the specified source.
*/
HAL_Handle GetPortHandleForRouting() const override;
/**
* @return The type of analog trigger output to be used.
*/
AnalogTriggerType GetAnalogTriggerTypeForRouting() const override;
/**
* Is source an AnalogTrigger
*/
bool IsAnalogTrigger() const override;
/**
* @return The channel of the source.
*/
int GetChannel() const override;
void InitSendable(SendableBuilder& builder) override;
protected:
/**
* Create an object that represents one of the four outputs from an analog
* trigger.
*
* Because this class derives from DigitalSource, it can be passed into
* routing functions for Counter, Encoder, etc.
*
* @param trigger A pointer to the trigger for which this is an output.
* @param outputType An enum that specifies the output on the trigger to
* represent.
*/
AnalogTriggerOutput(const AnalogTrigger& trigger,
AnalogTriggerType outputType);

View File

@@ -22,12 +22,36 @@ class BuiltInAccelerometer : public ErrorBase,
public SendableBase,
public Accelerometer {
public:
/**
* Constructor.
*
* @param range The range the accelerometer will measure
*/
explicit BuiltInAccelerometer(Range range = kRange_8G);
// Accelerometer interface
/**
* Set the measuring range of the accelerometer.
*
* @param range The maximum acceleration, positive or negative, that the
* accelerometer will measure. Not all accelerometers support all
* ranges.
*/
void SetRange(Range range) override;
/**
* @return The acceleration of the roboRIO along the X axis in g-forces
*/
double GetX() override;
/**
* @return The acceleration of the roboRIO along the Y axis in g-forces
*/
double GetY() override;
/**
* @return The acceleration of the roboRIO along the Z axis in g-forces
*/
double GetZ() override;
void InitSendable(SendableBuilder& builder) override;

View File

@@ -25,10 +25,44 @@ namespace frc {
*/
class Button : public Trigger {
public:
/**
* Specifies the command to run when a button is first pressed.
*
* @param command The pointer to the command to run
*/
virtual void WhenPressed(Command* command);
/**
* Specifies the command to be scheduled while the button is pressed.
*
* The command will be scheduled repeatedly while the button is pressed and
* will be canceled when the button is released.
*
* @param command The pointer to the command to run
*/
virtual void WhileHeld(Command* command);
/**
* Specifies the command to run when the button is released.
*
* The command will be scheduled a single time.
*
* @param command The pointer to the command to run
*/
virtual void WhenReleased(Command* command);
/**
* Cancels the specificed command when the button is pressed.
*
* @param command The command to be canceled
*/
virtual void CancelWhenPressed(Command* command);
/**
* Toggle the specified command when the button is pressed.
*
* @param command The command to be toggled
*/
virtual void ToggleWhenPressed(Command* command);
};

View File

@@ -33,17 +33,92 @@ struct CANData {
*/
class CAN : public ErrorBase {
public:
/**
* Create a new CAN communication interface with the specific device ID.
* The device ID is 6 bits (0-63)
*/
explicit CAN(int deviceId);
/**
* Closes the CAN communication.
*/
~CAN() override;
/**
* Write a packet to the CAN device with a specific ID. This ID is 10 bits.
*
* @param data The data to write (8 bytes max)
* @param length The data length to write
* @param apiId The API ID to write.
*/
void WritePacket(const uint8_t* data, int length, int apiId);
/**
* Write a repeating packet to the CAN device with a specific ID. This ID is
* 10 bits. The RoboRIO will automatically repeat the packet at the specified
* interval
*
* @param data The data to write (8 bytes max)
* @param length The data length to write
* @param apiId The API ID to write.
* @param repeatMs The period to repeat the packet at.
*/
void WritePacketRepeating(const uint8_t* data, int length, int apiId,
int repeatMs);
/**
* Stop a repeating packet with a specific ID. This ID is 10 bits.
*
* @param apiId The API ID to stop repeating
*/
void StopPacketRepeating(int apiId);
/**
* Read a new CAN packet. This will only return properly once per packet
* received. Multiple calls without receiving another packet will return
* false.
*
* @param apiId The API ID to read.
* @param data Storage for the received data.
* @return True if the data is valid, otherwise false.
*/
bool ReadPacketNew(int apiId, CANData* data);
/**
* Read a CAN packet. The will continuously return the last packet received,
* without accounting for packet age.
*
* @param apiId The API ID to read.
* @param data Storage for the received data.
* @return True if the data is valid, otherwise false.
*/
bool ReadPacketLatest(int apiId, CANData* data);
/**
* Read a CAN packet. The will return the last packet received until the
* packet is older then the requested timeout. Then it will return false.
*
* @param apiId The API ID to read.
* @param timeoutMs The timeout time for the packet
* @param data Storage for the received data.
* @return True if the data is valid, otherwise false.
*/
bool ReadPacketTimeout(int apiId, int timeoutMs, CANData* data);
/**
* Read a CAN packet. The will return the last packet received until the
* packet is older then the requested timeout. Then it will return false. The
* period parameter is used when you know the packet is sent at specific
* intervals, so calls will not attempt to read a new packet from the network
* until that period has passed. We do not recommend users use this API unless
* they know the implications.
*
* @param apiId The API ID to read.
* @param timeoutMs The timeout time for the packet
* @param periodMs The usual period for the packet
* @param data Storage for the received data.
* @return True if the data is valid, otherwise false.
*/
bool ReadPeriodicPacket(int apiId, int timeoutMs, int periodMs,
CANData* data);

View File

@@ -50,39 +50,251 @@ class Command : public ErrorBase, public SendableBase {
friend class Scheduler;
public:
/**
* Creates a new command.
*
* The name of this command will be default.
*/
Command();
/**
* Creates a new command with the given name and no timeout.
*
* @param name the name for this command
*/
explicit Command(const wpi::Twine& name);
/**
* Creates a new command with the given timeout and a default name.
*
* @param timeout the time (in seconds) before this command "times out"
* @see IsTimedOut()
*/
explicit Command(double timeout);
/**
* Creates a new command with the given name and timeout.
*
* @param name the name of the command
* @param timeout the time (in seconds) before this command "times out"
* @see IsTimedOut()
*/
Command(const wpi::Twine& name, double timeout);
~Command() override = default;
/**
* Returns the time since this command was initialized (in seconds).
*
* This function will work even if there is no specified timeout.
*
* @return the time since this command was initialized (in seconds).
*/
double TimeSinceInitialized() const;
/**
* This method specifies that the given Subsystem is used by this command.
*
* This method is crucial to the functioning of the Command System in general.
*
* Note that the recommended way to call this method is in the constructor.
*
* @param subsystem The Subsystem required
* @see Subsystem
*/
void Requires(Subsystem* s);
bool IsCanceled() const;
/**
* Starts up the command. Gets the command ready to start.
*
* Note that the command will eventually start, however it will not
* necessarily do so immediately, and may in fact be canceled before
* initialize is even called.
*/
void Start();
/**
* The run method is used internally to actually run the commands.
*
* @return Whether or not the command should stay within the Scheduler.
*/
bool Run();
/**
* This will cancel the current command.
*
* This will cancel the current command eventually. It can be called multiple
* times. And it can be called when the command is not running. If the command
* is running though, then the command will be marked as canceled and
* eventually removed.
*
* A command can not be canceled if it is a part of a command group, you must
* cancel the command group instead.
*/
void Cancel();
/**
* Returns whether or not the command is running.
*
* This may return true even if the command has just been canceled, as it may
* not have yet called Interrupted().
*
* @return whether or not the command is running
*/
bool IsRunning() const;
/**
* Returns whether or not the command has been initialized.
*
* @return whether or not the command has been initialized.
*/
bool IsInitialized() const;
/**
* Returns whether or not the command has completed running.
*
* @return whether or not the command has completed running.
*/
bool IsCompleted() const;
/**
* Returns whether or not this has been canceled.
*
* @return whether or not this has been canceled
*/
bool IsCanceled() const;
/**
* Returns whether or not this command can be interrupted.
*
* @return whether or not this command can be interrupted
*/
bool IsInterruptible() const;
/**
* Sets whether or not this command can be interrupted.
*
* @param interruptible whether or not this command can be interrupted
*/
void SetInterruptible(bool interruptible);
/**
* Checks if the command requires the given Subsystem.
*
* @param system the system
* @return whether or not the subsystem is required (false if given nullptr)
*/
bool DoesRequire(Subsystem* subsystem) const;
typedef std::set<Subsystem*> SubsystemSet;
/**
* Returns the requirements (as an std::set of Subsystem pointers) of this
* command.
*
* @return The requirements (as an std::set of Subsystem pointers) of this
* command
*/
SubsystemSet GetRequirements() const;
/**
* Returns the CommandGroup that this command is a part of.
*
* Will return null if this Command is not in a group.
*
* @return The CommandGroup that this command is a part of (or null if not in
* group)
*/
CommandGroup* GetGroup() const;
/**
* Sets whether or not this Command should run when the robot is disabled.
*
* By default a command will not run when the robot is disabled, and will in
* fact be canceled.
*
* @param run Whether this command should run when the robot is disabled.
*/
void SetRunWhenDisabled(bool run);
/**
* Returns whether or not this Command will run when the robot is disabled, or
* if it will cancel itself.
*
* @return Whether this Command will run when the robot is disabled, or if it
* will cancel itself.
*/
bool WillRunWhenDisabled() const;
/**
* Get the ID (sequence number) for this command.
*
* The ID is a unique sequence number that is incremented for each command.
*
* @return The ID of this command
*/
int GetID() const;
protected:
/**
* Sets the timeout of this command.
*
* @param timeout the timeout (in seconds)
* @see IsTimedOut()
*/
void SetTimeout(double timeout);
/**
* Returns whether or not the TimeSinceInitialized() method returns a number
* which is greater than or equal to the timeout for the command.
*
* If there is no timeout, this will always return false.
*
* @return whether the time has expired
*/
bool IsTimedOut() const;
/**
* If changes are locked, then this will generate a CommandIllegalUse error.
*
* @param message The message to report on error (it is appended by a default
* message)
* @return True if assert passed, false if assert failed.
*/
bool AssertUnlocked(const std::string& message);
/**
* Sets the parent of this command. No actual change is made to the group.
*
* @param parent the parent
*/
void SetParent(CommandGroup* parent);
/**
* Returns whether the command has a parent.
*
* @param True if the command has a parent.
*/
bool IsParented() const;
/**
* Clears list of subsystem requirements.
*
* This is only used by ConditionalCommand so cancelling the chosen command
* works properly in CommandGroup.
*/
void ClearRequirements();
/**
* The initialize method is called the first time this Command is run after
* being started.
*/
virtual void Initialize();
/**
* The execute method is called repeatedly until this Command either finishes
* or is canceled.
*/
virtual void Execute();
/**
@@ -103,21 +315,72 @@ class Command : public ErrorBase, public SendableBase {
*/
virtual bool IsFinished() = 0;
/**
* Called when the command ended peacefully.
*
* This is where you may want to wrap up loose ends, like shutting off a motor
* that was being used in the command.
*/
virtual void End();
/**
* Called when the command ends because somebody called Cancel() or another
* command shared the same requirements as this one, and booted it out.
*
* This is where you may want to wrap up loose ends, like shutting off a motor
* that was being used in the command.
*
* Generally, it is useful to simply call the End() method within this method,
* as done here.
*/
virtual void Interrupted();
virtual void _Initialize();
virtual void _Interrupted();
virtual void _Execute();
virtual void _End();
/**
* This works like Cancel(), except that it doesn't throw an exception if it
* is a part of a command group.
*
* Should only be called by the parent command group.
*/
virtual void _Cancel();
friend class ConditionalCommand;
private:
/**
* Prevents further changes from being made.
*/
void LockChanges();
/**
* Called when the command has been removed.
*
* This will call Interrupted() or End().
*/
void Removed();
/**
* This is used internally to mark that the command has been started.
*
* The lifecycle of a command is:
*
* StartRunning() is called. Run() is called (multiple times potentially).
* Removed() is called.
*
* It is very important that StartRunning() and Removed() be called in order
* or some assumptions of the code will be broken.
*/
void StartRunning();
/**
* Called to indicate that the timer should start.
*
* This is called right before Initialize() is, inside the Run() method.
*/
void StartTiming();
// The time since this command was initialized

View File

@@ -37,26 +37,130 @@ namespace frc {
class CommandGroup : public Command {
public:
CommandGroup() = default;
/**
* Creates a new CommandGroup with the given name.
*
* @param name The name for this command group
*/
explicit CommandGroup(const wpi::Twine& name);
virtual ~CommandGroup() = default;
/**
* Adds a new Command to the group. The Command will be started after all the
* previously added Commands.
*
* Note that any requirements the given Command has will be added to the
* group. For this reason, a Command's requirements can not be changed after
* being added to a group.
*
* It is recommended that this method be called in the constructor.
*
* @param command The Command to be added
*/
void AddSequential(Command* command);
/**
* Adds a new Command to the group with a given timeout. The Command will be
* started after all the previously added commands.
*
* Once the Command is started, it will be run until it finishes or the time
* expires, whichever is sooner. Note that the given Command will have no
* knowledge that it is on a timer.
*
* Note that any requirements the given Command has will be added to the
* group. For this reason, a Command's requirements can not be changed after
* being added to a group.
*
* It is recommended that this method be called in the constructor.
*
* @param command The Command to be added
* @param timeout The timeout (in seconds)
*/
void AddSequential(Command* command, double timeout);
/**
* Adds a new child Command to the group. The Command will be started after
* all the previously added Commands.
*
* Instead of waiting for the child to finish, a CommandGroup will have it run
* at the same time as the subsequent Commands. The child will run until
* either it finishes, a new child with conflicting requirements is started,
* or the main sequence runs a Command with conflicting requirements. In the
* latter two cases, the child will be canceled even if it says it can't be
* interrupted.
*
* Note that any requirements the given Command has will be added to the
* group. For this reason, a Command's requirements can not be changed after
* being added to a group.
*
* It is recommended that this method be called in the constructor.
*
* @param command The command to be added
*/
void AddParallel(Command* command);
/**
* Adds a new child Command to the group with the given timeout. The Command
* will be started after all the previously added Commands.
*
* Once the Command is started, it will run until it finishes, is interrupted,
* or the time expires, whichever is sooner. Note that the given Command will
* have no knowledge that it is on a timer.
*
* Instead of waiting for the child to finish, a CommandGroup will have it run
* at the same time as the subsequent Commands. The child will run until
* either it finishes, the timeout expires, a new child with conflicting
* requirements is started, or the main sequence runs a Command with
* conflicting requirements. In the latter two cases, the child will be
* canceled even if it says it can't be interrupted.
*
* Note that any requirements the given Command has will be added to the
* group. For this reason, a Command's requirements can not be changed after
* being added to a group.
*
* It is recommended that this method be called in the constructor.
*
* @param command The command to be added
* @param timeout The timeout (in seconds)
*/
void AddParallel(Command* command, double timeout);
bool IsInterruptible() const;
int GetSize() const;
protected:
/**
* Can be overridden by teams.
*/
virtual void Initialize();
/**
* Can be overridden by teams.
*/
virtual void Execute();
/**
* Can be overridden by teams.
*/
virtual bool IsFinished();
/**
* Can be overridden by teams.
*/
virtual void End();
/**
* Can be overridden by teams.
*/
virtual void Interrupted();
virtual void _Initialize();
virtual void _Interrupted();
virtual void _Execute();
virtual void _End();
virtual void _Interrupted();
private:
void CancelConflicts(Command* command);

View File

@@ -34,9 +34,24 @@ namespace frc {
*/
class ConditionalCommand : public Command {
public:
/**
* Creates a new ConditionalCommand with given onTrue and onFalse Commands.
*
* @param onTrue The Command to execute if Condition() returns true
* @param onFalse The Command to execute if Condition() returns false
*/
explicit ConditionalCommand(Command* onTrue, Command* onFalse = nullptr);
/**
* Creates a new ConditionalCommand with given onTrue and onFalse Commands.
*
* @param name The name for this command group
* @param onTrue The Command to execute if Condition() returns true
* @param onFalse The Command to execute if Condition() returns false
*/
ConditionalCommand(const wpi::Twine& name, Command* onTrue,
Command* onFalse = nullptr);
virtual ~ConditionalCommand() = default;
protected:

View File

@@ -20,7 +20,13 @@ namespace frc {
*/
class InstantCommand : public Command {
public:
/**
* Creates a new InstantCommand with the given name.
*
* @param name The name for this command
*/
explicit InstantCommand(const wpi::Twine& name);
InstantCommand() = default;
virtual ~InstantCommand() = default;

View File

@@ -29,36 +29,197 @@ namespace frc {
*/
class PIDSubsystem : public Subsystem, public PIDOutput, public PIDSource {
public:
/**
* Instantiates a PIDSubsystem that will use the given P, I, and D values.
*
* @param name the name
* @param p the proportional value
* @param i the integral value
* @param d the derivative value
*/
PIDSubsystem(const wpi::Twine& name, double p, double i, double d);
/**
* Instantiates a PIDSubsystem that will use the given P, I, and D values.
*
* @param name the name
* @param p the proportional value
* @param i the integral value
* @param d the derivative value
* @param f the feedforward value
*/
PIDSubsystem(const wpi::Twine& name, double p, double i, double d, double f);
/**
* Instantiates a PIDSubsystem that will use the given P, I, and D values.
*
* It will also space the time between PID loop calculations to be equal to
* the given period.
*
* @param name the name
* @param p the proportional value
* @param i the integral value
* @param d the derivative value
* @param f the feedfoward value
* @param period the time (in seconds) between calculations
*/
PIDSubsystem(const wpi::Twine& name, double p, double i, double d, double f,
double period);
/**
* Instantiates a PIDSubsystem that will use the given P, I, and D values.
*
* It will use the class name as its name.
*
* @param p the proportional value
* @param i the integral value
* @param d the derivative value
*/
PIDSubsystem(double p, double i, double d);
/**
* Instantiates a PIDSubsystem that will use the given P, I, and D values.
*
* It will use the class name as its name.
*
* @param p the proportional value
* @param i the integral value
* @param d the derivative value
* @param f the feedforward value
*/
PIDSubsystem(double p, double i, double d, double f);
/**
* Instantiates a PIDSubsystem that will use the given P, I, and D values.
*
* It will use the class name as its name. It will also space the time
* between PID loop calculations to be equal to the given period.
*
* @param p the proportional value
* @param i the integral value
* @param d the derivative value
* @param f the feedforward value
* @param period the time (in seconds) between calculations
*/
PIDSubsystem(double p, double i, double d, double f, double period);
~PIDSubsystem() override = default;
/**
* Enables the internal PIDController.
*/
void Enable();
/**
* Disables the internal PIDController.
*/
void Disable();
// PIDOutput interface
void PIDWrite(double output) override;
// PIDSource interface
double PIDGet() override;
/**
* Sets the setpoint to the given value.
*
* If SetRange() was called, then the given setpoint will be trimmed to fit
* within the range.
*
* @param setpoint the new setpoint
*/
void SetSetpoint(double setpoint);
/**
* Adds the given value to the setpoint.
*
* If SetRange() was used, then the bounds will still be honored by this
* method.
*
* @param deltaSetpoint the change in the setpoint
*/
void SetSetpointRelative(double deltaSetpoint);
/**
* Sets the maximum and minimum values expected from the input.
*
* @param minimumInput the minimum value expected from the input
* @param maximumInput the maximum value expected from the output
*/
void SetInputRange(double minimumInput, double maximumInput);
/**
* Sets the maximum and minimum values to write.
*
* @param minimumOutput the minimum value to write to the output
* @param maximumOutput the maximum value to write to the output
*/
void SetOutputRange(double minimumOutput, double maximumOutput);
/**
* Return the current setpoint.
*
* @return The current setpoint
*/
double GetSetpoint();
/**
* Returns the current position.
*
* @return the current position
*/
double GetPosition();
/**
* Returns the current rate.
*
* @return the current rate
*/
double GetRate();
/**
* Set the absolute error which is considered tolerable for use with
* OnTarget.
*
* @param absValue absolute error which is tolerable
*/
virtual void SetAbsoluteTolerance(double absValue);
/**
* Set the percentage error which is considered tolerable for use with
* OnTarget().
*
* @param percent percentage error which is tolerable
*/
virtual void SetPercentTolerance(double percent);
/**
* Return true if the error is within the percentage of the total input range,
* determined by SetTolerance().
*
* This asssumes that the maximum and minimum input were set using SetInput().
* Use OnTarget() in the IsFinished() method of commands that use this
* subsystem.
*
* Currently this just reports on target as the actual value passes through
* the setpoint. Ideally it should be based on being within the tolerance for
* some period of time.
*
* @return True if the error is within the percentage tolerance of the input
* range
*/
virtual bool OnTarget() const;
protected:
/**
* Returns the PIDController used by this PIDSubsystem.
*
* Use this if you would like to fine tune the PID loop.
*
* @return The PIDController used by this PIDSubsystem
*/
std::shared_ptr<PIDController> GetPIDController();
virtual double ReturnPIDInput() = 0;

View File

@@ -26,15 +26,65 @@ class Subsystem;
class Scheduler : public ErrorBase, public SendableBase {
public:
/**
* Returns the Scheduler, creating it if one does not exist.
*
* @return the Scheduler
*/
static Scheduler* GetInstance();
/**
* Add a command to be scheduled later.
*
* In any pass through the scheduler, all commands are added to the additions
* list, then at the end of the pass, they are all scheduled.
*
* @param command The command to be scheduled
*/
void AddCommand(Command* command);
void AddButton(ButtonScheduler* button);
/**
* Registers a Subsystem to this Scheduler, so that the Scheduler might know
* if a default Command needs to be run.
*
* All Subsystems should call this.
*
* @param system the system
*/
void RegisterSubsystem(Subsystem* subsystem);
/**
* Runs a single iteration of the loop.
*
* This method should be called often in order to have a functioning
* Command system. The loop has five stages:
*
* <ol>
* <li>Poll the Buttons</li>
* <li>Execute/Remove the Commands</li>
* <li>Send values to SmartDashboard</li>
* <li>Add Commands</li>
* <li>Add Defaults</li>
* </ol>
*/
void Run();
/**
* Removes the Command from the Scheduler.
*
* @param command the command to remove
*/
void Remove(Command* command);
void RemoveAll();
/**
* Completely resets the scheduler. Undefined behavior if running.
*/
void ResetAll();
void SetEnabled(bool enabled);
void InitSendable(SendableBuilder& builder) override;

View File

@@ -24,25 +24,133 @@ class Subsystem : public ErrorBase, public SendableBase {
friend class Scheduler;
public:
/**
* Creates a subsystem with the given name.
*
* @param name the name of the subsystem
*/
explicit Subsystem(const wpi::Twine& name);
/**
* Sets the default command. If this is not called or is called with null,
* then there will be no default command for the subsystem.
*
* <b>WARNING:</b> This should <b>NOT</b> be called in a constructor if the
* subsystem is a singleton.
*
* @param command the default command (or null if there should be none)
*/
void SetDefaultCommand(Command* command);
/**
* Returns the default command (or null if there is none).
*
* @return the default command
*/
Command* GetDefaultCommand();
/**
* Returns the default command name, or empty string is there is none.
*
* @return the default command name
*/
wpi::StringRef GetDefaultCommandName();
/**
* Sets the current command.
*
* @param command the new current command
*/
void SetCurrentCommand(Command* command);
/**
* Returns the command which currently claims this subsystem.
*
* @return the command which currently claims this subsystem
*/
Command* GetCurrentCommand() const;
/**
* Returns the current command name, or empty string if no current command.
*
* @return the current command name
*/
wpi::StringRef GetCurrentCommandName() const;
/**
* When the run method of the scheduler is called this method will be called.
*/
virtual void Periodic();
/**
* Initialize the default command for this subsystem.
*
* This is meant to be the place to call SetDefaultCommand in a subsystem and
* will be called on all the subsystems by the CommandBase method before the
* program starts running by using the list of all registered Subsystems
* inside the Scheduler.
*
* This should be overridden by a Subsystem that has a default Command
*/
virtual void InitDefaultCommand();
/**
* Associate a Sendable with this Subsystem.
* Also update the child's name.
*
* @param name name to give child
* @param child sendable
*/
void AddChild(const wpi::Twine& name, std::shared_ptr<Sendable> child);
/**
* Associate a Sendable with this Subsystem.
* Also update the child's name.
*
* @param name name to give child
* @param child sendable
*/
void AddChild(const wpi::Twine& name, Sendable* child);
/**
* Associate a Sendable with this Subsystem.
* Also update the child's name.
*
* @param name name to give child
* @param child sendable
*/
void AddChild(const wpi::Twine& name, Sendable& child);
/**
* Associate a {@link Sendable} with this Subsystem.
*
* @param child sendable
*/
void AddChild(std::shared_ptr<Sendable> child);
/**
* Associate a {@link Sendable} with this Subsystem.
*
* @param child sendable
*/
void AddChild(Sendable* child);
/**
* Associate a {@link Sendable} with this Subsystem.
*
* @param child sendable
*/
void AddChild(Sendable& child);
private:
/**
* Call this to alert Subsystem that the current command is actually the
* command.
*
* Sometimes, the Subsystem is told that it has no command while the Scheduler
* is going through the loop, only to be soon after given a new one. This will
* avoid that situation.
*/
void ConfirmCommand();
Command* m_currentCommand = nullptr;

View File

@@ -20,11 +20,27 @@ namespace frc {
*/
class TimedCommand : public Command {
public:
/**
* Creates a new TimedCommand with the given name and timeout.
*
* @param name the name of the command
* @param timeout the time (in seconds) before this command "times out"
*/
TimedCommand(const wpi::Twine& name, double timeout);
/**
* Creates a new WaitCommand with the given timeout.
*
* @param timeout the time (in seconds) before this command "times out"
*/
explicit TimedCommand(double timeout);
virtual ~TimedCommand() = default;
protected:
/**
* Ends command when timed out.
*/
bool IsFinished() override;
};

View File

@@ -15,8 +15,21 @@ namespace frc {
class WaitCommand : public TimedCommand {
public:
/**
* Creates a new WaitCommand with the given name and timeout.
*
* @param name the name of the command
* @param timeout the time (in seconds) before this command "times out"
*/
explicit WaitCommand(double timeout);
/**
* Creates a new WaitCommand with the given timeout.
*
* @param timeout the time (in seconds) before this command "times out"
*/
WaitCommand(const wpi::Twine& name, double timeout);
virtual ~WaitCommand() = default;
};

View File

@@ -15,11 +15,24 @@ namespace frc {
class WaitUntilCommand : public Command {
public:
/**
* A WaitCommand will wait until a certain match time before finishing.
*
* This will wait until the game clock reaches some value, then continue to
* the next command.
*
* @see CommandGroup
*/
explicit WaitUntilCommand(double time);
WaitUntilCommand(const wpi::Twine& name, double time);
virtual ~WaitUntilCommand() = default;
protected:
/**
* Check if we've reached the actual finish time.
*/
virtual bool IsFinished();
private:

View File

@@ -32,27 +32,135 @@ namespace frc {
*/
class Compressor : public ErrorBase, public SendableBase {
public:
// Default PCM ID is 0
/**
* Constructor. The default PCM ID is 0.
*
* @param module The PCM ID to use (0-62)
*/
explicit Compressor(int pcmID = SensorUtil::GetDefaultSolenoidModule());
~Compressor() override = default;
/**
* Starts closed-loop control. Note that closed loop control is enabled by
* default.
*/
void Start();
/**
* Stops closed-loop control. Note that closed loop control is enabled by
* default.
*/
void Stop();
/**
* Check if compressor output is active.
*
* @return true if the compressor is on
*/
bool Enabled() const;
/**
* Check if the pressure switch is triggered.
*
* @return true if pressure is low
*/
bool GetPressureSwitchValue() const;
/**
* Query how much current the compressor is drawing.
*
* @return The current through the compressor, in amps
*/
double GetCompressorCurrent() const;
/**
* Enables or disables automatically turning the compressor on when the
* pressure is low.
*
* @param on Set to true to enable closed loop control of the compressor.
* False to disable.
*/
void SetClosedLoopControl(bool on);
/**
* Returns true if the compressor will automatically turn on when the
* pressure is low.
*
* @return True if closed loop control of the compressor is enabled. False if
* disabled.
*/
bool GetClosedLoopControl() const;
/**
* Query if the compressor output has been disabled due to high current draw.
*
* @return true if PCM is in fault state : Compressor Drive is
* disabled due to compressor current being too high.
*/
bool GetCompressorCurrentTooHighFault() const;
/**
* Query if the compressor output has been disabled due to high current draw
* (sticky).
*
* A sticky fault will not clear on device reboot, it must be cleared through
* code or the webdash.
*
* @return true if PCM sticky fault is set : Compressor Drive is
* disabled due to compressor current being too high.
*/
bool GetCompressorCurrentTooHighStickyFault() const;
/**
* Query if the compressor output has been disabled due to a short circuit
* (sticky).
*
* A sticky fault will not clear on device reboot, it must be cleared through
* code or the webdash.
*
* @return true if PCM sticky fault is set : Compressor output
* appears to be shorted.
*/
bool GetCompressorShortedStickyFault() const;
/**
* Query if the compressor output has been disabled due to a short circuit.
*
* @return true if PCM is in fault state : Compressor output
* appears to be shorted.
*/
bool GetCompressorShortedFault() const;
/**
* Query if the compressor output does not appear to be wired (sticky).
*
* A sticky fault will not clear on device reboot, it must be cleared through
* code or the webdash.
*
* @return true if PCM sticky fault is set : Compressor does not
* appear to be wired, i.e. compressor is not drawing enough current.
*/
bool GetCompressorNotConnectedStickyFault() const;
/**
* Query if the compressor output does not appear to be wired.
*
* @return true if PCM is in fault state : Compressor does not
* appear to be wired, i.e. compressor is not drawing enough current.
*/
bool GetCompressorNotConnectedFault() const;
/**
* Clear ALL sticky faults inside PCM that Compressor is wired to.
*
* If a sticky fault is set, then it will be persistently cleared. Compressor
* drive maybe momentarily disable while flags are being cleared. Care should
* be taken to not call this too frequently, otherwise normal compressor
* functionality may be prevented.
*
* If no sticky faults are set then this call will have no effect.
*/
void ClearAllPCMStickyFaults();
void InitSendable(SendableBuilder& builder) override;

View File

@@ -13,32 +13,138 @@ namespace frc {
class ControllerPower {
public:
/**
* Get the input voltage to the robot controller.
*
* @return The controller input voltage value in Volts
* @deprecated Use RobotController static class method
*/
WPI_DEPRECATED("Use RobotController static class method")
static double GetInputVoltage();
/**
* Get the input current to the robot controller.
*
* @return The controller input current value in Amps
* @deprecated Use RobotController static class method
*/
WPI_DEPRECATED("Use RobotController static class method")
static double GetInputCurrent();
/**
* Get the voltage of the 3.3V rail.
*
* @return The controller 3.3V rail voltage value in Volts
* @deprecated Use RobotController static class method
*/
WPI_DEPRECATED("Use RobotController static class method")
static double GetVoltage3V3();
/**
* Get the current output of the 3.3V rail.
*
* @return The controller 3.3V rail output current value in Amps
* @deprecated Use RobotController static class method
*/
WPI_DEPRECATED("Use RobotController static class method")
static double GetCurrent3V3();
/**
* Get the enabled state of the 3.3V rail. The rail may be disabled due to a
* controller brownout, a short circuit on the rail, or controller
* over-voltage.
*
* @return The controller 3.3V rail enabled value. True for enabled.
* @deprecated Use RobotController static class method
*/
WPI_DEPRECATED("Use RobotController static class method")
static bool GetEnabled3V3();
/**
* Get the count of the total current faults on the 3.3V rail since the
* controller has booted.
*
* @return The number of faults
* @deprecated Use RobotController static class method
*/
WPI_DEPRECATED("Use RobotController static class method")
static int GetFaultCount3V3();
/**
* Get the voltage of the 5V rail.
*
* @return The controller 5V rail voltage value in Volts
* @deprecated Use RobotController static class method
*/
WPI_DEPRECATED("Use RobotController static class method")
static double GetVoltage5V();
/**
* Get the current output of the 5V rail.
*
* @return The controller 5V rail output current value in Amps
* @deprecated Use RobotController static class method
*/
WPI_DEPRECATED("Use RobotController static class method")
static double GetCurrent5V();
/**
* Get the enabled state of the 5V rail. The rail may be disabled due to a
* controller brownout, a short circuit on the rail, or controller
* over-voltage.
*
* @return The controller 5V rail enabled value. True for enabled.
* @deprecated Use RobotController static class method
*/
WPI_DEPRECATED("Use RobotController static class method")
static bool GetEnabled5V();
/**
* Get the count of the total current faults on the 5V rail since the
* controller has booted.
*
* @return The number of faults
* @deprecated Use RobotController static class method
*/
WPI_DEPRECATED("Use RobotController static class method")
static int GetFaultCount5V();
/**
* Get the voltage of the 6V rail.
*
* @return The controller 6V rail voltage value in Volts
* @deprecated Use RobotController static class method
*/
WPI_DEPRECATED("Use RobotController static class method")
static double GetVoltage6V();
/**
* Get the current output of the 6V rail.
*
* @return The controller 6V rail output current value in Amps
* @deprecated Use RobotController static class method
*/
WPI_DEPRECATED("Use RobotController static class method")
static double GetCurrent6V();
/**
* Get the enabled state of the 6V rail. The rail may be disabled due to a
* controller brownout, a short circuit on the rail, or controller
* over-voltage.
*
* @return The controller 6V rail enabled value. True for enabled.
* @deprecated Use RobotController static class method
*/
WPI_DEPRECATED("Use RobotController static class method")
static bool GetEnabled6V();
/**
* Get the count of the total current faults on the 6V rail since the
* controller has booted.
*
* @return The number of faults.
* @deprecated Use RobotController static class method
*/
WPI_DEPRECATED("Use RobotController static class method")
static int GetFaultCount6V();
};

View File

@@ -40,57 +40,378 @@ class Counter : public ErrorBase, public SendableBase, public CounterBase {
kExternalDirection = 3
};
/**
* Create an instance of a counter where no sources are selected.
*
* They all must be selected by calling functions to specify the upsource and
* the downsource independently.
*
* This creates a ChipObject counter and initializes status variables
* appropriately.
*
* The counter will start counting immediately.
*
* @param mode The counter mode
*/
explicit Counter(Mode mode = kTwoPulse);
/**
* Create an instance of a Counter object.
*
* Create an up-Counter instance given a channel.
*
* The counter will start counting immediately.
*
* @param channel The DIO channel to use as the up source. 0-9 are on-board,
* 10-25 are on the MXP
*/
explicit Counter(int channel);
/**
* Create an instance of a counter from a Digital Source (such as a Digital
* Input).
*
* This is used if an existing digital input is to be shared by multiple other
* objects such as encoders or if the Digital Source is not a Digital Input
* channel (such as an Analog Trigger).
*
* The counter will start counting immediately.
* @param source A pointer to the existing DigitalSource object. It will be
* set as the Up Source.
*/
explicit Counter(DigitalSource* source);
/**
* Create an instance of a counter from a Digital Source (such as a Digital
* Input).
*
* This is used if an existing digital input is to be shared by multiple other
* objects such as encoders or if the Digital Source is not a Digital Input
* channel (such as an Analog Trigger).
*
* The counter will start counting immediately.
*
* @param source A pointer to the existing DigitalSource object. It will be
* set as the Up Source.
*/
explicit Counter(std::shared_ptr<DigitalSource> source);
/**
* Create an instance of a Counter object.
*
* Create an instance of a simple up-Counter given an analog trigger.
* Use the trigger state output from the analog trigger.
*
* The counter will start counting immediately.
*
* @param trigger The reference to the existing AnalogTrigger object.
*/
explicit Counter(const AnalogTrigger& trigger);
/**
* Create an instance of a Counter object.
*
* Creates a full up-down counter given two Digital Sources.
*
* @param encodingType The quadrature decoding mode (1x or 2x)
* @param upSource The pointer to the DigitalSource to set as the up
* source
* @param downSource The pointer to the DigitalSource to set as the down
* source
* @param inverted True to invert the output (reverse the direction)
*/
Counter(EncodingType encodingType, DigitalSource* upSource,
DigitalSource* downSource, bool inverted);
/**
* Create an instance of a Counter object.
*
* Creates a full up-down counter given two Digital Sources.
*
* @param encodingType The quadrature decoding mode (1x or 2x)
* @param upSource The pointer to the DigitalSource to set as the up
* source
* @param downSource The pointer to the DigitalSource to set as the down
* source
* @param inverted True to invert the output (reverse the direction)
*/
Counter(EncodingType encodingType, std::shared_ptr<DigitalSource> upSource,
std::shared_ptr<DigitalSource> downSource, bool inverted);
~Counter() override;
/**
* Set the upsource for the counter as a digital input channel.
*
* @param channel The DIO channel to use as the up source. 0-9 are on-board,
* 10-25 are on the MXP
*/
void SetUpSource(int channel);
/**
* Set the up counting source to be an analog trigger.
*
* @param analogTrigger The analog trigger object that is used for the Up
* Source
* @param triggerType The analog trigger output that will trigger the
* counter.
*/
void SetUpSource(AnalogTrigger* analogTrigger, AnalogTriggerType triggerType);
/**
* Set the up counting source to be an analog trigger.
*
* @param analogTrigger The analog trigger object that is used for the Up
* Source
* @param triggerType The analog trigger output that will trigger the
* counter.
*/
void SetUpSource(std::shared_ptr<AnalogTrigger> analogTrigger,
AnalogTriggerType triggerType);
void SetUpSource(DigitalSource* source);
/**
* Set the source object that causes the counter to count up.
*
* Set the up counting DigitalSource.
*
* @param source Pointer to the DigitalSource object to set as the up source
*/
void SetUpSource(std::shared_ptr<DigitalSource> source);
/**
* Set the source object that causes the counter to count up.
*
* Set the up counting DigitalSource.
*
* @param source Reference to the DigitalSource object to set as the up source
*/
void SetUpSource(DigitalSource& source);
/**
* Set the edge sensitivity on an up counting source.
*
* Set the up source to either detect rising edges or falling edges or both.
*
* @param risingEdge True to trigger on rising edges
* @param fallingEdge True to trigger on falling edges
*/
void SetUpSourceEdge(bool risingEdge, bool fallingEdge);
/**
* Disable the up counting source to the counter.
*/
void ClearUpSource();
/**
* Set the down counting source to be a digital input channel.
*
* @param channel The DIO channel to use as the up source. 0-9 are on-board,
* 10-25 are on the MXP
*/
void SetDownSource(int channel);
/**
* Set the down counting source to be an analog trigger.
*
* @param analogTrigger The analog trigger object that is used for the Down
* Source
* @param triggerType The analog trigger output that will trigger the
* counter.
*/
void SetDownSource(AnalogTrigger* analogTrigger,
AnalogTriggerType triggerType);
/**
* Set the down counting source to be an analog trigger.
*
* @param analogTrigger The analog trigger object that is used for the Down
* Source
* @param triggerType The analog trigger output that will trigger the
* counter.
*/
void SetDownSource(std::shared_ptr<AnalogTrigger> analogTrigger,
AnalogTriggerType triggerType);
/**
* Set the source object that causes the counter to count down.
*
* Set the down counting DigitalSource.
*
* @param source Pointer to the DigitalSource object to set as the down source
*/
void SetDownSource(DigitalSource* source);
void SetDownSource(std::shared_ptr<DigitalSource> source);
/**
* Set the source object that causes the counter to count down.
*
* Set the down counting DigitalSource.
*
* @param source Reference to the DigitalSource object to set as the down
* source
*/
void SetDownSource(DigitalSource& source);
void SetDownSource(std::shared_ptr<DigitalSource> source);
/**
* Set the edge sensitivity on a down counting source.
*
* Set the down source to either detect rising edges or falling edges.
*
* @param risingEdge True to trigger on rising edges
* @param fallingEdge True to trigger on falling edges
*/
void SetDownSourceEdge(bool risingEdge, bool fallingEdge);
/**
* Disable the down counting source to the counter.
*/
void ClearDownSource();
/**
* Set standard up / down counting mode on this counter.
*
* Up and down counts are sourced independently from two inputs.
*/
void SetUpDownCounterMode();
/**
* Set external direction mode on this counter.
*
* Counts are sourced on the Up counter input.
* The Down counter input represents the direction to count.
*/
void SetExternalDirectionMode();
/**
* Set Semi-period mode on this counter.
*
* Counts up on both rising and falling edges.
*/
void SetSemiPeriodMode(bool highSemiPeriod);
/**
* Configure the counter to count in up or down based on the length of the
* input pulse.
*
* This mode is most useful for direction sensitive gear tooth sensors.
*
* @param threshold The pulse length beyond which the counter counts the
* opposite direction. Units are seconds.
*/
void SetPulseLengthMode(double threshold);
/**
* Set the Counter to return reversed sensing on the direction.
*
* This allows counters to change the direction they are counting in the case
* of 1X and 2X quadrature encoding only. Any other counter mode isn't
* supported.
*
* @param reverseDirection true if the value counted should be negated.
*/
void SetReverseDirection(bool reverseDirection);
// CounterBase interface
int Get() const override;
void Reset() override;
double GetPeriod() const override;
void SetMaxPeriod(double maxPeriod) override;
void SetUpdateWhenEmpty(bool enabled);
bool GetStopped() const override;
bool GetDirection() const override;
/**
* Set the Samples to Average which specifies the number of samples of the
* timer to average when calculating the period. Perform averaging to account
* for mechanical imperfections or as oversampling to increase resolution.
*
* @param samplesToAverage The number of samples to average from 1 to 127.
*/
void SetSamplesToAverage(int samplesToAverage);
/**
* Get the Samples to Average which specifies the number of samples of the
* timer to average when calculating the period.
*
* Perform averaging to account for mechanical imperfections or as
* oversampling to increase resolution.
*
* @return The number of samples being averaged (from 1 to 127)
*/
int GetSamplesToAverage() const;
int GetFPGAIndex() const { return m_index; }
int GetFPGAIndex() const;
// CounterBase interface
/**
* Read the current counter value.
*
* Read the value at this instant. It may still be running, so it reflects the
* current value. Next time it is read, it might have a different value.
*/
int Get() const override;
/**
* Reset the Counter to zero.
*
* Set the counter value to zero. This doesn't effect the running state of the
* counter, just sets the current value to zero.
*/
void Reset() override;
/**
* Get the Period of the most recent count.
*
* Returns the time interval of the most recent count. This can be used for
* velocity calculations to determine shaft speed.
*
* @returns The period between the last two pulses in units of seconds.
*/
double GetPeriod() const override;
/**
* Set the maximum period where the device is still considered "moving".
*
* Sets the maximum period where the device is considered moving. This value
* is used to determine the "stopped" state of the counter using the
* GetStopped method.
*
* @param maxPeriod The maximum period where the counted device is considered
* moving in seconds.
*/
void SetMaxPeriod(double maxPeriod) override;
/**
* Select whether you want to continue updating the event timer output when
* there are no samples captured.
*
* The output of the event timer has a buffer of periods that are averaged and
* posted to a register on the FPGA. When the timer detects that the event
* source has stopped (based on the MaxPeriod) the buffer of samples to be
* averaged is emptied. If you enable the update when empty, you will be
* notified of the stopped source and the event time will report 0 samples.
* If you disable update when empty, the most recent average will remain on
* the output until a new sample is acquired. You will never see 0 samples
* output (except when there have been no events since an FPGA reset) and you
* will likely not see the stopped bit become true (since it is updated at the
* end of an average and there are no samples to average).
*
* @param enabled True to enable update when empty
*/
void SetUpdateWhenEmpty(bool enabled);
/**
* Determine if the clock is stopped.
*
* Determine if the clocked input is stopped based on the MaxPeriod value set
* using the SetMaxPeriod method. If the clock exceeds the MaxPeriod, then the
* device (and counter) are assumed to be stopped and it returns true.
*
* @return Returns true if the most recent counter period exceeds the
* MaxPeriod value set by SetMaxPeriod.
*/
bool GetStopped() const override;
/**
* The last direction the counter value changed.
*
* @return The last direction the counter value changed.
*/
bool GetDirection() const override;
void InitSendable(SendableBuilder& builder) override;

View File

@@ -16,6 +16,12 @@ namespace frc {
*/
class DMC60 : public PWMSpeedController {
public:
/**
* Constructor for a Digilent DMC 60.
*
* @param channel The PWM channel that the DMC 60 is attached to. 0-9 are
* on-board, 10-19 are on the MXP port
*/
explicit DMC60(int channel);
};

View File

@@ -34,18 +34,83 @@ class DigitalGlitchFilter : public ErrorBase, public SendableBase {
DigitalGlitchFilter();
~DigitalGlitchFilter() override;
/**
* Assigns the DigitalSource to this glitch filter.
*
* @param input The DigitalSource to add.
*/
void Add(DigitalSource* input);
/**
* Assigns the Encoder to this glitch filter.
*
* @param input The Encoder to add.
*/
void Add(Encoder* input);
/**
* Assigns the Counter to this glitch filter.
*
* @param input The Counter to add.
*/
void Add(Counter* input);
/**
* Removes a digital input from this filter.
*
* Removes the DigitalSource from this glitch filter and re-assigns it to
* the default filter.
*
* @param input The DigitalSource to remove.
*/
void Remove(DigitalSource* input);
/**
* Removes an encoder from this filter.
*
* Removes the Encoder from this glitch filter and re-assigns it to
* the default filter.
*
* @param input The Encoder to remove.
*/
void Remove(Encoder* input);
/**
* Removes a counter from this filter.
*
* Removes the Counter from this glitch filter and re-assigns it to
* the default filter.
*
* @param input The Counter to remove.
*/
void Remove(Counter* input);
/**
* Sets the number of cycles that the input must not change state for.
*
* @param fpgaCycles The number of FPGA cycles.
*/
void SetPeriodCycles(int fpgaCycles);
/**
* Sets the number of nanoseconds that the input must not change state for.
*
* @param nanoseconds The number of nanoseconds.
*/
void SetPeriodNanoSeconds(uint64_t nanoseconds);
/**
* Gets the number of cycles that the input must not change state for.
*
* @return The number of cycles.
*/
int GetPeriodCycles();
/**
* Gets the number of nanoseconds that the input must not change state for.
*
* @return The number of nanoseconds.
*/
uint64_t GetPeriodNanoSeconds();
void InitSendable(SendableBuilder& builder) override;

View File

@@ -24,16 +24,45 @@ class DigitalGlitchFilter;
*/
class DigitalInput : public DigitalSource {
public:
/**
* Create an instance of a Digital Input class.
*
* Creates a digital input given a channel.
*
* @param channel The DIO channel 0-9 are on-board, 10-25 are on the MXP port
*/
explicit DigitalInput(int channel);
~DigitalInput() override;
/**
* Get the value from a digital input channel.
*
* Retrieve the value of a single digital input channel from the FPGA.
*/
bool Get() const;
int GetChannel() const override;
// Digital Source Interface
/**
* @return The HAL Handle to the specified source.
*/
HAL_Handle GetPortHandleForRouting() const override;
/**
* @return The type of analog trigger output to be used. 0 for Digitals
*/
AnalogTriggerType GetAnalogTriggerTypeForRouting() const override;
/**
* Is source an AnalogTrigger
*/
bool IsAnalogTrigger() const override;
/**
* @return The GPIO channel number that this object represents.
*/
int GetChannel() const override;
void InitSendable(SendableBuilder& builder) override;
private:

View File

@@ -23,16 +23,98 @@ namespace frc {
*/
class DigitalOutput : public ErrorBase, public SendableBase {
public:
/**
* Create an instance of a digital output.
*
* Create a digital output given a channel.
*
* @param channel The digital channel 0-9 are on-board, 10-25 are on the MXP
* port
*/
explicit DigitalOutput(int channel);
~DigitalOutput() override;
/**
* Set the value of a digital output.
*
* Set the value of a digital output to either one (true) or zero (false).
*
* @param value 1 (true) for high, 0 (false) for disabled
*/
void Set(bool value);
/**
* Gets the value being output from the Digital Output.
*
* @return the state of the digital output.
*/
bool Get() const;
/**
* @return The GPIO channel number that this object represents.
*/
int GetChannel() const;
/**
* Output a single pulse on the digital output line.
*
* Send a single pulse on the digital output line where the pulse duration is
* specified in seconds. Maximum pulse length is 0.0016 seconds.
*
* @param length The pulse length in seconds
*/
void Pulse(double length);
/**
* Determine if the pulse is still going.
*
* Determine if a previously started pulse is still going.
*/
bool IsPulsing() const;
/**
* Change the PWM frequency of the PWM output on a Digital Output line.
*
* The valid range is from 0.6 Hz to 19 kHz. The frequency resolution is
* logarithmic.
*
* There is only one PWM frequency for all digital channels.
*
* @param rate The frequency to output all digital output PWM signals.
*/
void SetPWMRate(double rate);
/**
* Enable a PWM Output on this line.
*
* Allocate one of the 6 DO PWM generator resources from this module.
*
* Supply the initial duty-cycle to output so as to avoid a glitch when first
* starting.
*
* The resolution of the duty cycle is 8-bit for low frequencies (1kHz or
* less) but is reduced the higher the frequency of the PWM signal is.
*
* @param initialDutyCycle The duty-cycle to start generating. [0..1]
*/
void EnablePWM(double initialDutyCycle);
/**
* Change this line from a PWM output back to a static Digital Output line.
*
* Free up one of the 6 DO PWM generator resources that were in use.
*/
void DisablePWM();
/**
* Change the duty-cycle that is being generated on the line.
*
* The resolution of the duty cycle is 8-bit for low frequencies (1kHz or
* less) but is reduced the higher the frequency of the PWM signal is.
*
* @param dutyCycle The duty-cycle to change to. [0..1]
*/
void UpdateDutyCycle(double dutyCycle);
void InitSendable(SendableBuilder& builder) override;

View File

@@ -24,12 +24,61 @@ class DoubleSolenoid : public SolenoidBase {
public:
enum Value { kOff, kForward, kReverse };
/**
* Constructor.
*
* Uses the default PCM ID of 0.
*
* @param forwardChannel The forward channel number on the PCM (0..7).
* @param reverseChannel The reverse channel number on the PCM (0..7).
*/
explicit DoubleSolenoid(int forwardChannel, int reverseChannel);
/**
* Constructor.
*
* @param moduleNumber The CAN ID of the PCM.
* @param forwardChannel The forward channel on the PCM to control (0..7).
* @param reverseChannel The reverse channel on the PCM to control (0..7).
*/
DoubleSolenoid(int moduleNumber, int forwardChannel, int reverseChannel);
~DoubleSolenoid() override;
/**
* Set the value of a solenoid.
*
* @param value The value to set (Off, Forward or Reverse)
*/
virtual void Set(Value value);
/**
* Read the current value of the solenoid.
*
* @return The current value of the solenoid.
*/
virtual Value Get() const;
/**
* Check if the forward solenoid is blacklisted.
*
* If a solenoid is shorted, it is added to the blacklist and disabled until
* power cycle, or until faults are cleared.
*
* @see ClearAllPCMStickyFaults()
* @return If solenoid is disabled due to short.
*/
bool IsFwdSolenoidBlackListed() const;
/**
* Check if the reverse solenoid is blacklisted.
*
* If a solenoid is shorted, it is added to the blacklist and disabled until
* power cycle, or until faults are cleared.
*
* @see ClearAllPCMStickyFaults()
* @return If solenoid is disabled due to short.
*/
bool IsRevSolenoidBlackListed() const;
void InitSendable(SendableBuilder& builder) override;

View File

@@ -101,21 +101,106 @@ class DifferentialDrive : public RobotDriveBase {
static constexpr double kDefaultQuickStopThreshold = 0.2;
static constexpr double kDefaultQuickStopAlpha = 0.1;
/**
* Construct a DifferentialDrive.
*
* To pass multiple motors per side, use a SpeedControllerGroup. If a motor
* needs to be inverted, do so before passing it in.
*/
DifferentialDrive(SpeedController& leftMotor, SpeedController& rightMotor);
~DifferentialDrive() override = default;
DifferentialDrive(const DifferentialDrive&) = delete;
DifferentialDrive& operator=(const DifferentialDrive&) = delete;
/**
* Arcade drive method for differential drive platform.
*
* Note: Some drivers may prefer inverted rotation controls. This can be done
* by negating the value passed for rotation.
*
* @param xSpeed The speed at which the robot should drive along the X
* axis [-1.0..1.0]. Forward is negative.
* @param zRotation The rotation rate of the robot around the Z axis
* [-1.0..1.0]. Clockwise is positive.
* @param squaredInputs If set, decreases the input sensitivity at low speeds.
*/
void ArcadeDrive(double xSpeed, double zRotation, bool squaredInputs = true);
/**
* Curvature drive method for differential drive platform.
*
* The rotation argument controls the curvature of the robot's path rather
* than its rate of heading change. This makes the robot more controllable at
* high speeds. Also handles the robot's quick turn functionality - "quick
* turn" overrides constant-curvature turning for turn-in-place maneuvers.
*
* @param xSpeed The robot's speed along the X axis [-1.0..1.0]. Forward
* is positive.
* @param zRotation The robot's rotation rate around the Z axis [-1.0..1.0].
* Clockwise is positive.
* @param isQuickTurn If set, overrides constant-curvature turning for
* turn-in-place maneuvers.
*/
void CurvatureDrive(double xSpeed, double zRotation, bool isQuickTurn);
/**
* Tank drive method for differential drive platform.
*
* @param leftSpeed The robot left side's speed along the X axis
* [-1.0..1.0]. Forward is positive.
* @param rightSpeed The robot right side's speed along the X axis
* [-1.0..1.0]. Forward is positive.
* @param squaredInputs If set, decreases the input sensitivity at low speeds.
*/
void TankDrive(double leftSpeed, double rightSpeed,
bool squaredInputs = true);
/**
* Sets the QuickStop speed threshold in curvature drive.
*
* QuickStop compensates for the robot's moment of inertia when stopping after
* a QuickTurn.
*
* While QuickTurn is enabled, the QuickStop accumulator takes on the rotation
* rate value outputted by the low-pass filter when the robot's speed along
* the X axis is below the threshold. When QuickTurn is disabled, the
* accumulator's value is applied against the computed angular power request
* to slow the robot's rotation.
*
* @param threshold X speed below which quick stop accumulator will receive
* rotation rate values [0..1.0].
*/
void SetQuickStopThreshold(double threshold);
/**
* Sets the low-pass filter gain for QuickStop in curvature drive.
*
* The low-pass filter filters incoming rotation rate commands to smooth out
* high frequency changes.
*
* @param alpha Low-pass filter gain [0.0..2.0]. Smaller values result in
* slower output changes. Values between 1.0 and 2.0 result in
* output oscillation. Values below 0.0 and above 2.0 are
* unstable.
*/
void SetQuickStopAlpha(double alpha);
/**
* Gets if the power sent to the right side of the drivetrain is multipled by
* -1.
*
* @return true if the right side is inverted
*/
bool IsRightSideInverted() const;
/**
* Sets if the power sent to the right side of the drivetrain should be
* multipled by -1.
*
* @param rightSideInverted true if right side power should be multipled by -1
*/
void SetRightSideInverted(bool rightSideInverted);
void StopMotor() override;

View File

@@ -50,18 +50,76 @@ class KilloughDrive : public RobotDriveBase {
static constexpr double kDefaultRightMotorAngle = 120.0;
static constexpr double kDefaultBackMotorAngle = 270.0;
/**
* Construct a Killough drive with the given motors and default motor angles.
*
* The default motor angles make the wheels on each corner parallel to their
* respective opposite sides.
*
* If a motor needs to be inverted, do so before passing it in.
*
* @param leftMotor The motor on the left corner.
* @param rightMotor The motor on the right corner.
* @param backMotor The motor on the back corner.
*/
KilloughDrive(SpeedController& leftMotor, SpeedController& rightMotor,
SpeedController& backMotor);
/**
* Construct a Killough drive with the given motors.
*
* Angles are measured in degrees clockwise from the positive X axis.
*
* @param leftMotor The motor on the left corner.
* @param rightMotor The motor on the right corner.
* @param backMotor The motor on the back corner.
* @param leftMotorAngle The angle of the left wheel's forward direction of
* travel.
* @param rightMotorAngle The angle of the right wheel's forward direction of
* travel.
* @param backMotorAngle The angle of the back wheel's forward direction of
* travel.
*/
KilloughDrive(SpeedController& leftMotor, SpeedController& rightMotor,
SpeedController& backMotor, double leftMotorAngle,
double rightMotorAngle, double backMotorAngle);
~KilloughDrive() override = default;
KilloughDrive(const KilloughDrive&) = delete;
KilloughDrive& operator=(const KilloughDrive&) = delete;
/**
* Drive method for Killough platform.
*
* Angles are measured clockwise from the positive X axis. The robot's speed
* is independent from its angle or rotation rate.
*
* @param ySpeed The robot's speed along the Y axis [-1.0..1.0]. Right is
* positive.
* @param xSpeed The robot's speed along the X axis [-1.0..1.0]. Forward is
* positive.
* @param zRotation The robot's rotation rate around the Z axis [-1.0..1.0].
* Clockwise is positive.
* @param gyroAngle The current angle reading from the gyro in degrees around
* the Z axis. Use this to implement field-oriented controls.
*/
void DriveCartesian(double ySpeed, double xSpeed, double zRotation,
double gyroAngle = 0.0);
/**
* Drive method for Killough platform.
*
* Angles are measured clockwise from the positive X axis. The robot's speed
* is independent from its angle or rotation rate.
*
* @param magnitude The robot's speed at a given angle [-1.0..1.0]. Forward is
* positive.
* @param angle The angle around the Z axis at which the robot drives in
* degrees [-180..180].
* @param zRotation The robot's rotation rate around the Z axis [-1.0..1.0].
* Clockwise is positive.
*/
void DrivePolar(double magnitude, double angle, double zRotation);
void StopMotor() override;

View File

@@ -64,19 +64,67 @@ class SpeedController;
*/
class MecanumDrive : public RobotDriveBase {
public:
/**
* Construct a MecanumDrive.
*
* If a motor needs to be inverted, do so before passing it in.
*/
MecanumDrive(SpeedController& frontLeftMotor, SpeedController& rearLeftMotor,
SpeedController& frontRightMotor,
SpeedController& rearRightMotor);
~MecanumDrive() override = default;
MecanumDrive(const MecanumDrive&) = delete;
MecanumDrive& operator=(const MecanumDrive&) = delete;
/**
* Drive method for Mecanum platform.
*
* Angles are measured clockwise from the positive X axis. The robot's speed
* is independent from its angle or rotation rate.
*
* @param ySpeed The robot's speed along the Y axis [-1.0..1.0]. Right is
* positive.
* @param xSpeed The robot's speed along the X axis [-1.0..1.0]. Forward is
* positive.
* @param zRotation The robot's rotation rate around the Z axis [-1.0..1.0].
* Clockwise is positive.
* @param gyroAngle The current angle reading from the gyro in degrees around
* the Z axis. Use this to implement field-oriented controls.
*/
void DriveCartesian(double ySpeed, double xSpeed, double zRotation,
double gyroAngle = 0.0);
/**
* Drive method for Mecanum platform.
*
* Angles are measured clockwise from the positive X axis. The robot's speed
* is independent from its angle or rotation rate.
*
* @param magnitude The robot's speed at a given angle [-1.0..1.0]. Forward is
* positive.
* @param angle The angle around the Z axis at which the robot drives in
* degrees [-180..180].
* @param zRotation The robot's rotation rate around the Z axis [-1.0..1.0].
* Clockwise is positive.
*/
void DrivePolar(double magnitude, double angle, double zRotation);
/**
* Gets if the power sent to the right side of the drivetrain is multipled by
* -1.
*
* @return true if the right side is inverted
*/
bool IsRightSideInverted() const;
/**
* Sets if the power sent to the right side of the drivetrain should be
* multipled by -1.
*
* @param rightSideInverted true if right side power should be multipled by -1
*/
void SetRightSideInverted(bool rightSideInverted);
void StopMotor() override;

View File

@@ -44,9 +44,32 @@ class RobotDriveBase : public MotorSafety, public SendableBase {
RobotDriveBase(const RobotDriveBase&) = delete;
RobotDriveBase& operator=(const RobotDriveBase&) = delete;
/**
* Sets the deadband applied to the drive inputs (e.g., joystick values).
*
* The default value is 0.02. Inputs smaller than the deadband are set to 0.0
* while inputs larger than the deadband are scaled from 0.0 to 1.0. See
* ApplyDeadband().
*
* @param deadband The deadband to set.
*/
void SetDeadband(double deadband);
/**
* Configure the scaling factor for using RobotDrive with motor controllers in
* a mode other than PercentVbus or to limit the maximum output.
*
* @param maxOutput Multiplied with the output percentage computed by the
* drive functions.
*/
void SetMaxOutput(double maxOutput);
/**
* Feed the motor safety object. Resets the timer that will stop the motors if
* it completes.
*
* @see MotorSafetyHelper::Feed()
*/
void FeedWatchdog();
void SetExpiration(double timeout) override;
@@ -58,8 +81,24 @@ class RobotDriveBase : public MotorSafety, public SendableBase {
void GetDescription(wpi::raw_ostream& desc) const override = 0;
protected:
/**
* Limit motor values to the -1.0 to +1.0 range.
*/
double Limit(double number);
/**
* Returns 0.0 if the given value is within the specified range around zero.
* The remaining range between the deadband and 1.0 is scaled from 0.0 to 1.0.
*
* @param value value to clip
* @param deadband range around zero
*/
double ApplyDeadband(double number, double deadband);
/**
* Normalize all wheel speeds if the magnitude of any wheel is greater than
* 1.0.
*/
void Normalize(wpi::MutableArrayRef<double> wheelSpeeds);
double m_deadband = 0.02;

View File

@@ -16,9 +16,30 @@ struct Vector2d {
Vector2d() = default;
Vector2d(double x, double y);
/**
* Rotate a vector in Cartesian space.
*
* @param angle angle in degrees by which to rotate vector counter-clockwise.
*/
void Rotate(double angle);
/**
* Returns dot product of this vector with argument.
*
* @param vec Vector with which to perform dot product.
*/
double Dot(const Vector2d& vec) const;
/**
* Returns magnitude of vector.
*/
double Magnitude() const;
/**
* Returns scalar projection of this vector onto argument.
*
* @param vec Vector onto which to project this vector.
*/
double ScalarProject(const Vector2d& vec) const;
double x = 0.0;

View File

@@ -37,41 +37,229 @@ class DriverStation : public ErrorBase, public RobotStateInterface {
enum MatchType { kNone, kPractice, kQualification, kElimination };
~DriverStation() override;
/**
* Return a reference to the singleton DriverStation.
*
* @return Reference to the DS instance
*/
static DriverStation& GetInstance();
/**
* Report an error to the DriverStation messages window.
*
* The error is also printed to the program console.
*/
static void ReportError(const wpi::Twine& error);
/**
* Report a warning to the DriverStation messages window.
*
* The warning is also printed to the program console.
*/
static void ReportWarning(const wpi::Twine& error);
/**
* Report an error to the DriverStation messages window.
*
* The error is also printed to the program console.
*/
static void ReportError(bool isError, int code, const wpi::Twine& error,
const wpi::Twine& location, const wpi::Twine& stack);
static constexpr int kJoystickPorts = 6;
/**
* The state of one joystick button. Button indexes begin at 1.
*
* @param stick The joystick to read.
* @param button The button index, beginning at 1.
* @return The state of the joystick button.
*/
bool GetStickButton(int stick, int button);
/**
* Whether one joystick button was pressed since the last check. Button
* indexes begin at 1.
*
* @param stick The joystick to read.
* @param button The button index, beginning at 1.
* @return Whether the joystick button was pressed since the last check.
*/
bool GetStickButtonPressed(int stick, int button);
/**
* Whether one joystick button was released since the last check. Button
* indexes begin at 1.
*
* @param stick The joystick to read.
* @param button The button index, beginning at 1.
* @return Whether the joystick button was released since the last check.
*/
bool GetStickButtonReleased(int stick, int button);
/**
* Get the value of the axis on a joystick.
*
* This depends on the mapping of the joystick connected to the specified
* port.
*
* @param stick The joystick to read.
* @param axis The analog axis value to read from the joystick.
* @return The value of the axis on the joystick.
*/
double GetStickAxis(int stick, int axis);
/**
* Get the state of a POV on the joystick.
*
* @return the angle of the POV in degrees, or -1 if the POV is not pressed.
*/
int GetStickPOV(int stick, int pov);
/**
* The state of the buttons on the joystick.
*
* @param stick The joystick to read.
* @return The state of the buttons on the joystick.
*/
int GetStickButtons(int stick) const;
/**
* Returns the number of axes on a given joystick port.
*
* @param stick The joystick port number
* @return The number of axes on the indicated joystick
*/
int GetStickAxisCount(int stick) const;
/**
* Returns the number of POVs on a given joystick port.
*
* @param stick The joystick port number
* @return The number of POVs on the indicated joystick
*/
int GetStickPOVCount(int stick) const;
/**
* Returns the number of buttons on a given joystick port.
*
* @param stick The joystick port number
* @return The number of buttons on the indicated joystick
*/
int GetStickButtonCount(int stick) const;
/**
* Returns a boolean indicating if the controller is an xbox controller.
*
* @param stick The joystick port number
* @return A boolean that is true if the controller is an xbox controller.
*/
bool GetJoystickIsXbox(int stick) const;
/**
* Returns the type of joystick at a given port.
*
* @param stick The joystick port number
* @return The HID type of joystick at the given port
*/
int GetJoystickType(int stick) const;
/**
* Returns the name of the joystick at the given port.
*
* @param stick The joystick port number
* @return The name of the joystick at the given port
*/
std::string GetJoystickName(int stick) const;
/**
* Returns the types of Axes on a given joystick port.
*
* @param stick The joystick port number and the target axis
* @return What type of axis the axis is reporting to be
*/
int GetJoystickAxisType(int stick, int axis) const;
/**
* Check if the DS has enabled the robot.
*
* @return True if the robot is enabled and the DS is connected
*/
bool IsEnabled() const override;
/**
* Check if the robot is disabled.
*
* @return True if the robot is explicitly disabled or the DS is not connected
*/
bool IsDisabled() const override;
/**
* Check if the DS is commanding autonomous mode.
*
* @return True if the robot is being commanded to be in autonomous mode
*/
bool IsAutonomous() const override;
/**
* Check if the DS is commanding teleop mode.
*
* @return True if the robot is being commanded to be in teleop mode
*/
bool IsOperatorControl() const override;
/**
* Check if the DS is commanding test mode.
*
* @return True if the robot is being commanded to be in test mode
*/
bool IsTest() const override;
/**
* Check if the DS is attached.
*
* @return True if the DS is connected to the robot
*/
bool IsDSAttached() const;
/**
* Has a new control packet from the driver station arrived since the last
* time this function was called?
*
* Warning: If you call this function from more than one place at the same
* time, you will not get the intended behavior.
*
* @return True if the control data has been updated since the last call.
*/
bool IsNewControlData() const;
/**
* Is the driver station attached to a Field Management System?
*
* @return True if the robot is competing on a field being controlled by a
* Field Management System
*/
bool IsFMSAttached() const;
/**
* Check if the FPGA outputs are enabled.
*
* The outputs may be disabled if the robot is disabled or e-stopped, the
* watchdog has expired, or if the roboRIO browns out.
*
* @return True if the FPGA outputs are enabled.
* @deprecated Use RobotController static class method
*/
WPI_DEPRECATED("Use RobotController static class method")
bool IsSysActive() const;
/**
* Check if the system is browned out.
*
* @return True if the system is browned out
* @deprecated Use RobotController static class method
*/
WPI_DEPRECATED("Use RobotController static class method")
bool IsBrownedOut() const;
@@ -81,11 +269,75 @@ class DriverStation : public ErrorBase, public RobotStateInterface {
int GetMatchNumber() const;
int GetReplayNumber() const;
/**
* Return the alliance that the driver station says it is on.
*
* This could return kRed or kBlue.
*
* @return The Alliance enum (kRed, kBlue or kInvalid)
*/
Alliance GetAlliance() const;
/**
* Return the driver station location on the field.
*
* This could return 1, 2, or 3.
*
* @return The location of the driver station (1-3, 0 for invalid)
*/
int GetLocation() const;
/**
* Wait until a new packet comes from the driver station.
*
* This blocks on a semaphore, so the waiting is efficient.
*
* This is a good way to delay processing until there is new driver station
* data to act on.
*/
void WaitForData();
/**
* Wait until a new packet comes from the driver station, or wait for a
* timeout.
*
* If the timeout is less then or equal to 0, wait indefinitely.
*
* Timeout is in milliseconds
*
* This blocks on a semaphore, so the waiting is efficient.
*
* This is a good way to delay processing until there is new driver station
* data to act on.
*
* @param timeout Timeout time in seconds
*
* @return true if new data, otherwise false
*/
bool WaitForData(double timeout);
/**
* Return the approximate match time.
*
* The FMS does not send an official match time to the robots, but does send
* an approximate match time. The value will count down the time remaining in
* the current period (auto or teleop).
*
* Warning: This is not an official time (so it cannot be used to dispute ref
* calls or guarantee that a function will trigger before the match ends).
*
* The Practice Match function of the DS approximates the behaviour seen on
* the field.
*
* @return Time remaining in current match period (auto or teleop)
*/
double GetMatchTime() const;
/**
* Read the battery voltage.
*
* @return The battery voltage in Volts.
*/
double GetBatteryVoltage() const;
/**
@@ -124,15 +376,49 @@ class DriverStation : public ErrorBase, public RobotStateInterface {
void InTest(bool entering) { m_userInTest = entering; }
protected:
/**
* Copy data from the DS task for the user.
*
* If no new data exists, it will just be returned, otherwise
* the data will be copied from the DS polling loop.
*/
void GetData();
private:
/**
* DriverStation constructor.
*
* This is only called once the first time GetInstance() is called
*/
DriverStation();
/**
* Reports errors related to unplugged joysticks.
*
* Throttles the errors so that they don't overwhelm the DS.
*/
void ReportJoystickUnpluggedError(const wpi::Twine& message);
/**
* Reports errors related to unplugged joysticks.
*
* Throttles the errors so that they don't overwhelm the DS.
*/
void ReportJoystickUnpluggedWarning(const wpi::Twine& message);
void Run();
/**
* Gets ControlWord data from the cache. If 50ms has passed, or the force
* parameter is set, the cached data is updated. Otherwise the data is just
* copied from the cache.
*
* @param force True to force an update to the cache, otherwise update if 50ms
* have passed.
* @param controlWord Structure to put the return control word data into.
*/
void UpdateControlWord(bool force, HAL_ControlWord& controlWord) const;
void SendMatchData();
// Joystick User Data

View File

@@ -49,48 +49,311 @@ class Encoder : public ErrorBase,
kResetOnRisingEdge
};
/**
* Encoder constructor.
*
* Construct a Encoder given a and b channels.
*
* The counter will start counting immediately.
*
* @param aChannel The a channel DIO channel. 0-9 are on-board, 10-25
* are on the MXP port
* @param bChannel The b channel DIO channel. 0-9 are on-board, 10-25
* are on the MXP port
* @param reverseDirection represents the orientation of the encoder and
* inverts the output values if necessary so forward
* represents positive values.
* @param encodingType either k1X, k2X, or k4X to indicate 1X, 2X or 4X
* decoding. If 4X is selected, then an encoder FPGA
* object is used and the returned counts will be 4x
* the encoder spec'd value since all rising and
* falling edges are counted. If 1X or 2X are selected
* then a counter object will be used and the returned
* value will either exactly match the spec'd count or
* be double (2x) the spec'd count.
*/
Encoder(int aChannel, int bChannel, bool reverseDirection = false,
EncodingType encodingType = k4X);
/**
* Encoder constructor.
*
* Construct a Encoder given a and b channels as digital inputs. This is used
* in the case where the digital inputs are shared. The Encoder class will not
* allocate the digital inputs and assume that they already are counted.
*
* The counter will start counting immediately.
*
* @param aSource The source that should be used for the a channel.
* @param bSource the source that should be used for the b channel.
* @param reverseDirection represents the orientation of the encoder and
* inverts the output values if necessary so forward
* represents positive values.
* @param encodingType either k1X, k2X, or k4X to indicate 1X, 2X or 4X
* decoding. If 4X is selected, then an encoder FPGA
* object is used and the returned counts will be 4x
* the encoder spec'd value since all rising and
* falling edges are counted. If 1X or 2X are selected
* then a counter object will be used and the returned
* value will either exactly match the spec'd count or
* be double (2x) the spec'd count.
*/
Encoder(DigitalSource* aSource, DigitalSource* bSource,
bool reverseDirection = false, EncodingType encodingType = k4X);
/**
* Encoder constructor.
*
* Construct a Encoder given a and b channels as digital inputs. This is used
* in the case where the digital inputs are shared. The Encoder class will not
* allocate the digital inputs and assume that they already are counted.
*
* The counter will start counting immediately.
*
* @param aSource The source that should be used for the a channel.
* @param bSource the source that should be used for the b channel.
* @param reverseDirection represents the orientation of the encoder and
* inverts the output values if necessary so forward
* represents positive values.
* @param encodingType either k1X, k2X, or k4X to indicate 1X, 2X or 4X
* decoding. If 4X is selected, then an encoder FPGA
* object is used and the returned counts will be 4x
* the encoder spec'd value since all rising and
* falling edges are counted. If 1X or 2X are selected
* then a counter object will be used and the returned
* value will either exactly match the spec'd count or
* be double (2x) the spec'd count.
*/
Encoder(DigitalSource& aSource, DigitalSource& bSource,
bool reverseDirection = false, EncodingType encodingType = k4X);
Encoder(std::shared_ptr<DigitalSource> aSource,
std::shared_ptr<DigitalSource> bSource, bool reverseDirection = false,
EncodingType encodingType = k4X);
Encoder(DigitalSource* aSource, DigitalSource* bSource,
bool reverseDirection = false, EncodingType encodingType = k4X);
Encoder(DigitalSource& aSource, DigitalSource& bSource,
bool reverseDirection = false, EncodingType encodingType = k4X);
~Encoder() override;
// CounterBase interface
/**
* Gets the current count.
*
* Returns the current count on the Encoder. This method compensates for the
* decoding type.
*
* @return Current count from the Encoder adjusted for the 1x, 2x, or 4x scale
* factor.
*/
int Get() const override;
int GetRaw() const;
int GetEncodingScale() const;
/**
* Reset the Encoder distance to zero.
*
* Resets the current count to zero on the encoder.
*/
void Reset() override;
/**
* Returns the period of the most recent pulse.
*
* Returns the period of the most recent Encoder pulse in seconds. This method
* compensates for the decoding type.
*
* Warning: This returns unscaled periods. Use GetRate() for rates that are
* scaled using the value from SetDistancePerPulse().
*
* @return Period in seconds of the most recent pulse.
*/
double GetPeriod() const override;
/**
* Sets the maximum period for stopped detection.
*
* Sets the value that represents the maximum period of the Encoder before it
* will assume that the attached device is stopped. This timeout allows users
* to determine if the wheels or other shaft has stopped rotating.
* This method compensates for the decoding type.
*
* @deprecated Use SetMinRate() in favor of this method. This takes unscaled
* periods and SetMinRate() scales using value from
* SetDistancePerPulse().
*
* @param maxPeriod The maximum time between rising and falling edges before
* the FPGA will report the device stopped. This is expressed
* in seconds.
*/
void SetMaxPeriod(double maxPeriod) override;
/**
* Determine if the encoder is stopped.
*
* Using the MaxPeriod value, a boolean is returned that is true if the
* encoder is considered stopped and false if it is still moving. A stopped
* encoder is one where the most recent pulse width exceeds the MaxPeriod.
*
* @return True if the encoder is considered stopped.
*/
bool GetStopped() const override;
/**
* The last direction the encoder value changed.
*
* @return The last direction the encoder value changed.
*/
bool GetDirection() const override;
/**
* Gets the raw value from the encoder.
*
* The raw value is the actual count unscaled by the 1x, 2x, or 4x scale
* factor.
*
* @return Current raw count from the encoder
*/
int GetRaw() const;
/**
* The encoding scale factor 1x, 2x, or 4x, per the requested encodingType.
*
* Used to divide raw edge counts down to spec'd counts.
*/
int GetEncodingScale() const;
/**
* Get the distance the robot has driven since the last reset.
*
* @return The distance driven since the last reset as scaled by the value
* from SetDistancePerPulse().
*/
double GetDistance() const;
/**
* Get the current rate of the encoder.
*
* Units are distance per second as scaled by the value from
* SetDistancePerPulse().
*
* @return The current rate of the encoder.
*/
double GetRate() const;
/**
* Set the minimum rate of the device before the hardware reports it stopped.
*
* @param minRate The minimum rate. The units are in distance per second as
* scaled by the value from SetDistancePerPulse().
*/
void SetMinRate(double minRate);
/**
* Set the distance per pulse for this encoder.
*
* This sets the multiplier used to determine the distance driven based on the
* count value from the encoder.
*
* Do not include the decoding type in this scale. The library already
* compensates for the decoding type.
*
* Set this value based on the encoder's rated Pulses per Revolution and
* factor in gearing reductions following the encoder shaft.
*
* This distance can be in any units you like, linear or angular.
*
* @param distancePerPulse The scale factor that will be used to convert
* pulses to useful units.
*/
void SetDistancePerPulse(double distancePerPulse);
/**
* Get the distance per pulse for this encoder.
*
* @return The scale factor that will be used to convert pulses to useful
* units.
*/
double GetDistancePerPulse() const;
/**
* Set the direction sensing for this encoder.
*
* This sets the direction sensing on the encoder so that it could count in
* the correct software direction regardless of the mounting.
*
* @param reverseDirection true if the encoder direction should be reversed
*/
void SetReverseDirection(bool reverseDirection);
/**
* Set the Samples to Average which specifies the number of samples of the
* timer to average when calculating the period.
*
* Perform averaging to account for mechanical imperfections or as
* oversampling to increase resolution.
*
* @param samplesToAverage The number of samples to average from 1 to 127.
*/
void SetSamplesToAverage(int samplesToAverage);
/**
* Get the Samples to Average which specifies the number of samples of the
* timer to average when calculating the period.
*
* Perform averaging to account for mechanical imperfections or as
* oversampling to increase resolution.
*
* @return The number of samples being averaged (from 1 to 127)
*/
int GetSamplesToAverage() const;
double PIDGet() override;
/**
* Set the index source for the encoder.
*
* When this source is activated, the encoder count automatically resets.
*
* @param channel A DIO channel to set as the encoder index
* @param type The state that will cause the encoder to reset
*/
void SetIndexSource(int channel, IndexingType type = kResetOnRisingEdge);
/**
* Set the index source for the encoder.
*
* When this source is activated, the encoder count automatically resets.
*
* @param channel A digital source to set as the encoder index
* @param type The state that will cause the encoder to reset
*/
void SetIndexSource(const DigitalSource& source,
IndexingType type = kResetOnRisingEdge);
void InitSendable(SendableBuilder& builder) override;
int GetFPGAIndex() const;
void InitSendable(SendableBuilder& builder) override;
private:
/**
* Common initialization code for Encoders.
*
* This code allocates resources for Encoders and is common to all
* constructors. The counter will start counting immediately.
*
* @param reverseDirection If true, counts down instead of up (this is all
* relative)
* @param encodingType either k1X, k2X, or k4X to indicate 1X, 2X or 4X
* decoding. If 4X is selected, then an encoder FPGA
* object is used and the returned counts will be 4x
* the encoder spec'd value since all rising and
* falling edges are counted. If 1X or 2X are selected
* then a counter object will be used and the returned
* value will either exactly match the spec'd count or
* be double (2x) the spec'd count.
*/
void InitEncoder(bool reverseDirection, EncodingType encodingType);
/**
* The scale needed to convert a raw counter value into a number of encoder
* pulses.
*/
double DecodingScaleFactor() const;
std::shared_ptr<DigitalSource> m_aSource; // The A phase of the quad encoder

View File

@@ -80,36 +80,119 @@ class ErrorBase {
ErrorBase(const ErrorBase&) = delete;
ErrorBase& operator=(const ErrorBase&) = delete;
/**
* @brief Retrieve the current error.
*
* Get the current error information associated with this sensor.
*/
virtual Error& GetError();
/**
* @brief Retrieve the current error.
*
* Get the current error information associated with this sensor.
*/
virtual const Error& GetError() const;
/**
* @brief Clear the current error information associated with this sensor.
*/
virtual void ClearError() const;
/**
* @brief Set error information associated with a C library call that set an
* error to the "errno" global variable.
*
* @param contextMessage A custom message from the code that set the error.
* @param filename Filename of the error source
* @param function Function of the error source
* @param lineNumber Line number of the error source
*/
virtual void SetErrnoError(const wpi::Twine& contextMessage,
wpi::StringRef filename, wpi::StringRef function,
int lineNumber) const;
/**
* @brief Set the current error information associated from the nivision Imaq
* API.
*
* @param success The return from the function
* @param contextMessage A custom message from the code that set the error.
* @param filename Filename of the error source
* @param function Function of the error source
* @param lineNumber Line number of the error source
*/
virtual void SetImaqError(int success, const wpi::Twine& contextMessage,
wpi::StringRef filename, wpi::StringRef function,
int lineNumber) const;
/**
* @brief Set the current error information associated with this sensor.
*
* @param code The error code
* @param contextMessage A custom message from the code that set the error.
* @param filename Filename of the error source
* @param function Function of the error source
* @param lineNumber Line number of the error source
*/
virtual void SetError(Error::Code code, const wpi::Twine& contextMessage,
wpi::StringRef filename, wpi::StringRef function,
int lineNumber) const;
/**
* @brief Set the current error information associated with this sensor.
* Range versions use for initialization code.
*
* @param code The error code
* @param minRange The minimum allowed allocation range
* @param maxRange The maximum allowed allocation range
* @param requestedValue The requested value to allocate
* @param contextMessage A custom message from the code that set the error.
* @param filename Filename of the error source
* @param function Function of the error source
* @param lineNumber Line number of the error source
*/
virtual void SetErrorRange(Error::Code code, int32_t minRange,
int32_t maxRange, int32_t requestedValue,
const wpi::Twine& contextMessage,
wpi::StringRef filename, wpi::StringRef function,
int lineNumber) const;
/**
* @brief Set the current error information associated with this sensor.
*
* @param errorMessage The error message from WPIErrors.h
* @param contextMessage A custom message from the code that set the error.
* @param filename Filename of the error source
* @param function Function of the error source
* @param lineNumber Line number of the error source
*/
virtual void SetWPIError(const wpi::Twine& errorMessage, Error::Code code,
const wpi::Twine& contextMessage,
wpi::StringRef filename, wpi::StringRef function,
int lineNumber) const;
virtual void CloneError(const ErrorBase& rhs) const;
virtual void ClearError() const;
/**
* @brief Check if the current error code represents a fatal error.
*
* @return true if the current error is fatal.
*/
virtual bool StatusIsFatal() const;
static void SetGlobalError(Error::Code code, const wpi::Twine& contextMessage,
wpi::StringRef filename, wpi::StringRef function,
int lineNumber);
static void SetGlobalWPIError(const wpi::Twine& errorMessage,
const wpi::Twine& contextMessage,
wpi::StringRef filename,
wpi::StringRef function, int lineNumber);
/**
* Retrieve the current global error.
*/
static Error& GetGlobalError();
protected:

View File

@@ -69,22 +69,106 @@ namespace frc {
*/
class LinearDigitalFilter : public Filter {
public:
/**
* Create a linear FIR or IIR filter.
*
* @param source The PIDSource object that is used to get values
* @param ffGains The "feed forward" or FIR gains
* @param fbGains The "feed back" or IIR gains
*/
LinearDigitalFilter(PIDSource& source, wpi::ArrayRef<double> ffGains,
wpi::ArrayRef<double> fbGains);
/**
* Create a linear FIR or IIR filter.
*
* @param source The PIDSource object that is used to get values
* @param ffGains The "feed forward" or FIR gains
* @param fbGains The "feed back" or IIR gains
*/
LinearDigitalFilter(std::shared_ptr<PIDSource> source,
wpi::ArrayRef<double> ffGains,
wpi::ArrayRef<double> fbGains);
// Static methods to create commonly used filters
/**
* Creates a one-pole IIR low-pass filter of the form:<br>
* y[n] = (1 - gain) * x[n] + gain * y[n-1]<br>
* where gain = e<sup>-dt / T</sup>, T is the time constant in seconds
*
* This filter is stable for time constants greater than zero.
*
* @param source The PIDSource object that is used to get values
* @param timeConstant The discrete-time time constant in seconds
* @param period The period in seconds between samples taken by the user
*/
static LinearDigitalFilter SinglePoleIIR(PIDSource& source,
double timeConstant, double period);
/**
* Creates a first-order high-pass filter of the form:<br>
* y[n] = gain * x[n] + (-gain) * x[n-1] + gain * y[n-1]<br>
* where gain = e<sup>-dt / T</sup>, T is the time constant in seconds
*
* This filter is stable for time constants greater than zero.
*
* @param source The PIDSource object that is used to get values
* @param timeConstant The discrete-time time constant in seconds
* @param period The period in seconds between samples taken by the user
*/
static LinearDigitalFilter HighPass(PIDSource& source, double timeConstant,
double period);
/**
* Creates a K-tap FIR moving average filter of the form:<br>
* y[n] = 1/k * (x[k] + x[k-1] + … + x[0])
*
* This filter is always stable.
*
* @param source The PIDSource object that is used to get values
* @param taps The number of samples to average over. Higher = smoother but
* slower
*/
static LinearDigitalFilter MovingAverage(PIDSource& source, int taps);
/**
* Creates a one-pole IIR low-pass filter of the form:<br>
* y[n] = (1 - gain) * x[n] + gain * y[n-1]<br>
* where gain = e<sup>-dt / T</sup>, T is the time constant in seconds
*
* This filter is stable for time constants greater than zero.
*
* @param source The PIDSource object that is used to get values
* @param timeConstant The discrete-time time constant in seconds
* @param period The period in seconds between samples taken by the user
*/
static LinearDigitalFilter SinglePoleIIR(std::shared_ptr<PIDSource> source,
double timeConstant, double period);
/**
* Creates a first-order high-pass filter of the form:<br>
* y[n] = gain * x[n] + (-gain) * x[n-1] + gain * y[n-1]<br>
* where gain = e<sup>-dt / T</sup>, T is the time constant in seconds
*
* This filter is stable for time constants greater than zero.
*
* @param source The PIDSource object that is used to get values
* @param timeConstant The discrete-time time constant in seconds
* @param period The period in seconds between samples taken by the user
*/
static LinearDigitalFilter HighPass(std::shared_ptr<PIDSource> source,
double timeConstant, double period);
/**
* Creates a K-tap FIR moving average filter of the form:<br>
* y[n] = 1/k * (x[k] + x[k-1] + … + x[0])
*
* This filter is always stable.
*
* @param source The PIDSource object that is used to get values
* @param taps The number of samples to average over. Higher = smoother but
* slower
*/
static LinearDigitalFilter MovingAverage(std::shared_ptr<PIDSource> source,
int taps);
@@ -93,6 +177,11 @@ class LinearDigitalFilter : public Filter {
void Reset() override;
// PIDSource interface
/**
* Calculates the next value of the filter
*
* @return The filtered value at this step
*/
double PIDGet() override;
private:

View File

@@ -26,11 +26,44 @@ class GearTooth : public Counter {
// 55 uSec for threshold
static constexpr double kGearToothThreshold = 55e-6;
/**
* Construct a GearTooth sensor given a channel.
*
* @param channel The DIO channel that the sensor is connected to.
* 0-9 are on-board, 10-25 are on the MXP.
* @param directionSensitive True to enable the pulse length decoding in
* hardware to specify count direction.
*/
explicit GearTooth(int channel, bool directionSensitive = false);
/**
* Construct a GearTooth sensor given a digital input.
*
* This should be used when sharing digital inputs.
*
* @param source A pointer to the existing DigitalSource object
* (such as a DigitalInput)
* @param directionSensitive True to enable the pulse length decoding in
* hardware to specify count direction.
*/
explicit GearTooth(DigitalSource* source, bool directionSensitive = false);
/**
* Construct a GearTooth sensor given a digital input.
*
* This should be used when sharing digital inputs.
*
* @param source A reference to the existing DigitalSource object
* (such as a DigitalInput)
* @param directionSensitive True to enable the pulse length decoding in
* hardware to specify count direction.
*/
explicit GearTooth(std::shared_ptr<DigitalSource> source,
bool directionSensitive = false);
/**
* Common code called by the constructors.
*/
void EnableDirectionSensing(bool directionSensitive);
void InitSendable(SendableBuilder& builder) override;

View File

@@ -52,25 +52,127 @@ class GenericHID : public ErrorBase {
virtual double GetX(JoystickHand hand = kRightHand) const = 0;
virtual double GetY(JoystickHand hand = kRightHand) const = 0;
/**
* Get the button value (starting at button 1).
*
* The buttons are returned in a single 16 bit value with one bit representing
* the state of each button. The appropriate button is returned as a boolean
* value.
*
* @param button The button number to be read (starting at 1)
* @return The state of the button.
*/
bool GetRawButton(int button) const;
/**
* Whether the button was pressed since the last check. Button indexes begin
* at 1.
*
* @param button The button index, beginning at 1.
* @return Whether the button was pressed since the last check.
*/
bool GetRawButtonPressed(int button);
/**
* Whether the button was released since the last check. Button indexes begin
* at 1.
*
* @param button The button index, beginning at 1.
* @return Whether the button was released since the last check.
*/
bool GetRawButtonReleased(int button);
/**
* Get the value of the axis.
*
* @param axis The axis to read, starting at 0.
* @return The value of the axis.
*/
double GetRawAxis(int axis) const;
/**
* Get the angle in degrees of a POV on the HID.
*
* The POV angles start at 0 in the up direction, and increase clockwise
* (e.g. right is 90, upper-left is 315).
*
* @param pov The index of the POV to read (starting at 0)
* @return the angle of the POV in degrees, or -1 if the POV is not pressed.
*/
int GetPOV(int pov = 0) const;
/**
* Get the number of axes for the HID.
*
* @return the number of axis for the current HID
*/
int GetAxisCount() const;
/**
* Get the number of POVs for the HID.
*
* @return the number of POVs for the current HID
*/
int GetPOVCount() const;
/**
* Get the number of buttons for the HID.
*
* @return the number of buttons on the current HID
*/
int GetButtonCount() const;
/**
* Get the type of the HID.
*
* @return the type of the HID.
*/
GenericHID::HIDType GetType() const;
/**
* Get the name of the HID.
*
* @return the name of the HID.
*/
std::string GetName() const;
/**
* Get the axis type of a joystick axis.
*
* @return the axis type of a joystick axis.
*/
int GetAxisType(int axis) const;
/**
* Get the port number of the HID.
*
* @return The port number of the HID.
*/
int GetPort() const;
/**
* Set a single HID output value for the HID.
*
* @param outputNumber The index of the output to set (1-32)
* @param value The value to set the output to
*/
void SetOutput(int outputNumber, bool value);
/**
* Set all output values for the HID.
*
* @param value The 32 bit output value (1 bit for each output)
*/
void SetOutputs(int value);
/**
* Set the rumble output for the HID.
*
* The DS currently supports 2 rumble values, left rumble and right rumble.
*
* @param type Which rumble value to set
* @param value The normalized value (0 to 1) to set the rumble to
*/
void SetRumble(RumbleType type, double value);
private:

View File

@@ -24,6 +24,12 @@ class GyroBase : public Gyro,
public PIDSource {
public:
// PIDSource interface
/**
* Get the PIDOutput for the PIDSource base object. Can be set to return
* angle or rate using SetPIDSourceType(). Defaults to angle.
*
* @return The PIDOutput (angle or rate, defaults to angle)
*/
double PIDGet() override;
void InitSendable(SendableBuilder& builder) override;

View File

@@ -25,19 +25,113 @@ class I2C : public ErrorBase {
public:
enum Port { kOnboard = 0, kMXP };
/**
* Constructor.
*
* @param port The I2C port to which the device is connected.
* @param deviceAddress The address of the device on the I2C bus.
*/
I2C(Port port, int deviceAddress);
~I2C() override;
I2C(const I2C&) = delete;
I2C& operator=(const I2C&) = delete;
/**
* Generic transaction.
*
* This is a lower-level interface to the I2C hardware giving you more control
* over each transaction.
*
* @param dataToSend Buffer of data to send as part of the transaction.
* @param sendSize Number of bytes to send as part of the transaction.
* @param dataReceived Buffer to read data into.
* @param receiveSize Number of bytes to read from the device.
* @return Transfer Aborted... false for success, true for aborted.
*/
bool Transaction(uint8_t* dataToSend, int sendSize, uint8_t* dataReceived,
int receiveSize);
/**
* Attempt to address a device on the I2C bus.
*
* This allows you to figure out if there is a device on the I2C bus that
* responds to the address specified in the constructor.
*
* @return Transfer Aborted... false for success, true for aborted.
*/
bool AddressOnly();
/**
* Execute a write transaction with the device.
*
* Write a single byte to a register on a device and wait until the
* transaction is complete.
*
* @param registerAddress The address of the register on the device to be
* written.
* @param data The byte to write to the register on the device.
* @return Transfer Aborted... false for success, true for aborted.
*/
bool Write(int registerAddress, uint8_t data);
/**
* Execute a bulk write transaction with the device.
*
* Write multiple bytes to a device and wait until the
* transaction is complete.
*
* @param data The data to write to the register on the device.
* @param count The number of bytes to be written.
* @return Transfer Aborted... false for success, true for aborted.
*/
bool WriteBulk(uint8_t* data, int count);
/**
* Execute a read transaction with the device.
*
* Read bytes from a device.
* Most I2C devices will auto-increment the register pointer internally
* allowing you to read consecutive registers on a device in a single
* transaction.
*
* @param registerAddress The register to read first in the transaction.
* @param count The number of bytes to read in the transaction.
* @param buffer A pointer to the array of bytes to store the data
* read from the device.
* @return Transfer Aborted... false for success, true for aborted.
*/
bool Read(int registerAddress, int count, uint8_t* data);
/**
* Execute a read only transaction with the device.
*
* Read bytes from a device. This method does not write any data to prompt the
* device.
*
* @param buffer A pointer to the array of bytes to store the data read from
* the device.
* @param count The number of bytes to read in the transaction.
* @return Transfer Aborted... false for success, true for aborted.
*/
bool ReadOnly(int count, uint8_t* buffer);
/**
* Verify that a device's registers contain expected values.
*
* Most devices will have a set of registers that contain a known value that
* can be used to identify them. This allows an I2C device driver to easily
* verify that the device contains the expected value.
*
* @pre The device must support and be configured to use register
* auto-increment.
*
* @param registerAddress The base register to start reading from the device.
* @param count The size of the field to be verified.
* @param expected A buffer containing the values expected from the
* device.
*/
bool VerifySensor(int registerAddress, int count, const uint8_t* expected);
private:

View File

@@ -29,36 +29,95 @@ class InterruptableSensorBase : public ErrorBase, public SendableBase {
virtual HAL_Handle GetPortHandleForRouting() const = 0;
virtual AnalogTriggerType GetAnalogTriggerTypeForRouting() const = 0;
// Asynchronous handler version.
/**
* Request one of the 8 interrupts asynchronously on this digital input.
*
* Request interrupts in asynchronous mode where the user's interrupt handler
* will be called when the interrupt fires. Users that want control over the
* thread priority should use the synchronous method with their own spawned
* thread. The default is interrupt on rising edges only.
*/
virtual void RequestInterrupts(HAL_InterruptHandlerFunction handler,
void* param);
// Synchronous wait version.
/**
* Request one of the 8 interrupts synchronously on this digital input.
*
* Request interrupts in synchronous mode where the user program will have to
* explicitly wait for the interrupt to occur using WaitForInterrupt.
* The default is interrupt on rising edges only.
*/
virtual void RequestInterrupts();
// Free up the underlying ChipObject functions.
/**
* Cancel interrupts on this device.
*
* This deallocates all the chipobject structures and disables any interrupts.
*/
virtual void CancelInterrupts();
// Synchronous version.
/**
* In synchronous mode, wait for the defined interrupt to occur.
*
* You should <b>NOT</b> attempt to read the sensor from another thread while
* waiting for an interrupt. This is not threadsafe, and can cause memory
* corruption
*
* @param timeout Timeout in seconds
* @param ignorePrevious If true, ignore interrupts that happened before
* WaitForInterrupt was called.
* @return What interrupts fired
*/
virtual WaitResult WaitForInterrupt(double timeout,
bool ignorePrevious = true);
// Enable interrupts - after finishing setup.
/**
* Enable interrupts to occur on this input.
*
* Interrupts are disabled when the RequestInterrupt call is made. This gives
* time to do the setup of the other options before starting to field
* interrupts.
*/
virtual void EnableInterrupts();
// Disable, but don't deallocate.
/**
* Disable Interrupts without without deallocating structures.
*/
virtual void DisableInterrupts();
// Return the timestamp for the rising interrupt that occurred.
/**
* Return the timestamp for the rising interrupt that occurred most recently.
*
* This is in the same time domain as GetClock().
* The rising-edge interrupt should be enabled with
* {@link #DigitalInput.SetUpSourceEdge}
*
* @return Timestamp in seconds since boot.
*/
virtual double ReadRisingTimestamp();
// Return the timestamp for the falling interrupt that occurred.
/**
* Return the timestamp for the falling interrupt that occurred most recently.
*
* This is in the same time domain as GetClock().
* The falling-edge interrupt should be enabled with
* {@link #DigitalInput.SetUpSourceEdge}
*
* @return Timestamp in seconds since boot.
*/
virtual double ReadFallingTimestamp();
/**
* Set which edge to trigger interrupts on
*
* @param risingEdge true to interrupt on rising edge
* @param fallingEdge true to interrupt on falling edge
*/
virtual void SetUpSourceEdge(bool risingEdge, bool fallingEdge);
protected:
HAL_InterruptHandle m_interrupt = HAL_kInvalidHandle;
void AllocateInterrupts(bool watcher);
};

View File

@@ -25,6 +25,12 @@ class IterativeRobot : public IterativeRobotBase {
IterativeRobot();
virtual ~IterativeRobot() = default;
/**
* Provide an alternate "main loop" via StartCompetition().
*
* This specific StartCompetition() implements "main loop" behaviour synced
* with the DS packets.
*/
void StartCompetition() override;
};

View File

@@ -42,16 +42,95 @@ namespace frc {
*/
class IterativeRobotBase : public RobotBase {
public:
/**
* Robot-wide initialization code should go here.
*
* Users should override this method for default Robot-wide initialization
* which will be called when the robot is first powered on. It will be called
* exactly one time.
*
* Warning: the Driver Station "Robot Code" light and FMS "Robot Ready"
* indicators will be off until RobotInit() exits. Code in RobotInit() that
* waits for enable will cause the robot to never indicate that the code is
* ready, causing the robot to be bypassed in a match.
*/
virtual void RobotInit();
/**
* Initialization code for disabled mode should go here.
*
* Users should override this method for initialization code which will be
* called each time
* the robot enters disabled mode.
*/
virtual void DisabledInit();
/**
* Initialization code for autonomous mode should go here.
*
* Users should override this method for initialization code which will be
* called each time the robot enters autonomous mode.
*/
virtual void AutonomousInit();
/**
* Initialization code for teleop mode should go here.
*
* Users should override this method for initialization code which will be
* called each time the robot enters teleop mode.
*/
virtual void TeleopInit();
/**
* Initialization code for test mode should go here.
*
* Users should override this method for initialization code which will be
* called each time the robot enters test mode.
*/
virtual void TestInit();
/**
* Periodic code for all modes should go here.
*
* This function is called each time a new packet is received from the driver
* station.
*/
virtual void RobotPeriodic();
/**
* Periodic code for disabled mode should go here.
*
* Users should override this method for code which will be called each time a
* new packet is received from the driver station and the robot is in disabled
* mode.
*/
virtual void DisabledPeriodic();
/**
* Periodic code for autonomous mode should go here.
*
* Users should override this method for code which will be called each time a
* new packet is received from the driver station and the robot is in
* autonomous mode.
*/
virtual void AutonomousPeriodic();
/**
* Periodic code for teleop mode should go here.
*
* Users should override this method for code which will be called each time a
* new packet is received from the driver station and the robot is in teleop
* mode.
*/
virtual void TeleopPeriodic();
/**
* Periodic code for test mode should go here.
*
* Users should override this method for code which will be called each time a
* new packet is received from the driver station and the robot is in test
* mode.
*/
virtual void TestPeriodic();
protected:

View File

@@ -16,6 +16,12 @@ namespace frc {
*/
class Jaguar : public PWMSpeedController {
public:
/**
* Constructor for a Jaguar connected via PWM.
*
* @param channel The PWM channel that the Jaguar is attached to. 0-9 are
* on-board, 10-19 are on the MXP port
*/
explicit Jaguar(int channel);
};

View File

@@ -45,55 +45,240 @@ class Joystick : public GenericHID {
enum AxisType { kXAxis, kYAxis, kZAxis, kTwistAxis, kThrottleAxis };
enum ButtonType { kTriggerButton, kTopButton };
/**
* Construct an instance of a joystick.
*
* The joystick index is the USB port on the Driver Station.
*
* @param port The port on the Driver Station that the joystick is plugged
* into (0-5).
*/
explicit Joystick(int port);
virtual ~Joystick() = default;
Joystick(const Joystick&) = delete;
Joystick& operator=(const Joystick&) = delete;
/**
* Set the channel associated with the X axis.
*
* @param channel The channel to set the axis to.
*/
void SetXChannel(int channel);
/**
* Set the channel associated with the Y axis.
*
* @param axis The axis to set the channel for.
* @param channel The channel to set the axis to.
*/
void SetYChannel(int channel);
/**
* Set the channel associated with the Z axis.
*
* @param axis The axis to set the channel for.
* @param channel The channel to set the axis to.
*/
void SetZChannel(int channel);
/**
* Set the channel associated with the twist axis.
*
* @param axis The axis to set the channel for.
* @param channel The channel to set the axis to.
*/
void SetTwistChannel(int channel);
/**
* Set the channel associated with the throttle axis.
*
* @param axis The axis to set the channel for.
* @param channel The channel to set the axis to.
*/
void SetThrottleChannel(int channel);
/**
* Set the channel associated with a specified axis.
*
* @param axis The axis to set the channel for.
* @param channel The channel to set the axis to.
*/
WPI_DEPRECATED("Use the more specific axis channel setter functions.")
void SetAxisChannel(AxisType axis, int channel);
/**
* Get the channel currently associated with the X axis.
*
* @return The channel for the axis.
*/
int GetXChannel() const;
/**
* Get the channel currently associated with the Y axis.
*
* @return The channel for the axis.
*/
int GetYChannel() const;
/**
* Get the channel currently associated with the Z axis.
*
* @return The channel for the axis.
*/
int GetZChannel() const;
/**
* Get the channel currently associated with the twist axis.
*
* @return The channel for the axis.
*/
int GetTwistChannel() const;
/**
* Get the channel currently associated with the throttle axis.
*
* @return The channel for the axis.
*/
int GetThrottleChannel() const;
WPI_DEPRECATED("Use the more specific axis channel getter functions.")
int GetAxisChannel(AxisType axis) const;
/**
* Get the X value of the joystick.
*
* This depends on the mapping of the joystick connected to the current port.
*
* @param hand This parameter is ignored for the Joystick class and is only
* here to complete the GenericHID interface.
*/
double GetX(JoystickHand hand = kRightHand) const override;
/**
* Get the Y value of the joystick.
*
* This depends on the mapping of the joystick connected to the current port.
*
* @param hand This parameter is ignored for the Joystick class and is only
* here to complete the GenericHID interface.
*/
double GetY(JoystickHand hand = kRightHand) const override;
/**
* Get the Z value of the current joystick.
*
* This depends on the mapping of the joystick connected to the current port.
*/
double GetZ() const;
/**
* Get the twist value of the current joystick.
*
* This depends on the mapping of the joystick connected to the current port.
*/
double GetTwist() const;
/**
* Get the throttle value of the current joystick.
*
* This depends on the mapping of the joystick connected to the current port.
*/
double GetThrottle() const;
/**
* For the current joystick, return the axis determined by the argument.
*
* This is for cases where the joystick axis is returned programatically,
* otherwise one of the previous functions would be preferable (for example
* GetX()).
*
* @param axis The axis to read.
* @return The value of the axis.
*/
WPI_DEPRECATED("Use the more specific axis channel getter functions.")
double GetAxis(AxisType axis) const;
/**
* Read the state of the trigger on the joystick.
*
* Look up which button has been assigned to the trigger and read its state.
*
* @return The state of the trigger.
*/
bool GetTrigger() const;
/**
* Whether the trigger was pressed since the last check.
*
* @return Whether the button was pressed since the last check.
*/
bool GetTriggerPressed();
/**
* Whether the trigger was released since the last check.
*
* @return Whether the button was released since the last check.
*/
bool GetTriggerReleased();
/**
* Read the state of the top button on the joystick.
*
* Look up which button has been assigned to the top and read its state.
*
* @return The state of the top button.
*/
bool GetTop() const;
/**
* Whether the top button was pressed since the last check.
*
* @return Whether the button was pressed since the last check.
*/
bool GetTopPressed();
/**
* Whether the top button was released since the last check.
*
* @return Whether the button was released since the last check.
*/
bool GetTopReleased();
WPI_DEPRECATED("Use Joystick instances instead.")
static Joystick* GetStickForPort(int port);
/**
* Get buttons based on an enumerated type.
*
* The button type will be looked up in the list of buttons and then read.
*
* @param button The type of button to read.
* @return The state of the button.
*/
WPI_DEPRECATED("Use the more specific button getter functions.")
bool GetButton(ButtonType button) const;
/**
* Get the magnitude of the direction vector formed by the joystick's
* current position relative to its origin.
*
* @return The magnitude of the direction vector
*/
double GetMagnitude() const;
/**
* Get the direction of the vector formed by the joystick and its origin
* in radians.
*
* @return The direction of the vector in radians
*/
double GetDirectionRadians() const;
/**
* Get the direction of the vector formed by the joystick and its origin
* in degrees.
*
* @return The direction of the vector in degrees
*/
double GetDirectionDegrees() const;
private:

View File

@@ -25,51 +25,182 @@ class LiveWindow {
LiveWindow(const LiveWindow&) = delete;
LiveWindow& operator=(const LiveWindow&) = delete;
/**
* Get an instance of the LiveWindow main class.
*
* This is a singleton to guarantee that there is only a single instance
* regardless of how many times GetInstance is called.
*/
static LiveWindow* GetInstance();
WPI_DEPRECATED("no longer required")
void Run() { UpdateValues(); }
void Run();
/**
* Add a Sensor associated with the subsystem and call it by the given name.
*
* @param subsystem The subsystem this component is part of.
* @param name The name of this component.
* @param component A Sendable component that represents a sensor.
*/
WPI_DEPRECATED("use Sendable::SetName() instead")
void AddSensor(const wpi::Twine& subsystem, const wpi::Twine& name,
Sendable* component);
/**
* Add a Sensor associated with the subsystem and call it by the given name.
*
* @param subsystem The subsystem this component is part of.
* @param name The name of this component.
* @param component A Sendable component that represents a sensor.
*/
WPI_DEPRECATED("use Sendable::SetName() instead")
void AddSensor(const wpi::Twine& subsystem, const wpi::Twine& name,
Sendable& component);
/**
* Add a Sensor associated with the subsystem and call it by the given name.
*
* @param subsystem The subsystem this component is part of.
* @param name The name of this component.
* @param component A Sendable component that represents a sensor.
*/
WPI_DEPRECATED("use Sendable::SetName() instead")
void AddSensor(const wpi::Twine& subsystem, const wpi::Twine& name,
std::shared_ptr<Sendable> component);
/**
* Add an Actuator associated with the subsystem and call it by the given
* name.
*
* @param subsystem The subsystem this component is part of.
* @param name The name of this component.
* @param component A Sendable component that represents a actuator.
*/
WPI_DEPRECATED("use Sendable::SetName() instead")
void AddActuator(const wpi::Twine& subsystem, const wpi::Twine& name,
Sendable* component);
/**
* Add an Actuator associated with the subsystem and call it by the given
* name.
*
* @param subsystem The subsystem this component is part of.
* @param name The name of this component.
* @param component A Sendable component that represents a actuator.
*/
WPI_DEPRECATED("use Sendable::SetName() instead")
void AddActuator(const wpi::Twine& subsystem, const wpi::Twine& name,
Sendable& component);
/**
* Add an Actuator associated with the subsystem and call it by the given
* name.
*
* @param subsystem The subsystem this component is part of.
* @param name The name of this component.
* @param component A Sendable component that represents a actuator.
*/
WPI_DEPRECATED("use Sendable::SetName() instead")
void AddActuator(const wpi::Twine& subsystem, const wpi::Twine& name,
std::shared_ptr<Sendable> component);
/**
* Meant for internal use in other WPILib classes.
*
* @deprecated Use SendableBase::SetName() instead.
*/
WPI_DEPRECATED("use SensorUtil::SetName() instead")
void AddSensor(const wpi::Twine& type, int channel, Sendable* component);
/**
* Meant for internal use in other WPILib classes.
*
* @deprecated Use SendableBase::SetName() instead.
*/
WPI_DEPRECATED("use SensorUtil::SetName() instead")
void AddActuator(const wpi::Twine& type, int channel, Sendable* component);
/**
* Meant for internal use in other WPILib classes.
*
* @deprecated Use SendableBase::SetName() instead.
*/
WPI_DEPRECATED("use SensorUtil::SetName() instead")
void AddActuator(const wpi::Twine& type, int module, int channel,
Sendable* component);
/**
* Add a component to the LiveWindow.
*
* @param sendable component to add
*/
void Add(std::shared_ptr<Sendable> component);
/**
* Add a component to the LiveWindow.
*
* @param sendable component to add
*/
void Add(Sendable* component);
/**
* Add a child component to a component.
*
* @param parent parent component
* @param child child component
*/
void AddChild(Sendable* parent, std::shared_ptr<Sendable> component);
/**
* Add a child component to a component.
*
* @param parent parent component
* @param child child component
*/
void AddChild(Sendable* parent, void* component);
/**
* Remove the component from the LiveWindow.
*
* @param sendable component to remove
*/
void Remove(Sendable* component);
/**
* Enable telemetry for a single component.
*
* @param sendable component
*/
void EnableTelemetry(Sendable* component);
/**
* Disable telemetry for a single component.
*
* @param sendable component
*/
void DisableTelemetry(Sendable* component);
/**
* Disable ALL telemetry.
*/
void DisableAllTelemetry();
bool IsEnabled() const;
/**
* Change the enabled status of LiveWindow.
*
* If it changes to enabled, start livewindow running otherwise stop it
*/
void SetEnabled(bool enabled);
/**
* Tell all the sensors to update (send) their values.
*
* Actuators are handled through callbacks on their value changing from the
* SmartDashboard widgets.
*/
void UpdateValues();
private:

View File

@@ -19,15 +19,84 @@ class MotorSafety;
class MotorSafetyHelper : public ErrorBase {
public:
/**
* The constructor for a MotorSafetyHelper object.
*
* The helper object is constructed for every object that wants to implement
* the Motor Safety protocol. The helper object has the code to actually do
* the timing and call the motors Stop() method when the timeout expires. The
* motor object is expected to call the Feed() method whenever the motors
* value is updated.
*
* @param safeObject a pointer to the motor object implementing MotorSafety.
* This is used to call the Stop() method on the motor.
*/
explicit MotorSafetyHelper(MotorSafety* safeObject);
~MotorSafetyHelper();
/**
* Feed the motor safety object.
*
* Resets the timer on this object that is used to do the timeouts.
*/
void Feed();
/**
* Set the expiration time for the corresponding motor safety object.
*
* @param expirationTime The timeout value in seconds.
*/
void SetExpiration(double expirationTime);
/**
* Retrieve the timeout value for the corresponding motor safety object.
*
* @return the timeout value in seconds.
*/
double GetExpiration() const;
/**
* Determine if the motor is still operating or has timed out.
*
* @return a true value if the motor is still operating normally and hasn't
* timed out.
*/
bool IsAlive() const;
/**
* Check if this motor has exceeded its timeout.
*
* This method is called periodically to determine if this motor has exceeded
* its timeout value. If it has, the stop method is called, and the motor is
* shut down until its value is updated again.
*/
void Check();
/**
* Enable/disable motor safety for this device
*
* Turn on and off the motor safety option for this PWM object.
*
* @param enabled True if motor safety is enforced for this object
*/
void SetSafetyEnabled(bool enabled);
/**
* Return the state of the motor safety enabled flag
*
* Return if the motor safety is currently enabled for this devicce.
*
* @return True if motor safety is enforced for this device
*/
bool IsSafetyEnabled() const;
/**
* Check the motors to see if any have timed out.
*
* This static method is called periodically to poll all the motors and stop
* any that have timed out.
*/
static void CheckMotors();
private:

View File

@@ -27,30 +27,103 @@ class NidecBrushless : public ErrorBase,
public SpeedController,
public MotorSafety {
public:
/**
* Constructor.
*
* @param pwmChannel The PWM channel that the Nidec Brushless controller is
* attached to. 0-9 are on-board, 10-19 are on the MXP port.
* @param dioChannel The DIO channel that the Nidec Brushless controller is
* attached to. 0-9 are on-board, 10-25 are on the MXP port.
*/
NidecBrushless(int pwmChannel, int dioChannel);
~NidecBrushless() override = default;
// SpeedController interface
/**
* Set the PWM value.
*
* The PWM value is set using a range of -1.0 to 1.0, appropriately scaling
* the value for the FPGA.
*
* @param speed The speed value between -1.0 and 1.0 to set.
*/
void Set(double speed) override;
/**
* Get the recently set value of the PWM.
*
* @return The most recently set value for the PWM between -1.0 and 1.0.
*/
double Get() const override;
void SetInverted(bool isInverted) override;
bool GetInverted() const override;
/**
* Disable the motor. The Enable() function must be called to re-enable the
* motor.
*/
void Disable() override;
/**
* Stop the motor.
*
* This is called by the MotorSafetyHelper object when it has a timeout for
* this PWM and needs to stop it from running. Calling Set() will re-enable
* the motor.
*/
void StopMotor() override;
/**
* Re-enable the motor after Disable() has been called. The Set() function
* must be called to set a new motor speed.
*/
void Enable();
// PIDOutput interface
/**
* Write out the PID value as seen in the PIDOutput base object.
*
* @param output Write out the PWM value as was found in the PIDController
*/
void PIDWrite(double output) override;
// MotorSafety interface
/**
* Set the safety expiration time.
*
* @param timeout The timeout (in seconds) for this motor object
*/
void SetExpiration(double timeout) override;
/**
* Return the safety expiration time.
*
* @return The expiration time value.
*/
double GetExpiration() const override;
/**
* Check if the motor is currently alive or stopped due to a timeout.
*
* @return a bool value that is true if the motor has NOT timed out and should
* still be running.
*/
bool IsAlive() const override;
void SetSafetyEnabled(bool enabled) override;
bool IsSafetyEnabled() const override;
void GetDescription(wpi::raw_ostream& desc) const override;
/**
* Gets the channel number associated with the object.
*
* @return The channel number.
*/
int GetChannel() const;
// Sendable interface

View File

@@ -25,6 +25,12 @@ typedef std::function<void()> TimerEventHandler;
class Notifier : public ErrorBase {
public:
/**
* Create a Notifier for timer event notification.
*
* @param handler The handler is called at the notification time which is set
* using StartSingle or StartPeriodic.
*/
explicit Notifier(TimerEventHandler handler);
template <typename Callable, typename Arg, typename... Args>
@@ -32,23 +38,65 @@ class Notifier : public ErrorBase {
: Notifier(std::bind(std::forward<Callable>(f), std::forward<Arg>(arg),
std::forward<Args>(args)...)) {}
/**
* Free the resources for a timer event.
*/
virtual ~Notifier();
Notifier(const Notifier&) = delete;
Notifier& operator=(const Notifier&) = delete;
/**
* Change the handler function.
*
* @param handler Handler
*/
void SetHandler(TimerEventHandler handler);
/**
* Register for single event notification.
*
* A timer event is queued for a single event after the specified delay.
*
* @param delay Seconds to wait before the handler is called.
*/
void StartSingle(double delay);
/**
* Register for periodic event notification.
*
* A timer event is queued for periodic event notification. Each time the
* interrupt occurs, the event will be immediately requeued for the same time
* interval.
*
* @param period Period in seconds to call the handler starting one period
* after the call to this method.
*/
void StartPeriodic(double period);
/**
* Stop timer events from occuring.
*
* Stop any repeating timer events from occuring. This will also remove any
* single notification events from the queue.
*
* If a timer-based call to the registered handler is in progress, this
* function will block until the handler call is complete.
*/
void Stop();
private:
// update the HAL alarm
/**
* Update the HAL alarm time.
*/
void UpdateAlarm();
// the thread waiting on the HAL alarm
// The thread waiting on the HAL alarm
std::thread m_thread;
// held while updating process information
// Held while updating process information
wpi::mutex m_processMutex;
// HAL handle, atomic for proper destruction
std::atomic<HAL_NotifierHandle> m_notifier{0};

View File

@@ -35,53 +35,267 @@ namespace frc {
*/
class PIDBase : public SendableBase, public PIDInterface, public PIDOutput {
public:
/**
* Allocate a PID object with the given constants for P, I, D.
*
* @param Kp the proportional coefficient
* @param Ki the integral coefficient
* @param Kd the derivative coefficient
* @param source The PIDSource object that is used to get values
* @param output The PIDOutput object that is set to the output value
*/
PIDBase(double p, double i, double d, PIDSource& source, PIDOutput& output);
/**
* Allocate a PID object with the given constants for P, I, D.
*
* @param Kp the proportional coefficient
* @param Ki the integral coefficient
* @param Kd the derivative coefficient
* @param source The PIDSource object that is used to get values
* @param output The PIDOutput object that is set to the output value
*/
PIDBase(double p, double i, double d, double f, PIDSource& source,
PIDOutput& output);
~PIDBase() override = default;
PIDBase(const PIDBase&) = delete;
PIDBase& operator=(const PIDBase) = delete;
/**
* Return the current PID result.
*
* This is always centered on zero and constrained the the max and min outs.
*
* @return the latest calculated output
*/
virtual double Get() const;
/**
* Set the PID controller to consider the input to be continuous,
*
* Rather then using the max and min input range as constraints, it considers
* them to be the same point and automatically calculates the shortest route
* to the setpoint.
*
* @param continuous true turns on continuous, false turns off continuous
*/
virtual void SetContinuous(bool continuous = true);
/**
* Sets the maximum and minimum values expected from the input.
*
* @param minimumInput the minimum value expected from the input
* @param maximumInput the maximum value expected from the output
*/
virtual void SetInputRange(double minimumInput, double maximumInput);
/**
* Sets the minimum and maximum values to write.
*
* @param minimumOutput the minimum value to write to the output
* @param maximumOutput the maximum value to write to the output
*/
virtual void SetOutputRange(double minimumOutput, double maximumOutput);
/**
* Set the PID Controller gain parameters.
*
* Set the proportional, integral, and differential coefficients.
*
* @param p Proportional coefficient
* @param i Integral coefficient
* @param d Differential coefficient
*/
void SetPID(double p, double i, double d) override;
/**
* Set the PID Controller gain parameters.
*
* Set the proportional, integral, and differential coefficients.
*
* @param p Proportional coefficient
* @param i Integral coefficient
* @param d Differential coefficient
* @param f Feed forward coefficient
*/
virtual void SetPID(double p, double i, double d, double f);
/**
* Set the Proportional coefficient of the PID controller gain.
*
* @param p proportional coefficient
*/
void SetP(double p);
/**
* Set the Integral coefficient of the PID controller gain.
*
* @param i integral coefficient
*/
void SetI(double i);
/**
* Set the Differential coefficient of the PID controller gain.
*
* @param d differential coefficient
*/
void SetD(double d);
/**
* Get the Feed forward coefficient of the PID controller gain.
*
* @param f Feed forward coefficient
*/
void SetF(double f);
/**
* Get the Proportional coefficient.
*
* @return proportional coefficient
*/
double GetP() const override;
/**
* Get the Integral coefficient.
*
* @return integral coefficient
*/
double GetI() const override;
/**
* Get the Differential coefficient.
*
* @return differential coefficient
*/
double GetD() const override;
/**
* Get the Feed forward coefficient.
*
* @return Feed forward coefficient
*/
virtual double GetF() const;
/**
* Set the setpoint for the PIDBase.
*
* @param setpoint the desired setpoint
*/
void SetSetpoint(double setpoint) override;
/**
* Returns the current setpoint of the PIDBase.
*
* @return the current setpoint
*/
double GetSetpoint() const override;
/**
* Returns the change in setpoint over time of the PIDBase.
*
* @return the change in setpoint over time
*/
double GetDeltaSetpoint() const;
/**
* Returns the current difference of the input from the setpoint.
*
* @return the current error
*/
virtual double GetError() const;
/**
* Returns the current average of the error over the past few iterations.
*
* You can specify the number of iterations to average with
* SetToleranceBuffer() (defaults to 1). This is the same value that is used
* for OnTarget().
*
* @return the average error
*/
WPI_DEPRECATED("Use a LinearDigitalFilter as the input and GetError().")
virtual double GetAvgError() const;
/**
* Sets what type of input the PID controller will use.
*/
virtual void SetPIDSourceType(PIDSourceType pidSource);
/**
* Returns the type of input the PID controller is using.
*
* @return the PID controller input type
*/
virtual PIDSourceType GetPIDSourceType() const;
/**
* Set the percentage error which is considered tolerable for use with
* OnTarget.
*
* @param percentage error which is tolerable
*/
WPI_DEPRECATED("Use SetPercentTolerance() instead.")
virtual void SetTolerance(double percent);
/**
* Set the absolute error which is considered tolerable for use with
* OnTarget.
*
* @param percentage error which is tolerable
*/
virtual void SetAbsoluteTolerance(double absValue);
/**
* Set the percentage error which is considered tolerable for use with
* OnTarget.
*
* @param percentage error which is tolerable
*/
virtual void SetPercentTolerance(double percentValue);
/**
* Set the number of previous error samples to average for tolerancing. When
* determining whether a mechanism is on target, the user may want to use a
* rolling average of previous measurements instead of a precise position or
* velocity. This is useful for noisy sensors which return a few erroneous
* measurements when the mechanism is on target. However, the mechanism will
* not register as on target for at least the specified bufLength cycles.
*
* @param bufLength Number of previous cycles to average. Defaults to 1.
*/
WPI_DEPRECATED("Use a LinearDigitalFilter as the input.")
virtual void SetToleranceBuffer(int buf = 1);
/**
* Return true if the error is within the percentage of the total input range,
* determined by SetTolerance. This asssumes that the maximum and minimum
* input were set using SetInput.
*
* Currently this just reports on target as the actual value passes through
* the setpoint. Ideally it should be based on being within the tolerance for
* some period of time.
*
* This will return false until at least one input value has been computed.
*/
virtual bool OnTarget() const;
/**
* Reset the previous error, the integral term, and disable the controller.
*/
void Reset() override;
/**
* Passes the output directly to SetSetpoint().
*
* PIDControllers can be nested by passing a PIDController as another
* PIDController's output. In that case, the output of the parent controller
* becomes the input (i.e., the reference) of the child.
*
* It is the caller's responsibility to put the data into a valid form for
* SetSetpoint().
*/
void PIDWrite(double output) override;
void InitSendable(SendableBuilder& builder) override;
@@ -100,8 +314,36 @@ class PIDBase : public SendableBase, public PIDInterface, public PIDOutput {
PIDOutput* m_pidOutput;
Timer m_setpointTimer;
/**
* Read the input, calculate the output accordingly, and write to the output.
* This should only be called by the Notifier.
*/
virtual void Calculate();
/**
* Calculate the feed forward term.
*
* Both of the provided feed forward calculations are velocity feed forwards.
* If a different feed forward calculation is desired, the user can override
* this function and provide his or her own. This function does no
* synchronization because the PIDBase class only calls it in synchronized
* code, so be careful if calling it oneself.
*
* If a velocity PID controller is being used, the F term should be set to 1
* over the maximum setpoint for the output. If a position PID controller is
* being used, the F term should be set to 1 over the maximum speed for the
* output measured in setpoint units per this controller's update period (see
* the default period in this class's constructor).
*/
virtual double CalculateFeedForward();
/**
* Wraps error around for continuous inputs. The original error is returned if
* continuous mode is disabled. This is an unsynchronized function.
*
* @param error The current error of the PID controller.
* @return Error for continuous inputs.
*/
double GetContinuousError(double error) const;
private:

View File

@@ -37,24 +37,95 @@ class PIDOutput;
*/
class PIDController : public PIDBase, public Controller {
public:
/**
* Allocate a PID object with the given constants for P, I, D.
*
* @param Kp the proportional coefficient
* @param Ki the integral coefficient
* @param Kd the derivative coefficient
* @param source The PIDSource object that is used to get values
* @param output The PIDOutput object that is set to the output value
* @param period the loop time for doing calculations. This particularly
* effects calculations of the integral and differental terms.
* The default is 50ms.
*/
PIDController(double p, double i, double d, PIDSource* source,
PIDOutput* output, double period = 0.05);
/**
* Allocate a PID object with the given constants for P, I, D.
*
* @param Kp the proportional coefficient
* @param Ki the integral coefficient
* @param Kd the derivative coefficient
* @param source The PIDSource object that is used to get values
* @param output The PIDOutput object that is set to the output value
* @param period the loop time for doing calculations. This particularly
* effects calculations of the integral and differental terms.
* The default is 50ms.
*/
PIDController(double p, double i, double d, double f, PIDSource* source,
PIDOutput* output, double period = 0.05);
/**
* Allocate a PID object with the given constants for P, I, D.
*
* @param Kp the proportional coefficient
* @param Ki the integral coefficient
* @param Kd the derivative coefficient
* @param source The PIDSource object that is used to get values
* @param output The PIDOutput object that is set to the output value
* @param period the loop time for doing calculations. This particularly
* effects calculations of the integral and differental terms.
* The default is 50ms.
*/
PIDController(double p, double i, double d, PIDSource& source,
PIDOutput& output, double period = 0.05);
/**
* Allocate a PID object with the given constants for P, I, D.
*
* @param Kp the proportional coefficient
* @param Ki the integral coefficient
* @param Kd the derivative coefficient
* @param source The PIDSource object that is used to get values
* @param output The PIDOutput object that is set to the output value
* @param period the loop time for doing calculations. This particularly
* effects calculations of the integral and differental terms.
* The default is 50ms.
*/
PIDController(double p, double i, double d, double f, PIDSource& source,
PIDOutput& output, double period = 0.05);
~PIDController() override;
PIDController(const PIDController&) = delete;
PIDController& operator=(const PIDController) = delete;
/**
* Begin running the PIDController.
*/
void Enable() override;
/**
* Stop running the PIDController, this sets the output to zero before
* stopping.
*/
void Disable() override;
/**
* Set the enabled state of the PIDController.
*/
void SetEnabled(bool enable);
/**
* Return true if PIDController is enabled.
*/
bool IsEnabled() const;
/**
* Reset the previous error, the integral term, and disable the controller.
*/
void Reset() override;
void InitSendable(SendableBuilder& builder) override;

View File

@@ -19,8 +19,15 @@ enum class PIDSourceType { kDisplacement, kRate };
*/
class PIDSource {
public:
/**
* Set which parameter you are using as a process control variable.
*
* @param pidSource An enum to select the parameter.
*/
virtual void SetPIDSourceType(PIDSourceType pidSource);
virtual PIDSourceType GetPIDSourceType() const;
virtual double PIDGet() = 0;
protected:

View File

@@ -53,25 +53,170 @@ class PWM : public ErrorBase, public SendableBase {
kPeriodMultiplier_4X = 4
};
/**
* Allocate a PWM given a channel number.
*
* Checks channel value range and allocates the appropriate channel.
* The allocation is only done to help users ensure that they don't double
* assign channels.
*
* @param channel The PWM channel number. 0-9 are on-board, 10-19 are on the
* MXP port
*/
explicit PWM(int channel);
/**
* Free the PWM channel.
*
* Free the resource associated with the PWM channel and set the value to 0.
*/
~PWM() override;
/**
* Set the PWM value directly to the hardware.
*
* Write a raw value to a PWM channel.
*
* @param value Raw PWM value.
*/
virtual void SetRaw(uint16_t value);
/**
* Get the PWM value directly from the hardware.
*
* Read a raw value from a PWM channel.
*
* @return Raw PWM control value.
*/
virtual uint16_t GetRaw() const;
/**
* Set the PWM value based on a position.
*
* This is intended to be used by servos.
*
* @pre SetMaxPositivePwm() called.
* @pre SetMinNegativePwm() called.
*
* @param pos The position to set the servo between 0.0 and 1.0.
*/
virtual void SetPosition(double pos);
/**
* Get the PWM value in terms of a position.
*
* This is intended to be used by servos.
*
* @pre SetMaxPositivePwm() called.
* @pre SetMinNegativePwm() called.
*
* @return The position the servo is set to between 0.0 and 1.0.
*/
virtual double GetPosition() const;
/**
* Set the PWM value based on a speed.
*
* This is intended to be used by speed controllers.
*
* @pre SetMaxPositivePwm() called.
* @pre SetMinPositivePwm() called.
* @pre SetCenterPwm() called.
* @pre SetMaxNegativePwm() called.
* @pre SetMinNegativePwm() called.
*
* @param speed The speed to set the speed controller between -1.0 and 1.0.
*/
virtual void SetSpeed(double speed);
/**
* Get the PWM value in terms of speed.
*
* This is intended to be used by speed controllers.
*
* @pre SetMaxPositivePwm() called.
* @pre SetMinPositivePwm() called.
* @pre SetMaxNegativePwm() called.
* @pre SetMinNegativePwm() called.
*
* @return The most recently set speed between -1.0 and 1.0.
*/
virtual double GetSpeed() const;
/**
* Temporarily disables the PWM output. The next set call will reenable
* the output.
*/
virtual void SetDisabled();
/**
* Slow down the PWM signal for old devices.
*
* @param mult The period multiplier to apply to this channel
*/
void SetPeriodMultiplier(PeriodMultiplier mult);
void SetZeroLatch();
/**
* Optionally eliminate the deadband from a speed controller.
*
* @param eliminateDeadband If true, set the motor curve on the Jaguar to
* eliminate the deadband in the middle of the range.
* Otherwise, keep the full range without modifying
* any values.
*/
void EnableDeadbandElimination(bool eliminateDeadband);
/**
* Set the bounds on the PWM pulse widths.
*
* This sets the bounds on the PWM values for a particular type of controller.
* The values determine the upper and lower speeds as well as the deadband
* bracket.
*
* @param max The max PWM pulse width in ms
* @param deadbandMax The high end of the deadband range pulse width in ms
* @param center The center (off) pulse width in ms
* @param deadbandMin The low end of the deadband pulse width in ms
* @param min The minimum pulse width in ms
*/
void SetBounds(double max, double deadbandMax, double center,
double deadbandMin, double min);
/**
* Set the bounds on the PWM values.
*
* This sets the bounds on the PWM values for a particular each type of
* controller. The values determine the upper and lower speeds as well as the
* deadband bracket.
*
* @param max The Minimum pwm value
* @param deadbandMax The high end of the deadband range
* @param center The center speed (off)
* @param deadbandMin The low end of the deadband range
* @param min The minimum pwm value
*/
void SetRawBounds(int max, int deadbandMax, int center, int deadbandMin,
int min);
/**
* Get the bounds on the PWM values.
*
* This Gets the bounds on the PWM values for a particular each type of
* controller. The values determine the upper and lower speeds as well as the
* deadband bracket.
*
* @param max The Minimum pwm value
* @param deadbandMax The high end of the deadband range
* @param center The center speed (off)
* @param deadbandMin The low end of the deadband range
* @param min The minimum pwm value
*/
void GetRawBounds(int32_t* max, int32_t* deadbandMax, int32_t* center,
int32_t* deadbandMin, int32_t* min);
int GetChannel() const { return m_channel; }
int GetChannel() const;
protected:
void InitSendable(SendableBuilder& builder) override;

View File

@@ -17,17 +17,47 @@ namespace frc {
*/
class PWMSpeedController : public SafePWM, public SpeedController {
public:
/**
* Set the PWM value.
*
* The PWM value is set using a range of -1.0 to 1.0, appropriately scaling
* the value for the FPGA.
*
* @param speed The speed value between -1.0 and 1.0 to set.
*/
void Set(double value) override;
/**
* Get the recently set value of the PWM.
*
* @return The most recently set value for the PWM between -1.0 and 1.0.
*/
double Get() const override;
void SetInverted(bool isInverted) override;
bool GetInverted() const override;
void Disable() override;
void StopMotor() override;
/**
* Write out the PID value as seen in the PIDOutput base object.
*
* @param output Write out the PWM value as was found in the PIDController
*/
void PIDWrite(double output) override;
protected:
/**
* Constructor for a PWM Speed Controller connected via PWM.
*
* @param channel The PWM channel that the controller is attached to. 0-9 are
* on-board, 10-19 are on the MXP port
*/
explicit PWMSpeedController(int channel);
void InitSendable(SendableBuilder& builder) override;
private:

View File

@@ -17,6 +17,12 @@ namespace frc {
*/
class PWMTalonSRX : public PWMSpeedController {
public:
/**
* Construct a PWMTalonSRX connected via PWM.
*
* @param channel The PWM channel that the PWMTalonSRX is attached to. 0-9 are
* on-board, 10-19 are on the MXP port
*/
explicit PWMTalonSRX(int channel);
};

View File

@@ -17,6 +17,12 @@ namespace frc {
*/
class PWMVictorSPX : public PWMSpeedController {
public:
/**
* Construct a PWMVictorSPX connected via PWM.
*
* @param channel The PWM channel that the PWMVictorSPX is attached to. 0-9
* are on-board, 10-19 are on the MXP port
*/
explicit PWMVictorSPX(int channel);
};

View File

@@ -21,13 +21,58 @@ class PowerDistributionPanel : public ErrorBase, public SendableBase {
PowerDistributionPanel();
explicit PowerDistributionPanel(int module);
/**
* Query the input voltage of the PDP.
*
* @return The voltage of the PDP in volts
*/
double GetVoltage() const;
/**
* Query the temperature of the PDP.
*
* @return The temperature of the PDP in degrees Celsius
*/
double GetTemperature() const;
/**
* Query the current of a single channel of the PDP.
*
* @return The current of one of the PDP channels (channels 0-15) in Amperes
*/
double GetCurrent(int channel) const;
/**
* Query the total current of all monitored PDP channels (0-15).
*
* @return The the total current drawn from the PDP channels in Amperes
*/
double GetTotalCurrent() const;
/**
* Query the total power drawn from the monitored PDP channels.
*
* @return The the total power drawn from the PDP channels in Watts
*/
double GetTotalPower() const;
/**
* Query the total energy drawn from the monitored PDP channels.
*
* @return The the total energy drawn from the PDP channels in Joules
*/
double GetTotalEnergy() const;
/**
* Reset the total energy drawn from the PDP.
*
* @see PowerDistributionPanel#GetTotalEnergy
*/
void ResetTotalEnergy();
/**
* Remove all of the fault flags on the PDP.
*/
void ClearStickyFaults();
void InitSendable(SendableBuilder& builder) override;

View File

@@ -35,23 +35,160 @@ namespace frc {
*/
class Preferences : public ErrorBase {
public:
/**
* Get the one and only {@link Preferences} object.
*
* @return pointer to the {@link Preferences}
*/
static Preferences* GetInstance();
/**
* Returns a vector of all the keys.
*
* @return a vector of the keys
*/
std::vector<std::string> GetKeys();
/**
* Returns the string at the given key. If this table does not have a value
* for that position, then the given defaultValue will be returned.
*
* @param key the key
* @param defaultValue the value to return if none exists in the table
* @return either the value in the table, or the defaultValue
*/
std::string GetString(wpi::StringRef key, wpi::StringRef defaultValue = "");
/**
* Returns the int at the given key. If this table does not have a value for
* that position, then the given defaultValue value will be returned.
*
* @param key the key
* @param defaultValue the value to return if none exists in the table
* @return either the value in the table, or the defaultValue
*/
int GetInt(wpi::StringRef key, int defaultValue = 0);
/**
* Returns the double at the given key. If this table does not have a value
* for that position, then the given defaultValue value will be returned.
*
* @param key the key
* @param defaultValue the value to return if none exists in the table
* @return either the value in the table, or the defaultValue
*/
double GetDouble(wpi::StringRef key, double defaultValue = 0.0);
/**
* Returns the float at the given key. If this table does not have a value
* for that position, then the given defaultValue value will be returned.
*
* @param key the key
* @param defaultValue the value to return if none exists in the table
* @return either the value in the table, or the defaultValue
*/
float GetFloat(wpi::StringRef key, float defaultValue = 0.0);
/**
* Returns the boolean at the given key. If this table does not have a value
* for that position, then the given defaultValue value will be returned.
*
* @param key the key
* @param defaultValue the value to return if none exists in the table
* @return either the value in the table, or the defaultValue
*/
bool GetBoolean(wpi::StringRef key, bool defaultValue = false);
/**
* Returns the long (int64_t) at the given key. If this table does not have a
* value for that position, then the given defaultValue value will be
* returned.
*
* @param key the key
* @param defaultValue the value to return if none exists in the table
* @return either the value in the table, or the defaultValue
*/
int64_t GetLong(wpi::StringRef key, int64_t defaultValue = 0);
/**
* Puts the given string into the preferences table.
*
* The value may not have quotation marks, nor may the key have any whitespace
* nor an equals sign.
*
* @param key the key
* @param value the value
*/
void PutString(wpi::StringRef key, wpi::StringRef value);
/**
* Puts the given int into the preferences table.
*
* The key may not have any whitespace nor an equals sign.
*
* @param key the key
* @param value the value
*/
void PutInt(wpi::StringRef key, int value);
/**
* Puts the given double into the preferences table.
*
* The key may not have any whitespace nor an equals sign.
*
* @param key the key
* @param value the value
*/
void PutDouble(wpi::StringRef key, double value);
/**
* Puts the given float into the preferences table.
*
* The key may not have any whitespace nor an equals sign.
*
* @param key the key
* @param value the value
*/
void PutFloat(wpi::StringRef key, float value);
/**
* Puts the given boolean into the preferences table.
*
* The key may not have any whitespace nor an equals sign.
*
* @param key the key
* @param value the value
*/
void PutBoolean(wpi::StringRef key, bool value);
/**
* Puts the given long (int64_t) into the preferences table.
*
* The key may not have any whitespace nor an equals sign.
*
* @param key the key
* @param value the value
*/
void PutLong(wpi::StringRef key, int64_t value);
/**
* Returns whether or not there is a key with the given name.
*
* @param key the key
* @return if there is a value at the given key
*/
bool ContainsKey(wpi::StringRef key);
/**
* Remove a preference.
*
* @param key the key
*/
void Remove(wpi::StringRef key);
/**
* Remove all preferences.
*/
void RemoveAll();
protected:

View File

@@ -37,19 +37,101 @@ class Relay : public MotorSafety, public ErrorBase, public SendableBase {
enum Value { kOff, kOn, kForward, kReverse };
enum Direction { kBothDirections, kForwardOnly, kReverseOnly };
/**
* Relay constructor given a channel.
*
* This code initializes the relay and reserves all resources that need to be
* locked. Initially the relay is set to both lines at 0v.
*
* @param channel The channel number (0-3).
* @param direction The direction that the Relay object will control.
*/
explicit Relay(int channel, Direction direction = kBothDirections);
/**
* Free the resource associated with a relay.
*
* The relay channels are set to free and the relay output is turned off.
*/
~Relay() override;
/**
* Set the relay state.
*
* Valid values depend on which directions of the relay are controlled by the
* object.
*
* When set to kBothDirections, the relay can be any of the four states:
* 0v-0v, 0v-12v, 12v-0v, 12v-12v
*
* When set to kForwardOnly or kReverseOnly, you can specify the constant for
* the direction or you can simply specify kOff and kOn. Using only kOff and
* kOn is recommended.
*
* @param value The state to set the relay.
*/
void Set(Value value);
/**
* Get the Relay State
*
* Gets the current state of the relay.
*
* When set to kForwardOnly or kReverseOnly, value is returned as kOn/kOff not
* kForward/kReverse (per the recommendation in Set).
*
* @return The current state of the relay as a Relay::Value
*/
Value Get() const;
int GetChannel() const;
/**
* Set the expiration time for the Relay object.
*
* @param timeout The timeout (in seconds) for this relay object
*/
void SetExpiration(double timeout) override;
/**
* Return the expiration time for the relay object.
*
* @return The expiration time value.
*/
double GetExpiration() const override;
/**
* Check if the relay object is currently alive or stopped due to a timeout.
*
* @return a bool value that is true if the motor has NOT timed out and should
* still be running.
*/
bool IsAlive() const override;
/**
* Stop the motor associated with this PWM object.
*
* This is called by the MotorSafetyHelper object when it has a timeout for
* this relay and needs to stop it from running.
*/
void StopMotor() override;
bool IsSafetyEnabled() const override;
/**
* Enable/disable motor safety for this device.
*
* Turn on and off the motor safety option for this relay object.
*
* @param enabled True if motor safety is enforced for this object
*/
void SetSafetyEnabled(bool enabled) override;
/**
* Check if motor safety is enabled for this object.
*
* @returns True if motor safety is enforced for this object
*/
bool IsSafetyEnabled() const override;
void GetDescription(wpi::raw_ostream& desc) const override;
void InitSendable(SendableBuilder& builder) override;

View File

@@ -36,11 +36,53 @@ class Resource : public ErrorBase {
Resource(const Resource&) = delete;
Resource& operator=(const Resource&) = delete;
/**
* Factory method to create a Resource allocation-tracker *if* needed.
*
* @param r address of the caller's Resource pointer. If *r == nullptr,
* this will construct a Resource and make *r point to it. If
* *r != nullptr, i.e. the caller already has a Resource
* instance, this won't do anything.
* @param elements the number of elements for this Resource allocator to
* track, that is, it will allocate resource numbers in the
* range [0 .. elements - 1].
*/
static void CreateResourceObject(std::unique_ptr<Resource>& r,
uint32_t elements);
/**
* Allocate storage for a new instance of Resource.
*
* Allocate a bool array of values that will get initialized to indicate that
* no resources have been allocated yet. The indicies of the resources are
* [0 .. elements - 1].
*/
explicit Resource(uint32_t size);
/**
* Allocate a resource.
*
* When a resource is requested, mark it allocated. In this case, a free
* resource value within the range is located and returned after it is marked
* allocated.
*/
uint32_t Allocate(const std::string& resourceDesc);
/**
* Allocate a specific resource value.
*
* The user requests a specific resource value, i.e. channel number and it is
* verified unallocated, then returned.
*/
uint32_t Allocate(uint32_t index, const std::string& resourceDesc);
/**
* Free an allocated resource.
*
* After a resource is no longer needed, for example a destructor is called
* for a channel assignment class, Free will release the resource value so it
* can be reused somewhere else in the program.
*/
void Free(uint32_t index);
private:

View File

@@ -52,13 +52,57 @@ int StartRobot() {
*/
class RobotBase {
public:
/**
* Determine if the Robot is currently enabled.
*
* @return True if the Robot is currently enabled by the field controls.
*/
bool IsEnabled() const;
/**
* Determine if the Robot is currently disabled.
*
* @return True if the Robot is currently disabled by the field controls.
*/
bool IsDisabled() const;
/**
* Determine if the robot is currently in Autonomous mode.
*
* @return True if the robot is currently operating Autonomously as determined
* by the field controls.
*/
bool IsAutonomous() const;
/**
* Determine if the robot is currently in Operator Control mode.
*
* @return True if the robot is currently operating in Tele-Op mode as
* determined by the field controls.
*/
bool IsOperatorControl() const;
/**
* Determine if the robot is currently in Test mode.
*
* @return True if the robot is currently running tests as determined by the
* field controls.
*/
bool IsTest() const;
/**
* Indicates if new data is available from the driver station.
*
* @return Has new data arrived over the network since the last time this
* function was called?
*/
bool IsNewDataAvailable() const;
/**
* Gets the ID of the main robot thread.
*/
static std::thread::id GetThreadId();
virtual void StartCompetition() = 0;
static constexpr bool IsReal() {
@@ -72,7 +116,19 @@ class RobotBase {
static constexpr bool IsSimulation() { return !IsReal(); }
protected:
/**
* Constructor for a generic robot program.
*
* User code should be placed in the constructor that runs before the
* Autonomous or Operator Control period starts. The constructor will run to
* completion before Autonomous is entered.
*
* This must be used to ensure that the communications code starts. In the
* future it would be nice to put this code into it's own task that loads on
* boot so ensure that it runs.
*/
RobotBase();
virtual ~RobotBase() = default;
RobotBase(const RobotBase&) = delete;

View File

@@ -22,26 +22,167 @@ struct CANStatus {
class RobotController {
public:
RobotController() = delete;
/**
* Return the FPGA Version number.
*
* For now, expect this to be competition year.
*
* @return FPGA Version number.
*/
static int GetFPGAVersion();
/**
* Return the FPGA Revision number.
*
* The format of the revision is 3 numbers. The 12 most significant bits are
* the Major Revision. The next 8 bits are the Minor Revision. The 12 least
* significant bits are the Build Number.
*
* @return FPGA Revision number.
*/
static int64_t GetFPGARevision();
/**
* Read the microsecond-resolution timer on the FPGA.
*
* @return The current time in microseconds according to the FPGA (since FPGA
* reset).
*/
static uint64_t GetFPGATime();
/**
* Get the state of the "USER" button on the roboRIO.
*
* @return True if the button is currently pressed down
*/
static bool GetUserButton();
/**
* Check if the FPGA outputs are enabled.
*
* The outputs may be disabled if the robot is disabled or e-stopped, the
* watchdog has expired, or if the roboRIO browns out.
*
* @return True if the FPGA outputs are enabled.
*/
static bool IsSysActive();
/**
* Check if the system is browned out.
*
* @return True if the system is browned out
*/
static bool IsBrownedOut();
/**
* Get the input voltage to the robot controller.
*
* @return The controller input voltage value in Volts
*/
static double GetInputVoltage();
/**
* Get the input current to the robot controller.
*
* @return The controller input current value in Amps
*/
static double GetInputCurrent();
/**
* Get the voltage of the 3.3V rail.
*
* @return The controller 3.3V rail voltage value in Volts
*/
static double GetVoltage3V3();
/**
* Get the current output of the 3.3V rail.
*
* @return The controller 3.3V rail output current value in Amps
*/
static double GetCurrent3V3();
/**
* Get the enabled state of the 3.3V rail. The rail may be disabled due to a
* controller brownout, a short circuit on the rail, or controller
* over-voltage.
*
* @return The controller 3.3V rail enabled value. True for enabled.
*/
static bool GetEnabled3V3();
/**
* Get the count of the total current faults on the 3.3V rail since the
* controller has booted.
*
* @return The number of faults
*/
static int GetFaultCount3V3();
/**
* Get the voltage of the 5V rail.
*
* @return The controller 5V rail voltage value in Volts
*/
static double GetVoltage5V();
/**
* Get the current output of the 5V rail.
*
* @return The controller 5V rail output current value in Amps
*/
static double GetCurrent5V();
/**
* Get the enabled state of the 5V rail. The rail may be disabled due to a
* controller brownout, a short circuit on the rail, or controller
* over-voltage.
*
* @return The controller 5V rail enabled value. True for enabled.
*/
static bool GetEnabled5V();
/**
* Get the count of the total current faults on the 5V rail since the
* controller has booted.
*
* @return The number of faults
*/
static int GetFaultCount5V();
/**
* Get the voltage of the 6V rail.
*
* @return The controller 6V rail voltage value in Volts
*/
static double GetVoltage6V();
/**
* Get the current output of the 6V rail.
*
* @return The controller 6V rail output current value in Amps
*/
static double GetCurrent6V();
/**
* Get the enabled state of the 6V rail. The rail may be disabled due to a
* controller brownout, a short circuit on the rail, or controller
* over-voltage.
*
* @return The controller 6V rail enabled value. True for enabled.
*/
static bool GetEnabled6V();
/**
* Get the count of the total current faults on the 6V rail since the
* controller has booted.
*
* @return The number of faults.
*/
static int GetFaultCount6V();
static CANStatus GetCANStatus();
};
} // namespace frc

View File

@@ -41,62 +41,364 @@ class RobotDrive : public MotorSafety, public ErrorBase {
kRearRightMotor = 3
};
/**
* Constructor for RobotDrive with 2 motors specified with channel numbers.
*
* Set up parameters for a two wheel drive system where the
* left and right motor pwm channels are specified in the call.
* This call assumes Talons for controlling the motors.
*
* @param leftMotorChannel The PWM channel number that drives the left motor.
* 0-9 are on-board, 10-19 are on the MXP port
* @param rightMotorChannel The PWM channel number that drives the right
* motor. 0-9 are on-board, 10-19 are on the MXP port
*/
WPI_DEPRECATED("Use DifferentialDrive or MecanumDrive classes instead.")
RobotDrive(int leftMotorChannel, int rightMotorChannel);
/**
* Constructor for RobotDrive with 4 motors specified with channel numbers.
*
* Set up parameters for a four wheel drive system where all four motor
* pwm channels are specified in the call.
* This call assumes Talons for controlling the motors.
*
* @param frontLeftMotor Front left motor channel number. 0-9 are on-board,
* 10-19 are on the MXP port
* @param rearLeftMotor Rear Left motor channel number. 0-9 are on-board,
* 10-19 are on the MXP port
* @param frontRightMotor Front right motor channel number. 0-9 are on-board,
* 10-19 are on the MXP port
* @param rearRightMotor Rear Right motor channel number. 0-9 are on-board,
* 10-19 are on the MXP port
*/
WPI_DEPRECATED("Use DifferentialDrive or MecanumDrive classes instead.")
RobotDrive(int frontLeftMotorChannel, int rearLeftMotorChannel,
int frontRightMotorChannel, int rearRightMotorChannel);
/**
* Constructor for RobotDrive with 2 motors specified as SpeedController
* objects.
*
* The SpeedController version of the constructor enables programs to use the
* RobotDrive classes with subclasses of the SpeedController objects, for
* example, versions with ramping or reshaping of the curve to suit motor bias
* or deadband elimination.
*
* @param leftMotor The left SpeedController object used to drive the robot.
* @param rightMotor The right SpeedController object used to drive the robot.
*/
WPI_DEPRECATED("Use DifferentialDrive or MecanumDrive classes instead.")
RobotDrive(SpeedController* leftMotor, SpeedController* rightMotor);
WPI_DEPRECATED("Use DifferentialDrive or MecanumDrive classes instead.")
RobotDrive(SpeedController& leftMotor, SpeedController& rightMotor);
WPI_DEPRECATED("Use DifferentialDrive or MecanumDrive classes instead.")
RobotDrive(std::shared_ptr<SpeedController> leftMotor,
std::shared_ptr<SpeedController> rightMotor);
/**
* Constructor for RobotDrive with 4 motors specified as SpeedController
* objects.
*
* Speed controller input version of RobotDrive (see previous comments).
*
* @param frontLeftMotor The front left SpeedController object used to drive
* the robot.
* @param rearLeftMotor The back left SpeedController object used to drive
* the robot.
* @param frontRightMotor The front right SpeedController object used to drive
* the robot.
* @param rearRightMotor The back right SpeedController object used to drive
* the robot.
*/
WPI_DEPRECATED("Use DifferentialDrive or MecanumDrive classes instead.")
RobotDrive(SpeedController* frontLeftMotor, SpeedController* rearLeftMotor,
SpeedController* frontRightMotor, SpeedController* rearRightMotor);
WPI_DEPRECATED("Use DifferentialDrive or MecanumDrive classes instead.")
RobotDrive(SpeedController& frontLeftMotor, SpeedController& rearLeftMotor,
SpeedController& frontRightMotor, SpeedController& rearRightMotor);
WPI_DEPRECATED("Use DifferentialDrive or MecanumDrive classes instead.")
RobotDrive(std::shared_ptr<SpeedController> frontLeftMotor,
std::shared_ptr<SpeedController> rearLeftMotor,
std::shared_ptr<SpeedController> frontRightMotor,
std::shared_ptr<SpeedController> rearRightMotor);
virtual ~RobotDrive() = default;
RobotDrive(const RobotDrive&) = delete;
RobotDrive& operator=(const RobotDrive&) = delete;
/**
* Drive the motors at "outputMagnitude" and "curve".
*
* Both outputMagnitude and curve are -1.0 to +1.0 values, where 0.0
* represents stopped and not turning. curve < 0 will turn left and curve > 0
* will turn right.
*
* The algorithm for steering provides a constant turn radius for any normal
* speed range, both forward and backward. Increasing m_sensitivity causes
* sharper turns for fixed values of curve.
*
* This function will most likely be used in an autonomous routine.
*
* @param outputMagnitude The speed setting for the outside wheel in a turn,
* forward or backwards, +1 to -1.
* @param curve The rate of turn, constant for different forward
* speeds. Set curve < 0 for left turn or curve > 0 for
* right turn.
*
* Set curve = e^(-r/w) to get a turn radius r for wheelbase w of your robot.
* Conversely, turn radius r = -ln(curve)*w for a given value of curve and
* wheelbase w.
*/
void Drive(double outputMagnitude, double curve);
/**
* Provide tank steering using the stored robot configuration.
*
* Drive the robot using two joystick inputs. The Y-axis will be selected from
* each Joystick object.
*
* @param leftStick The joystick to control the left side of the robot.
* @param rightStick The joystick to control the right side of the robot.
* @param squaredInputs If true, the sensitivity will be decreased for small
* values
*/
void TankDrive(GenericHID* leftStick, GenericHID* rightStick,
bool squaredInputs = true);
/**
* Provide tank steering using the stored robot configuration.
*
* Drive the robot using two joystick inputs. The Y-axis will be selected from
* each Joystick object.
*
* @param leftStick The joystick to control the left side of the robot.
* @param rightStick The joystick to control the right side of the robot.
* @param squaredInputs If true, the sensitivity will be decreased for small
* values
*/
void TankDrive(GenericHID& leftStick, GenericHID& rightStick,
bool squaredInputs = true);
/**
* Provide tank steering using the stored robot configuration.
*
* This function lets you pick the axis to be used on each Joystick object for
* the left and right sides of the robot.
*
* @param leftStick The Joystick object to use for the left side of the
* robot.
* @param leftAxis The axis to select on the left side Joystick object.
* @param rightStick The Joystick object to use for the right side of the
* robot.
* @param rightAxis The axis to select on the right side Joystick object.
* @param squaredInputs If true, the sensitivity will be decreased for small
* values
*/
void TankDrive(GenericHID* leftStick, int leftAxis, GenericHID* rightStick,
int rightAxis, bool squaredInputs = true);
void TankDrive(GenericHID& leftStick, int leftAxis, GenericHID& rightStick,
int rightAxis, bool squaredInputs = true);
/**
* Provide tank steering using the stored robot configuration.
*
* This function lets you directly provide joystick values from any source.
*
* @param leftValue The value of the left stick.
* @param rightValue The value of the right stick.
* @param squaredInputs If true, the sensitivity will be decreased for small
* values
*/
void TankDrive(double leftValue, double rightValue,
bool squaredInputs = true);
/**
* Arcade drive implements single stick driving.
*
* Given a single Joystick, the class assumes the Y axis for the move value
* and the X axis for the rotate value. (Should add more information here
* regarding the way that arcade drive works.)
*
* @param stick The joystick to use for Arcade single-stick driving.
* The Y-axis will be selected for forwards/backwards and
* the X-axis will be selected for rotation rate.
* @param squaredInputs If true, the sensitivity will be decreased for small
* values
*/
void ArcadeDrive(GenericHID* stick, bool squaredInputs = true);
/**
* Arcade drive implements single stick driving.
*
* Given a single Joystick, the class assumes the Y axis for the move value
* and the X axis for the rotate value. (Should add more information here
* regarding the way that arcade drive works.)
*
* @param stick The joystick to use for Arcade single-stick driving.
* The Y-axis will be selected for forwards/backwards and
* the X-axis will be selected for rotation rate.
* @param squaredInputs If true, the sensitivity will be decreased for small
* values
*/
void ArcadeDrive(GenericHID& stick, bool squaredInputs = true);
/**
* Arcade drive implements single stick driving.
*
* Given two joystick instances and two axis, compute the values to send to
* either two or four motors.
*
* @param moveStick The Joystick object that represents the
* forward/backward direction
* @param moveAxis The axis on the moveStick object to use for
* forwards/backwards (typically Y_AXIS)
* @param rotateStick The Joystick object that represents the rotation value
* @param rotateAxis The axis on the rotation object to use for the rotate
* right/left (typically X_AXIS)
* @param squaredInputs Setting this parameter to true increases the
* sensitivity at lower speeds
*/
void ArcadeDrive(GenericHID* moveStick, int moveChannel,
GenericHID* rotateStick, int rotateChannel,
bool squaredInputs = true);
/**
* Arcade drive implements single stick driving.
*
* Given two joystick instances and two axis, compute the values to send to
* either two or four motors.
*
* @param moveStick The Joystick object that represents the
* forward/backward direction
* @param moveAxis The axis on the moveStick object to use for
* forwards/backwards (typically Y_AXIS)
* @param rotateStick The Joystick object that represents the rotation value
* @param rotateAxis The axis on the rotation object to use for the rotate
* right/left (typically X_AXIS)
* @param squaredInputs Setting this parameter to true increases the
* sensitivity at lower speeds
*/
void ArcadeDrive(GenericHID& moveStick, int moveChannel,
GenericHID& rotateStick, int rotateChannel,
bool squaredInputs = true);
/**
* Arcade drive implements single stick driving.
*
* This function lets you directly provide joystick values from any source.
*
* @param moveValue The value to use for fowards/backwards
* @param rotateValue The value to use for the rotate right/left
* @param squaredInputs If set, increases the sensitivity at low speeds
*/
void ArcadeDrive(double moveValue, double rotateValue,
bool squaredInputs = true);
/**
* Drive method for Mecanum wheeled robots.
*
* A method for driving with Mecanum wheeled robots. There are 4 wheels
* on the robot, arranged so that the front and back wheels are toed in 45
* degrees.
* When looking at the wheels from the top, the roller axles should form an X
* across the robot.
*
* This is designed to be directly driven by joystick axes.
*
* @param x The speed that the robot should drive in the X direction.
* [-1.0..1.0]
* @param y The speed that the robot should drive in the Y direction.
* This input is inverted to match the forward == -1.0 that
* joysticks produce. [-1.0..1.0]
* @param rotation The rate of rotation for the robot that is completely
* independent of the translation. [-1.0..1.0]
* @param gyroAngle The current angle reading from the gyro. Use this to
* implement field-oriented controls.
*/
void MecanumDrive_Cartesian(double x, double y, double rotation,
double gyroAngle = 0.0);
/**
* Drive method for Mecanum wheeled robots.
*
* A method for driving with Mecanum wheeled robots. There are 4 wheels
* on the robot, arranged so that the front and back wheels are toed in 45
* degrees.
* When looking at the wheels from the top, the roller axles should form an X
* across the robot.
*
* @param magnitude The speed that the robot should drive in a given
* direction. [-1.0..1.0]
* @param direction The direction the robot should drive in degrees. The
* direction and maginitute are independent of the rotation
* rate.
* @param rotation The rate of rotation for the robot that is completely
* independent of the magnitute or direction. [-1.0..1.0]
*/
void MecanumDrive_Polar(double magnitude, double direction, double rotation);
/**
* Holonomic Drive method for Mecanum wheeled robots.
*
* This is an alias to MecanumDrive_Polar() for backward compatability
*
* @param magnitude The speed that the robot should drive in a given
* direction. [-1.0..1.0]
* @param direction The direction the robot should drive. The direction and
* magnitude are independent of the rotation rate.
* @param rotation The rate of rotation for the robot that is completely
* independent of the magnitude or direction. [-1.0..1.0]
*/
void HolonomicDrive(double magnitude, double direction, double rotation);
/**
* Set the speed of the right and left motors.
*
* This is used once an appropriate drive setup function is called such as
* TwoWheelDrive(). The motors are set to "leftOutput" and "rightOutput"
* and includes flipping the direction of one side for opposing motors.
*
* @param leftOutput The speed to send to the left side of the robot.
* @param rightOutput The speed to send to the right side of the robot.
*/
virtual void SetLeftRightMotorOutputs(double leftOutput, double rightOutput);
/*
* Invert a motor direction.
*
* This is used when a motor should run in the opposite direction as the drive
* code would normally run it. Motors that are direct drive would be inverted,
* the Drive code assumes that the motors are geared with one reversal.
*
* @param motor The motor index to invert.
* @param isInverted True if the motor should be inverted when operated.
*/
void SetInvertedMotor(MotorType motor, bool isInverted);
/**
* Set the turning sensitivity.
*
* This only impacts the Drive() entry-point.
*
* @param sensitivity Effectively sets the turning sensitivity (or turn radius
* for a given value)
*/
void SetSensitivity(double sensitivity);
/**
* Configure the scaling factor for using RobotDrive with motor controllers in
* a mode other than PercentVbus.
*
* @param maxOutput Multiplied with the output percentage computed by the
* drive functions.
*/
void SetMaxOutput(double maxOutput);
void SetExpiration(double timeout) override;
@@ -108,9 +410,29 @@ class RobotDrive : public MotorSafety, public ErrorBase {
void GetDescription(wpi::raw_ostream& desc) const override;
protected:
/**
* Common function to initialize all the robot drive constructors.
*
* Create a motor safety object (the real reason for the common code) and
* initialize all the motor assignments. The default timeout is set for the
* robot drive.
*/
void InitRobotDrive();
/**
* Limit motor values to the -1.0 to +1.0 range.
*/
double Limit(double number);
/**
* Normalize all wheel speeds if the magnitude of any wheel is greater than
* 1.0.
*/
void Normalize(double* wheelSpeeds);
/**
* Rotate a vector in Cartesian space.
*/
void RotateVector(double& x, double& y, double angle);
static constexpr int kMaxNumberOfMotors = 4;

View File

@@ -16,6 +16,12 @@ namespace frc {
*/
class SD540 : public PWMSpeedController {
public:
/**
* Constructor for a SD540.
*
* @param channel The PWM channel that the SD540 is attached to. 0-9 are
* on-board, 10-19 are on the MXP port
*/
explicit SD540(int channel);
};

View File

@@ -33,56 +33,285 @@ class SPI : public ErrorBase {
public:
enum Port { kOnboardCS0 = 0, kOnboardCS1, kOnboardCS2, kOnboardCS3, kMXP };
/**
* Constructor
*
* @param port the physical SPI port
*/
explicit SPI(Port port);
~SPI() override;
SPI(const SPI&) = delete;
SPI& operator=(const SPI&) = delete;
/**
* Configure the rate of the generated clock signal.
*
* The default value is 500,000Hz.
* The maximum value is 4,000,000Hz.
*
* @param hz The clock rate in Hertz.
*/
void SetClockRate(double hz);
/**
* Configure the order that bits are sent and received on the wire
* to be most significant bit first.
*/
void SetMSBFirst();
/**
* Configure the order that bits are sent and received on the wire
* to be least significant bit first.
*/
void SetLSBFirst();
/**
* Configure that the data is stable on the leading edge and the data
* changes on the trailing edge.
*/
void SetSampleDataOnLeadingEdge();
/**
* Configure that the data is stable on the trailing edge and the data
* changes on the leading edge.
*/
void SetSampleDataOnTrailingEdge();
/**
* Configure that the data is stable on the falling edge and the data
* changes on the rising edge.
*/
WPI_DEPRECATED("Use SetSampleDataOnTrailingEdge in most cases.")
void SetSampleDataOnFalling();
/**
* Configure that the data is stable on the rising edge and the data
* changes on the falling edge.
*/
WPI_DEPRECATED("Use SetSampleDataOnLeadingEdge in most cases")
void SetSampleDataOnRising();
/**
* Configure the clock output line to be active low.
* This is sometimes called clock polarity high or clock idle high.
*/
void SetClockActiveLow();
/**
* Configure the clock output line to be active high.
* This is sometimes called clock polarity low or clock idle low.
*/
void SetClockActiveHigh();
/**
* Configure the chip select line to be active high.
*/
void SetChipSelectActiveHigh();
/**
* Configure the chip select line to be active low.
*/
void SetChipSelectActiveLow();
/**
* Write data to the slave device. Blocks until there is space in the
* output FIFO.
*
* If not running in output only mode, also saves the data received
* on the MISO input during the transfer into the receive FIFO.
*/
virtual int Write(uint8_t* data, int size);
/**
* Read a word from the receive FIFO.
*
* Waits for the current transfer to complete if the receive FIFO is empty.
*
* If the receive FIFO is empty, there is no active transfer, and initiate
* is false, errors.
*
* @param initiate If true, this function pushes "0" into the transmit buffer
* and initiates a transfer. If false, this function assumes
* that data is already in the receive FIFO from a previous
* write.
*/
virtual int Read(bool initiate, uint8_t* dataReceived, int size);
/**
* Perform a simultaneous read/write transaction with the device
*
* @param dataToSend The data to be written out to the device
* @param dataReceived Buffer to receive data from the device
* @param size The length of the transaction, in bytes
*/
virtual int Transaction(uint8_t* dataToSend, uint8_t* dataReceived, int size);
/**
* Initialize automatic SPI transfer engine.
*
* Only a single engine is available, and use of it blocks use of all other
* chip select usage on the same physical SPI port while it is running.
*
* @param bufferSize buffer size in bytes
*/
void InitAuto(int bufferSize);
/**
* Frees the automatic SPI transfer engine.
*/
void FreeAuto();
/**
* Set the data to be transmitted by the engine.
*
* Up to 16 bytes are configurable, and may be followed by up to 127 zero
* bytes.
*
* @param dataToSend data to send (maximum 16 bytes)
* @param zeroSize number of zeros to send after the data
*/
void SetAutoTransmitData(wpi::ArrayRef<uint8_t> dataToSend, int zeroSize);
/**
* Start running the automatic SPI transfer engine at a periodic rate.
*
* InitAuto() and SetAutoTransmitData() must be called before calling this
* function.
*
* @param period period between transfers, in seconds (us resolution)
*/
void StartAutoRate(double period);
/**
* Start running the automatic SPI transfer engine when a trigger occurs.
*
* InitAuto() and SetAutoTransmitData() must be called before calling this
* function.
*
* @param source digital source for the trigger (may be an analog trigger)
* @param rising trigger on the rising edge
* @param falling trigger on the falling edge
*/
void StartAutoTrigger(DigitalSource& source, bool rising, bool falling);
/**
* Stop running the automatic SPI transfer engine.
*/
void StopAuto();
/**
* Force the engine to make a single transfer.
*/
void ForceAutoRead();
/**
* Read data that has been transferred by the automatic SPI transfer engine.
*
* Transfers may be made a byte at a time, so it's necessary for the caller
* to handle cases where an entire transfer has not been completed.
*
* Blocks until numToRead bytes have been read or timeout expires.
* May be called with numToRead=0 to retrieve how many bytes are available.
*
* @param buffer buffer where read bytes are stored
* @param numToRead number of bytes to read
* @param timeout timeout in seconds (ms resolution)
* @return Number of bytes remaining to be read
*/
int ReadAutoReceivedData(uint8_t* buffer, int numToRead, double timeout);
/**
* Get the number of bytes dropped by the automatic SPI transfer engine due
* to the receive buffer being full.
*
* @return Number of bytes dropped
*/
int GetAutoDroppedCount();
/**
* Initialize the accumulator.
*
* @param period Time between reads
* @param cmd SPI command to send to request data
* @param xferSize SPI transfer size, in bytes
* @param validMask Mask to apply to received data for validity checking
* @param validData After valid_mask is applied, required matching value for
* validity checking
* @param dataShift Bit shift to apply to received data to get actual data
* value
* @param dataSize Size (in bits) of data field
* @param isSigned Is data field signed?
* @param bigEndian Is device big endian?
*/
void InitAccumulator(double period, int cmd, int xferSize, int validMask,
int validValue, int dataShift, int dataSize,
bool isSigned, bool bigEndian);
/**
* Frees the accumulator.
*/
void FreeAccumulator();
/**
* Resets the accumulator to zero.
*/
void ResetAccumulator();
/**
* Set the center value of the accumulator.
*
* The center value is subtracted from each value before it is added to the
* accumulator. This is used for the center value of devices like gyros and
* accelerometers to make integration work and to take the device offset into
* account when integrating.
*/
void SetAccumulatorCenter(int center);
/**
* Set the accumulator's deadband.
*/
void SetAccumulatorDeadband(int deadband);
/**
* Read the last value read by the accumulator engine.
*/
int GetAccumulatorLastValue() const;
/**
* Read the accumulated value.
*
* @return The 64-bit value accumulated since the last Reset().
*/
int64_t GetAccumulatorValue() const;
/**
* Read the number of accumulated values.
*
* Read the count of the accumulated values since the accumulator was last
* Reset().
*
* @return The number of times samples from the channel were accumulated.
*/
int64_t GetAccumulatorCount() const;
/**
* Read the average of the accumulated value.
*
* @return The accumulated average value (value / count).
*/
double GetAccumulatorAverage() const;
/**
* Read the accumulated value and the number of accumulated values atomically.
*
* This function reads the value and count atomically.
* This can be used for averaging.
*
* @param value Pointer to the 64-bit accumulated output.
* @param count Pointer to the number of accumulation cycles.
*/
void GetAccumulatorOutput(int64_t& value, int64_t& count) const;
protected:

View File

@@ -27,17 +27,72 @@ namespace frc {
*/
class SafePWM : public PWM, public MotorSafety {
public:
/**
* Constructor for a SafePWM object taking a channel number.
*
* @param channel The PWM channel number 0-9 are on-board, 10-19 are on the
* MXP port
*/
explicit SafePWM(int channel);
virtual ~SafePWM() = default;
/**
* Set the expiration time for the PWM object.
*
* @param timeout The timeout (in seconds) for this motor object
*/
void SetExpiration(double timeout);
/**
* Return the expiration time for the PWM object.
*
* @returns The expiration time value.
*/
double GetExpiration() const;
/**
* Check if the PWM object is currently alive or stopped due to a timeout.
*
* @return a bool value that is true if the motor has NOT timed out and should
* still be running.
*/
bool IsAlive() const;
/**
* Stop the motor associated with this PWM object.
*
* This is called by the MotorSafetyHelper object when it has a timeout for
* this PWM and needs to stop it from running.
*/
void StopMotor();
bool IsSafetyEnabled() const;
/**
* Enable/disable motor safety for this device.
*
* Turn on and off the motor safety option for this PWM object.
*
* @param enabled True if motor safety is enforced for this object
*/
void SetSafetyEnabled(bool enabled);
/**
* Check if motor safety is enabled for this object.
*
* @returns True if motor safety is enforced for this object
*/
bool IsSafetyEnabled() const;
void GetDescription(wpi::raw_ostream& desc) const;
/**
* Feed the MotorSafety timer when setting the speed.
*
* This method is called by the subclass motor whenever it updates its speed,
* thereby reseting the timeout value.
*
* @param speed Value to pass to the PWM class
*/
virtual void SetSpeed(double speed);
private:

View File

@@ -19,13 +19,79 @@ class WPI_DEPRECATED(
"code will be much more difficult under this system. Use TimedRobot or "
"Command-Based instead.") SampleRobot : public RobotBase {
public:
/**
* Start a competition.
*
* This code needs to track the order of the field starting to ensure that
* everything happens in the right order. Repeatedly run the correct method,
* either Autonomous or OperatorControl or Test when the robot is enabled.
* After running the correct method, wait for some state to change, either the
* other mode starts or the robot is disabled. Then go back and wait for the
* robot to be enabled again.
*/
void StartCompetition() override;
/**
* Robot-wide initialization code should go here.
*
* Users should override this method for default Robot-wide initialization
* which will be called when the robot is first powered on. It will be called
* exactly one time.
*
* Warning: the Driver Station "Robot Code" light and FMS "Robot Ready"
* indicators will be off until RobotInit() exits. Code in RobotInit() that
* waits for enable will cause the robot to never indicate that the code is
* ready, causing the robot to be bypassed in a match.
*/
virtual void RobotInit();
/**
* Disabled should go here.
*
* Programmers should override this method to run code that should run while
* the field is disabled.
*/
virtual void Disabled();
/**
* Autonomous should go here.
*
* Programmers should override this method to run code that should run while
* the field is in the autonomous period. This will be called once each time
* the robot enters the autonomous state.
*/
virtual void Autonomous();
/**
* Operator control (tele-operated) code should go here.
*
* Programmers should override this method to run code that should run while
* the field is in the Operator Control (tele-operated) period. This is called
* once each time the robot enters the teleop state.
*/
virtual void OperatorControl();
/**
* Test program should go here.
*
* Programmers should override this method to run code that executes while the
* robot is in test mode. This will be called once whenever the robot enters
* test mode
*/
virtual void Test();
/**
* Robot main program for free-form programs.
*
* This should be overridden by user subclasses if the intent is to not use
* the Autonomous() and OperatorControl() methods. In that case, the program
* is responsible for sensing when to run the autonomous and operator control
* functions in their program.
*
* This method will be called immediately after the constructor is called. If
* it has not been overridden by a user subclass (i.e. the default version
* runs), then the Autonomous() and OperatorControl() methods will be called.
*/
virtual void RobotMain();
protected:

View File

@@ -15,15 +15,77 @@ namespace frc {
*/
class SensorUtil final {
public:
static int GetDefaultSolenoidModule() { return 0; }
static int GetDefaultSolenoidModule();
/**
* Check that the solenoid module number is valid.
*
* @return Solenoid module is valid and present
*/
static bool CheckSolenoidModule(int moduleNumber);
/**
* Check that the digital channel number is valid.
*
* Verify that the channel number is one of the legal channel numbers. Channel
* numbers are 1-based.
*
* @return Digital channel is valid
*/
static bool CheckDigitalChannel(int channel);
/**
* Check that the relay channel number is valid.
*
* Verify that the channel number is one of the legal channel numbers. Channel
* numbers are 0-based.
*
* @return Relay channel is valid
*/
static bool CheckRelayChannel(int channel);
/**
* Check that the digital channel number is valid.
*
* Verify that the channel number is one of the legal channel numbers. Channel
* numbers are 1-based.
*
* @return PWM channel is valid
*/
static bool CheckPWMChannel(int channel);
/**
* Check that the analog input number is value.
*
* Verify that the analog input number is one of the legal channel numbers.
* Channel numbers are 0-based.
*
* @return Analog channel is valid
*/
static bool CheckAnalogInputChannel(int channel);
/**
* Check that the analog output number is valid.
*
* Verify that the analog output number is one of the legal channel numbers.
* Channel numbers are 0-based.
*
* @return Analog channel is valid
*/
static bool CheckAnalogOutputChannel(int channel);
/**
* Verify that the solenoid channel number is within limits.
*
* @return Solenoid channel is valid
*/
static bool CheckSolenoidChannel(int channel);
/**
* Verify that the power distribution channel number is within limits.
*
* @return PDP channel is valid
*/
static bool CheckPDPChannel(int channel);
static const int kDigitalChannels;

View File

@@ -56,29 +56,161 @@ class SerialPort : public ErrorBase {
enum Port { kOnboard = 0, kMXP = 1, kUSB = 2, kUSB1 = 2, kUSB2 = 3 };
/**
* Create an instance of a Serial Port class.
*
* @param baudRate The baud rate to configure the serial port.
* @param port The physical port to use
* @param dataBits The number of data bits per transfer. Valid values are
* between 5 and 8 bits.
* @param parity Select the type of parity checking to use.
* @param stopBits The number of stop bits to use as defined by the enum
* StopBits.
*/
SerialPort(int baudRate, Port port = kOnboard, int dataBits = 8,
Parity parity = kParity_None, StopBits stopBits = kStopBits_One);
/**
* Create an instance of a Serial Port class.
*
* @param baudRate The baud rate to configure the serial port.
* @param port The physical port to use
* @param portName The direct port name to use
* @param dataBits The number of data bits per transfer. Valid values are
* between 5 and 8 bits.
* @param parity Select the type of parity checking to use.
* @param stopBits The number of stop bits to use as defined by the enum
* StopBits.
*/
WPI_DEPRECATED("Will be removed for 2019")
SerialPort(int baudRate, const wpi::Twine& portName, Port port = kOnboard,
int dataBits = 8, Parity parity = kParity_None,
StopBits stopBits = kStopBits_One);
~SerialPort();
SerialPort(const SerialPort&) = delete;
SerialPort& operator=(const SerialPort&) = delete;
/**
* Set the type of flow control to enable on this port.
*
* By default, flow control is disabled.
*/
void SetFlowControl(FlowControl flowControl);
/**
* Enable termination and specify the termination character.
*
* Termination is currently only implemented for receive.
* When the the terminator is recieved, the Read() or Scanf() will return
* fewer bytes than requested, stopping after the terminator.
*
* @param terminator The character to use for termination.
*/
void EnableTermination(char terminator = '\n');
/**
* Disable termination behavior.
*/
void DisableTermination();
/**
* Get the number of bytes currently available to read from the serial port.
*
* @return The number of bytes available to read
*/
int GetBytesReceived();
/**
* Read raw bytes out of the buffer.
*
* @param buffer Pointer to the buffer to store the bytes in.
* @param count The maximum number of bytes to read.
* @return The number of bytes actually read into the buffer.
*/
int Read(char* buffer, int count);
/**
* Write raw bytes to the buffer.
*
* @param buffer Pointer to the buffer to read the bytes from.
* @param count The maximum number of bytes to write.
* @return The number of bytes actually written into the port.
*/
int Write(const char* buffer, int count);
/**
* Write raw bytes to the buffer.
*
* Use Write({data, len}) to get a buffer that is shorter than the length of
* the string.
*
* @param buffer StringRef to the buffer to read the bytes from.
* @return The number of bytes actually written into the port.
*/
int Write(wpi::StringRef buffer);
/**
* Configure the timeout of the serial port.
*
* This defines the timeout for transactions with the hardware.
* It will affect reads and very large writes.
*
* @param timeout The number of seconds to to wait for I/O.
*/
void SetTimeout(double timeout);
/**
* Specify the size of the input buffer.
*
* Specify the amount of data that can be stored before data
* from the device is returned to Read or Scanf. If you want
* data that is recieved to be returned immediately, set this to 1.
*
* It the buffer is not filled before the read timeout expires, all
* data that has been received so far will be returned.
*
* @param size The read buffer size.
*/
void SetReadBufferSize(int size);
/**
* Specify the size of the output buffer.
*
* Specify the amount of data that can be stored before being
* transmitted to the device.
*
* @param size The write buffer size.
*/
void SetWriteBufferSize(int size);
/**
* Specify the flushing behavior of the output buffer.
*
* When set to kFlushOnAccess, data is synchronously written to the serial
* port after each call to either Printf() or Write().
*
* When set to kFlushWhenFull, data will only be written to the serial port
* when the buffer is full or when Flush() is called.
*
* @param mode The write buffer mode.
*/
void SetWriteBufferMode(WriteBufferMode mode);
/**
* Force the output buffer to be written to the port.
*
* This is used when SetWriteBufferMode() is set to kFlushWhenFull to force a
* flush before the buffer is full.
*/
void Flush();
/**
* Reset the serial port driver to a known state.
*
* Empty the transmit and receive buffers in the device and formatted I/O.
*/
void Reset();
private:

View File

@@ -20,19 +20,83 @@ namespace frc {
*/
class Servo : public SafePWM {
public:
/**
* @param channel The PWM channel to which the servo is attached. 0-9 are
* on-board, 10-19 are on the MXP port
*/
explicit Servo(int channel);
/**
* Set the servo position.
*
* Servo values range from 0.0 to 1.0 corresponding to the range of full left
* to full right.
*
* @param value Position from 0.0 to 1.0.
*/
void Set(double value);
/**
* Set the servo to offline.
*
* Set the servo raw value to 0 (undriven)
*/
void SetOffline();
/**
* Get the servo position.
*
* Servo values range from 0.0 to 1.0 corresponding to the range of full left
* to full right.
*
* @return Position from 0.0 to 1.0.
*/
double Get() const;
/**
* Set the servo angle.
*
* Assume that the servo angle is linear with respect to the PWM value (big
* assumption, need to test).
*
* Servo angles that are out of the supported range of the servo simply
* "saturate" in that direction. In other words, if the servo has a range of
* (X degrees to Y degrees) than angles of less than X result in an angle of
* X being set and angles of more than Y degrees result in an angle of Y being
* set.
*
* @param degrees The angle in degrees to set the servo.
*/
void SetAngle(double angle);
/**
* Get the servo angle.
*
* Assume that the servo angle is linear with respect to the PWM value (big
* assumption, need to test).
*
* @return The angle in degrees to which the servo is set.
*/
double GetAngle() const;
static double GetMaxAngle() { return kMaxServoAngle; }
static double GetMinAngle() { return kMinServoAngle; }
/**
* Get the maximum angle of the servo.
*
* @return The maximum angle of the servo in degrees.
*/
double GetMaxAngle() const;
/**
* Get the minimum angle of the servo.
*
* @return The minimum angle of the servo in degrees.
*/
double GetMinAngle() const;
void InitSendable(SendableBuilder& builder) override;
private:
double GetServoAngleRange() const { return kMaxServoAngle - kMinServoAngle; }
double GetServoAngleRange() const;
static constexpr double kMaxServoAngle = 180.0;
static constexpr double kMinServoAngle = 0.0;

View File

@@ -18,7 +18,13 @@ namespace frc {
class SendableBase : public Sendable {
public:
/**
* Creates an instance of the sensor base.
*
* @param addLiveWindow if true, add this Sendable to LiveWindow
*/
explicit SendableBase(bool addLiveWindow = true);
~SendableBase() override;
using Sendable::SetName;
@@ -29,10 +35,38 @@ class SendableBase : public Sendable {
void SetSubsystem(const wpi::Twine& subsystem) final;
protected:
/**
* Add a child component.
*
* @param child child component
*/
void AddChild(std::shared_ptr<Sendable> child);
/**
* Add a child component.
*
* @param child child component
*/
void AddChild(void* child);
/**
* Sets the name of the sensor with a channel number.
*
* @param moduleType A string that defines the module name in the label for
* the value
* @param channel The channel number the device is plugged into
*/
void SetName(const wpi::Twine& moduleType, int channel);
/**
* Sets the name of the sensor with a module and channel number.
*
* @param moduleType A string that defines the module name in the label for
* the value
* @param moduleNumber The number of the particular module type
* @param channel The channel number the device is plugged into (usually
* PWM)
*/
void SetName(const wpi::Twine& moduleType, int moduleNumber, int channel);
private:

View File

@@ -24,66 +24,386 @@ class SmartDashboard : public ErrorBase, public SendableBase {
public:
static void init();
/**
* Determines whether the given key is in this table.
*
* @param key the key to search for
* @return true if the table as a value assigned to the given key
*/
static bool ContainsKey(wpi::StringRef key);
/**
* @param types bitmask of types; 0 is treated as a "don't care".
* @return keys currently in the table
*/
static std::vector<std::string> GetKeys(int types = 0);
/**
* Makes a key's value persistent through program restarts.
*
* @param key the key to make persistent
*/
static void SetPersistent(wpi::StringRef key);
/**
* Stop making a key's value persistent through program restarts.
* The key cannot be null.
*
* @param key the key name
*/
static void ClearPersistent(wpi::StringRef key);
/**
* Returns whether the value is persistent through program restarts.
* The key cannot be null.
*
* @param key the key name
*/
static bool IsPersistent(wpi::StringRef key);
/**
* Sets flags on the specified key in this table. The key can
* not be null.
*
* @param key the key name
* @param flags the flags to set (bitmask)
*/
static void SetFlags(wpi::StringRef key, unsigned int flags);
/**
* Clears flags on the specified key in this table. The key can
* not be null.
*
* @param key the key name
* @param flags the flags to clear (bitmask)
*/
static void ClearFlags(wpi::StringRef key, unsigned int flags);
/**
* Returns the flags for the specified key.
*
* @param key the key name
* @return the flags, or 0 if the key is not defined
*/
static unsigned int GetFlags(wpi::StringRef key);
/**
* Deletes the specified key in this table.
*
* @param key the key name
*/
static void Delete(wpi::StringRef key);
/**
* Maps the specified key to the specified value in this table.
*
* The value can be retrieved by calling the get method with a key that is
* equal to the original key.
*
* @param keyName the key
* @param value the value
*/
static void PutData(wpi::StringRef key, Sendable* data);
/**
* Maps the specified key (where the key is the name of the Sendable)
* to the specified value in this table.
*
* The value can be retrieved by calling the get method with a key that is
* equal to the original key.
*
* @param value the value
*/
static void PutData(Sendable* value);
/**
* Returns the value at the specified key.
*
* @param keyName the key
* @return the value
*/
static Sendable* GetData(wpi::StringRef keyName);
/**
* Maps the specified key to the specified value in this table.
*
* The value can be retrieved by calling the get method with a key that is
* equal to the original key.
*
* @param keyName the key
* @param value the value
* @return False if the table key already exists with a different type
*/
static bool PutBoolean(wpi::StringRef keyName, bool value);
/**
* Gets the current value in the table, setting it if it does not exist.
* @param key the key
* @param defaultValue the default value to set if key doesn't exist.
* @returns False if the table key exists with a different type
*/
static bool SetDefaultBoolean(wpi::StringRef key, bool defaultValue);
/**
* Returns the value at the specified key.
*
* If the key is not found, returns the default value.
*
* @param keyName the key
* @return the value
*/
static bool GetBoolean(wpi::StringRef keyName, bool defaultValue);
/**
* Maps the specified key to the specified value in this table.
*
* The value can be retrieved by calling the get method with a key that is
* equal to the original key.
*
* @param keyName the key
* @param value the value
* @return False if the table key already exists with a different type
*/
static bool PutNumber(wpi::StringRef keyName, double value);
/**
* Gets the current value in the table, setting it if it does not exist.
*
* @param key The key.
* @param defaultValue The default value to set if key doesn't exist.
* @returns False if the table key exists with a different type
*/
static bool SetDefaultNumber(wpi::StringRef key, double defaultValue);
/**
* Returns the value at the specified key.
*
* If the key is not found, returns the default value.
*
* @param keyName the key
* @return the value
*/
static double GetNumber(wpi::StringRef keyName, double defaultValue);
/**
* Maps the specified key to the specified value in this table.
*
* The value can be retrieved by calling the get method with a key that is
* equal to the original key.
*
* @param keyName the key
* @param value the value
* @return False if the table key already exists with a different type
*/
static bool PutString(wpi::StringRef keyName, wpi::StringRef value);
/**
* Gets the current value in the table, setting it if it does not exist.
*
* @param key the key
* @param defaultValue the default value to set if key doesn't exist.
* @returns False if the table key exists with a different type
*/
static bool SetDefaultString(wpi::StringRef key, wpi::StringRef defaultValue);
/**
* Returns the value at the specified key.
*
* If the key is not found, returns the default value.
*
* @param keyName the key
* @return the value
*/
static std::string GetString(wpi::StringRef keyName,
wpi::StringRef defaultValue);
/**
* Put a boolean array in the table.
*
* @param key the key to be assigned to
* @param value the value that will be assigned
* @return False if the table key already exists with a different type
*
* @note The array must be of int's rather than of bool's because
* std::vector<bool> is special-cased in C++. 0 is false, any
* non-zero value is true.
*/
static bool PutBooleanArray(wpi::StringRef key, wpi::ArrayRef<int> value);
/**
* Gets the current value in the table, setting it if it does not exist.
*
* @param key the key
* @param defaultValue the default value to set if key doesn't exist.
* @returns False if the table key exists with a different type
*/
static bool SetDefaultBooleanArray(wpi::StringRef key,
wpi::ArrayRef<int> defaultValue);
/**
* Returns the boolean array the key maps to.
*
* If the key does not exist or is of different type, it will return the
* default value.
*
* @param key The key to look up.
* @param defaultValue The value to be returned if no value is found.
* @return the value associated with the given key or the given default value
* if there is no value associated with the key
*
* @note This makes a copy of the array. If the overhead of this is a concern,
* use GetValue() instead.
*
* @note The returned array is std::vector<int> instead of std::vector<bool>
* because std::vector<bool> is special-cased in C++. 0 is false, any
* non-zero value is true.
*/
static std::vector<int> GetBooleanArray(wpi::StringRef key,
wpi::ArrayRef<int> defaultValue);
/**
* Put a number array in the table.
*
* @param key The key to be assigned to.
* @param value The value that will be assigned.
* @return False if the table key already exists with a different type
*/
static bool PutNumberArray(wpi::StringRef key, wpi::ArrayRef<double> value);
/**
* Gets the current value in the table, setting it if it does not exist.
*
* @param key The key.
* @param defaultValue The default value to set if key doesn't exist.
* @returns False if the table key exists with a different type
*/
static bool SetDefaultNumberArray(wpi::StringRef key,
wpi::ArrayRef<double> defaultValue);
/**
* Returns the number array the key maps to.
*
* If the key does not exist or is of different type, it will return the
* default value.
*
* @param key The key to look up.
* @param defaultValue The value to be returned if no value is found.
* @return the value associated with the given key or the given default value
* if there is no value associated with the key
*
* @note This makes a copy of the array. If the overhead of this is a concern,
* use GetValue() instead.
*/
static std::vector<double> GetNumberArray(wpi::StringRef key,
wpi::ArrayRef<double> defaultValue);
/**
* Put a string array in the table.
*
* @param key The key to be assigned to.
* @param value The value that will be assigned.
* @return False if the table key already exists with a different type
*/
static bool PutStringArray(wpi::StringRef key,
wpi::ArrayRef<std::string> value);
/**
* Gets the current value in the table, setting it if it does not exist.
*
* @param key The key.
* @param defaultValue The default value to set if key doesn't exist.
* @returns False if the table key exists with a different type
*/
static bool SetDefaultStringArray(wpi::StringRef key,
wpi::ArrayRef<std::string> defaultValue);
/**
* Returns the string array the key maps to.
*
* If the key does not exist or is of different type, it will return the
* default value.
*
* @param key The key to look up.
* @param defaultValue The value to be returned if no value is found.
* @return the value associated with the given key or the given default value
* if there is no value associated with the key
*
* @note This makes a copy of the array. If the overhead of this is a concern,
* use GetValue() instead.
*/
static std::vector<std::string> GetStringArray(
wpi::StringRef key, wpi::ArrayRef<std::string> defaultValue);
/**
* Put a raw value (byte array) in the table.
*
* @param key The key to be assigned to.
* @param value The value that will be assigned.
* @return False if the table key already exists with a different type
*/
static bool PutRaw(wpi::StringRef key, wpi::StringRef value);
/**
* Gets the current value in the table, setting it if it does not exist.
*
* @param key The key.
* @param defaultValue The default value to set if key doesn't exist.
* @returns False if the table key exists with a different type
*/
static bool SetDefaultRaw(wpi::StringRef key, wpi::StringRef defaultValue);
/**
* Returns the raw value (byte array) the key maps to.
*
* If the key does not exist or is of different type, it will return the
* default value.
*
* @param key The key to look up.
* @param defaultValue The value to be returned if no value is found.
* @return the value associated with the given key or the given default value
* if there is no value associated with the key
*
* @note This makes a copy of the raw contents. If the overhead of this is a
* concern, use GetValue() instead.
*/
static std::string GetRaw(wpi::StringRef key, wpi::StringRef defaultValue);
/**
* Maps the specified key to the specified complex value (such as an array) in
* this table.
*
* The value can be retrieved by calling the RetrieveValue method with a key
* that is equal to the original key.
*
* @param keyName the key
* @param value the value
* @return False if the table key already exists with a different type
*/
static bool PutValue(wpi::StringRef keyName,
std::shared_ptr<nt::Value> value);
/**
* Gets the current value in the table, setting it if it does not exist.
*
* @param key the key
* @param defaultValue The default value to set if key doesn't exist.
* @returns False if the table key exists with a different type
*/
static bool SetDefaultValue(wpi::StringRef key,
std::shared_ptr<nt::Value> defaultValue);
/**
* Retrieves the complex value (such as an array) in this table into the
* complex data object.
*
* @param keyName the key
* @param value the object to retrieve the value into
*/
static std::shared_ptr<nt::Value> GetValue(wpi::StringRef keyName);
/**
* Puts all sendable data to the dashboard.
*/
static void UpdateValues();
private:

View File

@@ -21,13 +21,67 @@ namespace frc {
*/
class Solenoid : public SolenoidBase {
public:
/**
* Constructor using the default PCM ID (0).
*
* @param channel The channel on the PCM to control (0..7).
*/
explicit Solenoid(int channel);
/**
* Constructor.
*
* @param moduleNumber The CAN ID of the PCM the solenoid is attached to
* @param channel The channel on the PCM to control (0..7).
*/
Solenoid(int moduleNumber, int channel);
~Solenoid() override;
/**
* Set the value of a solenoid.
*
* @param on Turn the solenoid output off or on.
*/
virtual void Set(bool on);
/**
* Read the current value of the solenoid.
*
* @return The current value of the solenoid.
*/
virtual bool Get() const;
/**
* Check if solenoid is blacklisted.
*
* If a solenoid is shorted, it is added to the blacklist and
* disabled until power cycle, or until faults are cleared.
*
* @see ClearAllPCMStickyFaults()
*
* @return If solenoid is disabled due to short.
*/
bool IsBlackListed() const;
/**
* Set the pulse duration in the PCM. This is used in conjunction with
* the startPulse method to allow the PCM to control the timing of a pulse.
* The timing can be controlled in 0.01 second increments.
*
* @param durationSeconds The duration of the pulse, from 0.01 to 2.55
* seconds.
*
* @see startPulse()
*/
void SetPulseDuration(double durationSeconds);
/**
* Trigger the PCM to generate a pulse of the duration set in
* setPulseDuration.
*
* @see setPulseDuration()
*/
void StartPulse();
void InitSendable(SendableBuilder& builder) override;

View File

@@ -18,19 +18,102 @@ namespace frc {
*/
class SolenoidBase : public ErrorBase, public SendableBase {
public:
/**
* Read all 8 solenoids as a single byte
*
* @param module the module to read from
* @return The current value of all 8 solenoids on the module.
*/
static int GetAll(int module);
/**
* Read all 8 solenoids as a single byte
*
* @return The current value of all 8 solenoids on the module.
*/
int GetAll() const;
/**
* Reads complete solenoid blacklist for all 8 solenoids as a single byte.
*
* If a solenoid is shorted, it is added to the blacklist and
* disabled until power cycle, or until faults are cleared.
* @see ClearAllPCMStickyFaults()
*
* @param module the module to read from
* @return The solenoid blacklist of all 8 solenoids on the module.
*/
static int GetPCMSolenoidBlackList(int module);
/**
* Reads complete solenoid blacklist for all 8 solenoids as a single byte.
*
* If a solenoid is shorted, it is added to the blacklist and
* disabled until power cycle, or until faults are cleared.
* @see ClearAllPCMStickyFaults()
*
* @return The solenoid blacklist of all 8 solenoids on the module.
*/
int GetPCMSolenoidBlackList() const;
/**
* @param module the module to read from
* @return true if PCM sticky fault is set : The common highside solenoid
* voltage rail is too low, most likely a solenoid channel is shorted.
*/
static bool GetPCMSolenoidVoltageStickyFault(int module);
/**
* @return true if PCM sticky fault is set : The common highside solenoid
* voltage rail is too low, most likely a solenoid channel is shorted.
*/
bool GetPCMSolenoidVoltageStickyFault() const;
/**
* @param module the module to read from
* @return true if PCM is in fault state : The common highside solenoid
* voltage rail is too low, most likely a solenoid channel is shorted.
*/
static bool GetPCMSolenoidVoltageFault(int module);
/**
* @return true if PCM is in fault state : The common highside solenoid
* voltage rail is too low, most likely a solenoid channel is shorted.
*/
bool GetPCMSolenoidVoltageFault() const;
/**
* Clear ALL sticky faults inside PCM that Compressor is wired to.
*
* If a sticky fault is set, then it will be persistently cleared. Compressor
* drive maybe momentarily disable while flags are being cleared. Care should
* be taken to not call this too frequently, otherwise normal compressor
* functionality may be prevented.
*
* If no sticky faults are set then this call will have no effect.
*
* @param module the module to read from
*/
static void ClearAllPCMStickyFaults(int module);
/**
* Clear ALL sticky faults inside PCM that Compressor is wired to.
*
* If a sticky fault is set, then it will be persistently cleared. Compressor
* drive maybe momentarily disable while flags are being cleared. Care should
* be taken to not call this too frequently, otherwise normal compressor
* functionality may be prevented.
*
* If no sticky faults are set then this call will have no effect.
*/
void ClearAllPCMStickyFaults();
protected:
/**
* Constructor.
*
* @param moduleNumber The CAN PCM ID.
*/
explicit SolenoidBase(int pcmID);
static constexpr int m_maxModules = 63;

View File

@@ -16,6 +16,12 @@ namespace frc {
*/
class Spark : public PWMSpeedController {
public:
/**
* Constructor for a Spark.
*
* @param channel The PWM channel that the Spark is attached to. 0-9 are
* on-board, 10-19 are on the MXP port
*/
explicit Spark(int channel);
};

View File

@@ -19,14 +19,37 @@ namespace frc {
*/
class SynchronousPID : public PIDBase {
public:
/**
* Allocate a PID object with the given constants for P, I, and D.
*
* @param Kp the proportional coefficient
* @param Ki the integral coefficient
* @param Kd the derivative coefficient
* @param source The PIDSource object that is used to get values
* @param output The PIDOutput object that is set to the output percentage
*/
SynchronousPID(double Kp, double Ki, double Kd, PIDSource& source,
PIDOutput& output);
/**
* Allocate a PID object with the given constants for P, I, and D.
*
* @param Kp the proportional coefficient
* @param Ki the integral coefficient
* @param Kd the derivative coefficient
* @param Kf the feed forward term
* @param source The PIDSource object that is used to get values
* @param output The PIDOutput object that is set to the output percentage
*/
SynchronousPID(double Kp, double Ki, double Kd, double Kf, PIDSource& source,
PIDOutput& output);
SynchronousPID(const SynchronousPID&) = delete;
SynchronousPID& operator=(const SynchronousPID) = delete;
/**
* Read the input, calculate the output accordingly, and write to the output.
*/
void Calculate() override;
};

View File

@@ -16,6 +16,12 @@ namespace frc {
*/
class Talon : public PWMSpeedController {
public:
/**
* Constructor for a Talon (original or Talon SR).
*
* @param channel The PWM channel number that the Talon is attached to. 0-9
* are on-board, 10-19 are on the MXP port
*/
explicit Talon(int channel);
};

View File

@@ -11,9 +11,48 @@
namespace frc {
/**
* Get the thread priority for the specified thread.
*
* @param thread Reference to the thread to get the priority for.
* @param isRealTime Set to true if thread is realtime, otherwise false.
* @return The current thread priority. Scaled 1-99, with 1 being highest.
*/
int GetThreadPriority(std::thread& thread, bool* isRealTime);
/**
* Get the thread priority for the current thread
*
* @param isRealTime Set to true if thread is realtime, otherwise false.
* @return The current thread priority. Scaled 1-99.
*/
int GetCurrentThreadPriority(bool* isRealTime);
/**
* Sets the thread priority for the specified thread
*
* @param thread Reference to the thread to set the priority of.
* @param realTime Set to true to set a realtime priority, false for standard
* priority.
* @param priority Priority to set the thread to. Scaled 1-99, with 1 being
* highest. On RoboRIO, priority is ignored for non realtime
* setting.
*
* @return The success state of setting the priority
*/
bool SetThreadPriority(std::thread& thread, bool realTime, int priority);
/**
* Sets the thread priority for the current thread
*
* @param realTime Set to true to set a realtime priority, false for standard
* priority.
* @param priority Priority to set the thread to. Scaled 1-99, with 1 being
* highest. On RoboRIO, priority is ignored for non realtime
* setting.
*
* @return The success state of setting the priority
*/
bool SetCurrentThreadPriority(bool realTime, int priority);
} // namespace frc

View File

@@ -27,9 +27,25 @@ class TimedRobot : public IterativeRobotBase, public ErrorBase {
public:
static constexpr double kDefaultPeriod = 0.02;
/**
* Provide an alternate "main loop" via StartCompetition().
*/
void StartCompetition() override;
/**
* Set time period between calls to Periodic() functions.
*
* A timer event is queued for periodic event notification. Each time the
* interrupt occurs, the event will be immediately requeued for the same time
* interval.
*
* @param period Period in seconds.
*/
void SetPeriod(double seconds);
/**
* Get time period between calls to Periodic() functions.
*/
double GetPeriod() const;
protected:
@@ -48,6 +64,9 @@ class TimedRobot : public IterativeRobotBase, public ErrorBase {
// The relative time
double m_period = kDefaultPeriod;
/**
* Update the HAL alarm time.
*/
void UpdateAlarm();
};

View File

@@ -16,9 +16,33 @@ namespace frc {
typedef void (*TimerInterruptHandler)(void* param);
/**
* Pause the task for a specified time.
*
* Pause the execution of the program for a specified period of time given in
* seconds. Motors will continue to run at their last assigned values, and
* sensors will continue to update. Only the task containing the wait will pause
* until the wait time is expired.
*
* @param seconds Length of time to pause, in seconds.
*/
void Wait(double seconds);
/**
* Return the FPGA system clock time in seconds.
*
* This is deprecated and just forwards to Timer::GetFPGATimestamp().
*
* @return Robot running time in seconds.
*/
WPI_DEPRECATED("Use Timer::GetFPGATimestamp() instead.")
double GetClock();
/**
* @brief Gives real-time clock system time with nanosecond resolution
* @return The time, just in case you want the robot to start autonomous at 8pm
* on Saturday.
*/
double GetTime();
/**
@@ -32,19 +56,88 @@ double GetTime();
*/
class Timer {
public:
/**
* Create a new timer object.
*
* Create a new timer object and reset the time to zero. The timer is
* initially not running and must be started.
*/
Timer();
virtual ~Timer() = default;
Timer(const Timer&) = delete;
Timer& operator=(const Timer&) = delete;
/**
* Get the current time from the timer. If the clock is running it is derived
* from the current system clock the start time stored in the timer class. If
* the clock is not running, then return the time when it was last stopped.
*
* @return Current time value for this timer in seconds
*/
double Get() const;
/**
* Reset the timer by setting the time to 0.
*
* Make the timer startTime the current time so new requests will be relative
* to now.
*/
void Reset();
/**
* Start the timer running.
*
* Just set the running flag to true indicating that all time requests should
* be relative to the system clock.
*/
void Start();
/**
* Stop the timer.
*
* This computes the time as of now and clears the running flag, causing all
* subsequent time requests to be read from the accumulated time rather than
* looking at the system clock.
*/
void Stop();
/**
* Check if the period specified has passed and if it has, advance the start
* time by that period. This is useful to decide if it's time to do periodic
* work without drifting later by the time it took to get around to checking.
*
* @param period The period to check for (in seconds).
* @return True if the period has passed.
*/
bool HasPeriodPassed(double period);
/**
* Return the FPGA system clock time in seconds.
*
* Return the time from the FPGA hardware clock in seconds since the FPGA
* started. Rolls over after 71 minutes.
*
* @returns Robot running time in seconds.
*/
static double GetFPGATimestamp();
/**
* Return the approximate match time.
*
* The FMS does not send an official match time to the robots, but does send
* an approximate match time. The value will count down the time remaining in
* the current period (auto or teleop).
*
* Warning: This is not an official time (so it cannot be used to dispute ref
* calls or guarantee that a function will trigger before the match ends).
*
* The Practice Match function of the DS approximates the behavior seen on the
* field.
*
* @return Time remaining in current match period (auto or teleop)
*/
static double GetMatchTime();
// The time, in seconds, at which the 32-bit FPGA timestamp rolls over to 0

View File

@@ -38,34 +38,165 @@ class Ultrasonic : public ErrorBase, public SendableBase, public PIDSource {
public:
enum DistanceUnit { kInches = 0, kMilliMeters = 1 };
/**
* Create an instance of the Ultrasonic Sensor.
*
* This is designed to support the Daventech SRF04 and Vex ultrasonic sensors.
*
* @param pingChannel The digital output channel that sends the pulse to
* initiate the sensor sending the ping.
* @param echoChannel The digital input channel that receives the echo. The
* length of time that the echo is high represents the
* round trip time of the ping, and the distance.
* @param units The units returned in either kInches or kMilliMeters
*/
Ultrasonic(int pingChannel, int echoChannel, DistanceUnit units = kInches);
/**
* Create an instance of an Ultrasonic Sensor from a DigitalInput for the echo
* channel and a DigitalOutput for the ping channel.
*
* @param pingChannel The digital output object that starts the sensor doing a
* ping. Requires a 10uS pulse to start.
* @param echoChannel The digital input object that times the return pulse to
* determine the range.
* @param units The units returned in either kInches or kMilliMeters
*/
Ultrasonic(DigitalOutput* pingChannel, DigitalInput* echoChannel,
DistanceUnit units = kInches);
/**
* Create an instance of an Ultrasonic Sensor from a DigitalInput for the echo
* channel and a DigitalOutput for the ping channel.
*
* @param pingChannel The digital output object that starts the sensor doing a
* ping. Requires a 10uS pulse to start.
* @param echoChannel The digital input object that times the return pulse to
* determine the range.
* @param units The units returned in either kInches or kMilliMeters
*/
Ultrasonic(DigitalOutput& pingChannel, DigitalInput& echoChannel,
DistanceUnit units = kInches);
/**
* Create an instance of an Ultrasonic Sensor from a DigitalInput for the echo
* channel and a DigitalOutput for the ping channel.
*
* @param pingChannel The digital output object that starts the sensor doing a
* ping. Requires a 10uS pulse to start.
* @param echoChannel The digital input object that times the return pulse to
* determine the range.
* @param units The units returned in either kInches or kMilliMeters
*/
Ultrasonic(std::shared_ptr<DigitalOutput> pingChannel,
std::shared_ptr<DigitalInput> echoChannel,
DistanceUnit units = kInches);
Ultrasonic(int pingChannel, int echoChannel, DistanceUnit units = kInches);
~Ultrasonic() override;
/**
* Single ping to ultrasonic sensor.
*
* Send out a single ping to the ultrasonic sensor. This only works if
* automatic (round robin) mode is disabled. A single ping is sent out, and
* the counter should count the semi-period when it comes in. The counter is
* reset to make the current value invalid.
*/
void Ping();
bool IsRangeValid() const;
static void SetAutomaticMode(bool enabling);
double GetRangeInches() const;
double GetRangeMM() const;
bool IsEnabled() const { return m_enabled; }
void SetEnabled(bool enable) { m_enabled = enable; }
double PIDGet() override;
void SetPIDSourceType(PIDSourceType pidSource) override;
/**
* Check if there is a valid range measurement.
*
* The ranges are accumulated in a counter that will increment on each edge of
* the echo (return) signal. If the count is not at least 2, then the range
* has not yet been measured, and is invalid.
*/
bool IsRangeValid() const;
/**
* Turn Automatic mode on/off.
*
* When in Automatic mode, all sensors will fire in round robin, waiting a set
* time between each sensor.
*
* @param enabling Set to true if round robin scheduling should start for all
* the ultrasonic sensors. This scheduling method assures that
* the sensors are non-interfering because no two sensors fire
* at the same time. If another scheduling algorithm is
* prefered, it can be implemented by pinging the sensors
* manually and waiting for the results to come back.
*/
static void SetAutomaticMode(bool enabling);
/**
* Get the range in inches from the ultrasonic sensor.
*
* @return Range in inches of the target returned from the ultrasonic sensor.
* If there is no valid value yet, i.e. at least one measurement
* hasn't completed, then return 0.
*/
double GetRangeInches() const;
/**
* Get the range in millimeters from the ultrasonic sensor.
*
* @return Range in millimeters of the target returned by the ultrasonic
* sensor. If there is no valid value yet, i.e. at least one
* measurement hasn't completed, then return 0.
*/
double GetRangeMM() const;
bool IsEnabled() const;
void SetEnabled(bool enable);
/**
* Set the current DistanceUnit that should be used for the PIDSource base
* object.
*
* @param units The DistanceUnit that should be used.
*/
void SetDistanceUnits(DistanceUnit units);
/**
* Get the current DistanceUnit that is used for the PIDSource base object.
*
* @return The type of DistanceUnit that is being used.
*/
DistanceUnit GetDistanceUnits() const;
/**
* Get the range in the current DistanceUnit for the PIDSource base object.
*
* @return The range in DistanceUnit
*/
double PIDGet() override;
void SetPIDSourceType(PIDSourceType pidSource) override;
void InitSendable(SendableBuilder& builder) override;
private:
/**
* Initialize the Ultrasonic Sensor.
*
* This is the common code that initializes the ultrasonic sensor given that
* there are two digital I/O channels allocated. If the system was running in
* automatic mode (round robin) when the new sensor is added, it is stopped,
* the sensor is added, then automatic mode is restored.
*/
void Initialize();
/**
* Background task that goes through the list of ultrasonic sensors and pings
* each one in turn. The counter is configured to read the timing of the
* returned echo pulse.
*
* DANGER WILL ROBINSON, DANGER WILL ROBINSON:
* This code runs as a task and assumes that none of the ultrasonic sensors
* will change while it's running. Make sure to disable automatic mode before
* touching the list.
*/
static void UltrasonicChecker();
// Time (sec) for the ping trigger pulse.

View File

@@ -36,32 +36,92 @@
wpi_assertNotEqual_impl(a, b, #a, #b, message, __FILE__, __LINE__, \
__FUNCTION__)
/**
* Assert implementation.
*
* This allows breakpoints to be set on an assert. The users don't call this,
* but instead use the wpi_assert macros in Utility.h.
*/
bool wpi_assert_impl(bool conditionValue, const wpi::Twine& conditionText,
const wpi::Twine& message, wpi::StringRef fileName,
int lineNumber, wpi::StringRef funcName);
/**
* Assert equal implementation.
*
* This determines whether the two given integers are equal. If not, the value
* of each is printed along with an optional message string. The users don't
* call this, but instead use the wpi_assertEqual macros in Utility.h.
*/
bool wpi_assertEqual_impl(int valueA, int valueB,
const wpi::Twine& valueAString,
const wpi::Twine& valueBString,
const wpi::Twine& message, wpi::StringRef fileName,
int lineNumber, wpi::StringRef funcName);
/**
* Assert not equal implementation.
*
* This determines whether the two given integers are equal. If so, the value of
* each is printed along with an optional message string. The users don't call
* this, but instead use the wpi_assertNotEqual macros in Utility.h.
*/
bool wpi_assertNotEqual_impl(int valueA, int valueB,
const wpi::Twine& valueAString,
const wpi::Twine& valueBString,
const wpi::Twine& message, wpi::StringRef fileName,
int lineNumber, wpi::StringRef funcName);
void wpi_suspendOnAssertEnabled(bool enabled);
namespace frc {
/**
* Return the FPGA Version number.
*
* For now, expect this to be competition year.
*
* @return FPGA Version number.
* @deprecated Use RobotController static class method
*/
WPI_DEPRECATED("Use RobotController static class method")
int GetFPGAVersion();
/**
* Return the FPGA Revision number.
*
* The format of the revision is 3 numbers. The 12 most significant bits are the
* Major Revision. The next 8 bits are the Minor Revision. The 12 least
* significant bits are the Build Number.
*
* @return FPGA Revision number.
* @deprecated Use RobotController static class method
*/
WPI_DEPRECATED("Use RobotController static class method")
int64_t GetFPGARevision();
/**
* Read the microsecond-resolution timer on the FPGA.
*
* @return The current time in microseconds according to the FPGA (since FPGA
* reset).
* @deprecated Use RobotController static class method
*/
WPI_DEPRECATED("Use RobotController static class method")
uint64_t GetFPGATime();
/**
* Get the state of the "USER" button on the roboRIO.
*
* @return True if the button is currently pressed down
* @deprecated Use RobotController static class method
*/
WPI_DEPRECATED("Use RobotController static class method")
bool GetUserButton();
/**
* Get a stack trace, ignoring the first "offset" symbols.
*
* @param offset The number of symbols at the top of the stack to ignore
*/
std::string GetStackTrace(int offset);
} // namespace frc

View File

@@ -19,6 +19,12 @@ namespace frc {
*/
class Victor : public PWMSpeedController {
public:
/**
* Constructor for a Victor.
*
* @param channel The PWM channel number that the Victor is attached to. 0-9
* are on-board, 10-19 are on the MXP port
*/
explicit Victor(int channel);
};

View File

@@ -16,6 +16,12 @@ namespace frc {
*/
class VictorSP : public PWMSpeedController {
public:
/**
* Constructor for a VictorSP.
*
* @param channel The PWM channel that the VictorSP is attached to. 0-9 are
* on-board, 10-19 are on the MXP port
*/
explicit VictorSP(int channel);
};

View File

@@ -22,46 +22,214 @@ namespace frc {
*/
class XboxController : public GenericHID {
public:
/**
* Construct an instance of an Xbox controller.
*
* The controller index is the USB port on the Driver Station.
*
* @param port The port on the Driver Station that the controller is plugged
* into (0-5).
*/
explicit XboxController(int port);
virtual ~XboxController() = default;
XboxController(const XboxController&) = delete;
XboxController& operator=(const XboxController&) = delete;
/**
* Get the X axis value of the controller.
*
* @param hand Side of controller whose value should be returned.
*/
double GetX(JoystickHand hand) const override;
/**
* Get the Y axis value of the controller.
*
* @param hand Side of controller whose value should be returned.
*/
double GetY(JoystickHand hand) const override;
/**
* Get the trigger axis value of the controller.
*
* @param hand Side of controller whose value should be returned.
*/
double GetTriggerAxis(JoystickHand hand) const;
/**
* Read the value of the bumper button on the controller.
*
* @param hand Side of controller whose value should be returned.
*/
bool GetBumper(JoystickHand hand) const;
/**
* Whether the bumper was pressed since the last check.
*
* @param hand Side of controller whose value should be returned.
* @return Whether the button was pressed since the last check.
*/
bool GetBumperPressed(JoystickHand hand);
/**
* Whether the bumper was released since the last check.
*
* @param hand Side of controller whose value should be returned.
* @return Whether the button was released since the last check.
*/
bool GetBumperReleased(JoystickHand hand);
/**
* Read the value of the stick button on the controller.
*
* @param hand Side of controller whose value should be returned.
* @return The state of the button.
*/
bool GetStickButton(JoystickHand hand) const;
/**
* Whether the stick button was pressed since the last check.
*
* @param hand Side of controller whose value should be returned.
* @return Whether the button was pressed since the last check.
*/
bool GetStickButtonPressed(JoystickHand hand);
/**
* Whether the stick button was released since the last check.
*
* @param hand Side of controller whose value should be returned.
* @return Whether the button was released since the last check.
*/
bool GetStickButtonReleased(JoystickHand hand);
/**
* Read the value of the A button on the controller.
*
* @return The state of the button.
*/
bool GetAButton() const;
/**
* Whether the A button was pressed since the last check.
*
* @return Whether the button was pressed since the last check.
*/
bool GetAButtonPressed();
/**
* Whether the A button was released since the last check.
*
* @return Whether the button was released since the last check.
*/
bool GetAButtonReleased();
/**
* Read the value of the B button on the controller.
*
* @return The state of the button.
*/
bool GetBButton() const;
/**
* Whether the B button was pressed since the last check.
*
* @return Whether the button was pressed since the last check.
*/
bool GetBButtonPressed();
/**
* Whether the B button was released since the last check.
*
* @return Whether the button was released since the last check.
*/
bool GetBButtonReleased();
/**
* Read the value of the X button on the controller.
*
* @return The state of the button.
*/
bool GetXButton() const;
/**
* Whether the X button was pressed since the last check.
*
* @return Whether the button was pressed since the last check.
*/
bool GetXButtonPressed();
/**
* Whether the X button was released since the last check.
*
* @return Whether the button was released since the last check.
*/
bool GetXButtonReleased();
/**
* Read the value of the Y button on the controller.
*
* @return The state of the button.
*/
bool GetYButton() const;
/**
* Whether the Y button was pressed since the last check.
*
* @return Whether the button was pressed since the last check.
*/
bool GetYButtonPressed();
/**
* Whether the Y button was released since the last check.
*
* @return Whether the button was released since the last check.
*/
bool GetYButtonReleased();
/**
* Whether the Y button was released since the last check.
*
* @return Whether the button was released since the last check.
*/
bool GetBackButton() const;
/**
* Whether the back button was pressed since the last check.
*
* @return Whether the button was pressed since the last check.
*/
bool GetBackButtonPressed();
/**
* Whether the back button was released since the last check.
*
* @return Whether the button was released since the last check.
*/
bool GetBackButtonReleased();
/**
* Read the value of the start button on the controller.
*
* @param hand Side of controller whose value should be returned.
* @return The state of the button.
*/
bool GetStartButton() const;
/**
* Whether the start button was pressed since the last check.
*
* @return Whether the button was pressed since the last check.
*/
bool GetStartButtonPressed();
/**
* Whether the start button was released since the last check.
*
* @return Whether the button was released since the last check.
*/
bool GetStartButtonReleased();
private: