Skip to content

Commit 83313d4

Browse files
committed
Further refine David's sisotool clicking and zooming
1 parent 86ba12c commit 83313d4

5 files changed

Lines changed: 40 additions & 22 deletions

File tree

.DS_Store

-8 KB
Binary file not shown.

control/matlab/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,7 @@
8181
from ..margins import margin
8282
from ..rlocus import rlocus
8383
from ..dtime import c2d
84+
from ..sisotool import sisotool
8485

8586
# Import functions specific to Matlab compatibility package
8687
from .timeresp import *
@@ -241,6 +242,7 @@
241242
242243
== ========================== ============================================
243244
\* :func:`rlocus` evans root locus
245+
\* :func:`sisotool` SISO controller design
244246
\* :func:`~control.place` pole placement
245247
\ estim form estimator given estimator gain
246248
\ reg form regulator given state-feedback and

control/rlocus.py

Lines changed: 36 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,13 @@ def root_locus(sys, kvect=None, xlim=None, ylim=None, plotstr='b' if int(matplot
138138
f.canvas.mpl_connect(
139139
'button_release_event',partial(_RLClickDispatcher,sys=sys, fig=f,ax_rlocus=f.axes[1],plotstr=plotstr, sisotool=sisotool, bode_plot_params=kwargs['bode_plot_params'],tvect=kwargs['tvect']))
140140

141+
# zoom update on xlim/ylim changed, only then data on new limits
142+
# is available, i.e., cannot combine with _RLClickDispatcher
143+
dpfun = partial(
144+
_RLZoomDispatcher, sys=sys, ax_rlocus=ax, plotstr=plotstr)
145+
ax.callbacks.connect('xlim_changed', dpfun)
146+
ax.callbacks.connect('ylim_changed', dpfun)
147+
141148
# plot open loop poles
142149
poles = array(denp.r)
143150
ax.plot(real(poles), imag(poles), 'x')
@@ -427,23 +434,30 @@ def _RLSortRoots(mymat):
427434
prevrow = sorted[n, :]
428435
return sorted
429436

430-
def _RLClickDispatcher(event,sys,fig,ax_rlocus,plotstr,sisotool=False,bode_plot_params=None,tvect=None):
431-
"""Rootlocus plot click dispatcher"""
437+
def _RLZoomDispatcher(event, sys, ax_rlocus, plotstr):
438+
"""Rootlocus plot zoom dispatcher"""
432439

433-
# If zoom is used on the rootlocus plot smooth and update it
434-
if plt.get_current_fig_manager().toolbar.mode in ['zoom rect','pan/zoom'] and event.inaxes == ax_rlocus.axes:
435-
(nump, denp) = _systopoly1d(sys)
436-
xlim,ylim = ax_rlocus.get_xlim(),ax_rlocus.get_ylim()
440+
nump, denp = _systopoly1d(sys)
441+
xlim, ylim = ax_rlocus.get_xlim(), ax_rlocus.get_ylim()
442+
443+
kvect, mymat, xlim, ylim = _default_gains(
444+
nump, denp, xlim=None, ylim=None, zoom_xlim=xlim, zoom_ylim=ylim)
445+
_removeLine('rootlocus', ax_rlocus)
446+
447+
for i, col in enumerate(mymat.T):
448+
ax_rlocus.plot(real(col), imag(col), plotstr, label='rootlocus',
449+
scalex=False, scaley=False)
437450

438-
kvect,mymat, xlim,ylim = _default_gains(nump, denp,xlim=None,ylim=None, zoom_xlim=xlim,zoom_ylim=ylim)
439-
_removeLine('rootlocus', ax_rlocus)
451+
def _RLClickDispatcher(event,sys,fig,ax_rlocus,plotstr,sisotool=False,bode_plot_params=None,tvect=None):
452+
"""Rootlocus plot click dispatcher"""
440453

441-
for i,col in enumerate(mymat.T):
442-
ax_rlocus.plot(real(col), imag(col), plotstr,label='rootlocus')
454+
# Zoom is handled by specialized callback above, only do gain plot
455+
if event.inaxes == ax_rlocus.axes and \
456+
plt.get_current_fig_manager().toolbar.mode not in \
457+
{'zoom rect','pan/zoom'}:
443458

444-
# if a point is clicked on the rootlocus plot visually emphasize it
445-
else:
446-
K = _RLFeedbackClicksPoint(event, sys, fig,ax_rlocus,sisotool)
459+
# if a point is clicked on the rootlocus plot visually emphasize it
460+
K = _RLFeedbackClicksPoint(event, sys, fig, ax_rlocus, sisotool)
447461
if sisotool and K is not None:
448462
_SisotoolUpdate(sys, fig, K, bode_plot_params, tvect)
449463

@@ -473,16 +487,16 @@ def _RLFeedbackClicksPoint(event,sys,fig,ax_rlocus,sisotool=False):
473487
K = float('inf')
474488
K_xlim = float('inf')
475489
K_ylim = float('inf')
476-
print('gain',K)
477-
print('x_tolerance:',x_tolerance)
478-
print('y_tolerance:',y_tolerance)
479-
print('gain_tolerance:',gain_tolerance)
480-
print('margin:',abs(K.imag / K.real))
481-
print('Argument clickpoint',abs(K.imag / K.real))
482-
print('Argument X_scale:',abs(K_xlim.imag/K_xlim.real))
483-
print('Argument Y_scale:',abs(K_ylim.imag/K_ylim.real))
490+
# print('gain',K)
491+
# print('x_tolerance:',x_tolerance)
492+
# print('y_tolerance:',y_tolerance)
493+
# print('gain_tolerance:',gain_tolerance)
494+
# print('margin:',abs(K.imag / K.real))
495+
# print('Argument clickpoint',abs(K.imag / K.real))
496+
# print('Argument X_scale:',abs(K_xlim.imag/K_xlim.real))
497+
# print('Argument Y_scale:',abs(K_ylim.imag/K_ylim.real))
484498
gain_tolerance += 0.1*max([abs(K_ylim.imag/K_ylim.real),abs(K_xlim.imag/K_xlim.real)])
485-
print('New gain tolerance:',gain_tolerance)
499+
# print('New gain tolerance:',gain_tolerance)
486500

487501
if abs(K.real) > 1e-8 and abs(K.imag / K.real) < gain_tolerance and event.inaxes == ax_rlocus.axes and K.real > 0.:
488502

doc/control.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,7 @@ Control system analysis
8989
zero
9090
pzmap
9191
root_locus
92+
sisotool
9293

9394
Matrix computations
9495
===================

doc/matlab.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,7 @@ Compensator design
8282
:toctree: generated/
8383

8484
rlocus
85+
sisotool
8586
place
8687
lqr
8788

0 commit comments

Comments
 (0)