32 if (ref_points_.empty()) {
33 AERROR <<
"reference points empty, solver early terminates";
37 if (ref_points_.size() != bounds_around_refs_.size()) {
38 AERROR <<
"ref_points and bounds size not equal, solver early terminates";
42 if (ref_points_.size() < 3) {
43 AERROR <<
"ref_points size smaller than 3, solver early terminates";
47 if (ref_points_.size() > std::numeric_limits<int>::max()) {
48 AERROR <<
"ref_points size too large, solver early terminates";
53 num_of_points_ =
static_cast<int>(ref_points_.size());
54 num_of_variables_ = num_of_points_ * 2;
55 num_of_constraints_ = num_of_variables_;
58 std::vector<c_float> P_data;
59 std::vector<c_int> P_indices;
60 std::vector<c_int> P_indptr;
61 CalculateKernel(&P_data, &P_indices, &P_indptr);
64 std::vector<c_float> A_data;
65 std::vector<c_int> A_indices;
66 std::vector<c_int> A_indptr;
67 std::vector<c_float> lower_bounds;
68 std::vector<c_float> upper_bounds;
69 CalculateAffineConstraint(&A_data, &A_indices, &A_indptr, &lower_bounds,
73 std::vector<c_float> q;
77 std::vector<c_float> primal_warm_start;
78 SetPrimalWarmStart(&primal_warm_start);
80 OSQPData* data =
reinterpret_cast<OSQPData*
>(c_malloc(
sizeof(OSQPData)));
81 OSQPSettings* settings =
82 reinterpret_cast<OSQPSettings*
>(c_malloc(
sizeof(OSQPSettings)));
85 osqp_set_default_settings(settings);
86 settings->max_iter = max_iter_;
87 settings->time_limit = time_limit_;
88 settings->verbose = verbose_;
89 settings->scaled_termination = scaled_termination_;
90 settings->warm_start = warm_start_;
92 OSQPWorkspace* work =
nullptr;
94 bool res = OptimizeWithOsqp(num_of_variables_, lower_bounds.size(), &P_data,
95 &P_indices, &P_indptr, &A_data, &A_indices,
96 &A_indptr, &lower_bounds, &upper_bounds, &q,
97 &primal_warm_start, data, &work, settings);
98 if (res ==
false || work ==
nullptr || work->solution ==
nullptr) {
99 AERROR <<
"Failed to find solution.";
111 x_.resize(num_of_points_);
112 y_.resize(num_of_points_);
113 for (
int i = 0; i < num_of_points_; ++i) {
115 x_.at(i) = work->solution->x[index];
116 y_.at(i) = work->solution->x[index + 1];
129void FemPosDeviationOsqpInterface::CalculateKernel(
130 std::vector<c_float>* P_data, std::vector<c_int>* P_indices,
131 std::vector<c_int>* P_indptr) {
132 CHECK_GT(num_of_variables_, 4);
151 std::vector<std::vector<std::pair<c_int, c_float>>> columns;
152 columns.resize(num_of_variables_);
155 for (
int col = 0; col < 2; ++col) {
156 columns[col].emplace_back(col, weight_fem_pos_deviation_ +
157 weight_path_length_ +
158 weight_ref_deviation_);
162 for (
int col = 2; col < 4; ++col) {
163 columns[col].emplace_back(
164 col - 2, -2.0 * weight_fem_pos_deviation_ - weight_path_length_);
165 columns[col].emplace_back(col, 5.0 * weight_fem_pos_deviation_ +
166 2.0 * weight_path_length_ +
167 weight_ref_deviation_);
171 int second_point_from_last_index = num_of_points_ - 2;
172 for (
int point_index = 2; point_index < second_point_from_last_index;
174 int col_index = point_index * 2;
175 for (
int col = 0; col < 2; ++col) {
177 columns[col_index].emplace_back(col_index - 4, weight_fem_pos_deviation_);
178 columns[col_index].emplace_back(
180 -4.0 * weight_fem_pos_deviation_ - weight_path_length_);
181 columns[col_index].emplace_back(
182 col_index, 6.0 * weight_fem_pos_deviation_ +
183 2.0 * weight_path_length_ + weight_ref_deviation_);
188 int second_point_col_from_last_col = num_of_variables_ - 4;
189 int last_point_col_from_last_col = num_of_variables_ - 2;
190 for (
int col = second_point_col_from_last_col;
191 col < last_point_col_from_last_col; ++col) {
192 columns[col].emplace_back(col - 4, weight_fem_pos_deviation_);
193 columns[col].emplace_back(
194 col - 2, -4.0 * weight_fem_pos_deviation_ - weight_path_length_);
195 columns[col].emplace_back(col, 5.0 * weight_fem_pos_deviation_ +
196 2.0 * weight_path_length_ +
197 weight_ref_deviation_);
201 for (
int col = last_point_col_from_last_col; col < num_of_variables_; ++col) {
202 columns[col].emplace_back(col - 4, weight_fem_pos_deviation_);
203 columns[col].emplace_back(
204 col - 2, -2.0 * weight_fem_pos_deviation_ - weight_path_length_);
205 columns[col].emplace_back(col, weight_fem_pos_deviation_ +
206 weight_path_length_ +
207 weight_ref_deviation_);
211 CHECK_EQ(col_num, num_of_variables_);
214 for (
int i = 0; i < col_num; ++i) {
215 P_indptr->push_back(ind_p);
216 for (
const auto& row_data_pair : columns[i]) {
219 P_data->push_back(row_data_pair.second * 2.0);
220 P_indices->push_back(row_data_pair.first);
224 P_indptr->push_back(ind_p);
227void FemPosDeviationOsqpInterface::CalculateOffset(std::vector<c_float>* q) {
228 for (
int i = 0; i < num_of_points_; ++i) {
229 const auto& ref_point_xy = ref_points_[i];
230 q->push_back(-2.0 * weight_ref_deviation_ * ref_point_xy.first);
231 q->push_back(-2.0 * weight_ref_deviation_ * ref_point_xy.second);
235void FemPosDeviationOsqpInterface::CalculateAffineConstraint(
236 std::vector<c_float>* A_data, std::vector<c_int>* A_indices,
237 std::vector<c_int>* A_indptr, std::vector<c_float>* lower_bounds,
238 std::vector<c_float>* upper_bounds) {
240 for (
int i = 0; i < num_of_variables_; ++i) {
241 A_data->push_back(1.0);
242 A_indices->push_back(i);
243 A_indptr->push_back(ind_A);
246 A_indptr->push_back(ind_A);
248 for (
int i = 0; i < num_of_points_; ++i) {
249 const auto& ref_point_xy = ref_points_[i];
250 upper_bounds->push_back(ref_point_xy.first + bounds_around_refs_[i]);
251 upper_bounds->push_back(ref_point_xy.second + bounds_around_refs_[i]);
252 lower_bounds->push_back(ref_point_xy.first - bounds_around_refs_[i]);
253 lower_bounds->push_back(ref_point_xy.second - bounds_around_refs_[i]);
257void FemPosDeviationOsqpInterface::SetPrimalWarmStart(
258 std::vector<c_float>* primal_warm_start) {
259 CHECK_EQ(ref_points_.size(),
static_cast<size_t>(num_of_points_));
260 for (
const auto& ref_point_xy : ref_points_) {
261 primal_warm_start->push_back(ref_point_xy.first);
262 primal_warm_start->push_back(ref_point_xy.second);
266bool FemPosDeviationOsqpInterface::OptimizeWithOsqp(
267 const size_t kernel_dim,
const size_t num_affine_constraint,
268 std::vector<c_float>* P_data, std::vector<c_int>* P_indices,
269 std::vector<c_int>* P_indptr, std::vector<c_float>* A_data,
270 std::vector<c_int>* A_indices, std::vector<c_int>* A_indptr,
271 std::vector<c_float>* lower_bounds, std::vector<c_float>* upper_bounds,
272 std::vector<c_float>* q, std::vector<c_float>* primal_warm_start,
273 OSQPData* data, OSQPWorkspace** work, OSQPSettings* settings) {
274 CHECK_EQ(lower_bounds->size(), upper_bounds->size());
276 data->n = kernel_dim;
277 data->m = num_affine_constraint;
278 data->P = csc_matrix(data->n, data->n, P_data->size(), P_data->data(),
279 P_indices->data(), P_indptr->data());
281 data->A = csc_matrix(data->m, data->n, A_data->size(), A_data->data(),
282 A_indices->data(), A_indptr->data());
283 data->l = lower_bounds->data();
284 data->u = upper_bounds->data();
286 *work = osqp_setup(data, settings);
289 osqp_warm_start_x(*work, primal_warm_start->data());
294 auto status = (*work)->info->status_val;
297 AERROR <<
"failed optimization status:\t" << (*work)->info->status;
301 if (status != 1 && status != 2) {
302 AERROR <<
"failed optimization status:\t" << (*work)->info->status;
Planning module main class.