@@ -692,6 +692,105 @@ function validate_args(mpc::PredictiveController, ry, d, lastu, D̂, R̂y, R̂u)
692692 size (R̂u) ≠ (nu* Hp,) && throw (DimensionMismatch (" R̂u size $(size (R̂u)) ≠ manip. input size × Hp ($(nu* Hp) ,)" ))
693693end
694694
695+ @doc raw """
696+ init_ZtoΔU(estim::StateEstimator, transcription::TranscriptionMethod, Hp, Hc) -> PΔu
697+
698+ Init decision variables to input increments over ``H_c`` conversion matrix `PΔu`.
699+
700+ The conversion from the decision variables ``\m athbf{Z}`` to ``\m athbf{ΔU}``, the input
701+ increments over ``H_c``, is computed by:
702+ ```math
703+ \m athbf{ΔU} = \m athbf{P_{Δu}} \m athbf{Z}
704+ ```
705+
706+ in which ``\m athbf{P_{Δu}}`` is defined in the Extended Help section.
707+
708+ # Extended Help
709+ !!! details "Extended Help"
710+ Following the decision variable definition of the [`TranscriptionMethod`](@ref), the
711+ conversion matrix ``\m athbf{P_{Δu}}``, we have:
712+ - ``\m athbf{P_{Δu}} = \m athbf{I}`` if `transcription` is a [`SingleShooting`](@ref)
713+ - ``\m athbf{P_{Δu}} = [\b egin{smallmatrix}\m athbf{I} & \m athbf{0} \e nd{smallmatrix}]`` otherwise.
714+ The matrix is store as as `SparseMatrixCSC` to support both cases efficiently.
715+ """
716+ function init_ZtoΔU (
717+ estim:: StateEstimator{NT} , transcription:: TranscriptionMethod , Hp, Hc
718+ ) where {NT<: Real }
719+ I_nu_Hc = sparse (Matrix {NT} (I, estim. model. nu* Hc, estim. model. nu* Hc))
720+ nZ = get_nZ (estim, transcription, Hp, Hc)
721+ nΔU = estim. model. nu* Hc
722+ PΔu = [I_nu_Hc spzeros (NT, nΔU, nZ - nΔU)]
723+ return PΔu
724+ end
725+
726+ @doc raw """
727+ init_ZtoU(estim, transcription, Hp, Hc, nb) -> Pu, Tu
728+
729+ Init decision variables to inputs over ``H_p`` conversion matrices.
730+
731+ The conversion from the decision variables ``\m athbf{Z}`` to ``\m athbf{U}``, the manipulated
732+ inputs over ``H_p``, is computed by:
733+ ```math
734+ \m athbf{U} = \m athbf{P_u} \m athbf{Z} + \m athbf{T_u} \m athbf{u}(k-1)
735+ ```
736+ The ``\m athbf{P_u}`` and ``\m athbf{T_u}`` matrices are defined in the Extended Help section.
737+
738+ # Extended Help
739+ !!! details "Extended Help"
740+ With ``n_i``, the ``i``th element of the ``\m athbf{n_b}`` vector defined in [`move_blocking`](@ref)
741+ documentation, we introduce the ``\m athbf{Q}(n_i)`` matrix of size `(nu*ni, nu)`:
742+ ```math
743+ \m athbf{Q}(n_i) = \b egin{bmatrix}
744+ \m athbf{I} \\
745+ \m athbf{I} \\
746+ \v dots \\
747+ \m athbf{I} \e nd{bmatrix}
748+ ```
749+ The ``\m athbf{U}`` vector and the conversion matrices are defined as:
750+ ```math
751+ \m athbf{U} = \b egin{bmatrix}
752+ \m athbf{u}(k + 0) \\
753+ \m athbf{u}(k + 1) \\
754+ \v dots \\
755+ \m athbf{u}(k + H_p - 1) \e nd{bmatrix} , \q uad
756+ \m athbf{P_u^†} = \b egin{bmatrix}
757+ \m athbf{Q}(n_1) & \m athbf{0} & \c dots & \m athbf{0} \\
758+ \m athbf{Q}(n_2) & \m athbf{Q}(n_2) & \c dots & \m athbf{0} \\
759+ \v dots & \v dots & \d dots & \v dots \\
760+ \m athbf{Q}(n_{H_c}) & \m athbf{Q}(n_{H_c}) & \c dots & \m athbf{Q}(n_{H_c}) \e nd{bmatrix} , \q uad
761+ \m athbf{T_u} = \b egin{bmatrix}
762+ \m athbf{I} \\
763+ \m athbf{I} \\
764+ \v dots \\
765+ \m athbf{I} \e nd{bmatrix}
766+ ```
767+ and, depending on the transcription method, we have:
768+ - ``\m athbf{P_u} = \m athbf{P_u^†}`` if `transcription` is a [`SingleShooting`](@ref)
769+ - ``\m athbf{P_u} = [\b egin{smallmatrix}\m athbf{P_u^†} & \m athbf{0} \e nd{smallmatrix}]``
770+ if `transcription` is a [`MultipleShooting`](@ref)
771+ The conversion matrices are stored as `SparseMatrixCSC` since it was benchmarked that it
772+ is generally more performant than normal dense matrices, even for small `nu`, `Hp` and
773+ `Hc` values. Using `Bool` element type and `BitMatrix` is also slower.
774+ """
775+ function init_ZtoU (
776+ estim:: StateEstimator{NT} , transcription:: TranscriptionMethod , Hp, Hc, nb
777+ ) where {NT<: Real }
778+ nu = estim. model. nu
779+ I_nu = sparse (Matrix {NT} (I, nu, nu))
780+ PuDagger = Matrix {NT} (undef, nu* Hp, nu* Hc)
781+ for i= 1 : Hc
782+ ni = nb[i]
783+ Q_ni = repeat (I_nu, ni, 1 )
784+ iRows = (1 : nu* ni) .+ @views nu* sum (nb[1 : i- 1 ])
785+ PuDagger[iRows, :] = [repeat (Q_ni, 1 , i) spzeros (nu* ni, nu* (Hc- i))]
786+ end
787+ PuDagger = sparse (PuDagger)
788+ nZ = get_nZ (estim, transcription, Hp, Hc)
789+ Pu = [PuDagger spzeros (NT, nu* Hp, nZ - nu* Hc)]
790+ Tu = repeat (I_nu, Hp)
791+ return Pu, Tu
792+ end
793+
695794@doc raw """
696795 init_quadprog(
697796 model::LinModel, transcriptions::TranscriptionMethod, weights::ControllerWeights,
0 commit comments