21 template<
int StateDim,
int InputDim,
int OutputDim>
59 EIGEN_MAKE_ALIGNED_OPERATOR_NEW
68 double horizon_duration,
70 const WeightParam & weight_param)
73 if(horizon_duration <= 0 || horizon_dt <= 0)
75 throw std::runtime_error(
"[PreviewControl] Input arguments are invalid. horizon_duration: "
76 + std::to_string(horizon_duration) +
", horizon_dt: " + std::to_string(horizon_dt));
88 return -
K_ * x +
F_ * ref_output_seq;
93 void calcGain(
const WeightParam & weight_param)
101 const Eigen::Matrix<double, StateDim, StateDim> & A =
model_->Ad_;
102 const Eigen::Matrix<double, StateDim, InputDim> & B =
model_->Bd_;
103 const Eigen::Matrix<double, OutputDim, StateDim> & C =
model_->C_;
105 Eigen::Matrix<double, OutputDim, OutputDim> Q = weight_param.output.asDiagonal();
106 Eigen::Matrix<double, InputDim, InputDim> R = weight_param.input.asDiagonal();
107 Eigen::Matrix<double, InputDim, InputDim> Rinv = weight_param.input.cwiseInverse().asDiagonal();
110 int inputDim =
model_->inputDim();
111 int outputDim =
model_->outputDim();
116 double relNormThre = 1e-8;
117 Eigen::Matrix<double, StateDim, StateDim> A0 = A;
118 Eigen::Matrix<double, StateDim, StateDim> G0 = B * Rinv * B.transpose();
119 Eigen::Matrix<double, StateDim, StateDim> H0 = C.transpose() * Q * C;
120 Eigen::Matrix<double, StateDim, StateDim> A1, G1, H1;
121 for(
int i = 0; i < iterMax; i++)
123 Eigen::Matrix<double, StateDim, StateDim> I_GH_inv =
124 (Eigen::Matrix<double, StateDim, StateDim>::Identity() + G0 * H0).inverse();
125 A1 = A0 * I_GH_inv * A0;
126 G1 = G0 + A0 * I_GH_inv * G0 * A0.transpose();
127 H1 = H0 + A0.transpose() * H0 * I_GH_inv * A0;
129 double relNorm = (H1 - H0).norm() / H1.norm();
130 if(relNorm < relNormThre)
134 else if(i == iterMax - 1)
136 CCC_WARN_STREAM(
"[PreviewControl] Solution of Riccati equation did not converged: " << relNorm <<
" > "
147 - (A.transpose() *
P_ * A + C.transpose() * Q * C
148 - A.transpose() *
P_ * B * (R + B.transpose() *
P_ * B).inverse() * B.transpose() *
P_ * A))
152 Eigen::Matrix<double, InputDim, InputDim> R_BtPB_inv = (R + B.transpose() *
P_ * B).inverse();
154 K_ = R_BtPB_inv * B.transpose() *
P_ * A;
157 Eigen::Matrix<double, StateDim, StateDim> A_BK = A - B *
K_;
158 Eigen::Matrix<double, StateDim, StateDim> fSub = Eigen::Matrix<double, StateDim, StateDim>::Identity();
163 F_.middleCols(i * outputDim, outputDim) = R_BtPB_inv * B.transpose() * fSub * C.transpose() * Q;
168 F_.middleCols(i * outputDim, outputDim) = R_BtPB_inv * B.transpose() * fSub *
P_ * C.transpose();
170 fSub = fSub * A_BK.transpose();
176 std::shared_ptr<_StateSpaceModel>
model_;
189 Eigen::Matrix<double, StateDim, StateDim>
P_;
192 Eigen::Matrix<double, InputDim, StateDim>
K_;
195 Eigen::Matrix<double, InputDim, Eigen::Dynamic>
F_;