Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/inspector.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,5 +26,5 @@
"latestVersion":"6a5b6352807a8759bd0f012e57695c47f7ef7324"
}
],
"ignoredFiles": ["source/docs/software/commandbased/command-scheduler.rst", "source/docs/software/hardware-apis/pneumatics/pressure.rst", "source/docs/software/hardware-apis/pneumatics/solenoids.rst", "source/docs/software/advanced-controls/state-space/state-space-pose-estimators.rst", "source/docs/software/commandbased/pid-subsystems-commands.rst", "source/docs/software/commandbased/profilepid-subsystems-commands.rst", "source/docs/software/commandbased/subsystems.rst", "source/docs/software/telemetry/writing-sendable-classes.rst", "source/docs/software/advanced-controls/trajectories/troubleshooting.rst", "source/docs/software/hardware-apis/motors/wpi-drive-classes.rst", "source/docs/software/pathplanning/trajectory-tutorial/creating-drive-subsystem.rst", "source/docs/software/pathplanning/trajectory-tutorial/creating-following-trajectory.rst", "source/docs/software/pathplanning/trajectory-tutorial/entering-constants.rst"]
"ignoredFiles": ["source/docs/software/commandbased/command-scheduler.rst", "source/docs/software/hardware-apis/pneumatics/pressure.rst", "source/docs/software/hardware-apis/pneumatics/solenoids.rst", "source/docs/software/advanced-controls/state-space/state-space-pose-estimators.rst", "source/docs/software/commandbased/profilepid-subsystems-commands.rst", "source/docs/software/commandbased/subsystems.rst", "source/docs/software/telemetry/writing-sendable-classes.rst", "source/docs/software/advanced-controls/trajectories/troubleshooting.rst", "source/docs/software/hardware-apis/motors/wpi-drive-classes.rst", "source/docs/software/pathplanning/trajectory-tutorial/creating-drive-subsystem.rst", "source/docs/software/pathplanning/trajectory-tutorial/creating-following-trajectory.rst", "source/docs/software/pathplanning/trajectory-tutorial/entering-constants.rst"]
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

.. note:: This article focuses on in-code implementation of PID control in WPILib. For a conceptual explanation of the working of a PIDController, see :ref:`docs/software/advanced-controls/introduction/introduction-to-pid:Introduction to PID`

.. note:: For a guide on implementing PID control through the :ref:`command-based framework <docs/software/commandbased/what-is-command-based:What Is "Command-Based" Programming?>`, see :ref:`docs/software/commandbased/pid-subsystems-commands:PID Control through PIDSubsystems and PIDCommands`.
.. note:: For a guide on implementing PID control through the :ref:`command-based framework <docs/software/commandbased/what-is-command-based:What Is "Command-Based" Programming?>`, see :ref:`docs/software/commandbased/pid-subsystems-commands:PID Control in Command-based`.

WPILib supports PID control of mechanisms through the ``PIDController`` class ([Java](https://github.wpilib.org/allwpilib/docs/development/java/edu/wpi/first/math/controller/PIDController.html), [C++](https://github.wpilib.org/allwpilib/docs/development/cpp/classfrc_1_1_p_i_d_controller.html), :external:py:class:`Python <wpimath.controller.PIDController>`). This class handles the feedback loop calculation for the user, as well as offering methods for returning the error, setting tolerances, and checking if the control loop has reached its setpoint within the specified tolerances.

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

.. note:: This article covers the in-code generation of trapezoidal motion profiles. Documentation describing the involved concepts in more detail is forthcoming.

.. note:: For a guide on implementing the ``TrapezoidProfile`` class in the :ref:`command-based framework <docs/software/commandbased/what-is-command-based:What Is "Command-Based" Programming?>` framework, see :ref:`docs/software/commandbased/profile-subsystems-commands:Motion Profiling through TrapezoidProfileSubsystems and TrapezoidProfileCommands`.
.. note:: For a guide on implementing the ``TrapezoidProfile`` class in the :ref:`command-based framework <docs/software/commandbased/what-is-command-based:What Is "Command-Based" Programming?>` framework, see :doc:`/docs/software/commandbased/profile-subsystems-commands`.

.. note:: The ``TrapezoidProfile`` class, used on its own, is most useful when composed with a custom controller (such as a "smart" motor controller with a built-in PID functionality). To integrate it with a WPILib ``PIDController``, see :doc:`profiled-pidcontroller`.

Expand Down
4 changes: 1 addition & 3 deletions source/docs/software/commandbased/commands.rst
Original file line number Diff line number Diff line change
Expand Up @@ -308,9 +308,7 @@ To wait until a certain condition becomes ``true``, the library offers the ``Com

There are commands for various control setups:

- ``PIDCommand`` uses a PID controller. For more info, see :ref:`docs/software/commandbased/pid-subsystems-commands:PIDCommand`.

- ``TrapezoidProfileCommand`` tracks a trapezoid motion profile. For more info, see :ref:`docs/software/commandbased/profile-subsystems-commands:TrapezoidProfileCommand`.
- ``TrapezoidProfile`` tracks a trapezoid motion profile. For more info, see :doc:`/docs/software/commandbased/profile-subsystems-commands`.

- ``ProfiledPIDCommand`` combines PID control with trapezoid motion profiles. For more info, see :ref:`docs/software/commandbased/profilepid-subsystems-commands:ProfiledPIDCommand`.

Expand Down
246 changes: 7 additions & 239 deletions source/docs/software/commandbased/pid-subsystems-commands.rst
Original file line number Diff line number Diff line change
@@ -1,230 +1,18 @@
.. include:: <isonum.txt>

# PID Control through PIDSubsystems and PIDCommands
PID Control in Command-based
=================================================

.. note:: For a description of the WPILib PID control features used by these command-based wrappers, see :ref:`docs/software/advanced-controls/controllers/pidcontroller:PID Control in WPILib`.

One of the most common control algorithms used in FRC\ |reg| is the :term:`PID` controller. WPILib offers its own :ref:`PIDController <docs/software/advanced-controls/controllers/pidcontroller:PID Control in WPILib>` class to help teams implement this functionality on their robots. To further help teams integrate PID control into a command-based robot project, the command-based library includes two convenience wrappers for the ``PIDController`` class: ``PIDSubsystem``, which integrates the PID controller into a subsystem, and ``PIDCommand``, which integrates the PID controller into a command.

## PIDSubsystems

The ``PIDSubsystem`` class ([Java](https://github.wpilib.org/allwpilib/docs/development/java/edu/wpi/first/wpilibj2/command/PIDSubsystem.html), [C++](https://github.wpilib.org/allwpilib/docs/development/cpp/classfrc2_1_1_p_i_d_subsystem.html)) allows users to conveniently create a subsystem with a built-in ``PIDController``. In order to use the ``PIDSubsystem`` class, users must create a subclass of it.

### Creating a PIDSubsystem

.. note:: If ``periodic`` is overridden when inheriting from ``PIDSubsystem``, make sure to call ``super.periodic()``! Otherwise, PID functionality will not work properly.

When subclassing ``PIDSubsystem``, users must override two abstract methods to provide functionality that the class will use in its ordinary operation:

#### getMeasurement()

.. tab-set::

.. tab-item:: Java
:sync: Java

.. rli:: https://github.com/wpilibsuite/allwpilib/raw/v2024.1.1-beta-4/wpilibNewCommands/src/main/java/edu/wpi/first/wpilibj2/command/PIDSubsystem.java
:language: java
:lines: 85

.. tab-item:: C++
:sync: C++

.. rli:: https://github.com/wpilibsuite/allwpilib/raw/v2024.1.1-beta-4/wpilibNewCommands/src/main/native/include/frc2/command/PIDSubsystem.h
:language: c++
:lines: 80-80

The ``getMeasurement`` method returns the current measurement of the process variable. The ``PIDSubsystem`` will automatically call this method from its ``periodic()`` block, and pass its value to the control loop.

Users should override this method to return whatever sensor reading they wish to use as their process variable measurement.

#### useOutput()

.. tab-set::

.. tab-item:: Java
:sync: Java

.. rli:: https://github.com/wpilibsuite/allwpilib/raw/v2024.1.1-beta-4/wpilibNewCommands/src/main/java/edu/wpi/first/wpilibj2/command/PIDSubsystem.java
:language: java
:lines: 78

.. tab-item:: C++
:sync: C++

.. rli:: https://github.com/wpilibsuite/allwpilib/raw/v2024.1.1-beta-4/wpilibNewCommands/src/main/native/include/frc2/command/PIDSubsystem.h
:language: c++
:lines: 88-88


The ``useOutput()`` method consumes the output of the PID controller, and the current setpoint (which is often useful for computing a feedforward). The ``PIDSubsystem`` will automatically call this method from its ``periodic()`` block, and pass it the computed output of the control loop.

Users should override this method to pass the final computed control output to their subsystem's motors.

#### Passing In the Controller

Users must also pass in a ``PIDController`` to the ``PIDSubsystem`` base class through the superclass constructor call of their subclass. This serves to specify the PID gains, as well as the period (if the user is using a non-standard main robot loop period).

Additional modifications (e.g. enabling continuous input) can be made to the controller in the constructor body by calling ``getController()``.

### Using a PIDSubsystem

Once an instance of a ``PIDSubsystem`` subclass has been created, it can be used by commands through the following methods:

#### setSetpoint()

The ``setSetpoint()`` method can be used to set the setpoint of the ``PIDSubsystem``. The subsystem will automatically track to the setpoint using the defined output:

.. tab-set-code::

```java
// The subsystem will track to a setpoint of 5.
examplePIDSubsystem.setSetpoint(5);
```

```c++
// The subsystem will track to a setpoint of 5.
examplePIDSubsystem.SetSetpoint(5);
```

#### enable() and disable()

The ``enable()`` and ``disable()`` methods enable and disable the PID control of the ``PIDSubsystem``. When the subsystem is enabled, it will automatically run the control loop and track the setpoint. When it is disabled, no control is performed.

Additionally, the ``enable()`` method resets the internal ``PIDController``, and the ``disable()`` method calls the user-defined `useOutput()`_ method with both output and setpoint set to ``0``.

### Full PIDSubsystem Example

What does a ``PIDSubsystem`` look like when used in practice? The following examples are taken from the FrisbeeBot example project ([Java](https://github.com/wpilibsuite/allwpilib/tree/main/wpilibjExamples/src/main/java/edu/wpi/first/wpilibj/examples/frisbeebot), [C++](https://github.com/wpilibsuite/allwpilib/tree/main/wpilibcExamples/src/main/cpp/examples/Frisbeebot)):

.. tab-set::

.. tab-item:: Java
:sync: Java

.. remoteliteralinclude:: https://raw.githubusercontent.com/wpilibsuite/allwpilib/v2024.1.1/wpilibjExamples/src/main/java/edu/wpi/first/wpilibj/examples/frisbeebot/subsystems/ShooterSubsystem.java
:language: java
:lines: 5-
:linenos:
:lineno-start: 5

.. tab-item:: C++
:sync: C++ (Header)

.. remoteliteralinclude:: https://raw.githubusercontent.com/wpilibsuite/allwpilib/v2024.1.1/wpilibcExamples/src/main/cpp/examples/Frisbeebot/include/subsystems/ShooterSubsystem.h
:language: c++
:lines: 5-
:linenos:
:lineno-start: 5

.. tab-item:: C++ (Source)
:sync: C++ (Source)

.. remoteliteralinclude:: https://raw.githubusercontent.com/wpilibsuite/allwpilib/v2024.1.1/wpilibcExamples/src/main/cpp/examples/Frisbeebot/cpp/subsystems/ShooterSubsystem.cpp
:language: c++
:lines: 5-
:linenos:
:lineno-start: 5

Using a ``PIDSubsystem`` with commands can be very simple:

.. tab-set::

.. tab-item:: Java
:sync: Java

.. remoteliteralinclude:: https://raw.githubusercontent.com/wpilibsuite/allwpilib/v2024.1.1/wpilibjExamples/src/main/java/edu/wpi/first/wpilibj/examples/frisbeebot/RobotContainer.java
:language: java
:lines: 26-27, 80-87

.. tab-item:: C++
:sync: C++ (Header)

.. remoteliteralinclude:: https://raw.githubusercontent.com/wpilibsuite/allwpilib/v2024.1.1/wpilibcExamples/src/main/cpp/examples/Frisbeebot/include/RobotContainer.h
:language: c++
:lines: 45-49
:linenos:
:lineno-start: 45

.. tab-item:: C++ (Source)
:sync: C++ (Source)

.. remoteliteralinclude:: https://raw.githubusercontent.com/wpilibsuite/allwpilib/v2024.1.1/wpilibcExamples/src/main/cpp/examples/Frisbeebot/cpp/RobotContainer.cpp
:language: c++
:lines: 25-31
:linenos:
:lineno-start: 25

## PIDCommand

The ``PIDCommand`` class allows users to easily create commands with a built-in PIDController.

### Creating a PIDCommand

A ``PIDCommand`` can be created two ways - by subclassing the ``PIDCommand`` class, or by defining the command :ref:`inline <docs/software/commandbased/organizing-command-based:Inline Commands>`. Both methods ultimately extremely similar, and ultimately the choice of which to use comes down to where the user desires that the relevant code be located.

.. note:: If subclassing ``PIDCommand`` and overriding any methods, make sure to call the ``super`` version of those methods! Otherwise, PID functionality will not work properly.

In either case, a ``PIDCommand`` is created by passing the necessary parameters to its constructor (if defining a subclass, this can be done with a `super()` call):

.. tab-set::

.. tab-item:: Java
:sync: Java

.. remoteliteralinclude:: https://raw.githubusercontent.com/wpilibsuite/allwpilib/v2024.1.1-beta-4/wpilibNewCommands/src/main/java/edu/wpi/first/wpilibj2/command/PIDCommand.java
:language: java
:lines: 27-41
:linenos:
:lineno-start: 27

.. tab-item:: C++
:sync: C++

.. remoteliteralinclude:: https://raw.githubusercontent.com/wpilibsuite/allwpilib/v2024.1.1/wpilibNewCommands/src/main/native/include/frc2/command/PIDCommand.h
:language: c++
:lines: 28-42
:linenos:
:lineno-start: 28

#### controller

The ``controller`` parameter is the ``PIDController`` object that will be used by the command. By passing this in, users can specify the PID gains and the period for the controller (if the user is using a nonstandard main robot loop period).

When subclassing ``PIDCommand``, additional modifications (e.g. enabling continuous input) can be made to the controller in the constructor body by calling ``getController()``.

#### measurementSource

The ``measurementSource`` parameter is a function (usually passed as a :ref:`lambda <docs/software/commandbased/index:Lambda Expressions (Java)>`) that returns the measurement of the process variable. Passing in the ``measurementSource`` function in ``PIDCommand`` is functionally analogous to overriding the `getMeasurement()`_ function in ``PIDSubsystem``.

When subclassing ``PIDCommand``, advanced users may further modify the measurement supplier by modifying the class's ``m_measurement`` field.

#### setpointSource

The ``setpointSource`` parameter is a function (usually passed as a :ref:`lambda <docs/software/commandbased/index:Lambda Expressions (Java)>`) that returns the current setpoint for the control loop. If only a constant setpoint is needed, an overload exists that takes a constant setpoint rather than a supplier.

When subclassing ``PIDCommand``, advanced users may further modify the setpoint supplier by modifying the class's ``m_setpoint`` field.

#### useOutput

The ``useOutput`` parameter is a function (usually passed as a :ref:`lambda <docs/software/commandbased/index:Lambda Expressions (Java)>`) that consumes the output and setpoint of the control loop. Passing in the ``useOutput`` function in ``PIDCommand`` is functionally analogous to overriding the `useOutput()`_ function in ``PIDSubsystem``.

When subclassing ``PIDCommand``, advanced users may further modify the output consumer by modifying the class's ``m_useOutput`` field.

#### requirements

Like all inlineable commands, ``PIDCommand`` allows the user to specify its subsystem requirements as a constructor parameter.

### Full PIDCommand Example

What does a ``PIDCommand`` look like when used in practice? The following examples are from the GyroDriveCommands example project ([Java](https://github.com/wpilibsuite/allwpilib/tree/main/wpilibjExamples/src/main/java/edu/wpi/first/wpilibj/examples/gyrodrivecommands), [C++](https://github.com/wpilibsuite/allwpilib/tree/main/wpilibcExamples/src/main/cpp/examples/GyroDriveCommands)):
One of the most common control algorithms used in FRC\ |reg| is the :term:`PID` controller. WPILib offers its own :ref:`PIDController <docs/software/advanced-controls/controllers/pidcontroller:PID Control in WPILib>` class to help teams implement this functionality on their robots. The following example is from the RapidReactCommandBot example project (`Java <https://github.com/wpilibsuite/allwpilib/tree/main/wpilibjExamples/src/main/java/edu/wpi/first/wpilibj/examples/rapidreactcommandbot>`__, `C++ <https://github.com/wpilibsuite/allwpilib/tree/main/wpilibcExamples/src/main/cpp/examples/RapidReactCommandBot>`__) and shows how PIDControllers can be used within the command-based framework:

.. tab-set::

.. tab-item:: Java
:sync: Java

.. remoteliteralinclude:: https://raw.githubusercontent.com/wpilibsuite/allwpilib/v2024.1.1/wpilibjExamples/src/main/java/edu/wpi/first/wpilibj/examples/gyrodrivecommands/commands/TurnToAngle.java
.. remoteliteralinclude:: https://raw.githubusercontent.com/wpilibsuite/allwpilib/v2024.3.2/wpilibjExamples/src/main/java/edu/wpi/first/wpilibj/examples/rapidreactcommandbot/subsystems/Shooter.java
:language: java
:lines: 5-
:linenos:
Expand All @@ -233,7 +21,7 @@ What does a ``PIDCommand`` look like when used in practice? The following exampl
.. tab-item:: C++
:sync: C++ (Header)

.. remoteliteralinclude:: https://raw.githubusercontent.com/wpilibsuite/allwpilib/v2024.1.1/wpilibcExamples/src/main/cpp/examples/GyroDriveCommands/include/commands/TurnToAngle.h
.. remoteliteralinclude:: https://raw.githubusercontent.com/wpilibsuite/allwpilib/v2024.3.2/wpilibcExamples/src/main/cpp/examples/RapidReactCommandBot/include/subsystems/Shooter.h
:language: c++
:lines: 5-
:linenos:
Expand All @@ -242,30 +30,10 @@ What does a ``PIDCommand`` look like when used in practice? The following exampl
.. tab-item:: C++ (Source)
:sync: C++ (Source)

.. remoteliteralinclude:: https://raw.githubusercontent.com/wpilibsuite/allwpilib/v2024.1.1/wpilibcExamples/src/main/cpp/examples/GyroDriveCommands/cpp/commands/TurnToAngle.cpp
.. remoteliteralinclude:: https://raw.githubusercontent.com/wpilibsuite/allwpilib/v2024.3.2/wpilibcExamples/src/main/cpp/examples/RapidReactCommandBot/cpp/subsystems/Shooter.cpp
:language: c++
:lines: 5-
:linenos:
:lineno-start: 5

And, for an :ref:`inlined <docs/software/commandbased/organizing-command-based:Inline Commands>` example:

.. tab-set::

.. tab-item:: Java
:sync: Java

.. remoteliteralinclude:: https://raw.githubusercontent.com/wpilibsuite/allwpilib/v2024.1.1/wpilibjExamples/src/main/java/edu/wpi/first/wpilibj/examples/gyrodrivecommands/RobotContainer.java
:language: java
:lines: 64-79
:linenos:
:lineno-start: 64

.. tab-item:: C++
:sync: C++

.. remoteliteralinclude:: https://raw.githubusercontent.com/wpilibsuite/allwpilib/v2024.1.1/wpilibcExamples/src/main/cpp/examples/GyroDriveCommands/cpp/RobotContainer.cpp
:language: c++
:lines: 34-49
:linenos:
:lineno-start: 34
A ``PIDController`` is declared inside the ``Shooter`` subsystem. It is used by ``ShootCommand`` alongside a feedforward to spin the shooter flywheel to the specified velocity. Once the ``PIDController`` reaches the specified velocity, the ``ShootCommand`` runs the feeder.
Loading