@@ -561,8 +561,8 @@ def markov(Y, U, m=None, transpose=False):
561
561
def okid (* args , m = None , transpose = False , dt = True , truncate = False ):
562
562
"""okid(Y, U, [, m])
563
563
564
- Calculate the first `m` Markov parameters [D CB CAB ...]
565
- from data
564
+ Calculate the first `m+1 ` Markov parameters [D CB CAB ...]
565
+ from data.
566
566
567
567
This function computes the Markov parameters for a discrete time system
568
568
@@ -578,12 +578,12 @@ def okid(*args, m=None, transpose=False, dt=True, truncate=False):
578
578
579
579
The function can be called with either 1, 2 or 3 arguments:
580
580
581
- * ``H = okid(response )``
582
- * ``H = okid(respnose , m)``
581
+ * ``H = okid(data )``
582
+ * ``H = okid(data , m)``
583
583
* ``H = okid(Y, U)``
584
584
* ``H = okid(Y, U, m)``
585
585
586
- where `response ` is an `TimeResponseData` object, and `Y`, `U`, are 1D or 2D
586
+ where `data ` is an `TimeResponseData` object, and `Y`, `U`, are 1D or 2D
587
587
array and m is an integer.
588
588
589
589
Parameters
@@ -601,10 +601,10 @@ def okid(*args, m=None, transpose=False, dt=True, truncate=False):
601
601
m : int, optional
602
602
Number of Markov parameters to output. Defaults to len(U).
603
603
dt : True of float, optional
604
- True indicates discrete time with unspecified sampling time,
605
- positive number is discrete time with specified sampling time.It
606
- can be used to scale the markov parameters in order to match the
607
- impulse response of this library . Default is True.
604
+ True indicates discrete time with unspecified sampling time and a
605
+ positive float is discrete time with the specified sampling time.
606
+ It can be used to scale the Markov parameters in order to match
607
+ the unit-area impulse response of python-control . Default is True
608
608
truncate : bool, optional
609
609
Do not use first m equation for least least squares. Default is False.
610
610
transpose : bool, optional
@@ -615,7 +615,7 @@ def okid(*args, m=None, transpose=False, dt=True, truncate=False):
615
615
Returns
616
616
-------
617
617
H : ndarray
618
- First m Markov parameters, [D CB CAB ...]
618
+ First m Markov parameters, [D CB CAB ...].
619
619
620
620
References
621
621
----------
@@ -683,29 +683,17 @@ def okid(*args, m=None, transpose=False, dt=True, truncate=False):
683
683
684
684
# the algorithm - Construct a matrix of control inputs to invert
685
685
#
686
- # (q,l) = (q,p*m ) @ (p*m ,l)
687
- # YY.T = H @ UU .T
686
+ # (q,l) = (q,(p+q)*m+p ) @ ((p+q)*m+p ,l)
687
+ # YY.T = Ybar @ VV .T
688
688
#
689
689
# This algorithm sets up the following problem and solves it for
690
690
# the Markov parameters
691
691
#
692
- # (l,q) = (l,p*m) @ (p*m,q)
693
- # YY = UU @ H.T
694
- #
695
- # [ y(0) ] [ u(0) 0 0 ] [ D ]
696
- # [ y(1) ] [ u(1) u(0) 0 ] [ C B ]
697
- # [ y(2) ] = [ u(2) u(1) u(0) ] [ C A B ]
698
- # [ : ] [ : : : : ] [ : ]
699
- # [ y(l-1) ] [ u(l-1) u(l-2) u(l-3) ... u(l-m) ] [ C A^{m-2} B ]
692
+ # (l,q) = (l,(p+q)*m+p) @ ((p+q)*m+p,q)
693
+ # YY = VV @ Ybar.T
700
694
#
701
695
# truncated version t=m, do not use first m equation
702
696
#
703
- # [ y(t) ] [ u(t) u(t-1) u(t-2) u(t-m) ] [ D ]
704
- # [ y(t+1) ] [ u(t+1) u(t) u(t-1) u(t-m+1)] [ C B ]
705
- # [ y(t+2) ] = [ u(t+2) u(t+1) u(t) u(t-m+2)] [ C B ]
706
- # [ : ] [ : : : : ] [ : ]
707
- # [ y(l-1) ] [ u(l-1) u(l-2) u(l-3) ... u(l-m) ] [ C A^{m-2} B ]
708
- #
709
697
# Note: This algorithm assumes C A^{j} B = 0
710
698
# for j > m-2. See equation (3) in
711
699
#
@@ -716,42 +704,46 @@ def okid(*args, m=None, transpose=False, dt=True, truncate=False):
716
704
#
717
705
718
706
Vmat = np .concatenate ((Umat , Ymat ),axis = 0 )
719
- print (Vmat .shape )
720
707
721
- VVT = np .zeros (((q + p )* m + p , l ))
708
+ VVT = np .zeros (((p + q )* m + p , l ))
722
709
723
710
VVT [:p ,:] = Umat
724
711
for i in range (m ):
725
712
# Shift previous column down and keep zeros at the top
726
- VVT [i * ( q + p ) + p :(i + 1 )* (q + p )+ p ,i + 1 :] = Vmat [:,:l - i - 1 ]
713
+ VVT [( p + q ) * i + p :(p + q )* (i + 1 )+ p , i + 1 :] = Vmat [:, :l - i - 1 ]
727
714
728
715
YY = Ymat [:,t :].T
729
716
VV = VVT [:,t :].T
730
717
731
- # Solve for the Markov parameters from YY = VV @ Ybar.T
718
+ # Solve for the observer Markov parameters from YY = VV @ Ybar.T
732
719
YbarT , _ , _ , _ = np .linalg .lstsq (VV , YY , rcond = None )
733
- Ybar = YbarT .T / dt # scaling
720
+ Ybar = YbarT .T
734
721
722
+ # Equation 11, Page 9
735
723
D = Ybar [:,:p ]
736
- print (D .shape )
737
724
738
- Ybar_r = Ybar [:,p :].reshape (q ,m ,q + p ) # output, time*input -> output, time, input
739
- Ybar_r = Ybar_r .transpose (0 ,2 ,1 ) # output, input , time
725
+ Ybar_r = Ybar [:,p :].reshape (q ,m ,p + q ) # output, time*v_input -> output, time, v_input
726
+ Ybar_r = Ybar_r .transpose (0 ,2 ,1 ) # output, v_input , time
740
727
741
- Ybar1 = Ybar_r [:,:p ,:] # from input
742
- Ybar2 = Ybar_r [:,p :,:] # from output
728
+ Ybar1 = Ybar_r [:,:p ,:] # select observer Markov parameters generated by input
729
+ Ybar2 = Ybar_r [:,p :,:] # select observer Markov parameters generated by output
743
730
731
+ # Using recursive substitution to solve for Markov parameters
744
732
Y = np .zeros ((q ,p ,m ))
745
- Y [:,:,0 ] = Ybar1 [:,:,0 ] + Ybar1 [:,:,0 ]@D
733
+ # Equation 12, Page 9
734
+ Y [:,:,0 ] = Ybar1 [:,:,0 ] + Ybar2 [:,:,0 ]@D
735
+
736
+ # Equation 15, Page 10
746
737
for k in range (1 ,m ):
747
- Y [:,:,i ] = Ybar1 [:,:,i ] + Ybar1 [:,:,i ]@D
738
+ Y [:,:,k ] = Ybar1 [:,:,k ] + Ybar2 [:,:,k ]@D
748
739
for i in range (k - 1 ):
749
740
Y [:,:,k ] += Ybar2 [:,:,i ]@Y [:,:,k - i - 1 ]
750
741
751
-
752
- H = np .zeros ((q ,p ,m ))
742
+ # Equation 11, Page 9
743
+ H = np .zeros ((q ,p ,m + 1 ))
753
744
H [:,:,0 ] = D
754
- H [:,:,1 :] = Y [:,:,:- 1 ]
745
+ H [:,:,1 :] = Y [:,:,:]
746
+ H = H / dt # scaling
755
747
756
748
# Return the first m Markov parameters
757
749
return H if not transpose else np .transpose (H )
0 commit comments