Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Similar to configuration classes, devices will have a corresponding configuration accessor class. These accessor classes will contain methods to get parameters directly from the device. The structure of the accessor class resemble that of the respective configuration class where sub-configurations have corresponding nested accessors.
However, there is no need to manually instantiate a configuration accessor, as it is automatically handled by the device class. The device class has a public member object of its accessor class called configAccessor
which can be used to get configuration parameters.
Below is an example of how to get a configuration parameter from a device:
Here is how to get a nested configuration parameter:
Only SPARK MAX and SPARK Flex are affected by the REVLib 2025 release. Color Sensor V3 is unaffected.
The 2025 version of REVLib introduced a series of breaking changes from the previous year. These changes include:
An overhauled configuration system
Updated import paths
Renamed classes
For a more complete changelog, please see our 2025 beta release notes on GitHub.
Below shows how to migrate certain common tasks from previous versions of REVLib to the 2025 release.
In the 2025 version, all SPARK related classes moved to a spark
package in Java and a spark
namespace in C++.
In addition, some of the classes were renamed:
CANSparkMax
is now SparkMax
CANSparkFlex
is now SparkFlex
CANSparkLowLevel
is now SparkLowLevel
SparkPIDController
is now SparkClosedLoopController
Instead of imperatively configuring parameters of the SPARK by calling methods directly on it and its auxiliary objects (sensors, closed loop controller, etc.), configuration parameters are set in a more declarative way through configuration objects and applying that configuration to the SPARK.
A more complete guide on the new configuration system will soon be available.
For simplicity, only an example for SPARK MAX is provided. The following will still be valid for a SPARK Flex object.
With the new configuration system, parameter getters moved to a configAccessor
field in the SparkMax
and SparkFlex
.
For simplicity, only an example for SPARK MAX is provided. The following will still be valid for a SPARK Flex object.
Previously, setting status periods required the user to know which periodic status frame a signal belonged to. Now, status signals' periods can be individually configured, and REVLib will handle figuring out which status frame to adjust.
These values can be configured through the new configuration system.
For simplicity, only an example for SPARK MAX is provided. The following will still be valid for a SPARK Flex object.
REVLib is a software library that supports various REV devices within the context of programming in the FIRST Robotics Competition.
The following devices are supported in REVLib:
Use of the library outside of FRC is not currently supported
For a list and description of all classes:
Because configuration objects are not tied to a single device, they can be used multiples times for multiple devices of the same type, reducing the amount of boilerplate code for devices that function similarly.
Configuration classes provide an apply()
method to apply parameters from one configuration to another, providing greater flexibility when configuring multiple devices of the same type.
For example, you can create a common configuration for multiple devices of the same type and apply it to each device's individual configuration. This simplifies setup by avoiding duplicated code, allowing you to focus on setting only the unique parameters for each device.
Depending on the configuration class, multiple overloaded apply()
methods may be provided. However, the simplest form of apply()
accepts a configuration object of the same type as the target. Just like the other parameter setting methods, apply()
returns a modified instance of the object for method chaining.
Importantly, applying a configuration is distinct from copying it. Copying would completely overwrite the target configuration, including potentially removing parameters previously set. Instead, apply()
selectively updates parameters.
The apply()
method updates only the parameters that exist in the passed configuration object. Parameters in the target configuration that are not present in the passed configuration remain unchanged. If a parameter exists in both the target and the passed configurations, the value from the passed configuration takes precedence.
Below is a basic example of how apply()
can be used to create a starting point from another configuration:
You can also adjust parameters that were set from calling apply()
:
Calling apply()
may override previously set parameters, so it is important to keep ordering in consideration:
For configuration classes that contain sub-configurations, using the base apply()
will also apply the parameters from the passed object's sub-configurations to the target's. The same will apply to further nested sub-configurations.
Configuration classes that contain sub-configurations will also provide overloaded methods of apply()
for each of its sub-configurations. These methods allow you to apply a sub-configuration object to multiple parent configurations.
This only applies to Java and C++.
Starting 2025, REVLib shifted its device configuration paradigm towards something more declarative. This approach promotes better code organization and readability while also reducing boilerplate code. Additionally, it opens the door for enhanced configuration validation as well as reusability of code, aligning with principles of good object-oriented design.
This page explores how different parts of REVLib's configuration paradigm works and how you can use it effectively in your robot program. For more information on device specific configurations, see the following:
Color Sensor V3 does not follow the device configuration paradigm described on this page.
In this configuration paradigm, each device has its own dedicated configuration class which serves as a structure for organizing and storing the parameters to be configured for that device.
All parameters in a configuration are optional, meaning all parameters will remain unchanged unless otherwise specified. This minimizes the traffic between REVLib and the device when applying the configuration.
As a result, configuration classes are not intended to represent the device's complete configuration—though this is possible, it is generally unnecessary. Their primary purpose is to set only the parameters that are relevant to your needs.
For details on retrieving parameters from a device, refer to this section.
Configuration parameters can be set via methods on a config object, and those methods return a modified instance of the object, allowing you to perform method chaining for more organized and readable code.
Below is an example of how you would set parameters using method chaining:
Config classes can also contain sub-configs as members of the class, allowing for improved organization by grouping conceptually-related configuration parameters together. Since a sub-config is its own configuration class, its methods return the sub-config instead of its parent. To configure something outside the sub-config, you'll need to start a new chain of method calls.
Additionally, a sub-config can have its own sub-configs, allowing parameters to be deeply nested within the hierarchy.
Applying the concepts described above, this is how an example configuration class would be composed.
After setting up your configuration object, you can apply the configuration by calling the configure()
method on your device object.
The method signature may differ between devices, so be sure to consult the device's configuration documentation. In all cases, however, configure()
takes a configuration object and a ResetMode
value as arguments and returns a REVLibError
.
The ResetMode
argument specifies whether to reset the parameters before applying the configuration. This argument is required to ensure the user makes the conscious decision whether to reset the parameters, helping to avoid potential pitfalls.
Resetting parameters before applying a new configuration ensures the device starts in a known, good state. This is particularly useful when initializing the device at the start of a program, and by starting with a clean slate, you can guarantee the configuration is consistent each time the robot powers up. This approach is especially valuable when performing a drop-in replacement for a device, as the replacement may be in an unknown state.
A reason to not reset parameters when applying a configuration is to preserve previously set values during a mid-operation adjustment. While reconfiguring a device during operation is generally discouraged, some use cases may necessitate it.
Another reason to not reset parameters is when you are using the REV Hardware Client as your primary configuration tool. Although configuring devices through code is considered a best practice, the Hardware Client remains a valid and supported option for configuration.
Below is an example of either case:
Generally, the feature sets of the software for SPARK MAX and SPARK Flex are very similar, yet they are still very different devices and should be treated that way in code. Because of this, there are two separate device classes in REVLib: SparkMax
and SparkFlex
. Separating them enables better management of feature differences that currently exist or may exist later down the road.
It is important to ensure that the correct class is used for the device you are programming. Using the incorrect class for a SPARK motor controller will result in a warning in the driver station, and some functionalities may not work as intended.
The SPARK MAX supports using an "alternate" encoder while the SPARK Flex supports using an "external" encoder. Though these are largely similar concepts, both providing the ability to measure position and velocity external to the motor's primary encoder, the alternate encoder is limited by its inability to handle high RPM loads. Due to this caveat, separate classes exist: SparkMaxAlternateEncoder
and SparkFlexExternalEncoder
.
Additionally, an alternate encoder cannot be used with an absolute encoder and/or limit switches. Attempting to configure or use an alternate encoder alongside an absolute encoder/and or limit switches will throw an exception.
The external encoder on SPARK Flex does not have these limitations. More information about the alternate encoder can be found .
Since the majority of methods and interfaces in the two classes are largely similar, migrating between MAX and Flex can typically be done with a simple find-and-replace of class names. However, major differences listed above will need to be addressed on a case-by-case basis.
Below is a list of class names that can be interchanged between MAX and Flex:
Below is an example of how you would migrate how a SPARK object is constructed:
Below you will find information on how to download and install REVLib for LabVIEW, Java, and C++.
Download the latest REVLib LabVIEW package from the download link above.
Make sure LabVIEW for FRC 2025 is installed and updated.
Open the REVLib LabVIEW Package. The NI Package Manager should automatically open.
Click Next:
Once the installation is complete, you will be able to access the REVLib VIs at LabVIEW Functions Pallet -> WPI Robotics Library -> Third Party -> REV Robotics.
You can use the online method to install REVLib C++/Java if your development machine is connected to the internet:
Open your robot project in VSCode.
Click on the WPI icon in the corner to open the WPI Command Pallet.
Select Manage Vendor Libraries.
Select Install new library (online).
Enter the following installation URL and press ENTER:
Download and unzip the latest REVLib into the C:\Users\Public\wpilib\2025 directory on Windows and ~/wpilib/2025 directory on Unix-like systems.
For a detailed technical and mathematical description of each term and its effect, the is a good resource.
In FRC, PID loops are used in many types of mechanisms, from flywheel shooters to vertical arms. These need to be tuned to different constants, depending on the units they use and the physical design of the mechanism, however the process to find these constants is roughly the same.
Most teams find success using controllers tuned primarily with and , using a to account for .
P, the proportional gain, is the primary factor of the control loop. This is multiplied by the error and that gain is added to the output. This does the heavy lifting of the motion, pushing the motor in the direction it needs to go.
I, the integral gain, is not often recommended in FRC. It is useful for eliminating steady-state error, or error that the other gains leave behind and cannot address. It accumulates the error over time and multiplies it by the I gain, gradually increasing the power it supplies until that has evened out. If it is needed, it's recommended to use a limited to prevent .
The derivative gain, D, is used to tune out oscillation and dampen the motion. It resists motion, decreasing power when the mechanism is moving. A good balance of P and D is needed to make a smooth motion with no oscillation.
To then tune a basic PID loop, follow the steps below:
Set all constants (P, I, D, F, arb Feed Forward, etc) to 0
Ensure the mechanism is safe to actuate. This process will spin the motor, potentially at unexpected speeds and in unexpected directions
Check the direction of the motor, and invert it if needed so that positive output is in the desired direction
Set P to a very small number, relative to the units you are working in
Set a target for the motor to move to. Ensure this is within the range of your mechanism.
Gradually increase P until you see movement, by small increments
Once you see motion, increase P by small increments until it reaches the target at the desired speed
If you see oscillation, decrease P or begin to increment D by a small amount
Continue to adjust these parameters until the motion is quick, precise, and repeatable
The SPARK Flex and SPARK MAX do not have any support for more complex physics-based Feed Forward models, but do include a means of applying an arbitrary voltage which can be calculated in your team code and passed to the API.
Note the difference between a kF gain and an arbFF value: kF is a velocity PID gain that should be set to 0 when using position mode or MAXMotion Position Control Mode, while arbFF is an arbitrary voltage applied after the controller's PID calculations, and can be used with all position- and velocity-based control modes, including MAXMotion
It can be applied with the setpoint as seen below:
This page will discuss information about configuration concepts specific to only SPARK MAX and SPARK Flex. For more information on general configuration in REVLib, see .
SPARK MAX and SPARK Flex each have their own configuration classes, SparkMaxConfig
and SparkFlexConfig
. They are both derived from SparkBaseConfig
which includes shared configurations between the two devices. Configurations specific to SPARK MAX or SPARK Flex live in their respective configuration class.
For more information about what configurations and sub-configuration classes each class provides, refer to the links below:
Configuring a SPARK MAX and SPARK Flex differs from other devices in REVLib with the addition of the persistMode
parameter in their configure()
methods, which specifies whether the configuration settings applied to the device should be persisted between power cycles.
Persisting parameters involves saving them to the SPARK controller's memory, which is time-intensive and blocks communication with the device. To provide flexibility, this process is not automatic, as this behavior may be unnecessary or undesirable in some cases. Therefore, users must manually specify the persist mode, and to help avoid possible pitfalls, it is a required parameter.
It is recommended to persist parameters during the initial configuration of the device at the start of your program to ensure that the controller retains its configuration in the event of a power cycle during operation e.g. due to a breaker trip or a brownout.
When making updates to the configuration mid-operation, it is generally recommend to not persist the applied configuration changes to avoid blocking the program, depending on the use case. While reconfiguring a device during operation is generally discouraged, some use cases may necessitate it, and it is important to make the choice whether to persist parameters as it can affect performance of the robot.
Below is an example of either case:
Motor type is the only configuration parameter that must be set outside of a configuration object, specifically through the constructor of the SparkMax
and SparkFlex
classes. This ensures that the user makes the conscious decision the specify type of motor is being driven, as driving a brushless motor in brushed mode can permanently damage the motor.
Below is an example of how configuring for different motor types would look like:
Follow the WPILib instructions for .
Several guides for PID tuning are available, such as . It may be useful to consult multiple, especially those available that reference your specific mechanism.
Any method for PID tuning will start with the same concept, however, regardless of mechanism. Before you can tune your mechanism, you should setup a graph of the setpoint and that measured value, either through the or a similar utility. This will allow you to analyze each test and properly evaluate the changes to make.
If you are operating in Velocity Control Mode (or a velocity-based control mode), set F to the motor's value as discussed in . (Note that this is different from arbFF, which is detailed below)
WPILib offers that work great with arbFF
API Docs: ,
API Docs: ,
SparkMax
SparkFlex
SparkMaxConfig
SparkFlexConfig
SparkMaxConfigAccessor
SparkFlexConfigAccessor
SparkMaxAlternateEncoder
SparkFlexExternalEncoder
SparkMaxSim
SparkFlexSim
SparkMaxAlternateEncoderSim
SparkFlexExternalEncoderSim
SparkMaxConfig
SparkFlexConfig
SparkBaseConfig
Current Control uses a PID controller to run the motor at a consistent current providing a consistent torque. The PID controller is run using the setpoint, in Amps, and the internally measured current draw.
It is called as shown below:
API Docs: setReference
API Reference: SetReference
Current Control mode will turn your mechanism continuously and will speed up to maximum velocity if unloaded. Use caution when running this mode and avoid using it on mechanisms with a limited range of motion.
[SPARK] Improves SPARK error messages by adding the invalid value which caused the error
[SPARK] Improves SPARK error messages by displaying the parameter name as well as its ID
[Servo Hub] Fixes uninitialized variables
[REVLib] Fixes issue where REVLib doesn't clear a previous error (as viewed through GetLastError
)
[REVLib] Fixes threading issues encountered while running Googletest unit tests
[SPARK] Fixes issue where enabling a limit switch in Java simulation would cause it to always return that it was pressed
[SPARK] Fixes issue causing REVLib to have higher than normal CPU usage when retrieving SPARK status frames
[SPARK] Fixes issue where a status frame timeout would cause a segmentation fault
[REVLib] Requires non-prerelease versions of SPARK and Servo Hub firmware v25.0.0 or higher
[SPARK] Java/C++: Moves to a more declarative approach for configuring devices
Adds SparkFlexConfig
, SparkMaxConfig
which includes settings for different aspects of each device
Adds configure()
method to apply a config object's settings to one or more devices of the correct type
Adds configureAsync()
to configure a device without blocking the program
Adds a configAccessor
field to device classes for reading configuration parameters directly from the device
[SPARK] Java/C++: Adds better support for simulation
Moves away from REVPhysicsSim
to offer better support for WPILib physics simulation instead
Revamps simulation GUI data, including brand new fields for auxiliary devices
Adds Sim classes for each auxiliary device, allowing for more thorough simulation in the WPILib injection style
Adds SparkSim.iterate()
method which features simulated current limits, closed-loop control, and more
Adds SparkSimFaultManager
for throwing simulated faults
[SPARK] Adds support for MAXMotion
Adds control types MAXMotionPositionControl
and MAXMotionVelocityControl
Adds MAXMotionConfig
. Only trapezoidal profile is available at this time.
MAXMotion is not a drop-in replacement for Smart Motion, as you will need to retune PID gains.
[SPARK] Improves experience with managing status signals from SPARK devices
Adds SignalsConfig
to adjust signal periods and always on setting
Automatically enables relevant status frames if a signal is requested by the user
[Servo Hub] Java/C++: Adds initial support for Servo Hub
Follows the same paradigms used for SPARK
Includes basic simulation support for Servo Hub
[SPARK] Renames CANSparkFlex
and CANSparkMax
to SparkFlex
and SparkMax
respectively
[SPARK] Renames SparkPIDController
to SparkClosedLoopController
[SPARK] Removes configuration parameter setter/getter methods. Use SparkBase.configure()
and SparkBase.configAccessor
instead.
[SPARK] Removes burnFlash()
and restoreFactoryDefaults()
. Use the ResetMode
and PersistMode
options in SparkBase.configure()
instead.
[SPARK] Removes REVPhysicsSim
in favor of new simulation system
[SPARK] Removes async mechanism for setting parameters by setting CAN timeout to 0 in favor of configureAsync()
[SPARK] Moves all SPARK related classes into a spark
package in Java and namespace in C++
[SPARK] LabVIEW: Reworks entire VI palette
Improves organization of VI palette by separating VIs by configuration, device status, and utility
Moves towards increased usage of polymorphic VIs for easier navigation of the palette
[SPARK] Fixes issue where multiple setpoint commands would be sent when switching control types on a SPARK, resulting in the motor oscillating between the different setpoints
[SPARK] Deprecates kSmartMotion
and kSmartVelocity
control types in favor of kMAXMotionPositionControl
and kMAXMotionVelocityControl
respectively.
[SPARK] Deprecates SparkBase.setInverted()
and SparkBase.getInverted()
in favor of using the new configuration system
[SPARK] Updates ClosedLoopController.setReference()
to use the ClosedLoopSlot
enum instead of an int
[SPARK] Improves error description when attempting to persist parameters while the robot is enabled
[SPARK] Improves getting faults/warnings by returning a Faults
or Warnings
object
The raw bits of faults and warnings are available as a field in the respective struct
[SPARK] Adds hasActiveFault()
, hasStickyFault()
, hasActiveWarning()
, and hasStickyWarning()
to check if there is a fault/warning present at all on the SPARK device
[SPARK] Adds pauseFollowerMode()
and resumeFollowerMode()
[SPARK] Adds ability for follower mode to work even if the follower is not referenced in user code
[SPARK] Adds support for specifying an absolute encoder's duty cycle start and end pulse widths in AbsoluteEncoderConfig
[SPARK] Adds configuration option for setting whether the absolute encoder is zero-centered
[REVLib] Fixes potential memory leaks in string handling
[SPARK] LabVIEW: Improves reliability of CAN transactions by adding a retry mechanism
Changes to C++ and Java
Increases the default timeout to wait for a periodic status from 2*framePeriodMs to 500ms.
Reduces possibility of large, inaccurate jumps in data occurring when retrieving from status frames.
Reduces amount of "timed out while waiting for periodic status X" errors in driver station.
Improves reliability of RTR CAN frames such as setting parameters and other commands that expect a response from the device.
Adds mechanism to retry requests if sending the request or receiving the response failed. The default value for maximum number of retries is 5.
Fixes undefined behavior when SPARK motor controller information cannot be retrieved during initialization.
Changes to Java
Fixes issue introduced in v2024.2.2 where calling getEncoder() multiple times can cause a fatal exception in certain circumstances.
Changes to C++ and Java
Removes dynamic check for SPARK model when calling getEncoder(), causing unnecessary CAN traffic.
Moves zero argument CANSparkBase.getEncoder() to CANSparkMax and CANSparkFlex subclasses to determine default encoder values.
Changes to C++ and Java
Fixes issue where configuring the velocity filter for the default relative encoder of a SPARK Flex would not set the correct parameters.
Changes to Java
Improves memory allocation performance.
Changes to C++ and Java
Changes behavior of SPARK Flex and MAX initialization errors to throw exceptions rather than terminating the robot program.
Fixes issue where initializing a SPARK Flex or MAX in brushed mode while the device is disconnected from the CAN bus causes the robot program to terminate.
Fixes issue where initializing a SPARK Flex or MAX in brushed mode causes robot simulation to terminate.
Fixes warning about using the wrong class for a SPARK Flex or MAX during robot simulation.
Changes to C++
Fixes ambiguous overload error when no parameters are supplied when calling GetAnalogSensor()
.
Fixes ambiguous overload error when no parameters are supplied when calling GetEncoder()
.
Official 2024 FRC kickoff release for REVLib, with full support for SPARK Flex. Requires WPILib 2024 and SPARK Flex/SPARK MAX firmware 24.x.x.
Changes to C++, Java, and LabVIEW
Throws an error if firmware version is less than 24.0.0
Throws an error if the motor type is set to Brushed on a SPARK Flex while a SPARK Flex Dock is not connected
Gets main encoder position with enhanced precision
Changes to C++ and Java
Sends a warning to the Driver Station if the wrong class is used for the type of SPARK that is connected
Adds CanSparkBase
class that exposes functionality that is common to both the SPARK MAX and the SPARK Flex
Adds CanSparkFlex
class that exposes all functionality of the SPARK Flex
CanSparkFlex
has a getExternalEncoder()
method that returns a SparkFlexExternalEncoder
instead of a getAlternateEncoder()
method that returns a SparkMaxAlternateEncoder
.
This is because Alternate Encoder Mode is not necessary for SPARK Flex, and has been replaced by the External Encoder Data Port feature:
Can be used simultaneously with the internal encoders in NEO class motors
Can be used simultaneously with an absolute encoder and limit switches
Virtually no RPM limit
No special configuration
The following items have been deprecated in favor of new equivalents:
Instead of CANSparkMaxLowLevel
, use CANSparkLowLevel
Instead of SparkMaxAbsoluteEncoder
, use SparkAbsoluteEncoder
Instead of SparkMaxAnalogSensor
, use SparkAnalogSensor
Instead of SparkMaxLimitSwitch
, use SparkLimitSwitch
Instead of SparkMaxPIDController
, use SparkPIDController
Instead of SparkMaxRelativeEncoder
, use SparkRelativeEncoder
Instead of ExternalFollower.kFollowerSparkMax
, use ExternalFollower.kFollowerSpark
The ExternalFollower
enum can be accessed at CANSparkMax.ExternalFollower
, CANSparkFlex.ExternalFollower
, or CANSparkBase.ExternalFollower
Adds a CANSparkBase.getSparkModel()
method that returns a SparkModel
enum
Changes to LabVIEW
Deprecates old VIs that are prefixed with "Spark MAX" and replaces them with VIs prefixed with "SPARK"
Deprecated icons are "grayed out"
Help context (documentation) for deprecated VIs point the user to the equivalent new VI
New icons say "SPARK" instead of "REV MAX"
Adds SPARK Get Model.vi
Fixes SPARK Get Analog Sensor Voltage.vi
when used with a SPARK Flex
Updates SPARK Get I Accum.vi
to get I Accum from status 7 instead of status 2
Updates "Alternate Encoder" VIs to be "Alternate or External Encoder"
Only throw the data port config warnings when the device is a SPARK MAX
This version of REVLib requires SPARK MAX Firmware v1.6.3. Please update your SPARK MAX through the REV Hardware Client.
Improves documentation for the setZeroOffset() and getZeroOffset() methods on Absolute Encoder objects
Fixes issue where reading an absolute encoder’s zero offset could return an incorrect value in certain conditions
This version of REVLib requires SPARK MAX Firmware v1.6.2. Please update your SPARK MAX through the REV Hardware Client.
Adds support to configure the hall sensor's velocity measurement
C++/Java: Updates SetMeasurementPeriod()
and SetAverageDepth()
in the SparkMaxRelativeEncoder
class to be used when the relative encoder is configured to be of type kHallSensor
.
LabVIEW: Adds SPARK MAX Configure Hall Sensor.vi
and SPARK MAX Get Hall Sensor Config.vi
to set and get the hall sensor's measurement period and average depth.
Adds support for WPILib 2023
Adds support for using a duty cycle absolute encoder as a feedback device for the SPARK MAX
C++/Java: Adds SparkMaxAbsoluteEncoder class
LabVIEW: Adds VIs for configuring and getting the values from a duty cycle absolute encoder
Adds Position PID Wrapping to allow continuous input for the SPARK MAX PID controller
C++/Java: Adds PositionPIDWrapping methods to the SparkMaxPIDController class
LabVIEW: Adds VIs for setting and getting the Position PID Wrapping configuration
Allows configuring the periodic frame rates for status frames 4-6
Breaking Changes
LabVIEW: The version of NI Package Manager bundled with the FRC LabVIEW offline installer will no longer work when installing the REVLib package. NIPM must be updated to the latest version or installed from the FRC LabVIEW online installer to be able to install this package of REVLib for LabVIEW
Breaking changes
C++/Java: CANError
has been renamed to REVLibError
.
Java: ColorMatch.makeColor()
and the ColorShim
class have been removed. Use the WPILib Color
class instead.
C++/Java: Deleted deprecated constructors, methods, and types
Replace deprecated constructors with CANSparkMax.getX()
functions.
Replace CANEncoder.getCPR()
with getCountsPerRevolution()
.
Remove all usages of CANDigitalInput.LimitSwitch
.
Replace CANSparkMax.getAlternateEncoder()
with CANSparkMax.getAlternateEncoder(int countsPerRev)
.
Remove all usages of CANSparkMax.setMotorType()
. You can only set the motor type in the constructor now.
Replace SparkMax
with PWMSparkMax
, which is built into WPILib.
Java: CANSparkMax.get()
now returns the velocity setpoint set by set(double speed)
rather than the actual velocity, in accordance with the WPILib MotorController
API contract.
C++/Java: CANPIDController.getSmartMotionAccelStrategy()
now returns SparkMaxPIDController.AccelStrategy
.
C++/Java: Trying to do the following things will now throw an exception:
Creating a CANSparkMax
object for a device that already has one
Specifying an incorrect countsPerRev
value for a NEO hall sensor
Java: Calling a CANSparkMax.getX()
method using different settings than were used previously in the program
Java: Trying to use a CANSparkMax
(or another object retrieved from it) after close()
has been called
C++: Calling a CANSparkMax.getX()
method more than once for a single device
C++/Java: Deprecated classes in favor of renamed versions
C++ users will get cannot declare field to be of abstract type
errors until they replace their object declarations with ones for the new classes. Java users will be able to continue to use the old classes through the 2022 season.
AlternateEncoderType
is replaced by SparkMaxAlternateEncoder.Type
.
CANAnalog
is replaced by SparkMaxAnalogSensor
.
CANDigitalInput
is replaced by SparkMaxLimitSwitch
.
Java: CANEncoder
is replaced by RelativeEncoder
.
C++: CANEncoder is replaced by
SparkMaxRelativeEncoderand
SparkMaxAlternateEncoder`.
CANPIDController
is replaced by SparkMaxPIDController
.
CANSensor
is replaced by MotorFeedbackSensor
.
ControlType
is replaced by CANSparkMax.ControlType
.
EncoderType
is replaced by SparkMaxRelativeEncoder.Type
.
Enhancements:
C++/Java: Added the ability to set the rate of periodic frame 3
Fixes:
C++/Java: CANSparkMax.getMotorType()
no longer uses the Get Parameter API, which means that it is safe to call frequently
Java: The CANSparkMax.getX()
methods no longer create a new object on every call
Known issues:
SparkMaxPIDController.setIAccum()
only works while the control mode is active
2025.0.0
Embedded (Press Ctrl-H)
2025.0.2
2025.0.2
Smart Motion Control is a complex control mode that allows for smoother and more controlled movements from one position to another. By configuring the maximum velocity and acceleration, as shown in Smart Motion Parameters, this control mode will create a motion that accelerates, holds a constant "cruise" velocity, and then decelerates to a stop at the setpoint.
Tuning the PID Controller for Smart Motion may be difficult on mechanisms with a very limited range of motion.
This control mode takes a setpoint in units of rotations, but the underlying implementation executes a Velocity PID controller, so the PID tuning process will be more like a Velocity controller.
The Smart Motion Example Program is a good tool for tuning this control loop, as it allows you to toggle between Smart Motion and Velocity control to fine-tune the constants and parameters.
Smart Motion's function is the same as that of WPILib's TrapezoidalProfile, which uses an underlying position-based PID controller which may be easier to tune and can sometimes provide better results.
Running Smart Motion Control is as easy as any other control mode: configure the constants, pick your setpoints, and set it as the mode when you apply the position target, as seen below:
API Docs: setReference
API Reference: SetReference
Using the Velocity Control mode will rotate your mechanism continuously. Please exercise caution while tuning. Utilize hard and soft limits to protect your robot.
Smart Motion is deprecated as of the 2025 release of REVLib, and teams using it should migrate to MAXMotion Position Control Mode
Smart Motion Control is a complex control mode that allows for smoother and more controlled movements from one position to another. By configuring the maximum velocity and acceleration, as shown in
Position Control is used to point the motor in a specific direction. It takes a setpoint in rotations and uses the PID loop to move to that position. The Position control mode pipes directly into a PID controller with the configured encoder.
For more complex mechanisms or motions where closer control over acceleration and velocity are needed, see MAXMotion Position Control
A properly tuned Position control loop should respond quickly and accurately to a setpoint change and should not oscillate around the target.
To run the motor in Position control mode, set the PID Controller setpoint as shown below.
API Docs: setReference
API Reference: SetReference
Velocity Control uses the PID controller to run the motor at a set speed in RPM. An FF gain, as detailed in F Parameter, is your friend in finding consistency when tuning this mode.
Want to control the acceleration of your velocity controller? See MAXMotion Velocity Control for an improved version of Velocity Control with more features and control.
It is called in the same way as Position Control:
API Docs: setReference
API Reference: SetReference
Velocity Control mode will turn your motor continuously,. Be sure your mechanism does not have any hard limits for rotation.
Velocity Loop constants are often of a very low magnitude, so if your mechanism isn't behaving as expected, try decreasing your gains.
MAXMotion Velocity Control utilizes the to improve upon velocity control. Honoring the maximum acceleration, MAXMotion Velocity Control will speed up your flywheel or rotary mechanism in a controlled way, reducing power draw and increasing consistency.
MAXMotion Velocity Control utilizes an internal velocity closed-loop controller, so transitioning from Velocity Control mode to MAXMotion Velocity Control is as simple as setting a maximum acceleration and changing the setReference call.
It is called as seen below:
API Docs:
API Reference:
MAXMotion Velocity Control will turn your motor continuously. Be sure your mechanism does not have any hard limits for rotation.
If your motion seems jittery, try reducing your PID constants, especially P. If the underlying velocity PID outruns the acceleration target, the motion may seem jittery and the velocity will not increase smoothly.
Make sure your units are correct: maximum velocity is set in RPM by default and maximum acceleration is set in RPM per second by default.
At low speeds, the acceleration may seem wobbly or inconsistent if the loop has been tuned for higher speeds or vice versa. If both are needed, try tuning separate PIDs and switching between slots when needed. This may be easier than finding those perfect constants that work beautifully across the board.
As MAXMotion Velocity Control Mode uses an internal velocity PID loop, a kF gain () is recommended for more consistent control
Passing a calculated arbitrary feed forward () via arbFF may be helpful for large or heavy velocity-controlled mechanisms
All Smart Velocity constants and PIDs can be transferred to MAXMotion Velocity Mode. Be sure to transcribe any Smart Motion parameters to the MAXMotion parameters.
MAXMotion Position Control is a second-degree closed loop controller, allowing for smooth and consistent motions from one position to another by limiting both the velocity and acceleration of the motor. These can be configured via the , setting a target acceleration and a "cruise" velocity. The motor will spin up, honoring the acceleration target, hold speed at the cruise velocity, and then slow down honoring the acceleration target to arrive at the setpoint. MAXMotion updates its motion profile every 10ms and the underlying PID controller every 1ms, which makes it extremely fast and responsive.
MAXMotion Position Control runs on top of an internal position PID controller, so the tuning process begins similarly to a typical position closed loop controller, with the P and D constants (See for more on this). Note that these values may need tweaked once you set your velocity and acceleration targets in order to smooth out the motion.
When setting your maximum velocity and maximum acceleration parameters, keep a few things in mind:
Maximum velocity is in units of revolutions per minute by default
Maximum acceleration is in units of RPM per second by default
Your current limits may interfere with motions that move too quickly or hold against gravity for too long
Try to achieve a good balance of smoothness and consistency with speed
Setting a high acceleration or velocity could cause the mechanism to shift or move your robot and may be dangerous to stand close to, so use extra caution when speeding things up
If your motion seems jittery, try adjusting your PID constants. If the target acceleration is faster or slower than your PIDs allow, the mechanism may appear to shake or jitter and speed and accuracy will be lost.
Keep an eye on the current draw, as hitting limits may interfere with the functionality of MAXMotion. Increasing current limits or changing the gear ratio on your mechanism can help reduce the chances of this happening.
Feed forwards (See ) may help smooth out your motion and stabilize your mechanism, but if not perfectly tuned could also introduce noise or fight the internal PID (especially if the gains are too high). MAXMotion may be able to handle the motion on its own without any help at all, especially on a lightweight mechanism.
As MAXMotion runs on an underlying position closed loop controller, a kF gain () is not recommended and may lead to unexpected results. Instead, lean on the PID constants to handle this.
After tuning your constants, calling MAXMotion is as simple as passing in the setpoint to the controller.
As Smart Motion and MAXMotion Position Control use different underlying control methods, all PID constants will need to be re-tuned from scratch
Smart Motion used a different method for smooth second-degree motion control, but MAXMotion can be applied anywhere Smart Motion was previously. Maximum velocity and acceleration constants may be transferable, but should be tested with caution. All other constants will need re-tuned from scratch, including all PIDs.
MAXMotion has several improvements over Smart Motion, and should offer better consistency, a better tuning experience, better position retention, and an all-around better user experience. It is highly recommended to migrate all systems using Smart Motion to MAXMotion.
This page will discuss information about configuration concepts specific to the Servo Hub. For more information on general configuration in REVLib, see .
Though Servo Hub has its own configuration class, ServoHubConfig
, the majority of configuration occurs in the ServoChannelConfig
class.
For more information about what configurations and sub-configuration classes the Servo Hub provides, refer to the links below:
Configuring a Servo Hub automatically persists the configuration settings between power cycles when calling the configure()
method.
Persisting parameters involves saving them to the Servo Hub's memory, which is time-intensive and blocks communication with the device.
It is recommended to update the the majority of device parameters during the initial configuration of the device at the start of your program to ensure that the controller retains its configuration in the event of a power cycle during operation e.g. due to a breaker trip or a brownout.
It is generally recommended to not make updates to the configuration mid-operation to avoid blocking the program and affecting the performance of the robot.
Below is an example of either case:
Testing is an important part of building solid software, and programming robots is no different. When writing code for an FRC robot, testing often involves a fully assembled robot and dedicated time for the Programming team to experiment on it, both of which can be hard to come by at times. When time with the robot is valuable, it's important that your code works how you expect it to on the first try. That's where simulation comes in.
Simulating your robot code allows you to control every input and view every output of your robot code in a simulated environment, letting you put your "robot" in scenarios to see that it does what you want. A simple usage might be to make sure your controls aren't inverted, and a more complicated application may be physics simulating an entire autonomous routine or running automated unit tests on every build. With (quite a lot of) work, you could even practice driving entire matches before the robot is even built.
The basic flow of the simulation is shown in the diagram below, where your code does its thing and all the simulation magic can happen behind the scenes. Your inputs and setup on the GUI are fed right to your code as if the robot was actually there, allowing you to test simple systems without adding anything at all. To test more complicated systems or run physics simulations, you can add some simulation specific code to address the simulation directly and allow you to further customize your control over the simulation.
Simulation is something that can help every team, from the first-time programmers who want to make sure something works as expected to the high-level teams who want to run physics simulations and test complicated algorithms. The more work you put into developing your simulations, the more complex and detailed they can become. That being said, getting started is simple and you can see immediate results with little to no code.
Smart Velocity is deprecated as of the 2025 release of REVLib, and teams using it should migrate to MAXMotion Velocity Control Mode
The Smart Velocity control mode utilizes the to improve upon velocity control. Honoring the maximum acceleration, Smart Velocity will speed up and slow down your flywheel or rotary mechanism in a controlled way, reducing power draw and increasing consistency.
It is called as seen below:
API Docs:
API Reference:
Smart Velocity Control mode will turn your motor continuously. Be sure your mechanism does not have any hard limits for rotation.
Each Spark device has a set of additional sensors, limit switches, and encoders that can be accessed and addressed in your robot code. To simulate each of these, we use a similar model where the user can directly set, either via the GUI or programmatically, each value that these devices measure.
As each auxiliary device is addressed in your native robot code they will be added to the simulation GUI, allowing you to easily adjust their values and test a variety of scenarios.
For example, the code below will generate the GUI display shown below:
In the same fashion as the Spark devices, all auxiliary devices have their own Sim classes for accessing the simulation tooling. These follow a similar model, where all physics and motion or change in sensor values need to be handled externally, allowing you to configure these auxiliary devices in the simulation to match how they behave on your robot.
Each Encoder Sim class also contains a .iterate function, which automatically updates both position and velocity from a velocity input, streamlining the process of integrating with an existing WPILib physics simulation. For example, an External/Alternate Encoder attached after a gearbox could be updated with the motor's velocity transformed by the gear ratio to provide accurate measurements, or an independent simulation could be run for the auxiliary device.
In WPILib VSCode, running a robot code simulation is easy: click the WPILib icon in the top right corner of the UI and select 'Simulate Robot Code'. This will compile your code and launch the Simulation GUI, which displays controls and data during your simulation.
You may be prompted to enable Desktop support for your project, especially if you are using C++, or you may need to manually enable it if features don't work as expected. This can be changed by clicking the WPILib logo and selecting 'Change Desktop Support Enabled Setting'.
Once your simulation is running, you'll be prompted to use the Simulation GUI or the normal driver station for simulation control. The Sim GUI has many helpful interfaces all in one place, like the NetworkTables GUI and Other Devices display, so that's what we'll cover here.
To access the Other Devices display, shown on the right, open it via Hardware > Other Devices at the top of the screen. These drop down interfaces are generated by your code and will contain the list of applicable devices, without any simulation-specific code needed.
Without any simulation-specific code, your Spark devices will still offer some simulation features. Parameters and settings will be able to be set and retrieved, the setpoint and control mode can be set, and the simulation GUI will reflect all of these changes. However, additional code is required to update the applied output or position/velocity and to access the more complex features of the simulation.
As shown below, both the Spark Flex and Spark MAX have Sim classes, which give you full control over the devices and give you access to the methods needed to update the output of the simulated motor controllers.
With these Spark sim objects, you can read and write many fields within the simulation, like manually setting the position, velocity, or motor temperature. The values you set will be visible in the sim GUI and will also be returned by the native functions to get these values in your robot code.
These Spark sim objects also have a method, called .iterate, that will simulate many of the features of the motor controller and allow you to simulate the motion of the motor with the help of a WPILib physics simulation.
During a simulation, the physics model takes in the voltage applied to the motor and returns the velocity with which the motor is rotating. The Spark sim's .iterate method takes in the velocity of the motor from the physics model, the bus voltage (supply voltage to the controller), and the time interval for calculations (0.02 seconds, unless you want to track time differently), and updates all the fields of the Spark sim and native Spark to reflect the new state. An example with a simulated arm and a Spark Flex is shown below, but the Spark MAX behavior is the same and the Arm system could be substituted for another WPILib model.
Closed-loop control in REVLib is accessed through the SPARK's closed loop controller object. This object is specific to each motor and contains all the methods needed to control your motor with closed-loop control. It can be accessed as shown below:
API Docs: ,
API Docs: ,
To drive your motor in a closed-loop control mode, address the closed loop controller object and give it a set point (a target in whatever units are required by your control mode: , , or ) and a control mode as shown below:
This will run your motor in the provided mode, but it won't move until you've configured the
API Docs: ,
API Docs: ,
The provided example above runs the motor in position control mode, which is just a conventional PID loop reading the motor's current position from the configured encoder and taking a setpoint in rotations.
Use caution when running motors in closed-loop modes, as they may move very quickly and unexpectedly if improperly tuned.
To run a PID loop, several constants are required. For a more advanced controller, even more parameters need to be set and tuned.
These gains can be configured on the with the closedLoop
member of a SparkFlexConfig
or SparkMaxConfig
object as seen below:
The SPARK family of motor controllers also offer an F term, which is a velocity feed-forward. This is unique to each type of motor, and can be calculated by taking the reciprocal of the motor's velocity constant (Kv), in other words 1/Kv.
For a NEO Vortex, this value is 1/565. This is only needed when running a velocity-based control loop (velocity mode, Smart Motion, and Smart Velocity). The F parameter can be set as seen below:
The F parameter should only be set when using a velocity-based PID controller, and should be set to zero otherwise to avoid unwanted behavior.
MAXMotion has parameters that allow you to configure and tune the motion profiles generated by MAXMotion. The parameters can be set through the maxMotion
member of the closedLoop
config.
The MAXMotion Max Velocity parameter only applies to MAXMotion Position Control Mode, while MAXMotion Velocity Control Mode does not honor it in order to ensure any setpoint is reachable. This means any top-speed clamping you want to do must be done before you send the setpoint to the Motor Controller.
Smart Motion is deprecated and marked for removal. It is recommended to use MAXMotion instead.
Maximum Velocity is in units of Revolutions per Minute (RPM)
Maximum Acceleration is in units of RPM per Second (RPM/s)
The SPARK MAX and SPARK Flex each have 4 closed-loop slots, each with their own set of constants. These slots are numbered 0-3. You can pass the desired as an argument to each of the applicable configurations.
When applying the setpoint, pass the slot number and the motor controller will switch to the appropriate config.
As your simulation runs, GUI elements will be added to the Devices tab as they are called, with specific dialogues for each sensor and tool.
Every device simulation object includes a .iterate method designed for easy integration with WPILib's Physics models and tools.
Nearly every attribute of the Spark object is directly addressable via the SparkSim object, allowing you to tailor your simulations to any scenario.
By creating a SimFaultManager object, you are given the ability to throw each possible fault individually, either through the GUI or programmatically with the object.
Position, velocity, current, MAXMotion Position Control, and MAXMotion Velocity Control algorithms have been translated into the simulation.
Both MAXMotion Position Control and MAXMotion Velocity Control are able to be fully simulated.
The Voltage Compensation algorithm from the Sparks has been ported to the simulation.
The Smart Current Limiting algorithm from the Sparks has been ported to the simulation.
Adds setPeriodicFrameTimeout()
to configure the CAN timeout for periodic status frames.
Adds setCANMaxRetries()
to configure the value for maximum number of retries.
API Docs:
API Reference:
The GUI in the center contains the NetworkTables, the one at the top left controls enable/disable state, and the one at the bottom left controls joystick order. These give you basic control over the simulation and how you want to interface with it and outputs like you'd see during a match. You can even use a keyboard to emulate a controller if you don't have one! For more information on other elements, .
. These will help us simulate the motion of a motor, as they handle the underlying physics of the load of the motor. Selecting a model and filling out the appropriate fields to describe your physical system will make the simulation as close to real life as possible. These values can be calculated from a CAD model, or measured on a robot.
To see the full list of features, check out
To simulate sensors and auxiliary devices, see
This section uses concepts about configuration which is discussed . For more information about SPARK specific configuration, see .
A PID controller has 3 core parameters or gains. For more information on these gains and how to tune them, see .
API Docs:
API Docs:
Note that this is not the same as an arbitrary feed forward. The F parameter is multiplied by the velocity setpoint to achieve more consistent velocity control, while an arbFF value that is passed in with the setpoint can be used to apply kS, kV, kA, and kG gains. For more info on arbFF, see .
The Kv values for the NEO family of Brushless Motors are documented within each motor's specifications table: , ,
API Docs:
API Docs:
API Docs:
API Docs:
and have parameters that allow you to configure and tune the motion profiles that they generate. The parameters can be set through the smartMotion
member of the closedLoop
config.
API Docs:
API Docs:
API Docs:
API Docs:
API Docs: ,
API Docs: ,
All auxiliary devices are able to be fully controlled, through their individual simulation objects. Selected sensors will automatically be updated by the SparkSim.iterate() method. For more details on how to set these device simulations up, see .
ServoHubConfig
A Closed-Loop Control System in its most basic form is a process that uses feedback to improve the accuracy of its outputs. Closed-Loop Control Systems, sometimes referred to as Feedback Controllers, are frequently used when maintaining or reaching a steady output is important or if the system may have outside influences that could affect the system's output.
A simple example using this type of Control is an automatic coffee maker. In its Closed-Loop Control System, the output is hot coffee and the process we are getting feedback on is the heating of the water. If the coffee maker receives feedback that the water is cold, it will start to heat the pot. When the water is almost hot enough to brew the coffee, the control algorithm will continue to heat the water until the correct goal temperature has been reached. Once the water reaches it's goal temperature, or if it gets too hot, the system will stop heating the water and wait until it receives feedback that the heater needs to begin again.
Closed-Loop Control is a staple of complex FRC mechanism programming. WPILib offers several sets of libraries to allow teams to run PID loops on the roboRIO, but they require setup in your team's code, only update every 20ms by default, and may require specifically-configured feedback devices for fast responses, especially at high frequencies.
With a PID loop onboard a SPARK Motor Controller, the setup is simple, doesn't clutter your code, and the loop is updated every 1ms, increasing the responsiveness and precision of the controller. Even when using a more complex control algorithm on the roboRIO, it's still recommended to put as much processing on the motor controller as possible.
Both the SPARK MAX and SPARK Flex can operate in several closed-loop control modes, using sensor input to tightly control the motor velocity, position or current. The internal control loop follows a standard PID algorithm with a feed-forward (F) term to compensate for known system offsets. This allows the motor to follow precise and repeatable motions, useful for complex mechanisms.
Below is a diagram of the firmware implementation of the internal PIDF.
Additionally, an arbitrary feedforward signal is added to the output of the control loop after all calculations are done. The units for this signal can be selected as either voltage or duty cycle. This feature allows more advanced feedforward calculations to be performed by the controller. More details about the types of feedforward calculations can be found on the WPILib documentation. Using the voltage units for arbitrary feedforward allows the user to send the calculated feedforward voltage from the WPILib API directly to the control loop.
Servo motors are specialized motors that can be controlled to move to a specific angle instead of continuously rotating like a DC motor. For more general information on servos, see ; for more detailed information, see https://en.wikipedia.org/wiki/Servo_control.
Servo control in REVLib is accessed through the ServoHub's object. This object manages the individual ServoChannel objects and monitors the overall device. The ServoChannel object controls each servo motor and monitors its operation. It also contains all the methods to configure and control your servo. It can be accessed as shown below:
API Docs: ServoHub, ServoChannel
API Docs: ServoHub,
With a servo motor, the width of the pulse will determine how far the motor turns. The Pulse Period, on the other hand, will determine how often the pulse is sent to the servo. The ServoHub supports a Pulse Period of 4.5 - 20ms (specified in microseconds). The ServoHub supports a separate Pulse Period for each bank, composing servos 0-2 and 3-5, respectively. These settings can be accessed as shown below:
API Docs: setBankPulsePeriod
API Docs: SetBankPulsePeriod
Individual servos are controlled via the ServoChannel objects. As shown above, you obtain a reference to a ServoChannel object by calling the getServoChannel() method on the ServoHub. You may set the following on a ServoChannel:
PulseWidth - determines the servo's position (500 - 2500 microseconds).
Enabled - enables/disables the servo - when disabled, the servo will maintain power according to the DisableBehavior configured for the specific channel.
Powered - turns on/off the power to the servo
API Docs: setPulseWidth, setPowered, setEnabled
API Docs: SetPulseWidth, SetEnabled, SetPowered