Skip to content

Commit 36771de

Browse files
authored
perf(velocity_smoother): use ProxQP for faster optimization (autowarefoundation#8028)
* perf(velocity_smoother): use ProxQP for faster optimization Signed-off-by: Takayuki Murooka <takayuki5168@gmail.com> * consider max_iteration Signed-off-by: Takayuki Murooka <takayuki5168@gmail.com> * disable warm start Signed-off-by: Takayuki Murooka <takayuki5168@gmail.com> * fix test Signed-off-by: Takayuki Murooka <takayuki5168@gmail.com> --------- Signed-off-by: Takayuki Murooka <takayuki5168@gmail.com>
1 parent 72f28ef commit 36771de

File tree

9 files changed

+28
-38
lines changed

9 files changed

+28
-38
lines changed

common/qp_interface/include/qp_interface/osqp_interface.hpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ class OSQPInterface : public QPInterface
3333
public:
3434
/// \brief Constructor without problem formulation
3535
OSQPInterface(
36-
const bool enable_warm_start = false,
36+
const bool enable_warm_start = false, const int max_iteration = 20000,
3737
const c_float eps_abs = std::numeric_limits<c_float>::epsilon(),
3838
const c_float eps_rel = std::numeric_limits<c_float>::epsilon(), const bool polish = true,
3939
const bool verbose = false);

common/qp_interface/include/qp_interface/proxqp_interface.hpp

+2-2
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,8 @@ class ProxQPInterface : public QPInterface
3131
{
3232
public:
3333
explicit ProxQPInterface(
34-
const bool enable_warm_start, const double eps_abs, const double eps_rel,
35-
const bool verbose = false);
34+
const bool enable_warm_start, const int max_iteration, const double eps_abs,
35+
const double eps_rel, const bool verbose = false);
3636

3737
int getIterationNumber() const override;
3838
bool isSolved() const override;

common/qp_interface/src/osqp_interface.cpp

+4-4
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,8 @@
2121
namespace autoware::common
2222
{
2323
OSQPInterface::OSQPInterface(
24-
const bool enable_warm_start, const c_float eps_abs, const c_float eps_rel, const bool polish,
25-
const bool verbose)
24+
const bool enable_warm_start, const int max_iteration, const c_float eps_abs,
25+
const c_float eps_rel, const bool polish, const bool verbose)
2626
: QPInterface(enable_warm_start), work_{nullptr, OSQPWorkspaceDeleter}
2727
{
2828
settings_ = std::make_unique<OSQPSettings>();
@@ -35,8 +35,8 @@ OSQPInterface::OSQPInterface(
3535
settings_->eps_abs = eps_abs;
3636
settings_->eps_prim_inf = 1.0E-4;
3737
settings_->eps_dual_inf = 1.0E-4;
38-
settings_->warm_start = true;
39-
settings_->max_iter = 4000;
38+
settings_->warm_start = enable_warm_start;
39+
settings_->max_iter = max_iteration;
4040
settings_->verbose = verbose;
4141
settings_->polish = polish;
4242
}

common/qp_interface/src/proxqp_interface.cpp

+3-1
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,11 @@ namespace autoware::common
1919
using proxsuite::proxqp::QPSolverOutput;
2020

2121
ProxQPInterface::ProxQPInterface(
22-
const bool enable_warm_start, const double eps_abs, const double eps_rel, const bool verbose)
22+
const bool enable_warm_start, const int max_iteration, const double eps_abs, const double eps_rel,
23+
const bool verbose)
2324
: QPInterface(enable_warm_start)
2425
{
26+
settings_.max_iter = max_iteration;
2527
settings_.eps_abs = eps_abs;
2628
settings_.eps_rel = eps_rel;
2729
settings_.verbose = verbose;

common/qp_interface/test/test_osqp_interface.cpp

+6-6
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ TEST(TestOsqpInterface, BasicQp)
6363

6464
{
6565
// Define problem during optimization
66-
autoware::common::OSQPInterface osqp(false, 1e-6);
66+
autoware::common::OSQPInterface osqp(false, 4000, 1e-6);
6767
const auto solution = osqp.QPInterface::optimize(P, A, q, l, u);
6868
const auto status = osqp.getStatus();
6969
const auto polish_status = osqp.getPolishStatus();
@@ -72,7 +72,7 @@ TEST(TestOsqpInterface, BasicQp)
7272

7373
{
7474
// Define problem during initialization
75-
autoware::common::OSQPInterface osqp(false, 1e-6);
75+
autoware::common::OSQPInterface osqp(false, 4000, 1e-6);
7676
const auto solution = osqp.QPInterface::optimize(P, A, q, l, u);
7777
const auto status = osqp.getStatus();
7878
const auto polish_status = osqp.getPolishStatus();
@@ -87,15 +87,15 @@ TEST(TestOsqpInterface, BasicQp)
8787
std::vector<double> q_ini(2, 0.0);
8888
std::vector<double> l_ini(4, 0.0);
8989
std::vector<double> u_ini(4, 0.0);
90-
autoware::common::OSQPInterface osqp(false, 1e-6);
90+
autoware::common::OSQPInterface osqp(false, 4000, 1e-6);
9191
osqp.QPInterface::optimize(P_ini, A_ini, q_ini, l_ini, u_ini);
9292
}
9393

9494
{
9595
// Define problem during initialization with csc matrix
9696
CSC_Matrix P_csc = calCSCMatrixTrapezoidal(P);
9797
CSC_Matrix A_csc = calCSCMatrix(A);
98-
autoware::common::OSQPInterface osqp(false, 1e-6);
98+
autoware::common::OSQPInterface osqp(false, 4000, 1e-6);
9999

100100
const auto solution = osqp.optimize(P_csc, A_csc, q, l, u);
101101
const auto status = osqp.getStatus();
@@ -111,7 +111,7 @@ TEST(TestOsqpInterface, BasicQp)
111111
std::vector<double> q_ini(2, 0.0);
112112
std::vector<double> l_ini(4, 0.0);
113113
std::vector<double> u_ini(4, 0.0);
114-
autoware::common::OSQPInterface osqp(false, 1e-6);
114+
autoware::common::OSQPInterface osqp(false, 4000, 1e-6);
115115
osqp.optimize(P_ini_csc, A_ini_csc, q_ini, l_ini, u_ini);
116116

117117
// Redefine problem before optimization
@@ -132,7 +132,7 @@ TEST(TestOsqpInterface, BasicQp)
132132
std::vector<double> q_ini(2, 0.0);
133133
std::vector<double> l_ini(4, 0.0);
134134
std::vector<double> u_ini(4, 0.0);
135-
autoware::common::OSQPInterface osqp(true, 1e-6); // enable warm start
135+
autoware::common::OSQPInterface osqp(true, 4000, 1e-6); // enable warm start
136136
osqp.optimize(P_ini_csc, A_ini_csc, q_ini, l_ini, u_ini);
137137

138138
// Redefine problem before optimization

common/qp_interface/test/test_proxqp_interface.cpp

+2-2
Original file line numberDiff line numberDiff line change
@@ -57,15 +57,15 @@ TEST(TestProxqpInterface, BasicQp)
5757

5858
{
5959
// Define problem during optimization
60-
autoware::common::ProxQPInterface proxqp(false, 1e-9, 1e-9, false);
60+
autoware::common::ProxQPInterface proxqp(false, 4000, 1e-9, 1e-9, false);
6161
const auto solution = proxqp.QPInterface::optimize(P, A, q, l, u);
6262
const auto status = proxqp.getStatus();
6363
check_result(solution, status);
6464
}
6565

6666
{
6767
// Define problem during optimization with warm start
68-
autoware::common::ProxQPInterface proxqp(true, 1e-9, 1e-9, false);
68+
autoware::common::ProxQPInterface proxqp(true, 4000, 1e-9, 1e-9, false);
6969
{
7070
const auto solution = proxqp.QPInterface::optimize(P, A, q, l, u);
7171
const auto status = proxqp.getStatus();

planning/autoware_velocity_smoother/include/autoware/velocity_smoother/smoother/jerk_filtered_smoother.hpp

+2-2
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
#include "autoware/universe_utils/geometry/geometry.hpp"
2020
#include "autoware/universe_utils/system/time_keeper.hpp"
2121
#include "autoware/velocity_smoother/smoother/smoother_base.hpp"
22-
#include "osqp_interface/osqp_interface.hpp"
22+
#include "qp_interface/qp_interface.hpp"
2323

2424
#include "autoware_planning_msgs/msg/trajectory_point.hpp"
2525

@@ -59,7 +59,7 @@ class JerkFilteredSmoother : public SmootherBase
5959

6060
private:
6161
Param smoother_param_;
62-
autoware::common::osqp::OSQPInterface qp_solver_;
62+
std::shared_ptr<autoware::common::QPInterface> qp_interface_;
6363
rclcpp::Logger logger_{rclcpp::get_logger("smoother").get_child("jerk_filtered_smoother")};
6464

6565
TrajectoryPoints forwardJerkFilter(

planning/autoware_velocity_smoother/package.xml

+1
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
<depend>interpolation</depend>
3131
<depend>nav_msgs</depend>
3232
<depend>osqp_interface</depend>
33+
<depend>qp_interface</depend>
3334
<depend>rclcpp</depend>
3435
<depend>tf2</depend>
3536
<depend>tf2_ros</depend>

planning/autoware_velocity_smoother/src/smoother/jerk_filtered_smoother.cpp

+7-20
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
#include "autoware/velocity_smoother/smoother/jerk_filtered_smoother.hpp"
1616

1717
#include "autoware/velocity_smoother/trajectory_utils.hpp"
18+
#include "qp_interface/proxqp_interface.hpp"
1819

1920
#include <Eigen/Core>
2021

@@ -40,11 +41,8 @@ JerkFilteredSmoother::JerkFilteredSmoother(
4041
p.over_j_weight = node.declare_parameter<double>("over_j_weight");
4142
p.jerk_filter_ds = node.declare_parameter<double>("jerk_filter_ds");
4243

43-
qp_solver_.updateMaxIter(20000);
44-
qp_solver_.updateRhoInterval(0); // 0 means automatic
45-
qp_solver_.updateEpsRel(1.0e-6); // def: 1.0e-4
46-
qp_solver_.updateEpsAbs(1.0e-8); // def: 1.0e-4
47-
qp_solver_.updateVerbose(false);
44+
qp_interface_ =
45+
std::make_shared<autoware::common::ProxQPInterface>(false, 20000, 1.0e-8, 1.0e-6, false);
4846
}
4947

5048
void JerkFilteredSmoother::setParam(const Param & smoother_param)
@@ -301,14 +299,13 @@ bool JerkFilteredSmoother::apply(
301299

302300
// execute optimization
303301
time_keeper_->start_track("optimize");
304-
const auto result = qp_solver_.optimize(P, A, q, lower_bound, upper_bound);
302+
const auto optval = qp_interface_->optimize(P, A, q, lower_bound, upper_bound);
305303
time_keeper_->end_track("optimize");
306-
const std::vector<double> optval = std::get<0>(result);
307-
const int status_val = std::get<3>(result);
308-
if (status_val != 1) {
309-
RCLCPP_WARN(logger_, "optimization failed : %s", qp_solver_.getStatusMessage().c_str());
304+
if (!qp_interface_->isSolved()) {
305+
RCLCPP_WARN(logger_, "optimization failed : %s", qp_interface_->getStatus().c_str());
310306
return false;
311307
}
308+
312309
const auto has_nan =
313310
std::any_of(optval.begin(), optval.end(), [](const auto v) { return std::isnan(v); });
314311
if (has_nan) {
@@ -332,16 +329,6 @@ bool JerkFilteredSmoother::apply(
332329
output.at(i).acceleration_mps2 = a_stop_decel;
333330
}
334331

335-
qp_solver_.logUnsolvedStatus("[autoware_velocity_smoother]");
336-
337-
const int status_polish = std::get<2>(result);
338-
if (status_polish != 1) {
339-
const auto msg = status_polish == 0 ? "unperformed"
340-
: status_polish == -1 ? "unsuccessful"
341-
: "unknown";
342-
RCLCPP_DEBUG(logger_, "osqp polish process failed : %s. The result may be inaccurate", msg);
343-
}
344-
345332
if (VERBOSE_TRAJECTORY_VELOCITY) {
346333
const auto s_output = trajectory_utils::calcArclengthArray(output);
347334

0 commit comments

Comments
 (0)