Skip to content
Merged
Changes from 4 commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
ffc3041
add unsupervised calculation on gains for root locus plot.
gonmolina Mar 21, 2017
2aada8b
fix bug concatenating zero dimensional array
gonmolina Mar 21, 2017
7130434
fix bug concatenating zero dimensional when test in matlab_test.py
gonmolina Mar 21, 2017
8b829cc
fix bug with array==0! problem test in matlab_test.py
gonmolina Mar 21, 2017
d4cbc95
fix bug with axis limits with no asymptotes
gonmolina Mar 23, 2017
6d55d57
fix bug calculating kmax
gonmolina Mar 23, 2017
01e33ea
add unsupervised calculation on gains for root locus plot.
gonmolina Mar 21, 2017
95d6908
fix bug with axis limits with no asymptotes
gonmolina Mar 23, 2017
1b20bd4
add sgrid to rlocus plot, to the last version of unsupervised gains.
gonmolina Mar 31, 2017
5e47d1f
add origin to rlocus plot and x=0 line (zeta =0 grid line).
gonmolina Mar 31, 2017
ebd3904
add grid arguments in docstring.
gonmolina Mar 31, 2017
3fb2c86
Merge remote-tracking branch 'origin/unsup_rlocus_gain_selection' int…
gonmolina Mar 31, 2017
de87bb0
reorder code that calculate defaults damp coefficents constant lines …
gonmolina Apr 2, 2017
5438746
formatting code to make easier sgrid() function in future.
gonmolina Apr 2, 2017
1e356b8
trying that algorithm work with 0 degrees root locus with equal numbe…
gonmolina Jun 8, 2017
6c813ce
adding some support for 0 degrees root locus.
gonmolina Jun 13, 2017
6e4d14f
add book reference of root locus calculation.
gonmolina Jun 13, 2017
a680c6a
fix minor bug when fartest point is zero.
gonmolina Jun 14, 2017
81b73a6
fix minor bugs when that solves problems in paricular cases
gonmolina Jun 17, 2017
62ed2aa
Fixed requested issues.
gonmolina Jun 30, 2017
4eedde4
fix build problem (numerical problem)
gonmolina Jul 1, 2017
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
77 changes: 71 additions & 6 deletions control/rlocus.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@

# Main function: compute a root locus diagram
def root_locus(sys, kvect=None, xlim=None, ylim=None, plotstr='-', Plot=True,
PrintGain=True):
PrintGain=True, grid=False):
"""Root locus plot

Calculate the root locus by finding the roots of 1+k*TF(s)
Expand All @@ -77,10 +77,12 @@ def root_locus(sys, kvect=None, xlim=None, ylim=None, plotstr='-', Plot=True,
ylim : tuple or list, optional
control of y-axis range
Plot : boolean, optional (default = True)
If True, plot magnitude and phase
If True, plot root locus diagram.
PrintGain: boolean (default = True)
If True, report mouse clicks when close to the root-locus branches,
calculate gain, damping and print
grid: boolean (default = False)
If True plot s-plane grid.

Returns
-------
Expand All @@ -99,9 +101,17 @@ def root_locus(sys, kvect=None, xlim=None, ylim=None, plotstr='-', Plot=True,
mymat = _RLFindRoots(nump, denp, kvect)
mymat = _RLSortRoots(mymat)

# Create the plot
if (Plot):
f = pylab.figure()
# Create the Plot
if Plot:
figure_number = pylab.get_fignums()
figure_title = [pylab.figure(numb).canvas.get_window_title() for numb in figure_number]
new_figure_name = "Root Locus"
rloc_num = 1
while new_figure_name in figure_title:
new_figure_name = "Root Locus " + str(rloc_num)
rloc_num += 1
f = pylab.figure(new_figure_name)

if PrintGain:
f.canvas.mpl_connect(
'button_release_event', partial(_RLFeedbackClicks, sys=sys))
Expand All @@ -127,6 +137,8 @@ def root_locus(sys, kvect=None, xlim=None, ylim=None, plotstr='-', Plot=True,
ax.set_ylim(ylim)
ax.set_xlabel('Real')
ax.set_ylabel('Imaginary')
if grid:
sgrid_func(f)

return mymat, kvect

Expand All @@ -150,6 +162,7 @@ def _default_gains(num, den, xlim, ylim):
mymat_xl = mymat
singular_points = np.concatenate((num.roots, den.roots), axis=0)
important_points = np.concatenate((singular_points, real_break), axis=0)
important_points = np.concatenate((singular_points, np.zeros(2)), axis=0)
mymat_xl = np.append(mymat_xl, important_points)

if xlim is None:
Expand Down Expand Up @@ -305,6 +318,58 @@ def _RLFeedbackClicks(event, sys):
K = -1./sys.horner(s)
if abs(K.real) > 1e-8 and abs(K.imag/K.real) < 0.04:
print("Clicked at %10.4g%+10.4gj gain %10.4g damp %10.4g" %
(s.real, s.imag, K.real, -1*s.real/abs(s)))
(s.real, s.imag, K.real, -1 * s.real / abs(s)))


def sgrid_func(fig):
ax = fig.gca()
ylocator = ax.get_yaxis().get_major_locator()
xlocator = ax.get_yaxis().get_major_locator()

angules = np.arange(-90, 80, 15)*np.pi/180

# zeta-constant lines
y_over_x = np.tan(angules[1::])*ylocator()[-1]/xlocator()[-1]
ylim = ax.get_ylim()
ytext_pos_lim = ylim[1]-(ylim[1]-ylim[0])*0.03
xlim = ax.get_xlim()
xtext_pos_lim = xlim[0]+(xlim[1]-xlim[0])*0.0
index = 0
zeta = np.sin(np.pi/2-angules[1::])

for yp in y_over_x:
ax.plot([0, xlocator()[0]], [0, yp*xlocator()[0]], color='gray',
linestyle='dashed', linewidth=0.5)
an = "%.2f" % zeta[index]
if yp > 0:
xtext_pos = -1/yp * ylim[1]
ytext_pos = -yp * xtext_pos_lim
if np.abs(xtext_pos) > np.abs(xtext_pos_lim):
xtext_pos = xtext_pos_lim
else:
ytext_pos = ytext_pos_lim
ax.annotate(an, textcoords='data', xy=[xtext_pos, ytext_pos], fontsize=8)
elif yp < 0:
xtext_pos = -1/yp * ylim[1]
ytext_pos = yp * xtext_pos_lim
if np.abs(xtext_pos) > np.abs(xtext_pos_lim):
xtext_pos = xtext_pos_lim
ytext_pos = - ytext_pos
else:
ytext_pos = ylim[0]
xtext_pos = -xtext_pos
ax.annotate(an, textcoords='data', xy=[xtext_pos, ytext_pos], fontsize=8)
index += 1
ax.plot([0, 0], [ylim[0], ylim[1]], color='gray', linestyle='dashed', linewidth=0.5)

angules = np.linspace(-90, 90, 20)*np.pi/180
for xt in xlocator():
if xt < 0:
yp = np.sin(angules)*np.abs(xt)
xp = -np.cos(angules)*np.abs(xt)
ax.plot(xp, yp, color='gray',
linestyle='dashed', linewidth=0.5)
an = "%.2f" % -xt
ax.annotate(an, textcoords='data', xy=[xt, 0], fontsize=8)

rlocus = root_locus