2222
2323from .iosys import InputOutputSystem , LinearIOSystem , NonlinearIOSystem
2424from .lti import LTI
25- from .namedio import isctime , isdtime , _process_indices
25+ from .namedio import isctime , isdtime
26+ from .namedio import _process_indices , _process_control_disturbance_indices
2627from .mateqn import care , dare , _check_shape
2728from .statesp import StateSpace , _ssmatrix
2829from .exception import ControlArgument , ControlNotImplemented
@@ -308,9 +309,8 @@ def dlqe(*args, **kwargs):
308309
309310# Function to create an estimator
310311#
311- # TODO: add `control_indices` keyword to match create_mhe_iosystem (?)
312- # TODO: change name to create_kalmanestimaor_iosystem (?)
313312# TODO: create predictor/corrector, UKF, and other variants (?)
313+ # TODO: change *_labels to *_fmtstr and use signal keywords instead
314314#
315315def create_estimator_iosystem (
316316 sys , QN , RN , P0 = None , G = None , C = None ,
@@ -441,35 +441,9 @@ def create_estimator_iosystem(
441441 # Set the state matrix for later use
442442 A = sys .A
443443
444- # Set the disturbance matrices (indices take priority over G)
445- ctrl_idx = _process_indices (
446- control_indices , 'control' , sys .input_labels , sys .ninputs )
447-
448- if disturbance_indices is None and control_indices is not None :
449- # Disturbance indices are the complement of control indices
450- dist_idx = [i for i in range (sys .ninputs ) if i not in ctrl_idx ]
451- if G is not None :
452- warn ("'control_indices' and 'G' both specified; ignoring 'G'" )
453- G = sys .B [:, dist_idx ]
454-
455- elif disturbance_indices is not None :
456- if G is not None :
457- warn ("'disturbance_indices' and 'G' both specified; ignoring 'G'" )
458-
459- # If passed an integer, count from the end of the input vector
460- arg = - disturbance_indices if isinstance (disturbance_indices , int ) \
461- else disturbance_indices
462-
463- dist_idx = _process_indices (
464- arg , 'disturbance' , sys .input_labels , sys .ninputs )
465- G = sys .B [:, dist_idx ]
466-
467- # Set control indices to complement disturbance indices, if needed
468- if control_indices is None :
469- ctrl_idx = [i for i in range (sys .ninputs ) if i not in dist_idx ]
470-
471- elif G is None :
472- G = sys .B
444+ # Determine the control and disturbance indices
445+ ctrl_idx , dist_idx = _process_control_disturbance_indices (
446+ sys , control_indices , disturbance_indices )
473447
474448 # Set the input and direct matrices
475449 B = sys .B [:, ctrl_idx ]
@@ -491,6 +465,10 @@ def create_estimator_iosystem(
491465 if sensor_labels is None :
492466 sensor_labels = sys .output_labels
493467
468+ # Generate the disturbance matrix (G)
469+ if G is None :
470+ G = sys .B if len (dist_idx ) == 0 else sys .B [:, dist_idx ]
471+
494472 # Initialize the covariance matrix
495473 if P0 is None :
496474 # Initalize P0 to the steady state value
0 commit comments