/*
* Strongback
* Copyright 2015, Strongback and individual contributors by the @authors tag.
* See the COPYRIGHT.txt in the distribution for a full listing of individual
* contributors.
*
* Licensed under the MIT License; you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
* http://opensource.org/licenses/MIT
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.strongback.components;
import org.strongback.annotation.Experimental;
/**
* A motor controlled by a Talon SRX with built-in current sensor, position (angle) sensor, and optional external limit switches
* wired into the SRX so that it can automatically stop the forward and reverse directions when the limit switches are
* triggered.
* <p>
* This class is currently experimental. It certainly works as a simple motor, but most of this interface exposes functionality
* of the Talon SRX motor controller, including various input sensors. Little beyond setting and reading the speed has been
* tested.
*/
@Experimental
public interface TalonSRX extends LimitedMotor {
@Override
public TalonSRX setSpeed(double speed);
/**
* Get the CAN device ID.
*
* @return the device ID.
*/
public int getDeviceID();
/**
* <b>Deprecated.</b> Use {@link #getEncoderInput()} instead.
* <p>
* Get the angle sensor (encoder) hooked up to the Talon SRX motor controller.
*
* @return the angle sensor; never null, but if not hooked up the sensor will always return a meaningless value
* @deprecated Use {@link #getEncoderInput()} instead.
*/
@Deprecated
public default AngleSensor getAngleSensor() {
return getEncoderInput();
}
/**
* Get the current encoder angle and rate, regardless of whether it is the current feedback device.
*
* @return the gyroscope that reads the encoder sensor; or null if the motor was created with no quadrature encoder input
* @see org.strongback.hardware.Hardware.Motors#talonSRX(int)
* @see org.strongback.hardware.Hardware.Motors#talonSRX(int, double)
* @see org.strongback.hardware.Hardware.Motors#talonSRX(int, double, double)
*/
public Gyroscope getEncoderInput();
/**
* Get the current analog angle and rate, regardless of whether it is the current feedback device.
*
* @return the gyroscope that reads the 3.3V analog sensor; or null if the motor was created with no analog input
* @see org.strongback.hardware.Hardware.Motors#talonSRX(int)
* @see org.strongback.hardware.Hardware.Motors#talonSRX(int, double)
* @see org.strongback.hardware.Hardware.Motors#talonSRX(int, double, double)
*/
public Gyroscope getAnalogInput();
/**
* Get the input angle and rate of the current {@link #setFeedbackDevice(FeedbackDevice) feedback device}.
*
* @return the selected input device sensor; never null, but it may return a meaningless value if a sensor is not physically
* wired as an input to the Talon device
*/
public Gyroscope getSelectedSensor();
/**
* Get the Talon SRX's output current sensor.
*
* @return the output current sensor; never null
*/
public CurrentSensor getCurrentSensor();
/**
* Get the Talon SRX's output voltage sensor.
*
* @return the output voltage sensor; never null
*/
public VoltageSensor getVoltageSensor();
/**
* Get the Talon SRX's bus voltage.
*
* @return the bus voltage sensor; never null
*/
public VoltageSensor getBusVoltageSensor();
/**
* Get the Talon SRX's temperature sensor.
*
* @return the temperature sensor; never null
*/
public TemperatureSensor getTemperatureSensor();
/**
* Set the feedback device for this controller.
*
* @param device the feedback device; may not be null
* @return this object so that methods can be chained; never null
* @see #reverseSensor(boolean)
*/
public TalonSRX setFeedbackDevice(FeedbackDevice device);
/**
* Set the status frame rate for this controller.
*
* @param frameRate the status frame rate; may not be null
* @param periodMillis frame rate period in milliseconds
* @return this object so that methods can be chained; never null
*/
public TalonSRX setStatusFrameRate(StatusFrameRate frameRate, int periodMillis);
/**
* Flips the sign (multiplies by negative one) the {@link #setFeedbackDevice(FeedbackDevice) feedback device} values read by
* the Talon.
* <p>
* This only affects position and velocity closed loop control. Allows for situations where you may have a sensor flipped
* and going in the wrong direction.
*
* @param flip <code>true</code> if sensor input should be flipped, or <code>false</code> if not.
* @return this object so that methods can be chained; never null
*/
public TalonSRX reverseSensor(boolean flip);
/**
* Set the soft limit for the forward throttle, in terms of the angle as measured by the {@link #getSelectedSensor()
* selected input sensor}. Soft limits can be used to disable motor drive when the "Sensor Position" is outside of a
* specified range: forward throttle will be disabled if the "Sensor Position" is greater than the forward soft limit.
* This takes effect only when the forward soft limit is {@link #enableForwardSoftLimit(boolean)}.
* <p>
* Soft limits can be used to disable motor drive when the “Sensor Position” is outside of a specified range. Forward
* throttle will be disabled if the “Sensor Position” is greater than the Forward Soft Limit. Reverse throttle will be
* disabled if the “Sensor Position” is less than the Reverse Soft Limit. The respective Soft Limit Enable must be enabled
* for this feature to take effect.
*
* @param forwardLimitInDegrees the angle at which the forward throttle should be disabled, where the angle in terms of the
* {@link #getSelectedSensor()}
* @return this object so that methods can be chained; never null
* @see #enableForwardSoftLimit(boolean)
*/
public TalonSRX setForwardSoftLimit(int forwardLimitInDegrees);
/**
* Set the soft limit for the reverse throttle, in terms of the angle as measured by the {@link #getSelectedSensor()
* selected input sensor}. Soft limits can be used to disable motor drive when the "Sensor Position" it outside of a
* specified range: reverse throttle will be disabled if the "Sensor Position" is less than the reverse soft limit.
* This takes effect only when the reverse soft limit is {@link #enableReverseSoftLimit(boolean)}.
* <p>
* Soft limits can be used to disable motor drive when the “Sensor Position” is outside of a specified range. Forward
* throttle will be disabled if the “Sensor Position” is greater than the Forward Soft Limit. Reverse throttle will be
* disabled if the “Sensor Position” is less than the Reverse Soft Limit. The respective Soft Limit Enable must be enabled
* for this feature to take effect.
*
* @param reverseLimitInDegrees the angle at which the reverse throttle should be disabled, where the angle in terms of the
* {@link #getSelectedSensor()}
* @return this object so that methods can be chained; never null
* @see #enableForwardSoftLimit(boolean)
*/
public TalonSRX setReverseSoftLimit(int reverseLimitInDegrees);
/**
* Enable the soft limit for forward throttle, which is set via the {@link #setForwardSoftLimit(int)}.
*
* @param enable {@code true} if the forward throttle soft limit should be enabled
* @return this object so that methods can be chained; never null
* @see #setForwardLimitSwitchNormallyOpen(boolean)
*/
public TalonSRX enableForwardSoftLimit(boolean enable);
/**
* Enable the soft limit for reverse throttle, which is set via the {@link #setReverseSoftLimit(int)}.
*
* @param enable {@code true} if the forward throttle soft limit should be enabled
* @return this object so that methods can be chained; never null
* @see #setReverseLimitSwitchNormallyOpen(boolean)
*/
public TalonSRX enableReverseSoftLimit(boolean enable);
/**
* Enable the forward and reverse limit switches.
*
* @param forward <code>true</code> if the forward limit is to be enabled, or <code>false</code> otherwise
* @param reverse <code>true</code> if the reverse limit is to be enabled, or <code>false</code> otherwise
* @return this object so that methods can be chained; never null
*/
public TalonSRX enableLimitSwitch(boolean forward, boolean reverse);
/**
* Configure the forward limit switch to be normally open or normally closed. Talon will disable momentarily if the Talon's
* current setting is dissimilar to the caller's requested setting.
*
* Since Talon saves setting to flash this should only affect a given Talon initially during robot install.
*
* @param normallyOpen <code>true</code> for normally open, or <code>false</code> for normally closed.
* @return this object so that methods can be chained; never null
*/
public TalonSRX setForwardLimitSwitchNormallyOpen(boolean normallyOpen);
/**
* Configure the reverse limit switch to be normally open or normally closed. Talon will disable momentarily if the Talon's
* current setting is dissimilar to the caller's requested setting.
*
* Since Talon saves setting to flash this should only affect a given Talon initially during robot install.
*
* @param normallyOpen <code>true</code> for normally open, or <code>false</code> for normally closed.
* @return this object so that methods can be chained; never null
*/
public TalonSRX setReverseLimitSwitchNormallyOpen(boolean normallyOpen);
/**
* Enable the brake mode.
*
* @param brake <code>true</code> if the brake mode is to be enabled, or <code>false</code> otherwise
* @return this object so that methods can be chained; never null
*/
public TalonSRX enableBrakeMode(boolean brake);
/**
* The Talon SRX can be set to honor a ramp rate to prevent instantaneous changes in throttle. This ramp rate is in effect
* regardless of which mode is selected (throttle, slave, or closed-loop). For example, setting the ramp rate to
* <code>6.0</code> will limit the maximum voltage change within any second to be less than or equal to 6.0 volts.
*
* @param rampRate maximum change in voltage per second, in volts / second
* @return this object so that methods can be chained; never null
*/
public TalonSRX setVoltageRampRate(double rampRate);
/**
* Get the faults currently associated with the Talon controller. These state of these faults may change at any time based
* upon the state of the module, and so they cannot be manually cleared.
*
* @return the current faults; never null
* @see #stickyFaults()
*/
public Faults faults();
/**
* Get the sticky faults associated with the Talon controller. Once these faults are triggered, they are only reset with
* #clearStickyFaults
*
* @return the sticky faults; never null
* @see #faults()
* @see #clearStickyFaults()
*/
public Faults stickyFaults();
/**
* Clear all {@link #stickyFaults() sticky faults} that may have been triggered.
*
* @return this instance so that methods can be chained; never null
*/
public TalonSRX clearStickyFaults();
/**
* Get the firmware version.
*
* @return the version of the firmware running on the Talon
*/
public long getFirmwareVersion();
/**
* Determine whether this motor controller's safety mode is enabled.
*
* @return <code>true</code> if the motor will be automatically disabled if it is not used within the expiration time, or
* <code>false</code> otherwise
*/
public boolean isSafetyEnabled();
/**
* Set whether this motor controller's safety mode is enabled.
*
* @param enabled <code>true</code> if the motor will be automatically disabled if it is not used within the expiration
* time, or <code>false</code> otherwise
* @return this instance so that methods can be chained; never null
*/
public TalonSRX setSafetyEnabled(boolean enabled);
/**
* Get the motor safety expiration time in milliseconds. When {@link #isSafetyEnabled() safety is enabled}, then the motor
* will be automatically disabled if it is not used within the expiration time, which is typically 100ms. This can be
* adjusted to a larger value when debugging the robot.
*
* @return the safety expiration time in milliseconds
*/
public double getExpiration();
/**
* Set the motor safety expiration time in milliseconds. When {@link #isSafetyEnabled() safety is enabled}, then the motor
* will be automatically disabled if it is not used within the expiration time, which is typically 100ms. This can be
* adjusted to a larger value when debugging the robot.
*
* @param timeout the safety expiration time in milliseconds
* @return this instance so that methods can be chained; never null
*/
public TalonSRX setExpiration(double timeout);
/**
* Determine if this motor controller is alive or has been disabled because it has not been used within the
* {@link #getExpiration() expiration}.
*
* @return <code>true</code> if the controller is alive, or <code>false</code> if it has been disabled after expiring.
*/
public boolean isAlive();
/**
* The type of feedback sensor used by this Talon controller.
*/
public enum FeedbackDevice {
/**
* Use Quadrature Encoder.
*/
QUADRATURE_ENCODER(0),
/**
* Analog potentiometer or any other analog device, 0-3.3V
*/
ANALOG_POTENTIOMETER(2),
/**
* Analog encoder or any other analog device, 0-3.3V
*/
ANALOG_ENCODER(3),
/**
* Encoder that increments position per rising edge (and never decrements) on Quadrature-A.
*/
ENCODER_RISING(4),
/**
* Encoder that increments position per falling edge (and never decrements) on Quadrature-A. Note: Was not supported in
* 2015 firmware, per the
* <a href="https://www.ctr-electronics.com/Talon%20SRX%20Software%20Reference%20Manual.pdf">Talon SRX Software
* Reference Manual</a>, section 21.3
*/
ENCODER_FALLING(5);
public int value;
public static FeedbackDevice valueOf(int value) {
for (FeedbackDevice mode : values()) {
if (mode.value == value) {
return mode;
}
}
return null;
}
private FeedbackDevice(int value) {
this.value = value;
}
public int value() {
return this.value;
}
}
/**
* Types of status frame rates.
*/
public enum StatusFrameRate {
/**
* The General Status frame has a default period of 10ms, and provides:
* <ul>
* <li>Closed Loop Error - the closed-loop target minus actual position/velocity.</li>
* <li>Throttle - the current 10bit motor output duty cycle (-1023 full reverse to +1023 full forward).</li>
* <li>Forward Limit Switch Pin State</li>
* <li>Reverse Limit Switch Pin State</li>
* <li>Fault bits</li>
* <li>Applied Control Mode</li>
* </ul>
*/
GENERAL(0),
/**
* The Feedback Status frame has a default period of 20ms, and provides:
* <ul>
* <li>Sensor Position - position of the selected sensor</li>
* <li>Sensor Velocity - velocity of the selected sensor</li>
* <li>Motor Current</li>
* <li>Sticky Faults</li>
* <li>Brake Neutral State</li>
* <li>Motor Control Profile Select</li>
* </ul>
*/
FEEDBACK(1),
/**
* The Quadrature Encoder Status frame has a default period of 100ms, and provides:
* <ul>
* <li>Encoder Position - position of the quadrature sensor</li>
* <li>Encoder Velocity - velocity of the selected sensor</li>
* <li>Number of rising edges counted on the Index Pin.</li>
* <li>Quad A pin state.</li>
* <li>Quad B pin state.</li>
* <li>Quad Index pin state.</li>
* </ul>
* The quadrature decoder is always engaged, whether the feedback device is selected or not, and whether a quadrature
* encoder is actually wired or not. This means that the Quadrature Encoder signals are always available in programming
* API regardless of how the Talon is used. The 100ms update rate is sufficient for logging, instrumentation and
* debugging. If a faster update rate is required the robot application can select the appropriate sensor and leverage
* the Sensor Position and Sensor Velocity sent over the {@link #FEEDBACK} frame every 20ms (by default).
*/
QUADRATURE_ENCODER(2),
/**
* The Analog, Temperature, and Battery Voltage status frame has a default period of 100ms, and provides:
* <ul>
* <li>Analog Position - position of the analog sensor</li>
* <li>Analog Velocity - velocity of the analog sensor</li>
* <li>Temperature</li>
* <li>Battery Voltage</li>
* </ul>
* The Analog to Digital Converter is always engaged, whether the feedback device is selected or not, and whether an
* analog sensor is actually wired or not. This means that the Analog In signals are always available in programming API
* regardless of how the Talon is used. The 100ms update rate is sufficient for logging, instrumentation and debugging.
* If a faster update rate is required the robot application can select the appropriate sensor and leverage the Sensor
* Position and Sensor Velocity sent over the {@link #FEEDBACK} frame every 20ms (by default).
*/
ANALOG_TEMPERATURE_BATTERY_VOLTAGE(3);
public int value;
public static StatusFrameRate valueOf(int value) {
for (StatusFrameRate mode : values()) {
if (mode.value == value) {
return mode;
}
}
return null;
}
private StatusFrameRate(int value) {
this.value = value;
}
public int value() {
return this.value;
}
}
/**
* The set of possible faults that this module can trigger.
*/
public static interface Faults {
/**
* The switch that is {@link Switch#isTriggered() triggered} when the Talon's over-temperature fault is tripped.
*
* @return the switch; never null
*/
Switch overTemperature();
/**
* The switch that is {@link Switch#isTriggered() triggered} when the voltage is too low.
*
* @return the switch; never null
*/
Switch underVoltage();
/**
* The switch that is {@link Switch#isTriggered() triggered} when the forward limit switch fault is tripped.
*
* @return the switch; never null
*/
Switch forwardLimitSwitch();
/**
* The switch that is {@link Switch#isTriggered() triggered} when the reverse limit switch fault is tripped.
*
* @return the switch; never null
*/
Switch reverseLimitSwitch();
/**
* The switch that is {@link Switch#isTriggered() triggered} when the forward soft limit is tripped.
*
* @return the switch; never null
*/
Switch forwardSoftLimit();
/**
* The switch that is {@link Switch#isTriggered() triggered} when the reverse soft limit is tripped.
*
* @return the switch; never null
*/
Switch reverseSoftLimit();
/**
* The switch that is {@link Switch#isTriggered() triggered} when a hardware fault occurs.
*
* @return the switch; never null
*/
Switch hardwareFailure();
}
}