Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commitbe59f62

Browse files
authored
Merge pull request#264 from don4get/refactor/cleaning-nichols
Clean up nichols.py
2 parents5ff1184 +9179e89 commitbe59f62

File tree

1 file changed

+34
-22
lines changed

1 file changed

+34
-22
lines changed

‎control/nichols.py

Lines changed: 34 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,13 @@
1+
"""nichols.py
2+
3+
Functions for plotting Black-Nichols charts.
4+
5+
Routines in this module:
6+
7+
nichols.nichols_plot aliased as nichols.nichols
8+
nichols.nichols_grid
9+
"""
10+
111
# nichols.py - Nichols plot
212
#
313
# Contributed by Allan McInnes <Allan.McInnes@canterbury.ac.nz>
@@ -45,17 +55,17 @@
4555
from .ctrlutilimportunwrap
4656
from .freqplotimportdefault_frequency_range
4757

48-
__all__= ['nichols_plot','nichols']
58+
__all__= ['nichols_plot','nichols','nichols_grid']
59+
4960

50-
# Nichols plot
51-
defnichols_plot(syslist,omega=None,grid=True):
61+
defnichols_plot(sys_list,omega=None,grid=True):
5262
"""Nichols plot for a system
5363
5464
Plots a Nichols plot for the system over a (optional) frequency range.
5565
5666
Parameters
5767
----------
58-
syslist : list of LTI, or LTI
68+
sys_list : list of LTI, or LTI
5969
List of linear input/output systems (single system is OK)
6070
omega : array_like
6171
Range of frequencies (list or bounds) in rad/sec
@@ -68,14 +78,14 @@ def nichols_plot(syslist, omega=None, grid=True):
6878
"""
6979

7080
# If argument was a singleton, turn it into a list
71-
if(notgetattr(syslist,'__iter__',False)):
72-
syslist= (syslist,)
81+
ifnotgetattr(sys_list,'__iter__',False):
82+
sys_list= (sys_list,)
7383

7484
# Select a default range if none is provided
7585
ifomegaisNone:
76-
omega=default_frequency_range(syslist)
86+
omega=default_frequency_range(sys_list)
7787

78-
forsysinsyslist:
88+
forsysinsys_list:
7989
# Get the magnitude and phase of the system
8090
mag_tmp,phase_tmp,omega=sys.freqresp(omega)
8191
mag=np.squeeze(mag_tmp)
@@ -100,9 +110,8 @@ def nichols_plot(syslist, omega=None, grid=True):
100110
ifgrid:
101111
nichols_grid()
102112

103-
# Nichols grid
104-
#! TODO: Consider making linestyle configurable
105-
defnichols_grid(cl_mags=None,cl_phases=None):
113+
114+
defnichols_grid(cl_mags=None,cl_phases=None,line_style='dotted'):
106115
"""Nichols chart grid
107116
108117
Plots a Nichols chart grid on the current axis, or creates a new chart
@@ -116,6 +125,8 @@ def nichols_grid(cl_mags=None, cl_phases=None):
116125
cl_phases : array-like (degrees), optional
117126
Array of closed-loop phases defining the iso-phase lines on a custom
118127
Nichols chart. Must be in the range -360 < cl_phases < 0
128+
line_style : string, optional
129+
.. seealso:: https://matplotlib.org/gallery/lines_bars_and_markers/linestyles.html
119130
120131
Returns
121132
-------
@@ -137,12 +148,12 @@ def nichols_grid(cl_mags=None, cl_phases=None):
137148
# The key set of magnitudes are always generated, since this
138149
# guarantees a recognizable Nichols chart grid.
139150
key_cl_mags=np.array([-40.0,-20.0,-12.0,-6.0,-3.0,-1.0,-0.5,0.0,
140-
0.25,0.5,1.0,3.0,6.0,12.0])
151+
0.25,0.5,1.0,3.0,6.0,12.0])
141152
# Extend the range of magnitudes if necessary. The extended arange
142153
# will end up empty if no extension is required. Assumes that closed-loop
143154
# magnitudes are approximately aligned with open-loop magnitudes beyond
144155
# the value of np.min(key_cl_mags)
145-
cl_mag_step=-20.0# dB
156+
cl_mag_step=-20.0# dB
146157
extended_cl_mags=np.arange(np.min(key_cl_mags),
147158
ol_mag_min+cl_mag_step,cl_mag_step)
148159
cl_mags=np.concatenate((extended_cl_mags,key_cl_mags))
@@ -163,12 +174,12 @@ def nichols_grid(cl_mags=None, cl_phases=None):
163174
# Find the M-contours
164175
m=m_circles(cl_mags,phase_min=np.min(cl_phases),phase_max=np.max(cl_phases))
165176
m_mag=20*sp.log10(np.abs(m))
166-
m_phase=sp.mod(sp.degrees(sp.angle(m)),-360.0)# Unwrap
177+
m_phase=sp.mod(sp.degrees(sp.angle(m)),-360.0)# Unwrap
167178

168179
# Find the N-contours
169180
n=n_circles(cl_phases,mag_min=np.min(cl_mags),mag_max=np.max(cl_mags))
170181
n_mag=20*sp.log10(np.abs(n))
171-
n_phase=sp.mod(sp.degrees(sp.angle(n)),-360.0)# Unwrap
182+
n_phase=sp.mod(sp.degrees(sp.angle(n)),-360.0)# Unwrap
172183

173184
# Plot the contours behind other plot elements.
174185
# The "phase offset" is used to produce copies of the chart that cover
@@ -182,10 +193,10 @@ def nichols_grid(cl_mags=None, cl_phases=None):
182193

183194
forphase_offsetinphase_offsets:
184195
# Draw M and N contours
185-
plt.plot(m_phase+phase_offset,m_mag,color='gray',
186-
linestyle='dotted',zorder=0)
187-
plt.plot(n_phase+phase_offset,n_mag,color='gray',
188-
linestyle='dotted',zorder=0)
196+
plt.plot(m_phase+phase_offset,m_mag,color='lightgray',
197+
linestyle=line_style,zorder=0)
198+
plt.plot(n_phase+phase_offset,n_mag,color='lightgray',
199+
linestyle=line_style,zorder=0)
189200

190201
# Add magnitude labels
191202
forx,y,minzip(m_phase[:][-1]+phase_offset,m_mag[:][-1],cl_mags):
@@ -203,7 +214,7 @@ def nichols_grid(cl_mags=None, cl_phases=None):
203214
# generating Nichols plots
204215
#
205216

206-
# Compute contours of a closed-loop transfer function
217+
207218
defclosed_loop_contours(Gcl_mags,Gcl_phases):
208219
"""Contours of the function Gcl = Gol/(1+Gol), where
209220
Gol is an open-loop transfer function, and Gcl is a corresponding
@@ -229,7 +240,7 @@ def closed_loop_contours(Gcl_mags, Gcl_phases):
229240
# Invert Gcl = Gol/(1+Gol) to map the contours into the open-loop space
230241
returnGcl/(1.0-Gcl)
231242

232-
# M-circle
243+
233244
defm_circles(mags,phase_min=-359.75,phase_max=-0.25):
234245
"""Constant-magnitude contours of the function Gcl = Gol/(1+Gol), where
235246
Gol is an open-loop transfer function, and Gcl is a corresponding
@@ -255,7 +266,7 @@ def m_circles(mags, phase_min=-359.75, phase_max=-0.25):
255266
Gcl_mags,Gcl_phases=sp.meshgrid(10.0**(mags/20.0),phases)
256267
returnclosed_loop_contours(Gcl_mags,Gcl_phases)
257268

258-
# N-circle
269+
259270
defn_circles(phases,mag_min=-40.0,mag_max=12.0):
260271
"""Constant-phase contours of the function Gcl = Gol/(1+Gol), where
261272
Gol is an open-loop transfer function, and Gcl is a corresponding
@@ -281,5 +292,6 @@ def n_circles(phases, mag_min=-40.0, mag_max=12.0):
281292
Gcl_phases,Gcl_mags=sp.meshgrid(sp.radians(phases),mags)
282293
returnclosed_loop_contours(Gcl_mags,Gcl_phases)
283294

295+
284296
# Function aliases
285297
nichols=nichols_plot

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp