From c23485cf8d3f67d370cf4567e81fc07f5fdfff35 Mon Sep 17 00:00:00 2001 From: Fredrik Bagge Carlson Date: Fri, 15 May 2026 19:35:25 +0200 Subject: [PATCH 1/2] Fix pid_tf coefficients for Ki=0 with first-order derivative filter MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit For Kp + Kd*s/(Tf*s+1) the numerator polynomial is ((Kp*Tf + Kd)*s + Kp), but the code was using [Kd*Tf + Kd, Kd] — Kp dropped entirely and replaced by Kd. The returned transfer function therefore did not contain the proportional term. The other branches in the same function (Ki!=0/filter_order=1 on the next line) use the correct form, which this brings into line. Co-Authored-By: Claude Opus 4.7 (1M context) --- lib/ControlSystemsBase/src/pid_design.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/ControlSystemsBase/src/pid_design.jl b/lib/ControlSystemsBase/src/pid_design.jl index 81c0bbd52..6e75ab45b 100644 --- a/lib/ControlSystemsBase/src/pid_design.jl +++ b/lib/ControlSystemsBase/src/pid_design.jl @@ -68,7 +68,7 @@ function pid_tf(param_p, param_i, param_d=zero(typeof(param_p)); form=:standard, else if Ki == 0 if filter_order == 1 - tf([Kd*Tf + Kd, Kd], [Tf, 1]) + return tf([Kd + Kp*Tf, Kp], [Tf, 1]) else return tf([Kd, Kp], [Tf^2/(4d^2), Tf, 1]) end From 850b8e7ffd7ee2b4c3f64db34d6d5df77f7c3d87 Mon Sep 17 00:00:00 2001 From: Fredrik Bagge Carlson Date: Sat, 16 May 2026 06:13:03 +0200 Subject: [PATCH 2/2] Add regression test for pid_tf Ki=0 filter_order=1 fix Cross-check the transfer-function PID controller against the state-space realization, and against the analytical numerator [Kp*Tf+Kd, Kp]. On master both checks failed because the implementation emitted [Kd*Tf+Kd, Kd] (Kp dropped and replaced with Kd). Co-Authored-By: Claude Opus 4.7 (1M context) --- lib/ControlSystemsBase/test/test_pid_design.jl | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/lib/ControlSystemsBase/test/test_pid_design.jl b/lib/ControlSystemsBase/test/test_pid_design.jl index 4bab4aeea..0e30c5438 100644 --- a/lib/ControlSystemsBase/test/test_pid_design.jl +++ b/lib/ControlSystemsBase/test/test_pid_design.jl @@ -77,6 +77,13 @@ Ctf = pid(1.1, 1.2, 0, Tf=0.1, filter_order=1) Css = pid(1.1, 1.2, 0, Tf=0.1, filter_order=1, state_space=true) @test freqresptest(Ctf, Css) < 1e-10 +# Regression for #1058: pid_tf for Ki=0 and filter_order=1 used to emit +# tf([Kd*Tf + Kd, Kd], [Tf, 1]) — Kp dropped and replaced with Kd. +Ctf = pid(1.1, 0, 1.5, Tf=0.1, filter_order=1, form=:parallel) +Css = pid(1.1, 0, 1.5, Tf=0.1, filter_order=1, form=:parallel, state_space=true) +@test freqresptest(Ctf, Css) < 1e-10 +@test Ctf ≈ tf([1.5 + 1.1*0.1, 1.1], [0.1, 1]) + # bodeplot([Ctf, Css])