Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
19 changes: 17 additions & 2 deletions control/freqplot.py
Original file line number Diff line number Diff line change
Expand Up @@ -1312,6 +1312,8 @@ def nyquist_response(
# Use existing dictionary, to keep track of processed keywords
_kwargs |= kwargs

indent_direction_arg = 'indent_direction' in _kwargs

# Get values for params
omega_num_given = omega_num is not None
omega_num = config._get_param('freqplot', 'number_of_samples', omega_num)
Expand Down Expand Up @@ -1469,8 +1471,21 @@ def nyquist_response(
- (s - p).real

# Figure out which way to offset the contour point
if p.real < 0 or (p.real == 0 and
indent_direction == 'right'):
if indent_direction_arg:
if indent_direction == 'right':
# Indent to the right
splane_contour[i] += offset

elif indent_direction == 'left':
# Indent to the left
splane_contour[i] -= offset

else:
raise ValueError(
"unknown value for indent_direction")

elif p.real < 0 or (p.real == 0 and
indent_direction == 'right'):
# Indent to the right
splane_contour[i] += offset

Expand Down
23 changes: 23 additions & 0 deletions control/tests/nyquist_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -372,6 +372,29 @@ def test_nyquist_indent_im():
assert _Z(sys) == response.count + _P(sys)


def test_nyquist_indent_near_imaginary_axis():
"""Test indent direction for poles near the imaginary axis."""
sys = ct.tf([1, 11, 10], [0.01, 1, 0.01, 1])
omega = np.linspace(0, 2, 21)

_, contour_default = ct.nyquist_response(
sys, omega, indent_radius=0.1, return_contour=True,
warn_encirclements=False)
_, contour_right = ct.nyquist_response(
sys, omega, indent_radius=0.1, indent_direction='right',
return_contour=True, warn_encirclements=False)
_, contour_left = ct.nyquist_response(
sys, omega, indent_radius=0.1, indent_direction='left',
return_contour=True, warn_encirclements=False)

# The pole near +1j has a small positive real part, so the default
# behavior indents to the left. Explicit directions override this.
pole_index = np.argmin(np.abs(contour_default.imag - 1))
assert contour_default[pole_index].real < 0
assert contour_right[pole_index].real > 0
assert contour_left[pole_index].real < 0


def test_nyquist_exceptions():
# MIMO not implemented
sys = ct.rss(2, 2, 2)
Expand Down
Loading