Documentation
¶
Overview ¶
Package pidcontroller implements a Proportional-Integral-Derivative (PID) controller.
A PID controller is a control loop mechanism employing feedback that is widely used in industrial control systems and a variety of other applications requiring continuously modulated control. A PID controller calculates an error value as the difference between a desired setpoint (SP) and a measured process variable (PV) and applies a correction based on proportional, integral, and derivative terms (denoted P, I, and D respectively).
Concepts ¶
The PID controller algorithm involves three separate constant parameters, and is accordingly sometimes called three-term control: the proportional, the integral and derivative values, denoted P, I, and D. Simply put, these values can be interpreted in terms of time: P depends on the present error, I on the accumulation of past errors, and D is a prediction of future errors, based on current rate of change. The weighted sum of these three actions is used to adjust the process via a control element such as the position of a control valve, a damper, or the power supplied to a heating element.
Data Flow ¶
The following diagram illustrates the data flow within the PID controller:
Setpoint (SP)
|
v
+-----------+ Error (e) +-----------+
| | ----------------> | |
| Comparator| | PID |
| | <---------------- | Algorithm |
+-----------+ | |
^ +-----------+
| | Control Variable (u)
| v
Process Variable (PV) +-----------+
| Process |
+-----------+
Mathematical Model ¶
The overall control function u(t) can be expressed mathematically as:
u(t) = Kp * e(t) + Ki * ∫ e(t) dt + Kd * de(t)/dt
Where:
- Kp is the proportional gain, a tuning parameter.
- Ki is the integral gain, a tuning parameter.
- Kd is the derivative gain, a tuning parameter.
- e(t) = SP - PV(t) is the error (SP is the setpoint, and PV(t) is the process variable).
- t is the time or instantaneous time (the present).
- τ is the variable of integration (takes on values from time 0 to the present t).
Usage ¶
This package provides a simple interface `PID` to create and use a PID controller. The primary use case is generating a smooth transition from a starting value to a target value, controlled by the PID parameters to simulate physical constraints or desired behaviors (e.g., easing, overshoot).
Quick Start ¶
To use the PID controller, first create a new instance using the `New` function, providing the P, I, and D coefficients. Then, use the `Range` or `RangeCtx` methods to generate a sequence of values.
Example:
package main
import (
"fmt"
"github.com/nabbar/golib/pidcontroller"
)
func main() {
// Initialize a PID controller with specific gains
// Kp = 0.5 (Proportional)
// Ki = 0.1 (Integral)
// Kd = 0.2 (Derivative)
pid := pidcontroller.New(0.5, 0.1, 0.2)
// Generate a range of values from 0 to 100
// The PID controller will determine the steps based on the gains.
values := pid.Range(0, 100)
// Output the generated sequence
for i, v := range values {
fmt.Printf("Step %d: %f\n", i, v)
}
}
Use Cases ¶
1. Smooth Animation: Calculating intermediate frames for an animation where the transition needs to be natural and physics-based. 2. Process Simulation: Simulating a heating process where temperature rises to a setpoint. 3. Rate Limiting: Controlling the rate of resource consumption or request processing.
Example (Duration) ¶
Example_duration demonstrates how to use the PID controller to generate a sequence of durations between a minimum and maximum wait time. This can be useful for implementing backoff strategies.
package main
import (
"fmt"
"time"
"github.com/nabbar/golib/pidcontroller"
)
func main() {
// Initialize a PID controller suitable for duration calculation.
// A lower Kp will result in more, smaller steps.
pid := pidcontroller.New(0.05, 0.01, 0.01)
// Define the minimum and maximum durations (e.g., 5s to 1m).
minDuration := 5 * time.Second
maxDuration := 1 * time.Minute
// Convert durations to float64 (nanoseconds) for the PID controller.
start := float64(minDuration)
end := float64(maxDuration)
// Generate the sequence of durations.
steps := pid.Range(start, end)
fmt.Printf("Generating backoff steps from %s to %s\n", minDuration, maxDuration)
fmt.Printf("Total steps: %d\n", len(steps))
if len(steps) > 0 {
// Convert the first and last step back to time.Duration for display.
firstStep := time.Duration(steps[0])
lastStep := time.Duration(steps[len(steps)-1])
fmt.Printf("First backoff: %s\n", firstStep.Round(time.Second))
fmt.Printf("Last backoff: %s\n", lastStep.Round(time.Second))
}
}
Output: Generating backoff steps from 5s to 1m0s Total steps: 13 First backoff: 9s Last backoff: 1m0s
Index ¶
Examples ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func Float64ToInt64 ¶ added in v1.21.0
Float64ToInt64 converts a float64 value to an int64 representation. It handles potential overflow/underflow by clamping the value to the range of int64.
func Int64ToFloat64 ¶ added in v1.21.0
Int64ToFloat64 converts an int64 value to a float64 representation. This is a simple type conversion helper.
Types ¶
type PID ¶
type PID interface {
// RangeCtx generates a slice of float64 values representing the progression from a minimum value
// to a maximum value, utilizing the PID controller to determine the step size at each iteration.
//
// The provided context.Context allows for cancellation or timeout of the operation.
// If the context is cancelled before the target is reached, the function returns the values
// generated up to that point, appending the target value as the final element to ensure closure.
//
// Parameters:
// - ctx: The context to manage the lifecycle of the operation (e.g., timeout, cancellation).
// - min: The starting value (Process Variable initial state).
// - max: The target value (SetPoint).
//
// Returns:
// A slice of float64 containing the sequence of values generated by the PID controller.
RangeCtx(ctx context.Context, min, max float64) []float64
// Range acts as a wrapper around RangeCtx with a default timeout.
// It generates a sequence of values from min to max.
//
// This method enforces a default timeout (e.g., 5 seconds) to prevent infinite loops
// in case the PID controller fails to converge or the target is unreachable.
//
// Parameters:
// - min: The starting value.
// - max: The target value.
//
// Returns:
// A slice of float64 containing the sequence of values.
Range(min, max float64) []float64
}
PID defines the interface for a Proportional-Integral-Derivative controller. It provides methods to generate a sequence of values transitioning from a start point to a target point, controlled by the PID algorithm.
func New ¶
New creates and initializes a new PID controller instance.
The PID controller is initialized with the specified coefficients for the Proportional, Integral, and Derivative terms. These coefficients dictate the behavior of the controller:
- rateProportional (Kp): Reacts to the current error.
- rateIntegral (Ki): Reacts to the accumulation of past errors.
- rateDerivative (Kd): Reacts to the rate of change of the error.
Parameters:
- rateProportional: The proportional gain coefficient.
- rateIntegral: The integral gain coefficient.
- rateDerivative: The derivative gain coefficient.
Returns:
A new instance of the PID interface.