All Downloads are FREE. Search and download functionalities are using the official Maven repository.

gov.sandia.cognition.math.signals.PIDController Maven / Gradle / Ivy

/*
 * File:                PIDController.java
 * Authors:             Kevin R. Dixon
 * Company:             Sandia National Laboratories
 * Project:             Cognitive Foundry
 * 
 * Copyright Apr 4, 2009, Sandia Corporation.
 * Under the terms of Contract DE-AC04-94AL85000, there is a non-exclusive
 * license for use of this work by or on behalf of the U.S. Government.
 * Export of this program may require a license from the United States
 * Government. See CopyrightHistory.txt for complete details.
 * 
 */

package gov.sandia.cognition.math.signals;

import gov.sandia.cognition.annotation.PublicationReference;
import gov.sandia.cognition.annotation.PublicationReferences;
import gov.sandia.cognition.annotation.PublicationType;
import gov.sandia.cognition.evaluator.AbstractStatefulEvaluator;
import gov.sandia.cognition.util.AbstractCloneableSerializable;

/**
 * This class defines a Proportional-plus-Integral-plus-Derivative set-point
 * controller.  The goal of this PID controller is to minimize the difference
 * between its target-value input and a given input by changing a control
 * variable to implicitly change its given input at the next time step.
 * @author Kevin R. Dixon
 * @since 3.0
 */
@PublicationReferences(
    references={
        @PublicationReference(
            author="Control Tutorial for MATLAB",
            title="PID Tutorial",
            type=PublicationType.WebPage,
            year=1997,
            url="http://www.engin.umich.edu/group/ctm/PID/PID.html"
        ),
        @PublicationReference(
            author="Wikipedia",
            title="PID Controller",
            type=PublicationType.WebPage,
            year=2009,
            url="http://en.wikipedia.org/wiki/PID_controller",
            notes="This article pretty much sucks"
        )
    }
)
public class PIDController 
    extends AbstractStatefulEvaluator
{

    /**
     * Set point target to achieve at steady-state.
     */
    private double targetInput;

    /**
     * Proportional-error gain.
     */
    private double proportionalGain;

    /**
     * Integral-error gain.
     */
    private double integralGain;

    /**
     * Derivative-error gain.
     */
    private double derivativeGain;

    /**
     * Default proportional-error gain, {@value}.
     */
    public static final double DEFAULT_PROPORTIONAL_GAIN = 0.5;

    /**
     * Default integral-error gain, {@value}.
     */
    public static final double DEFAULT_INTEGRAL_GAIN = 0.0;

    /**
     * Default derivative-error gain, {@value}.
     */
    public static final double DEFAULT_DERIVATIVE_GAIN = 0.25;


    /** 
     * Creates a new instance of PIDController 
     */
    public PIDController()
    {
        this( DEFAULT_PROPORTIONAL_GAIN, DEFAULT_INTEGRAL_GAIN, DEFAULT_DERIVATIVE_GAIN );
    }

    /**
     * Creates a new instance of PIDController.
     * @param proportionalGain
     * Proportional-error gain.
     * @param integralGain
     * Integral-error gain.
     * @param derivativeGain
     * Derivative-error gain.
     */
    public PIDController(
        double proportionalGain,
        double integralGain,
        double derivativeGain )
    {
        this( proportionalGain, integralGain, derivativeGain, 0.0 );
    }

    /**
     * Creates a new instance of PIDController.
     * @param proportionalGain
     * Proportional-error gain.
     * @param integralGain
     * Integral-error gain.
     * @param derivativeGain
     * Derivative-error gain.
     * @param targetInput
     * Set point target to achieve at steady-state.
     */
    public PIDController(
        double proportionalGain,
        double integralGain,
        double derivativeGain,
        double targetInput )
    {
        super();
        this.setProportionalGain( proportionalGain );
        this.setIntegralGain( integralGain );
        this.setDerivativeGain( derivativeGain );
        this.setTargetInput( targetInput );
    }

    /**
     * Getter for targetInput.
     * @return
     * Set point target to achieve at steady-state.
     */
    public double getTargetInput()
    {
        return this.targetInput;
    }

    /**
     * Setter for targetInput
     * @param targetInput
     * Set point target to achieve at steady-state.
     */
    public void setTargetInput(
        double targetInput )
    {
        this.targetInput = targetInput;
    }

    /**
     * Getter for proportionalGain
     * @return
     * Proportional-error gain.
     */
    public double getProportionalGain()
    {
        return this.proportionalGain;
    }

    /**
     * Setter for proportionalGain
     * @param proportionalGain
     * Proportional-error gain.
     */
    public void setProportionalGain(
        double proportionalGain )
    {
        this.proportionalGain = proportionalGain;
    }

    /**
     * Getter for integralGain.
     * @return
     * Integral-error gain.
     */
    public double getIntegralGain()
    {
        return this.integralGain;
    }

    /**
     * Setter for integralGain
     * @param integralGain
     * Integral-error gain.
     */
    public void setIntegralGain(
        double integralGain )
    {
        this.integralGain = integralGain;
    }

    /**
     * Getter for derivativeGain
     * @return
     * Derivative-error gain.
     */
    public double getDerivativeGain()
    {
        return this.derivativeGain;
    }

    /**
     * Setter for derivativeGain
     * @param derivativeGain
     * Derivative-error gain.
     */
    public void setDerivativeGain(
        double derivativeGain )
    {
        this.derivativeGain = derivativeGain;
    }

    public Double evaluate(
        Double input )
    {
        double err = this.targetInput - input;
        
        double errSum = err + this.getState().getErrSum();
        double diffErr = err - this.getState().getLastErr();

        this.getState().setErrSum( errSum );
        this.getState().setLastErr( err );
        
        double pid = this.proportionalGain * err
            + this.integralGain * errSum
            + this.derivativeGain * diffErr;
        
        return pid;
    }

    public State createDefaultState()
    {
        return new State();
    }

    /**
     * State of a PIDController
     */
    public static class State
        extends AbstractCloneableSerializable
    {

        /**
         * Last error.
         */
        private double lastErr;

        /**
         * Sum of all errors.
         */
        private double errSum;

        /**
         * Default constructor.
         */
        public State()
        {
            this( 0.0, 0.0 );
        }


        /**
         * Creates a new instance of State
         * @param lastErr
         * Last error.
         * @param errSum
         * Sum of all errors.
         */
        public State(
            double lastErr,
            double errSum )
        {
            this.setLastErr( lastErr );
            this.setErrSum( errSum );
        }

        /**
         * Getter for lastErr
         * @return
         * Last error.
         */
        public double getLastErr()
        {
            return this.lastErr;
        }

        /**
         * Setter for lastErr
         * @param lastErr
         * Last error.
         */
        public void setLastErr(
            double lastErr )
        {
            this.lastErr = lastErr;
        }

        /**
         * Getter for errSum
         * @return
         * Sum of all errors.
         */
        public double getErrSum()
        {
            return this.errSum;
        }

        /**
         * Setter for errSum
         * @param errSum
         * Sum of all errors.
         */
        public void setErrSum(
            double errSum )
        {
            this.errSum = errSum;
        }

    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy