Skip to content

Commit

Permalink
chore: changing IntegralPartDischargeFactor to IntegralPartDischargeT…
Browse files Browse the repository at this point in the history
…imeConstant

Instead of using a factor equal to the inverse of a time constant,
the time constant itself is used instead, and the formula adapted accordingly.
Additional comments added.
  • Loading branch information
camillechasset authored and odsod committed Dec 22, 2020
1 parent fe16b5f commit c2ec3fe
Show file tree
Hide file tree
Showing 4 changed files with 50 additions and 48 deletions.
9 changes: 5 additions & 4 deletions antiwindupcontroller.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,8 @@ type AntiWindupControllerConfig struct {
DerivativeGain float64
// AntiWindUpGain is the anti-windup tracking gain.
AntiWindUpGain float64
// Inverse of the time constant to discharge the integral part of the PID controller (1/s)
IntegralPartDischargeFactor float64
// IntegralDischargeTimeConstant is the time constant to discharge the integral state of the PID controller (s)
IntegralDischargeTimeConstant float64
// LowPassTimeConstant is the D part low-pass filter time constant => cut-off frequency 1/LowPassTimeConstant.
LowPassTimeConstant time.Duration
// MaxOutput is the max output from the PID.
Expand Down Expand Up @@ -84,11 +84,12 @@ func (c *AntiWindupController) Update(input AntiWindupControllerInput) {
c.State.ControlError = e
}

// TODO: Document me.
// DischargeIntegral provides the ability to discharge the controller integral state
// over a configurable period of time.
func (c *AntiWindupController) DischargeIntegral(dt time.Duration) {
c.State.ControlErrorIntegrand = 0.0
c.State.ControlErrorIntegral = math.Max(
0,
math.Min(1-dt.Seconds()*c.Config.IntegralPartDischargeFactor, 1.0),
math.Min(1-dt.Seconds()/c.Config.IntegralDischargeTimeConstant, 1.0),
) * c.State.ControlErrorIntegral
}
52 changes: 26 additions & 26 deletions antiwindupcontroller_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,11 @@ func TestAntiWindupController_PControllerUpdate(t *testing.T) {
// Given a saturated P controller
c := &AntiWindupController{
Config: AntiWindupControllerConfig{
LowPassTimeConstant: 1 * time.Second,
ProportionalGain: 1,
IntegralPartDischargeFactor: 0.1,
MinOutput: -10,
MaxOutput: 10,
LowPassTimeConstant: 1 * time.Second,
ProportionalGain: 1,
IntegralDischargeTimeConstant: 10,
MinOutput: -10,
MaxOutput: 10,
},
}
for _, tt := range []struct {
Expand Down Expand Up @@ -65,14 +65,14 @@ func TestAntiWindupController_PIDUpdate(t *testing.T) {
// Given a saturated PID controller
c := &AntiWindupController{
Config: AntiWindupControllerConfig{
LowPassTimeConstant: 1 * time.Second,
DerivativeGain: 0.01,
ProportionalGain: 1,
IntegralGain: 10,
AntiWindUpGain: 10,
IntegralPartDischargeFactor: 0.1,
MinOutput: -10,
MaxOutput: 10,
LowPassTimeConstant: 1 * time.Second,
DerivativeGain: 0.01,
ProportionalGain: 1,
IntegralGain: 10,
AntiWindUpGain: 10,
IntegralDischargeTimeConstant: 10,
MinOutput: -10,
MaxOutput: 10,
},
}
for _, tt := range []struct {
Expand Down Expand Up @@ -119,11 +119,11 @@ func TestAntiWindupPID_FFUpdate(t *testing.T) {
// Given a saturated I controller
c := &AntiWindupController{
Config: AntiWindupControllerConfig{
LowPassTimeConstant: 1 * time.Second,
IntegralGain: 10,
IntegralPartDischargeFactor: 0.1,
MinOutput: -10,
MaxOutput: 10,
LowPassTimeConstant: 1 * time.Second,
IntegralGain: 10,
IntegralDischargeTimeConstant: 10,
MinOutput: -10,
MaxOutput: 10,
},
}
for _, tt := range []struct {
Expand Down Expand Up @@ -197,14 +197,14 @@ func TestAntiWindupController_OffloadIntegralTerm(t *testing.T) {
// Given a saturated PID controller
c := &AntiWindupController{
Config: AntiWindupControllerConfig{
LowPassTimeConstant: 1 * time.Second,
ProportionalGain: 1,
DerivativeGain: 10,
IntegralGain: 0.01,
AntiWindUpGain: 0.5,
IntegralPartDischargeFactor: 0.1,
MinOutput: -10,
MaxOutput: 10,
LowPassTimeConstant: 1 * time.Second,
ProportionalGain: 1,
DerivativeGain: 10,
IntegralGain: 0.01,
AntiWindUpGain: 0.5,
IntegralDischargeTimeConstant: 10,
MinOutput: -10,
MaxOutput: 10,
},
}
c.State = AntiWindupControllerState{
Expand Down
9 changes: 5 additions & 4 deletions trackingcontroller.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,8 @@ type TrackingControllerConfig struct {
DerivativeGain float64
// AntiWindUpGain is the anti-windup tracking gain.
AntiWindUpGain float64
// Inverse of the time constant to discharge the integral part of the PID controller (1/s)
IntegralPartDischargeFactor float64
// IntegralDischargeTimeConstant is the time constant to discharge the integral state of the PID controller (s)
IntegralDischargeTimeConstant float64
// LowPassTimeConstant is the D part low-pass filter time constant => cut-off frequency 1/LowPassTimeConstant.
LowPassTimeConstant time.Duration
// MaxOutput is the max output from the PID.
Expand Down Expand Up @@ -93,11 +93,12 @@ func (c *TrackingController) Update(input TrackingControllerInput) {
c.State.ControlError = e
}

// TODO: Document me.
// DischargeIntegral provides the ability to discharge the controller integral state
// over a configurable period of time.
func (c *TrackingController) DischargeIntegral(dt time.Duration) {
c.State.ControlErrorIntegrand = 0.0
c.State.ControlErrorIntegral = math.Max(
0,
math.Min(1-dt.Seconds()*c.Config.IntegralPartDischargeFactor, 1.0),
math.Min(1-dt.Seconds()/c.Config.IntegralDischargeTimeConstant, 1.0),
) * c.State.ControlErrorIntegral
}
28 changes: 14 additions & 14 deletions trackingcontroller_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,12 @@ func TestTrackingController_PControllerUpdate(t *testing.T) {
// Given a tracking P controller
c := &TrackingController{
Config: TrackingControllerConfig{
LowPassTimeConstant: 1 * time.Second,
ProportionalGain: 1,
AntiWindUpGain: 0,
IntegralPartDischargeFactor: 0.1,
MinOutput: -10,
MaxOutput: 10,
LowPassTimeConstant: 1 * time.Second,
ProportionalGain: 1,
AntiWindUpGain: 0,
IntegralDischargeTimeConstant: 10,
MinOutput: -10,
MaxOutput: 10,
},
}
for _, tt := range []struct {
Expand Down Expand Up @@ -98,14 +98,14 @@ func TestTrackingController_OffloadIntegralTerm(t *testing.T) {
// Given a tracking PID controller
c := &TrackingController{
Config: TrackingControllerConfig{
LowPassTimeConstant: 1 * time.Second,
ProportionalGain: 1,
DerivativeGain: 10,
IntegralGain: 0.01,
AntiWindUpGain: 0.5,
IntegralPartDischargeFactor: 0.1,
MinOutput: -10,
MaxOutput: 10,
LowPassTimeConstant: 1 * time.Second,
ProportionalGain: 1,
DerivativeGain: 10,
IntegralGain: 0.01,
AntiWindUpGain: 0.5,
IntegralDischargeTimeConstant: 10,
MinOutput: -10,
MaxOutput: 10,
},
}
c.State = TrackingControllerState{
Expand Down

0 comments on commit c2ec3fe

Please sign in to comment.