Skip to content

Commit 8375127

Browse files
committed
add standard _process_indices function
1 parent bd7ba6d commit 8375127

2 files changed

Lines changed: 47 additions & 34 deletions

File tree

control/namedio.py

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -584,3 +584,23 @@ def _process_signal_list(signals, prefix='s'):
584584

585585
else:
586586
raise TypeError("Can't parse signal list %s" % str(signals))
587+
588+
589+
# Utility function to process signal indices
590+
def _process_indices(arg, name, labels, default=None):
591+
arg = default if arg is None else arg
592+
if arg is None:
593+
return None;
594+
595+
if isinstance(arg, int):
596+
return range(arg)
597+
elif isinstance(arg, slice):
598+
return arg
599+
elif isinstance(arg, list):
600+
arg=arg.copy()
601+
for i, idx in enumerate(arg):
602+
if isinstance(idx, str):
603+
arg[i] = labels.index(arg[i])
604+
return arg
605+
else:
606+
raise ValueError(f"invalid argument for {name}_indices")

control/statefbk.py

Lines changed: 27 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@
4848
from .mateqn import care, dare, _check_shape
4949
from .statesp import StateSpace, _ssmatrix, _convert_to_statespace
5050
from .lti import LTI
51-
from .namedio import isdtime, isctime
51+
from .namedio import isdtime, isctime, _process_indices
5252
from .iosys import InputOutputSystem, NonlinearIOSystem, LinearIOSystem, \
5353
interconnect, ss
5454
from .exception import ControlSlycot, ControlArgument, ControlDimension, \
@@ -668,14 +668,16 @@ def create_statefbk_iosystem(
668668
If an estimator is provided, use the states of the estimator as
669669
the system inputs for the controller.
670670
671-
gainsched_indices : list of int or str, optional
671+
gainsched_indices : int, slice, or list of int or str, optional
672672
If a gain scheduled controller is specified, specify the indices of
673673
the controller input to use for scheduling the gain. The input to
674674
the controller is the desired state xd, the desired input ud, and
675675
the system state x (or state estimate xhat, if an estimator is
676-
given). The indices can either be specified as integer offsets into
677-
the input vector or as strings matching the signal names of the
678-
input vector. The default is to use the desire state xd.
676+
given). If value is an integer `q`, the first `q` values of the
677+
[xd, ud, x] vector are used. Otherwise, the value should be a
678+
slice or a list of indices. The list of indices can be specified
679+
as either integer offsets or as signal names. The default is to
680+
use the desire state xd.
679681
680682
gainsched_method : str, optional
681683
The method to use for gain scheduling. Possible values are 'linear'
@@ -714,19 +716,21 @@ def create_statefbk_iosystem(
714716
715717
Other Parameters
716718
----------------
717-
control_indices : list of int or str, optional
719+
control_indices : int, slice, or list of int or str, optional
718720
Specify the indices of the system inputs that should be determined
719-
by the state feedback controller. If not specified, defaults to
720-
the first `m` system inputs, where `m` is determined by the shape
721-
of the gain matrix, with the remaining inputs remaining as inputs
722-
to the overall closed loop system.
723-
724-
state_indices : list of int or str, optional
725-
Specify the indices of the system (or estimator) outputs that
726-
should be used by the state feedback controller. If not specified,
727-
defaults to the first `n` system/estimator outputs, where `n` is
728-
determined by the shape of the gain matrix, with the remaining
729-
outputs remaining as outputs to the overall closed loop system.
721+
by the state feedback controller. If value is an integer `m`, the
722+
first `m` system inputs are used. Otherwise, the value should be a
723+
slice or a list of indices. The list of indices can be specified
724+
as either integer offsets or as system input signal names. If not
725+
specified, defaults to the system inputs.
726+
727+
state_indices : int, slice, or list of int or str, optional
728+
Specify the indices of the system (or estimator) outputs that should
729+
be used by the state feedback controller. If value is an integer
730+
`n`, the first `n` system states are used. Otherwise, the value
731+
should be a slice or a list of indices. The list of indices can be
732+
specified as either integer offsets or as estimator/system output
733+
signal names. If not specified, defaults to the system states.
730734
731735
inputs, outputs : str, or list of str, optional
732736
List of strings that name the individual signals of the transformed
@@ -755,23 +759,17 @@ def create_statefbk_iosystem(
755759
raise TypeError("unrecognized keywords: ", str(kwargs))
756760

757761
# Figure out what inputs to the system to use
758-
control_indices = range(sys.ninputs) if control_indices is None \
759-
else list(control_indices)
760-
for i, idx in enumerate(control_indices):
761-
if isinstance(idx, str):
762-
control_indices[i] = sys.input_labels.index(control_indices[i])
762+
control_indices = _process_indices(
763+
control_indices, 'control', sys.input_labels, sys.ninputs)
763764
sys_ninputs = len(control_indices)
764765

765766
# Decide what system is going to pass the states to the controller
766767
if estimator is None:
767768
estimator = sys
768769

769770
# Figure out what outputs (states) from the system/estimator to use
770-
state_indices = range(sys.nstates) if state_indices is None \
771-
else list(state_indices)
772-
for i, idx in enumerate(state_indices):
773-
if isinstance(idx, str):
774-
state_indices[i] = estimator.state_labels.index(state_indices[i])
771+
state_indices = _process_indices(
772+
state_indices, 'state', estimator.state_labels, sys.nstates)
775773
sys_nstates = len(state_indices)
776774

777775
# Make sure the system/estimator states are proper dimension
@@ -858,8 +856,8 @@ def create_statefbk_iosystem(
858856
# Process gainscheduling variables, if present
859857
if gainsched:
860858
# Create a copy of the scheduling variable indices (default = xd)
861-
gainsched_indices = range(sys_nstates) if gainsched_indices is None \
862-
else list(gainsched_indices)
859+
gainsched_indices = _process_indices(
860+
gainsched_indices, 'gainsched', inputs, sys_nstates)
863861

864862
# If points is a 1D list, convert to 2D
865863
if points.ndim == 1:
@@ -871,11 +869,6 @@ def create_statefbk_iosystem(
871869
"length of gainsched_indices must match dimension of"
872870
" scheduling variables")
873871

874-
# Process scheduling variables
875-
for i, idx in enumerate(gainsched_indices):
876-
if isinstance(idx, str):
877-
gainsched_indices[i] = inputs.index(gainsched_indices[i])
878-
879872
# Create interpolating function
880873
if points.shape[1] < 2:
881874
_interp = sp.interpolate.interp1d(

0 commit comments

Comments
 (0)