001// Copyright (c) FIRST and other WPILib contributors.
002// Open Source Software; you can modify and/or share it under the terms of
003// the WPILib BSD license file in the root directory of this project.
004
005package edu.wpi.first.wpilibj2.command;
006
007import static edu.wpi.first.wpilibj.util.ErrorMessages.requireNonNullParam;
008
009import edu.wpi.first.math.controller.PIDController;
010
011/**
012 * A subsystem that uses a {@link PIDController} to control an output. The controller is run
013 * synchronously from the subsystem's periodic() method.
014 */
015public abstract class PIDSubsystem extends SubsystemBase {
016  protected final PIDController m_controller;
017  protected boolean m_enabled;
018
019  private double m_setpoint;
020
021  /**
022   * Creates a new PIDSubsystem.
023   *
024   * @param controller the PIDController to use
025   * @param initialPosition the initial setpoint of the subsystem
026   */
027  public PIDSubsystem(PIDController controller, double initialPosition) {
028    setSetpoint(initialPosition);
029    m_controller = requireNonNullParam(controller, "controller", "PIDSubsystem");
030    addChild("PID Controller", m_controller);
031  }
032
033  /**
034   * Creates a new PIDSubsystem. Initial setpoint is zero.
035   *
036   * @param controller the PIDController to use
037   */
038  public PIDSubsystem(PIDController controller) {
039    this(controller, 0);
040  }
041
042  @Override
043  public void periodic() {
044    if (m_enabled) {
045      useOutput(m_controller.calculate(getMeasurement(), m_setpoint), m_setpoint);
046    }
047  }
048
049  public PIDController getController() {
050    return m_controller;
051  }
052
053  /**
054   * Sets the setpoint for the subsystem.
055   *
056   * @param setpoint the setpoint for the subsystem
057   */
058  public void setSetpoint(double setpoint) {
059    m_setpoint = setpoint;
060  }
061
062  /**
063   * Returns the current setpoint of the subsystem.
064   *
065   * @return The current setpoint
066   */
067  public double getSetpoint() {
068    return m_setpoint;
069  }
070
071  /**
072   * Uses the output from the PIDController.
073   *
074   * @param output the output of the PIDController
075   * @param setpoint the setpoint of the PIDController (for feedforward)
076   */
077  protected abstract void useOutput(double output, double setpoint);
078
079  /**
080   * Returns the measurement of the process variable used by the PIDController.
081   *
082   * @return the measurement of the process variable
083   */
084  protected abstract double getMeasurement();
085
086  /** Enables the PID control. Resets the controller. */
087  public void enable() {
088    m_enabled = true;
089    m_controller.reset();
090  }
091
092  /** Disables the PID control. Sets output to zero. */
093  public void disable() {
094    m_enabled = false;
095    useOutput(0, 0);
096  }
097
098  /**
099   * Returns whether the controller is enabled.
100   *
101   * @return Whether the controller is enabled.
102   */
103  public boolean isEnabled() {
104    return m_enabled;
105  }
106}