2222from . import config
2323
2424__all__ = ['describing_function' , 'describing_function_plot' ,
25- 'describing_function_response' , 'DescribingFunctionNonlinearity ' ,
26- 'friction_backlash_nonlinearity ' , 'relay_hysteresis_nonlinearity ' ,
27- 'saturation_nonlinearity' ]
25+ 'describing_function_response' , 'DescribingFunctionResponse ' ,
26+ 'DescribingFunctionNonlinearity ' , 'friction_backlash_nonlinearity ' ,
27+ 'relay_hysteresis_nonlinearity' , ' saturation_nonlinearity' ]
2828
2929# Class for nonlinearities with a built-in describing function
3030class DescribingFunctionNonlinearity ():
@@ -213,13 +213,46 @@ def describing_function(
213213
214214# Simple class to store the describing function response
215215class DescribingFunctionResponse :
216+ """Results of describing function analysis.
217+
218+ Describing functions allow analysis of a linear I/O systems with a
219+ static nonlinear feedback function. The DescribingFunctionResponse
220+ class is used by the :func:`~control.describing_function_response`
221+ function to return the results of a describing function analysis. The
222+ response object can be used to obtain information about the describing
223+ function analysis or generate a Nyquist plot showing the frequency
224+ response of the linear systems and the describing function for the
225+ nonlinear element.
226+
227+ Attributes
228+ ----------
229+ response : :class:`~control.FrequencyResponseData`
230+ Frequency response of the linear system component of the system.
231+ intersections : 1D array of 2-tuples or None
232+ A list of all amplitudes and frequencies in which
233+ :math:`H(j\\ omega) N(a) = -1`, where :math:`N(a)` is the describing
234+ function associated with `F`, or `None` if there are no such
235+ points. Each pair represents a potential limit cycle for the
236+ closed loop system with amplitude given by the first value of the
237+ tuple and frequency given by the second value.
238+ N_vals : complex array
239+ Complex value of the describing function.
240+ positions : list of complex
241+ Location of the intersections in the complex plane.
242+
243+ """
216244 def __init__ (self , response , N_vals , positions , intersections ):
245+ """Create a describing function response data object."""
217246 self .response = response
218247 self .N_vals = N_vals
219248 self .positions = positions
220249 self .intersections = intersections
221250
222251 def plot (self , ** kwargs ):
252+ """Plot the results of a describing function analysis.
253+
254+ See :func:`~control.describing_function_plot` for details.
255+ """
223256 return describing_function_plot (self , ** kwargs )
224257
225258 # Implement iter, getitem, len to allow recovering the intersections
@@ -262,21 +295,27 @@ def describing_function_response(
262295
263296 Returns
264297 -------
265- intersections : 1D array of 2-tuples or None
266- A list of all amplitudes and frequencies in which :math:`H(j\\ omega)
267- N(a) = -1`, where :math:`N(a)` is the describing function associated
268- with `F`, or `None` if there are no such points. Each pair represents
269- a potential limit cycle for the closed loop system with amplitude
270- given by the first value of the tuple and frequency given by the
271- second value.
298+ response : :class:`~control.DescribingFunctionResponse` object
299+ Response object that contains the result of the describing function
300+ analysis. The following information can be retrieved from this
301+ object:
302+ response.intersections : 1D array of 2-tuples or None
303+ A list of all amplitudes and frequencies in which
304+ :math:`H(j\\ omega) N(a) = -1`, where :math:`N(a)` is the describing
305+ function associated with `F`, or `None` if there are no such
306+ points. Each pair represents a potential limit cycle for the
307+ closed loop system with amplitude given by the first value of the
308+ tuple and frequency given by the second value.
272309
273310 Examples
274311 --------
275312 >>> H_simple = ct.tf([8], [1, 2, 2, 1])
276313 >>> F_saturation = ct.saturation_nonlinearity(1)
277314 >>> amp = np.linspace(1, 4, 10)
278- >>> ct.describing_function_response(H_simple, F_saturation, amp) # doctest: +SKIP
315+ >>> response = ct.describing_function_response(H_simple, F_saturation, amp)
316+ >>> response.intersections # doctest: +SKIP
279317 [(3.343844998258643, 1.4142293090899216)]
318+ >>> lines = response.plot()
280319
281320 """
282321 # Decide whether to turn on warnings or not
@@ -340,14 +379,29 @@ def _cost(x):
340379
341380def describing_function_plot (
342381 * sysdata , label = "%5.2g @ %-5.2g" , ** kwargs ):
343- """Plot a Nyquist plot with a describing function for a nonlinear system.
382+ """describing_function_plot(data, *args, **kwargs)
383+
384+ Plot a Nyquist plot with a describing function for a nonlinear system.
344385
345386 This function generates a Nyquist plot for a closed loop system
346387 consisting of a linear system with a static nonlinear function in the
347388 feedback path.
348389
390+ The function may be called in one of two forms:
391+
392+ describing_function_plot(response[, options])
393+
394+ describing_function_plot(H, F, A[, omega[, options]])
395+
396+ In the first form, the response should be generated using the
397+ :func:`~control.describing_function_response` function. In the second
398+ form, that function is called internally, with the listed arguments.
399+
349400 Parameters
350401 ----------
402+ data : :class:`~control.DescribingFunctionData`
403+ A describing function response data object created by
404+ :func:`~control.describing_function_response`.
351405 H : LTI system
352406 Linear time-invariant (LTI) system (state space, transfer function, or
353407 FRD)
@@ -357,7 +411,9 @@ def describing_function_plot(
357411 A : list
358412 List of amplitudes to be used for the describing function plot.
359413 omega : list, optional
360- List of frequencies to be used for the linear system Nyquist curve.
414+ List of frequencies to be used for the linear system Nyquist
415+ curve. If not specified (or None), frequencies are computed
416+ automatically based on the properties of the linear system.
361417 refine : bool, optional
362418 If True (default), refine the location of the intersection of the
363419 Nyquist curve for the linear system and the describing function to
@@ -368,21 +424,19 @@ def describing_function_plot(
368424
369425 Returns
370426 -------
371- intersections : 1D array of 2-tuples or None
372- A list of all amplitudes and frequencies in which :math:`H(j\\ omega)
373- N(a) = -1`, where :math:`N(a)` is the describing function associated
374- with `F`, or `None` if there are no such points. Each pair represents
375- a potential limit cycle for the closed loop system with amplitude
376- given by the first value of the tuple and frequency given by the
377- second value.
427+ lines : 1D array of Line2D
428+ Arrray of Line2D objects for each line in the plot. The first
429+ element of the array is a list of lines (typically only one) for
430+ the Nyquist plot of the linear I/O styem. The second element of
431+ the array is a list of lines (typically only one) for the
432+ describing function curve.
378433
379434 Examples
380435 --------
381436 >>> H_simple = ct.tf([8], [1, 2, 2, 1])
382437 >>> F_saturation = ct.saturation_nonlinearity(1)
383438 >>> amp = np.linspace(1, 4, 10)
384- >>> ct.describing_function_plot(H_simple, F_saturation, amp) # doctest: +SKIP
385- [(3.343844998258643, 1.4142293090899216)]
439+ >>> lines = ct.describing_function_plot(H_simple, F_saturation, amp)
386440
387441 """
388442 # Process keywords
0 commit comments