Discrete Step Response Works With 'Bilinear' But Not With 'ZOH' #1238
|
Hello community, I am performing a step response for a unity feedback plant - compensator process combination. It works fine when testing in the continuous time domain. However, when transitioning to the discrete time domain, it fails if I select the 'zoh' method but works fine if using the 'bilinear' method. Is this to be expected or is it a 'zoh' issue? Here is the Python test script: Step response observed results recap:
Can someone please advise if this is to be expected or if this is a bug. Thank you. |
Replies: 6 comments
|
I do not think this points to a For the numbers in the example, that produces a discrete closed-loop pole well outside the unit circle with So the failed process_fdbk = ct.feedback(ct.c2d(Ls, Ts=T, method="zoh"), 1)
print(ct.poles(process_fdbk))Conceptually, process_fdbk = ct.c2d(fdbk_Ls, Ts=T, method="zoh")Those are different systems, which is why the |
|
thank you for your time for looking into this. Point 1. Point 2. Tbh, for me this is a little odd since it is ok to perform the open-loop (L(s)) continuous to discrete time conversion in the case when you want to perform the root locus test. Again, appreciate your feedback and your time. Thank you. |
|
Thanks, those are good questions. I would separate three different uses that are easy to mix together here. 1. Why an exception instead of just plotting the unstable response? In principle, yes, an unstable discrete system can be plotted. In this specific case the unstable pole is very large in magnitude, about So I would treat the exception as possibly a usability/error-message issue, but the underlying control result is still: the discrete closed loop created by 2. Should you always discretize only after closing the loop? No, not always. It depends what system you are trying to model. If you want the sampled response of the already-designed continuous closed loop, then this is appropriate: process_fdbk = ct.c2d(Ls_fdbk, T, method="zoh")But that is not the same as modeling an implemented digital controller. For a digital controller, the usual block diagram is closer to: In that case, the plant gets the ZOH discretization, while the controller is already discrete, or is discretized separately using whatever method you intend to implement. Schematically: Gz = ct.c2d(plant, T, method="zoh")
Dz = ct.c2d(Gc, T, method="bilinear") # if starting from an analog compensator
Lz = ct.series(Dz, Gz)
process_fdbk = ct.feedback(Lz, 1)If your compensator is already 3. Why is open-loop conversion OK for root locus? Root locus is indeed based on the open-loop transfer function. The issue is not "open loop vs closed loop" by itself. The issue is whether the open-loop transfer function you discretized represents the physical digital loop you intend. For digital root locus, the open-loop object should usually be something like: Lz = D(z) * G_zoh(z)where So yes: if you close the continuous loop first and then discretize, you bypass the detail that the ZOH belongs at the plant input. That can be useful for comparing sampled behavior of a continuous design, but it is not the model I would use to validate an actual digital compensator implementation. |
|
thank you very much for your detailed response. This really cleared things up for me. Especially point 2. This now makes total sense for me. I liked that you explicitly created the Dz compensator using the 'bilinear' method. I was under the impression (incorrectly of course), that I could implement the compensator using the same 'zoh' method as the plant (for 'consistency'). This perked my curiousity and so I googled if they required having the same method. This is the response that was provided: No, they do not need to use the same discretization method. In fact, standard digital control theory generally dictates using different methods because the plant and the compensator serve entirely different roles in a sampled-data system. The Plant: Should be discretized using a Zero-Order Hold (ZOH) equivalent. This is because real-world physical actuators (like DACs or motor drives) hold signals constant between sampling intervals, making ZOH the theoretically perfect representation of the system. The Compensator: Is a mathematical algorithm running on a digital processor (e.g., FPGA, PLC, or microcontroller). Discretizing it with ZOH would mathematically double-count the hold effect, resulting in incorrect phase characteristics. Instead, approximations that don't add hold logic—like the Bilinear (Tustin) transformation or Pole-Zero matching - are preferred. You have definitely helped me more than you can imagine. Wow! As always, I am very grateful for your kindness with your time. Thank you very much sir. May you be repayed ten fold. 👌💯🙂 |
|
Following up with the discretization discussed in your last response. The explanation makes total sense and I believe as per theory, that this should work. However, I am a little baffled as to why, when passing in the closed loop discretized transfer function, it does not plot as expected but if I perform the discretization to the continuous time domain closed loop, it does. Here is the test script in its totality where both continuous and discretized are provided (thought the discretized is not plotted as expected when following the steps as highlighted in the last post - you will have to comment/uncomment one version to test the other): Update: Well, I am glad resolved this. Hope it helps anyone else that is perhaps having a similar issue. 🙂 |

Thanks, those are good questions. I would separate three different uses that are easy to mix together here.
1. Why an exception instead of just plotting the unstable response?
In principle, yes, an unstable discrete system can be plotted. In this specific case the unstable pole is very large in magnitude, about
-30.5. That means the response grows roughly like(-30.5)**k, so it becomes enormous after only a few samples. Ifstep_responseis choosing the time base automatically, it can run into numerical or time-vector issues rather than producing a useful plot. If you pass a short explicit discrete-time vector, you may be able to inspect the first few samples, but the response will blow up…