Skip to content

Commit 1b20bd4

Browse files
committed
add sgrid to rlocus plot, to the last version of unsupervised gains.
1 parent 6d55d57 commit 1b20bd4

File tree

1 file changed

+72
-5
lines changed

1 file changed

+72
-5
lines changed

control/rlocus.py

Lines changed: 72 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@
5959

6060
# Main function: compute a root locus diagram
6161
def root_locus(sys, kvect=None, xlim=None, ylim=None, plotstr='-', Plot=True,
62-
PrintGain=True):
62+
PrintGain=True, grid = False):
6363
"""Root locus plot
6464
6565
Calculate the root locus by finding the roots of 1+k*TF(s)
@@ -99,9 +99,17 @@ def root_locus(sys, kvect=None, xlim=None, ylim=None, plotstr='-', Plot=True,
9999
mymat = _RLFindRoots(nump, denp, kvect)
100100
mymat = _RLSortRoots(mymat)
101101

102-
# Create the plot
103-
if (Plot):
104-
f = pylab.figure()
102+
# Create the Plot
103+
if Plot:
104+
figure_number = pylab.get_fignums()
105+
figure_title = [pylab.figure(numb).canvas.get_window_title() for numb in figure_number]
106+
new_figure_name = "Root Locus"
107+
rloc_num = 1
108+
while new_figure_name in figure_title:
109+
new_figure_name = "Root Locus " + str(rloc_num)
110+
rloc_num += 1
111+
f = pylab.figure(new_figure_name)
112+
105113
if PrintGain:
106114
f.canvas.mpl_connect(
107115
'button_release_event', partial(_RLFeedbackClicks, sys=sys))
@@ -127,6 +135,8 @@ def root_locus(sys, kvect=None, xlim=None, ylim=None, plotstr='-', Plot=True,
127135
ax.set_ylim(ylim)
128136
ax.set_xlabel('Real')
129137
ax.set_ylabel('Imaginary')
138+
if grid:
139+
sgrid_func(f)
130140

131141
return mymat, kvect
132142

@@ -305,6 +315,63 @@ def _RLFeedbackClicks(event, sys):
305315
K = -1./sys.horner(s)
306316
if abs(K.real) > 1e-8 and abs(K.imag/K.real) < 0.04:
307317
print("Clicked at %10.4g%+10.4gj gain %10.4g damp %10.4g" %
308-
(s.real, s.imag, K.real, -1*s.real/abs(s)))
318+
(s.real, s.imag, K.real, -1 * s.real / abs(s)))
319+
320+
321+
def sgrid_func(fig):
322+
ax = fig.gca()
323+
ylocator = ax.get_yaxis().get_major_locator()
324+
xlocator = ax.get_yaxis().get_major_locator()
325+
326+
long_xaxis = xlocator()[-1] - xlocator()[0]
327+
long_yaxis = ylocator()[-1] - ylocator()[0]
328+
329+
angules = np.arange(-90, 80, 15)*np.pi/180
330+
331+
# radial lines
332+
y_over_x = np.tan(angules[1::])*ylocator()[-1]/xlocator()[-1]
333+
334+
ylim = ax.get_ylim()
335+
ytext_pos_lim = ylim[1]-(ylim[1]-ylim[0])*0.03
336+
337+
xlim = ax.get_xlim()
338+
xtext_pos_lim = xlim[0]+(xlim[1]-xlim[0])*0.0
339+
340+
index = 0
341+
zeta = np.sin(np.pi/2-angules[1::])
342+
343+
for yp in y_over_x:
344+
ax.plot([0, xlocator()[0]], [0, yp*xlocator()[0]], color='gray',
345+
linestyle='dashed', linewidth=0.5)
346+
an = "%.2f" % zeta[index]
347+
if yp > 0:
348+
xtext_pos = -1/yp * ylim[1]
349+
ytext_pos = -yp * xtext_pos_lim
350+
if np.abs(xtext_pos) > np.abs(xtext_pos_lim):
351+
xtext_pos = xtext_pos_lim
352+
else:
353+
ytext_pos = ytext_pos_lim
354+
ax.annotate(an, textcoords='data', xy=[xtext_pos, ytext_pos], fontsize=8)
355+
elif yp < 0:
356+
xtext_pos = -1/yp * ylim[1]
357+
ytext_pos = yp * xtext_pos_lim
358+
if np.abs(xtext_pos) > np.abs(xtext_pos_lim):
359+
xtext_pos = xtext_pos_lim
360+
ytext_pos = - ytext_pos
361+
else:
362+
ytext_pos = ylim[0]
363+
xtext_pos = -xtext_pos
364+
ax.annotate(an, textcoords='data', xy=[xtext_pos, ytext_pos], fontsize=8)
365+
index += 1
366+
367+
angules = np.linspace(-90, 90, 20)*np.pi/180
368+
for xt in xlocator():
369+
if xt < 0:
370+
yp = np.sin(angules)*np.abs(xt)
371+
xp = -np.cos(angules)*np.abs(xt)
372+
ax.plot(xp, yp, color='gray',
373+
linestyle='dashed', linewidth=0.5)
374+
an = "%.2f" % -xt
375+
ax.annotate(an, textcoords='data', xy=[xt, 0], fontsize=8)
309376

310377
rlocus = root_locus

0 commit comments

Comments
 (0)