Skip to content

Commit bea8012

Browse files
refactor(autoware_mpc_lateral_controller): speed up matrix calculation with sparse matrix
Signed-off-by: kyoichi-sugahara <kyoichi.sugahara@tier4.jp>
1 parent edb4179 commit bea8012

File tree

1 file changed

+47
-19
lines changed
  • control/autoware_mpc_lateral_controller/src

1 file changed

+47
-19
lines changed

control/autoware_mpc_lateral_controller/src/mpc.cpp

+47-19
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@
2020
#include "interpolation/linear_interpolation.hpp"
2121
#include "rclcpp/rclcpp.hpp"
2222

23+
#include <Eigen/Sparse>
24+
2325
#include <algorithm>
2426
#include <limits>
2527

@@ -576,22 +578,47 @@ std::pair<bool, VectorXd> MPC::executeOptimization(
576578

577579
const int DIM_U_N = m_param.prediction_horizon * m_vehicle_model_ptr->getDimU();
578580

581+
Eigen::SparseMatrix<double> Cex_sparse = m.Cex.sparseView();
582+
Eigen::SparseMatrix<double> Bex_sparse = m.Bex.sparseView();
583+
Eigen::SparseMatrix<double> Qex_sparse = m.Qex.sparseView();
584+
Eigen::SparseMatrix<double> R1ex_sparse = m.R1ex.sparseView();
585+
Eigen::SparseMatrix<double> R2ex_sparse = m.R2ex.sparseView();
586+
579587
// cost function: 1/2 * Uex' * H * Uex + f' * Uex, H = B' * C' * Q * C * B + R
580-
const MatrixXd CB = m.Cex * m.Bex;
581-
const MatrixXd QCB = m.Qex * CB;
582-
// MatrixXd H = CB.transpose() * QCB + m.R1ex + m.R2ex; // This calculation is heavy. looking for
583-
// a good way. //NOLINT
584-
MatrixXd H = MatrixXd::Zero(DIM_U_N, DIM_U_N);
585-
H.triangularView<Eigen::Upper>() = CB.transpose() * QCB;
586-
H.triangularView<Eigen::Upper>() += m.R1ex + m.R2ex;
587-
H.triangularView<Eigen::Lower>() = H.transpose();
588-
MatrixXd f = (m.Cex * (m.Aex * x0 + m.Wex)).transpose() * QCB - m.Uref_ex.transpose() * m.R1ex;
588+
Eigen::SparseMatrix<double> CB_sparse(DIM_U_N, DIM_U_N);
589+
CB_sparse = Cex_sparse * Bex_sparse;
590+
591+
Eigen::SparseMatrix<double> QCB_sparse(DIM_U_N, DIM_U_N);
592+
QCB_sparse = Qex_sparse * CB_sparse;
593+
594+
Eigen::SparseMatrix<double> H_sparse(DIM_U_N, DIM_U_N);
595+
{
596+
Eigen::SparseMatrix<double> temp_sparse(DIM_U_N, DIM_U_N);
597+
temp_sparse = CB_sparse.transpose() * QCB_sparse;
598+
599+
H_sparse = temp_sparse + R1ex_sparse + R2ex_sparse;
600+
}
601+
602+
VectorXd f = VectorXd::Zero(DIM_U_N);
603+
{
604+
VectorXd CAW = VectorXd::Zero(Cex_sparse.rows());
605+
CAW = Cex_sparse * (m.Aex * x0 + m.Wex);
606+
607+
f = QCB_sparse.transpose() * CAW;
608+
f -= m.Uref_ex.transpose() * R1ex_sparse;
609+
}
610+
589611
addSteerWeightF(prediction_dt, f);
590612

591-
MatrixXd A = MatrixXd::Identity(DIM_U_N, DIM_U_N);
592-
for (int i = 1; i < DIM_U_N; i++) {
593-
A(i, i - 1) = -1.0;
613+
Eigen::SparseMatrix<double> A_sparse(DIM_U_N, DIM_U_N);
614+
std::vector<Eigen::Triplet<double>> triplets;
615+
for (int i = 0; i < DIM_U_N; ++i) {
616+
triplets.emplace_back(i, i, 1.0);
617+
if (i > 0) {
618+
triplets.emplace_back(i, i - 1, -1.0);
619+
}
594620
}
621+
A_sparse.setFromTriplets(triplets.begin(), triplets.end());
595622

596623
// steering angle limit
597624
VectorXd lb = VectorXd::Constant(DIM_U_N, -m_steer_lim); // min steering angle
@@ -605,7 +632,8 @@ std::pair<bool, VectorXd> MPC::executeOptimization(
605632
lbA(0) = m_raw_steer_cmd_prev - steer_rate_limits(0) * m_ctrl_period;
606633

607634
auto t_start = std::chrono::system_clock::now();
608-
bool solve_result = m_qpsolver_ptr->solve(H, f.transpose(), A, lb, ub, lbA, ubA, Uex);
635+
bool solve_result =
636+
m_qpsolver_ptr->solve(H_sparse, f.transpose(), A_sparse, lb, ub, lbA, ubA, Uex);
609637
auto t_end = std::chrono::system_clock::now();
610638
if (!solve_result) {
611639
warn_throttle("qp solver error");
@@ -667,16 +695,16 @@ void MPC::addSteerWeightR(const double prediction_dt, MatrixXd & R) const
667695
}
668696
}
669697

670-
void MPC::addSteerWeightF(const double prediction_dt, MatrixXd & f) const
698+
void MPC::addSteerWeightF(const double prediction_dt, VectorXd & f) const
671699
{
672-
if (f.rows() < 2) {
700+
if (f.size() < 2) {
673701
return;
674702
}
675703

676704
const double DT = prediction_dt;
677705

678706
// steer rate for i = 0
679-
f(0, 0) += -2.0 * m_param.nominal_weight.steer_rate / (std::pow(DT, 2)) * 0.5;
707+
f(0) += -2.0 * m_param.nominal_weight.steer_rate / (std::pow(DT, 2)) * 0.5;
680708

681709
// const double steer_acc_r = m_param.weight_steer_acc / std::pow(DT, 4);
682710
const double steer_acc_r_cp1 =
@@ -686,11 +714,11 @@ void MPC::addSteerWeightF(const double prediction_dt, MatrixXd & f) const
686714
const double steer_acc_r_cp4 = m_param.nominal_weight.steer_acc / std::pow(m_ctrl_period, 4);
687715

688716
// steer acc i = 0
689-
f(0, 0) += ((-2.0 * m_raw_steer_cmd_prev + m_raw_steer_cmd_pprev) * steer_acc_r_cp4) * 0.5;
717+
f(0) += ((-2.0 * m_raw_steer_cmd_prev + m_raw_steer_cmd_pprev) * steer_acc_r_cp4) * 0.5;
690718

691719
// steer acc for i = 1
692-
f(0, 0) += (-2.0 * m_raw_steer_cmd_prev * (steer_acc_r_cp1 + steer_acc_r_cp2)) * 0.5;
693-
f(0, 1) += (2.0 * m_raw_steer_cmd_prev * steer_acc_r_cp1) * 0.5;
720+
f(0) += (-2.0 * m_raw_steer_cmd_prev * (steer_acc_r_cp1 + steer_acc_r_cp2)) * 0.5;
721+
f(1) += (2.0 * m_raw_steer_cmd_prev * steer_acc_r_cp1) * 0.5;
694722
}
695723

696724
double MPC::getPredictionDeltaTime(

0 commit comments

Comments
 (0)