Apollo 11.0
自动驾驶开放平台
lat_plus_controller.cc
浏览该文件的文档.
1/******************************************************************************
2 * Copyright 2017 The Apollo Authors. All Rights Reserved.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 *****************************************************************************/
16
18
19#include <algorithm>
20#include <iomanip>
21#include <utility>
22#include <vector>
23
24#include "Eigen/LU"
25#include "absl/strings/str_cat.h"
26
27#include "cyber/common/log.h"
28#include "cyber/time/clock.h"
36
37namespace apollo {
38namespace control {
39
45using Matrix = Eigen::MatrixXd;
48namespace {
49
50std::string GetLogFileName() {
51 time_t raw_time;
52 char name_buffer[80];
53 std::time(&raw_time);
54 std::tm time_tm;
55 localtime_r(&raw_time, &time_tm);
56 strftime(name_buffer, 80, "/tmp/steer_log_simple_optimal_%F_%H%M%S.csv", &time_tm);
57 return std::string(name_buffer);
58}
59
60void WriteHeaders(std::ofstream &file_stream) {
61 file_stream << "current_lateral_error," << "current_ref_heading," << "current_heading," << "current_heading_error,"
62 << "heading_error_rate," << "lateral_error_rate," << "current_curvature," << "steer_angle,"
63 << "steer_angle_feedforward," << "steer_angle_lateral_contribution,"
64 << "steer_angle_lateral_rate_contribution," << "steer_angle_heading_contribution,"
65 << "steer_angle_heading_rate_contribution," << "steer_angle_feedback," << "steering_position," << "v"
66 << std::endl;
67}
68} // namespace
69
70LatPlusController::LatPlusController() : name_("LQR-based Lateral Plus Controller") {
71 if (FLAGS_enable_csv_debug) {
72 steer_log_file_.open(GetLogFileName());
73 steer_log_file_ << std::fixed;
74 steer_log_file_ << std::setprecision(6);
75 WriteHeaders(steer_log_file_);
76 }
77 AINFO << "Using " << name_;
78}
79
83
85 const LatBaseLqrPlusControllerConf &current_lat_based_lqr_plus_controller_conf) {
86 vehicle_param_ = common::VehicleConfigHelper::Instance()->GetConfig().vehicle_param();
87
88 ts_ = current_lat_based_lqr_plus_controller_conf.ts();
89 if (ts_ <= 0.0) {
90 AERROR << "[LatPlusController] Invalid control update interval.";
91 return false;
92 }
93 preview_window_ = current_lat_based_lqr_plus_controller_conf.preview_window();
97
98 AHC_container_.resize(current_lat_based_lqr_plus_controller_conf.ahc_container_size());
101
102 // Matrix init operations.
103 const int matrix_size = basic_state_size_ + preview_window_;
106 matrix_adc_ = Matrix::Zero(matrix_size, matrix_size);
107
108 matrix_a_coeff_ = Matrix::Zero(matrix_size, matrix_size);
109
110 /*
111 b = [0.0, c_f / m, 0.0, l_f * c_f / i_z]^T
112 */
113 matrix_b_ = Matrix::Zero(basic_state_size_, 1);
114 matrix_bd_ = Matrix::Zero(basic_state_size_, 1);
115 matrix_bdc_ = Matrix::Zero(matrix_size, 1);
116
117 matrix_state_ = Matrix::Zero(matrix_size, 1);
118 matrix_k_ = Matrix::Zero(1, matrix_size);
119 matrix_r_ = Matrix::Identity(1, 1);
120 matrix_q_ = Matrix::Zero(matrix_size, matrix_size);
121
122 return true;
123}
124
126 const LatBaseLqrPlusControllerConf &current_lat_based_lqr_plus_controller_conf) {
127 cf_ = current_lat_based_lqr_plus_controller_conf.cf();
128 cr_ = current_lat_based_lqr_plus_controller_conf.cr();
129 preview_window_ = current_lat_based_lqr_plus_controller_conf.preview_window();
130 lookahead_station_low_speed_ = current_lat_based_lqr_plus_controller_conf.lookahead_station();
131 lookback_station_low_speed_ = current_lat_based_lqr_plus_controller_conf.lookback_station();
132 lookahead_station_high_speed_ = current_lat_based_lqr_plus_controller_conf.lookahead_station_high_speed();
133 lookback_station_high_speed_ = current_lat_based_lqr_plus_controller_conf.lookback_station_high_speed();
134 max_lat_acc_ = current_lat_based_lqr_plus_controller_conf.max_lateral_acceleration();
135 low_speed_bound_ = current_lat_based_lqr_plus_controller_conf.switch_speed();
136 low_speed_window_ = current_lat_based_lqr_plus_controller_conf.switch_speed_window();
137
138 const double mass_fl = current_lat_based_lqr_plus_controller_conf.mass_fl();
139 const double mass_fr = current_lat_based_lqr_plus_controller_conf.mass_fr();
140 const double mass_rl = current_lat_based_lqr_plus_controller_conf.mass_rl();
141 const double mass_rr = current_lat_based_lqr_plus_controller_conf.mass_rr();
142 const double mass_front = mass_fl + mass_fr;
143 const double mass_rear = mass_rl + mass_rr;
144 mass_ = mass_front + mass_rear;
145
146 lf_ = wheelbase_ * (1.0 - mass_front / mass_);
147 lr_ = wheelbase_ * (1.0 - mass_rear / mass_);
148
149 // moment of inertia
150 iz_ = lf_ * lf_ * mass_front + lr_ * lr_ * mass_rear;
151
152 lqr_eps_ = current_lat_based_lqr_plus_controller_conf.eps();
153 lqr_max_iteration_ = current_lat_based_lqr_plus_controller_conf.max_iteration();
154
155 query_relative_time_ = current_lat_based_lqr_plus_controller_conf.query_relative_time();
156
157 minimum_speed_protection_ = FLAGS_minimum_speed_protection;
158
159 // Matrix init operations.
160 /*
161 A matrix (Gear Drive)
162 [0.0, 1.0, 0.0, 0.0;
163 0.0, (-(c_f + c_r) / m) / v, (c_f + c_r) / m,
164 (l_r * c_r - l_f * c_f) / m / v;
165 0.0, 0.0, 0.0, 1.0;
166 0.0, ((lr * cr - lf * cf) / i_z) / v, (l_f * c_f - l_r * c_r) / i_z,
167 (-1.0 * (l_f^2 * c_f + l_r^2 * c_r) / i_z) / v;]
168 */
169 matrix_a_(0, 1) = 1.0;
170 matrix_a_(1, 2) = (cf_ + cr_) / mass_;
171 matrix_a_(2, 3) = 1.0;
172 matrix_a_(3, 2) = (lf_ * cf_ - lr_ * cr_) / iz_;
173
174 // matrix_a_coeff_ = Matrix::Zero(matrix_size, matrix_size);
175 matrix_a_coeff_(1, 1) = -(cf_ + cr_) / mass_;
176 matrix_a_coeff_(1, 3) = (lr_ * cr_ - lf_ * cf_) / mass_;
177 matrix_a_coeff_(3, 1) = (lr_ * cr_ - lf_ * cf_) / iz_;
178 matrix_a_coeff_(3, 3) = -1.0 * (lf_ * lf_ * cf_ + lr_ * lr_ * cr_) / iz_;
179
180 /*
181 b = [0.0, c_f / m, 0.0, l_f * c_f / i_z]^T
182 */
183 matrix_b_(1, 0) = cf_ / mass_;
184 matrix_b_(3, 0) = lf_ * cf_ / iz_;
186
187 const int matrix_size = basic_state_size_ + preview_window_;
188 int q_param_size = current_lat_based_lqr_plus_controller_conf.matrix_q_size();
189 if (matrix_size != q_param_size) {
190 const auto error_msg = absl::StrCat(
191 "lateral controller error: matrix_q size: ",
192 q_param_size,
193 " in parameter file not equal to matrix_size: ",
194 matrix_size);
195 AERROR << error_msg;
196 return false;
197 }
198
199 for (int i = 0; i < q_param_size; ++i) {
200 matrix_q_(i, i) = current_lat_based_lqr_plus_controller_conf.matrix_q(i);
201 }
202
204 enable_leadlag_ = current_lat_based_lqr_plus_controller_conf.enable_reverse_leadlag_compensation();
205 enable_look_ahead_back_control_ = current_lat_based_lqr_plus_controller_conf.enable_look_ahead_back_control();
206 use_new_look_ahead_back_ = current_lat_based_lqr_plus_controller_conf.use_new_look_ahead_back();
207 enable_enhance_qparam_ = current_lat_based_lqr_plus_controller_conf.enable_enhance_qparam();
208 check_continous_errors_window_ = current_lat_based_lqr_plus_controller_conf.check_continous_errors_window();
209 if (!is_lat_turbulence_) {
211 }
212
213 return true;
214}
215
217 const std::string log_str = absl::StrCat(
218 debug->lateral_error(),
219 ",",
220 debug->ref_heading(),
221 ",",
222 debug->heading(),
223 ",",
224 debug->heading_error(),
225 ",",
226 debug->heading_error_rate(),
227 ",",
228 debug->lateral_error_rate(),
229 ",",
230 debug->curvature(),
231 ",",
232 debug->steer_angle(),
233 ",",
235 ",",
237 ",",
239 ",",
241 ",",
243 ",",
244 debug->steer_angle_feedback(),
245 ",",
246 chassis->steering_percentage(),
247 ",",
248 injector_->vehicle_state()->linear_velocity());
249 if (FLAGS_enable_csv_debug) {
250 steer_log_file_ << log_str << std::endl;
251 }
252 ADEBUG << "Steer_Control_Detail: " << log_str;
253}
254
256 if (mass_current_ != mass_) {
257 AINFO << "Update the vehicle mass.";
258 AINFO << "[LatPlusController parameters]" << " mass_: " << mass_ << "," << " iz_: " << iz_ << ","
259 << " lf_: " << lf_ << "," << " lr_: " << lr_;
261 }
262}
263
265 // Low pass filter
266 std::vector<double> den(3, 0.0);
267 std::vector<double> num(3, 0.0);
271 static_cast<std::uint_fast8_t>(lat_based_lqr_plus_controller_conf_.mean_filter_window_size()));
273 static_cast<std::uint_fast8_t>(lat_based_lqr_plus_controller_conf_.mean_filter_window_size()));
274}
275
276Status LatPlusController::Init(std::shared_ptr<DependencyInjector> injector) {
277 if (!ControlTask::LoadConfig<LatBaseLqrPlusControllerConf>(&lat_based_lqr_plus_controller_conf_)) {
278 AERROR << "failed to load control conf in init.";
279 return Status(ErrorCode::CONTROL_INIT_ERROR, "failed to load lat control_conf init");
280 }
281
283 AERROR << "failed to load control conf in init.";
284 return Status(ErrorCode::CONTROL_INIT_ERROR, "failed to load control_conf init");
285 }
286
288 AERROR << "failed to update control conf in init.";
289 return Status(ErrorCode::CONTROL_INIT_ERROR, "failed to update control_conf init");
290 }
291
292 if (!ControlTaskExtend::LoadParamsPipelineConfig<ParamsPipeline>(&params_pipeline_)) {
293 AERROR << "failed to load lon pid params pipeline config in init.";
294 return Status(ErrorCode::CONTROL_INIT_ERROR, "failed to load lon pid params pipeline config");
295 }
296
298 AERROR << "failed to load lat lqr controller params.";
299 return Status(ErrorCode::CONTROL_INIT_ERROR, "failed to load lon pid params pipeline config");
300 }
301
302 AINFO << name_ << " begin.";
305
306 injector_ = injector;
308
309 enable_mrac_ = lat_based_lqr_plus_controller_conf_.enable_steer_mrac_control();
310 if (enable_mrac_) {
313 }
314
315 return Status::OK();
316}
317
318bool LatPlusController::LoadParams(ParamsPipeline *params_pipeline) {
319 AINFO << "Into the lat load params.";
320 for (int i = 0; i < params_pipeline->params_declare_size(); i++) {
321 LatBaseLqrPlusControllerConf param_config;
322 auto param_config_path = params_pipeline->params_declare(i).config_path();
323 std::string param_config_path_relative = absl::StrCat("conf", "/", param_config_path);
324 AINFO << "Param config_path_relative is " << param_config_path_relative;
325 std::string param_config_path_absolute
327 "apollo::control::LatPlusController", param_config_path_relative);
328 AINFO << "Param config_path_absolute is " << param_config_path_absolute;
329 if (!apollo::cyber::common::GetProtoFromFile(param_config_path_absolute, &param_config)) {
330 AERROR << "Load config: " << params_pipeline->params_declare(i).config_name() << " param failed!";
331 return false;
332 }
333 AINFO << "Load the lat config file successfully, file path: " << param_config_path;
334 params_list_.push_back(std::make_pair(params_pipeline->params_declare(i).config_name(), param_config));
335 }
336 return true;
337}
338
340 if (FLAGS_enable_csv_debug && steer_log_file_.is_open()) {
341 steer_log_file_.close();
342 }
343}
344
346 const std::string param_config_name,
347 LatBaseLqrPlusControllerConf &current_lat_based_lqr_plus_controller_conf) {
348 bool set_success = false;
349 for (const auto &param : params_list_) {
350 if (param.first == param_config_name) {
351 current_lat_based_lqr_plus_controller_conf.CopyFrom(param.second);
352 set_success = true;
353 break;
354 }
355 }
356 if (!set_success) {
357 AERROR << "Fail to find lat current param[" << param_config_name << "]";
358 }
359 return set_success;
360}
361
363 LatBaseLqrPlusControllerConf &current_lat_based_lqr_plus_controller_conf,
364 const planning::ADCTrajectory *planning_published_trajectory) {
365 std::string param_config_name = "public_road_forward_param";
366
367 if (!IsForwardModel()) {
368 param_config_name = "public_road_backward_param";
369 }
370
372 std::fabs(ref_curvature_last_),
375 && IsForwardModel()) {
376 param_config_name = "public_road_forward_s_turn_param";
377 }
378
379 if (planning_published_trajectory->trajectory_type() == ADCTrajectory::OPEN_SPACE) {
380 if (IsForwardModel()) {
381 param_config_name = "open_space_forward_param";
382 } else {
383 param_config_name = "open_space_backward_param";
384 }
385 }
386
387 if (IsEdgeFollow()) {
388 if (!IsLargeCurvature(
389 std::fabs(ref_curvature_last_),
392 param_config_name = "edge_follow_public_road_forward_param";
393 } else {
395 param_config_name = "edge_follow_public_road_forward_sl_turn_param";
396 } else {
397 param_config_name = "edge_follow_public_road_forward_sr_turn_param";
398 }
399 }
400 }
401
402 if (planning_published_trajectory->debug().planning_data().scenario().scenario_plugin_type() == "ZONE_COVER") {
403 if (!IsForwardModel()) {
404 param_config_name = "zone_cover_backward_param";
405 } else {
406 param_config_name = "zone_cover_forward_param";
407 }
408 }
409
410 if (!SetCurrentParam(param_config_name, current_lat_based_lqr_plus_controller_conf)) {
411 AERROR << "Failed to set current lat param config: " << param_config_name;
412 return false;
413 } else {
414 if (param_config_name != current_param_config_name_) {
415 AINFO << "Update the current lat param config name is " << param_config_name;
416 current_param_config_name_ = param_config_name;
417 }
418 return true;
419 }
420}
421
425
426std::string LatPlusController::Name() const {
427 return name_;
428}
429
431 const localization::LocalizationEstimate *localization,
432 const canbus::Chassis *chassis,
433 const planning::ADCTrajectory *planning_published_trajectory,
434 ControlCommand *cmd) {
435 chassis_ = chassis;
436
437 if (!VehicleStatusIdentificationUpdate(localization, chassis, planning_published_trajectory)) {
438 AERROR << "Fail to update the vehicle status identification!";
439 return Status(ErrorCode::CONTROL_COMPUTE_ERROR, "Fail to update the vehicle status identification!");
440 }
441
442 if (!ChooseCurrentParam(current_lat_based_lqr_plus_controller_conf_, planning_published_trajectory)) {
443 AERROR << "Fail to load the current lon control param!";
444 return Status(ErrorCode::CONTROL_COMPUTE_ERROR, "Fail to load the current lon control param!");
445 }
446
448 AERROR << "failed to load control conf";
449 return Status(ErrorCode::CONTROL_COMPUTE_ERROR, "failed to load control_conf");
450 }
451
453
455
456 auto vehicle_state = injector_->vehicle_state();
457 auto previous_lon_debug = injector_->Get_previous_lon_debug_info();
458 auto target_tracking_trajectory = *planning_published_trajectory;
459
460 if (FLAGS_use_navigation_mode
461 && current_lat_based_lqr_plus_controller_conf_.enable_navigation_mode_position_update()) {
462 auto time_stamp_diff = planning_published_trajectory->header().timestamp_sec() - current_trajectory_timestamp_;
463
464 auto curr_vehicle_x = localization->pose().position().x();
465 auto curr_vehicle_y = localization->pose().position().y();
466
467 double curr_vehicle_heading = 0.0;
468 const auto &orientation = localization->pose().orientation();
469 if (localization->pose().has_heading()) {
470 curr_vehicle_heading = localization->pose().heading();
471 } else {
472 curr_vehicle_heading = common::math::QuaternionToHeading(
473 orientation.qw(), orientation.qx(), orientation.qy(), orientation.qz());
474 }
475
476 // new planning trajectory
477 if (time_stamp_diff > 1.0e-6) {
478 init_vehicle_x_ = curr_vehicle_x;
479 init_vehicle_y_ = curr_vehicle_y;
480 init_vehicle_heading_ = curr_vehicle_heading;
481
482 current_trajectory_timestamp_ = planning_published_trajectory->header().timestamp_sec();
483 } else {
484 auto x_diff_map = curr_vehicle_x - init_vehicle_x_;
485 auto y_diff_map = curr_vehicle_y - init_vehicle_y_;
486 auto theta_diff = curr_vehicle_heading - init_vehicle_heading_;
487
488 auto cos_map_veh = std::cos(init_vehicle_heading_);
489 auto sin_map_veh = std::sin(init_vehicle_heading_);
490
491 auto x_diff_veh = cos_map_veh * x_diff_map + sin_map_veh * y_diff_map;
492 auto y_diff_veh = -sin_map_veh * x_diff_map + cos_map_veh * y_diff_map;
493
494 auto cos_theta_diff = std::cos(-theta_diff);
495 auto sin_theta_diff = std::sin(-theta_diff);
496
497 auto tx = -(cos_theta_diff * x_diff_veh - sin_theta_diff * y_diff_veh);
498 auto ty = -(sin_theta_diff * x_diff_veh + cos_theta_diff * y_diff_veh);
499
500 auto ptr_trajectory_points = target_tracking_trajectory.mutable_trajectory_point();
501 std::for_each(
502 ptr_trajectory_points->begin(),
503 ptr_trajectory_points->end(),
504 [&cos_theta_diff, &sin_theta_diff, &tx, &ty, &theta_diff](common::TrajectoryPoint &p) {
505 auto x = p.path_point().x();
506 auto y = p.path_point().y();
507 auto theta = p.path_point().theta();
508
509 auto x_new = cos_theta_diff * x - sin_theta_diff * y + tx;
510 auto y_new = sin_theta_diff * x + cos_theta_diff * y + ty;
511 auto theta_new = common::math::NormalizeAngle(theta - theta_diff);
512
513 p.mutable_path_point()->set_x(x_new);
514 p.mutable_path_point()->set_y(y_new);
515 p.mutable_path_point()->set_theta(theta_new);
516 });
517 }
518 }
519
520 trajectory_analyzer_ = std::move(TrajectoryAnalyzerExtend(&target_tracking_trajectory));
521
522 // Transform the coordinate of the planning trajectory from the center of the
523 // rear-axis to the center of mass, if conditions matched
524 if (((current_lat_based_lqr_plus_controller_conf_.trajectory_transform_to_com_reverse() && (!IsForwardModel()))
525 || (current_lat_based_lqr_plus_controller_conf_.trajectory_transform_to_com_drive() && IsForwardModel()))
528 }
529
530 // Re-build the vehicle dynamic models at reverse driving (in particular,
531 // replace the lateral translational motion dynamics with the corresponding
532 // kinematic models)
533 if (!IsForwardModel()) {
534 /*
535 A matrix (Gear Reverse)
536 [0.0, 0.0, 1.0 * v 0.0;
537 0.0, (-(c_f + c_r) / m) / v, (c_f + c_r) / m,
538 (l_r * c_r - l_f * c_f) / m / v;
539 0.0, 0.0, 0.0, 1.0;
540 0.0, ((lr * cr - lf * cf) / i_z) / v, (l_f * c_f - l_r * c_r) / i_z,
541 (-1.0 * (l_f^2 * c_f + l_r^2 * c_r) / i_z) / v;]
542 */
545 matrix_a_(0, 1) = 0.0;
546 matrix_a_coeff_(0, 2) = 1.0;
547 } else {
548 /*
549 A matrix (Gear Drive)
550 [0.0, 1.0, 0.0, 0.0;
551 0.0, (-(c_f + c_r) / m) / v, (c_f + c_r) / m,
552 (l_r * c_r - l_f * c_f) / m / v;
553 0.0, 0.0, 0.0, 1.0;
554 0.0, ((lr * cr - lf * cf) / i_z) / v, (l_f * c_f - l_r * c_r) / i_z,
555 (-1.0 * (l_f^2 * c_f + l_r^2 * c_r) / i_z) / v;]
556 */
559 matrix_a_(0, 1) = 1.0;
560 matrix_a_coeff_(0, 2) = 0.0;
561 }
562 matrix_a_(1, 2) = (cf_ + cr_) / mass_;
563 matrix_a_(3, 2) = (lf_ * cf_ - lr_ * cr_) / iz_;
564 matrix_a_coeff_(1, 1) = -(cf_ + cr_) / mass_;
565 matrix_a_coeff_(1, 3) = (lr_ * cr_ - lf_ * cf_) / mass_;
566 matrix_a_coeff_(3, 1) = (lr_ * cr_ - lf_ * cf_) / iz_;
567 matrix_a_coeff_(3, 3) = -1.0 * (lf_ * lf_ * cf_ + lr_ * lr_ * cr_) / iz_;
568
569 /*
570 b = [0.0, c_f / m, 0.0, l_f * c_f / i_z]^T
571 */
572 matrix_b_(1, 0) = cf_ / mass_;
573 matrix_b_(3, 0) = lf_ * cf_ / iz_;
575
577
578 SimpleLateralDebug *debug = cmd->mutable_debug()->mutable_simple_lat_debug();
579 debug->Clear();
580 auto lat_debug_info = injector_->mutable_control_debug_info()->mutable_simple_lat_debug();
581 lat_debug_info->Clear();
582
583 // Update state = [Lateral Error, Lateral Error Rate, Heading Error, Heading
584 // Error Rate, preview lateral error1 , preview lateral error2, ...]
585 UpdateState(debug, lat_debug_info, chassis);
586
587 UpdateMatrix();
588
589 // Compound discrete matrix with road preview model
591
592 // Adjust matrix_q_updated when in reverse gear
593 int q_param_size = current_lat_based_lqr_plus_controller_conf_.matrix_q_size();
594 for (int i = 0; i < q_param_size; ++i) {
596 }
597
598 if (enable_enhance_qparam_ && (!previous_lon_debug->is_full_stop()) && (!previous_lon_debug->is_full_stop_soft())) {
600 lat_debug_info->lateral_error_match_local(),
601 lat_debug_info->heading_error_match_local(),
602 planning_published_trajectory,
603 previous_lon_debug,
604 debug,
605 lat_debug_info);
606 }
607
608 uint num_iteration;
609 double result_diff;
610 // Add gain scheduler for higher speed steering
611 if (FLAGS_enable_gain_scheduler) {
612 double curvature = std::fabs(debug->curvature());
613 double speed = std::fabs(vehicle_state->linear_velocity());
614
615 matrix_q_updated_(0, 0) = ed_date_ * matrix_q_(0, 0)
617 speed,
619 current_lat_based_lqr_plus_controller_conf_.lat_err_speed_gain_output())
621 curvature,
623 current_lat_based_lqr_plus_controller_conf_.lat_err_curvature_gain_output());
624
626 = matrix_q_(1, 1)
628 speed,
630 current_lat_based_lqr_plus_controller_conf_.lat_err_delta_speed_gain_output())
632 curvature,
634 current_lat_based_lqr_plus_controller_conf_.lat_err_delta_curvature_gain_output());
635
637 = efai_rate_ * matrix_q_(2, 2)
639 speed,
641 current_lat_based_lqr_plus_controller_conf_.heading_err_speed_gain_output())
643 curvature,
645 current_lat_based_lqr_plus_controller_conf_.heading_err_curvature_gain_output());
646
648 = matrix_q_(3, 3)
650 speed,
652 current_lat_based_lqr_plus_controller_conf_.heading_err_delta_speed_gain_output())
654 curvature,
656 current_lat_based_lqr_plus_controller_conf_.heading_err_delta_curvature_gain_output());
657 ADEBUG << "current vehicle is " << speed << ", curvature is " << curvature;
658 ADEBUG << "matrix_q_updated_(0, 0) is " << matrix_q_updated_(0, 0);
659 ADEBUG << "matrix_q_updated_(1, 1) is " << matrix_q_updated_(1, 1);
660 ADEBUG << "matrix_q_updated_(2, 2) is " << matrix_q_updated_(2, 2);
661 ADEBUG << "matrix_q_updated_(3, 3) is " << matrix_q_updated_(3, 3);
662
667 matrix_r_,
668 lqr_eps_,
670 &matrix_k_,
671 &num_iteration,
672 &result_diff);
673 } else {
677 matrix_q_,
678 matrix_r_,
679 lqr_eps_,
681 &matrix_k_,
682 &num_iteration,
683 &result_diff);
684 }
685
686 ADEBUG << "LQR num_iteration is " << num_iteration << ", max iteration threshold is " << lqr_max_iteration_
687 << "; result_diff is " << result_diff;
688
689 lat_debug_info->set_lqr_iteration_num(num_iteration);
690 lat_debug_info->set_lqr_result_diff(result_diff);
691
692 // feedback = - K * state
693 // Convert vehicle steer angle from rad to degree and then to steer degree
694 // then to 100% ratio
695 const double steer_angle_feedback
697
698 double curvature = 0.0;
701 if (!IsForwardModel()) {
702 curvature = lat_debug_info->lookback_curvature_new();
703 } else {
704 curvature = lat_debug_info->lookahead_curvature_new();
705 }
706 } else {
707 curvature = lat_debug_info->lookahead_curvature();
708 }
709 } else {
710 curvature = debug->curvature();
711 }
712
713 const double steer_angle_feedforward = ComputeFeedForward(curvature);
714
715 double steer_angle = 0.0;
716 double steer_angle_feedback_augment = 0.0;
717 // Augment the feedback control on lateral error at the desired speed domain
718 if (enable_leadlag_) {
719 if (current_lat_based_lqr_plus_controller_conf_.enable_feedback_augment_on_high_speed()
720 || std::fabs(vehicle_state->linear_velocity()) < low_speed_bound_) {
721 steer_angle_feedback_augment = leadlag_controller_.Control(-matrix_state_(0, 0), ts_) * 180 / M_PI
723 if (std::fabs(vehicle_state->linear_velocity()) > low_speed_bound_ - low_speed_window_) {
724 // Within the low-high speed transition window, linerly interplolate the
725 // augment control gain for "soft" control switch
726 steer_angle_feedback_augment = common::math::lerp(
727 steer_angle_feedback_augment,
729 0.0,
731 std::fabs(vehicle_state->linear_velocity()));
732 }
733 }
734 }
735 steer_angle = steer_angle_feedback + steer_angle_feedforward + steer_angle_feedback_augment;
736
737 // Compute the steering command limit with the given maximum lateral
738 // acceleration
739 const double steer_limit = FLAGS_set_steer_limit
740 ? std::atan(
741 max_lat_acc_ * wheelbase_ / (vehicle_state->linear_velocity() * vehicle_state->linear_velocity()))
743 : 100.0;
744
745 const double steer_diff_with_max_rate
746 = current_lat_based_lqr_plus_controller_conf_.enable_maximum_steer_rate_limit()
748 : 100.0;
749
750 const double steering_position = chassis->steering_percentage();
751
752 // Re-compute the steering command if the MRAC control is enabled, with steer
753 // angle limitation and steer rate limitation
754 if (enable_mrac_) {
755 const int mrac_model_order = current_lat_based_lqr_plus_controller_conf_.steer_mrac_conf().mrac_model_order();
756 Matrix steer_state = Matrix::Zero(mrac_model_order, 1);
757 steer_state(0, 0) = chassis->steering_percentage();
758 if (mrac_model_order > 1) {
759 steer_state(1, 0) = (steering_position - pre_steering_position_) / ts_;
760 }
761 if (std::fabs(vehicle_state->linear_velocity()) > FLAGS_minimum_speed_resolution) {
764 } else {
767 }
768 steer_angle = mrac_controller_.Control(steer_angle, steer_state, steer_limit, steer_diff_with_max_rate / ts_);
769 // Set the steer mrac debug message
770 MracDebug *mracdebug = debug->mutable_steer_mrac_debug();
772 mracdebug->set_mrac_model_order(mrac_model_order);
773 for (int i = 0; i < mrac_model_order; ++i) {
774 mracdebug->add_mrac_reference_state(steer_reference(i, 0));
775 mracdebug->add_mrac_state_error(steer_state(i, 0) - steer_reference(i, 0));
776 mracdebug->mutable_mrac_adaptive_gain()->add_state_adaptive_gain(
778 }
779 mracdebug->mutable_mrac_adaptive_gain()->add_input_adaptive_gain(
781 mracdebug->set_mrac_reference_saturation_status(mrac_controller_.ReferenceSaturationStatus());
782 mracdebug->set_mrac_control_saturation_status(mrac_controller_.ControlSaturationStatus());
783 }
784 pre_steering_position_ = steering_position;
785 debug->set_steer_mrac_enable_status(enable_mrac_);
786
787 // Clamp the steer angle with steer limitations at current speed
788 double steer_angle_limited = common::math::Clamp(steer_angle, -steer_limit, steer_limit);
789 steer_angle = steer_angle_limited;
790 debug->set_steer_angle_limited(steer_angle_limited);
791 // Limit the steering command with the designed digital filter
792 steer_angle = digital_filter_.Filter(steer_angle);
793 steer_angle = common::math::Clamp(steer_angle, -100.0, 100.0);
794
795 // Check if the steer is locked and hence the previous steer angle should be
796 // executed
797 if (injector_->vehicle_state()->gear() != canbus::Chassis::GEAR_REVERSE) {
798 if ((std::abs(vehicle_state->linear_velocity()) < current_lat_based_lqr_plus_controller_conf_.lock_steer_speed()
799 || previous_lon_debug->path_remain() <= 0)
800 && vehicle_state->gear() == canbus::Chassis::GEAR_DRIVE
802 ADEBUG << "Into lock steer, path_remain is " << previous_lon_debug->path_remain() << "linear_velocity is "
803 << vehicle_state->linear_velocity();
804 lat_debug_info->set_is_lock_steer(true);
805 steer_angle = pre_steer_angle_;
806 } else {
807 lat_debug_info->set_is_lock_steer(false);
808 }
809 }
810
811 // Set the steer commands
812 cmd->set_steering_target(common::math::Clamp(
813 steer_angle, pre_steer_angle_ - steer_diff_with_max_rate, pre_steer_angle_ + steer_diff_with_max_rate));
814 cmd->set_steering_rate(FLAGS_steer_angle_rate);
815
817
818 // compute extra information for logging and debugging
819 const double steer_angle_lateral_contribution = -matrix_k_(0, 0) * matrix_state_(0, 0) * 180 / M_PI * steer_ratio_
821
822 const double steer_angle_lateral_rate_contribution = -matrix_k_(0, 1) * matrix_state_(1, 0) * 180 / M_PI
824
825 const double steer_angle_heading_contribution = -matrix_k_(0, 2) * matrix_state_(2, 0) * 180 / M_PI * steer_ratio_
827
828 const double steer_angle_heading_rate_contribution = -matrix_k_(0, 3) * matrix_state_(3, 0) * 180 / M_PI
830
831 debug->set_heading(driving_orientation_);
832 debug->set_steer_angle(steer_angle);
833 debug->set_steer_angle_feedforward(steer_angle_feedforward);
834 debug->set_steer_angle_lateral_contribution(steer_angle_lateral_contribution);
835 debug->set_steer_angle_lateral_rate_contribution(steer_angle_lateral_rate_contribution);
836 debug->set_steer_angle_heading_contribution(steer_angle_heading_contribution);
837 debug->set_steer_angle_heading_rate_contribution(steer_angle_heading_rate_contribution);
838 debug->set_steer_angle_feedback(steer_angle_feedback);
839 debug->set_steer_angle_feedback_augment(steer_angle_feedback_augment);
840 debug->set_steering_position(steering_position);
841 debug->set_ref_speed(vehicle_state->linear_velocity());
842
843 lat_debug_info->set_efai_rate(efai_rate_);
844 lat_debug_info->set_ed_rate(ed_date_);
845 lat_debug_info->set_enable_look_ahead_back_control(enable_look_ahead_back_control_);
846 lat_debug_info->set_is_in_large_curvature(is_in_large_curvature_);
847
848 ProcessLogs(debug, chassis);
849 return Status::OK();
850}
851
869
871 SimpleLateralDebug *debug,
872 SimpleLateralPlusDebug *debug_info,
873 const canbus::Chassis *chassis) {
874 auto vehicle_state = injector_->vehicle_state();
875 if (FLAGS_use_navigation_mode) {
877 0.0,
878 0.0,
880 vehicle_state->linear_velocity(),
881 vehicle_state->angular_velocity(),
882 vehicle_state->linear_acceleration(),
884 chassis,
886 debug,
887 debug_info);
888 } else {
889 // Transform the coordinate of the vehicle states from the center of the
890 // rear-axis to the center of mass, if conditions matched
891 double com_length = 0.0;
892 if (is_lat_turbulence_) {
893 com_length = com_length_turbulence_;
898 if (com_length >= lr_ + current_lat_based_lqr_plus_controller_conf_.lat_err_position_add()) {
901 }
902 } else if (current_lat_based_lqr_plus_controller_conf_.is_need_turn_out_lane()) {
903 com_length = current_lat_based_lqr_plus_controller_conf_.turn_out_lane_com_length();
905 } else if (
906 !current_lat_based_lqr_plus_controller_conf_.is_need_turn_out_lane()
908 com_length = current_lat_based_lqr_plus_controller_conf_.turn_out_lane_com_length()
911 if (com_length >= lr_ + current_lat_based_lqr_plus_controller_conf_.lat_err_position_add()) {
914 }
915 } else {
916 com_length = lr_ + current_lat_based_lqr_plus_controller_conf_.lat_err_position_add();
917 if (current_lat_based_lqr_plus_controller_conf_.use_continous_errors_check()) {
918 com_length = lr_ + current_lat_based_lqr_plus_controller_conf_.lat_err_position_add() + com_change_add_;
919 } else {
920 com_length = lr_ + current_lat_based_lqr_plus_controller_conf_.lat_err_position_add() + com_change_add_;
922 }
923 }
924
925 com_length = common::math::Clamp(com_length, -2 * lr_, 2 * lr_);
926 debug_info->set_com_length(com_length);
927 const auto &com = vehicle_state->ComputeCOMPosition(com_length);
928 debug_info->mutable_lat_com_position()->set_x(com.x());
929 debug_info->mutable_lat_com_position()->set_y(com.y());
931 com.x(),
932 com.y(),
934 vehicle_state->linear_velocity(),
935 vehicle_state->angular_velocity(),
936 vehicle_state->linear_acceleration(),
938 chassis,
940 debug,
941 debug_info);
942 }
943 // State matrix update;
944 // First four elements are fixed;
947 matrix_state_(0, 0) = debug_info->lateral_error_feedback_new();
948 matrix_state_(2, 0) = debug_info->heading_error_feedback_new();
949 } else {
950 matrix_state_(0, 0) = debug->lateral_error_feedback();
951 matrix_state_(2, 0) = debug->heading_error_feedback();
952 }
953 } else {
954 matrix_state_(0, 0) = debug_info->lateral_error_lqr_input();
955 matrix_state_(2, 0) = debug_info->heading_error_lqr_input();
956 }
957 matrix_state_(1, 0) = debug->lateral_error_rate();
958 matrix_state_(3, 0) = debug->heading_error_rate();
959
960 // Next elements are depending on preview window size;
961 for (int i = 0; i < preview_window_; ++i) {
962 const double preview_time = ts_ * (i + 1);
963 const auto preview_point = trajectory_analyzer_.QueryNearestPointByRelativeTime(preview_time);
964
965 const auto matched_point = trajectory_analyzer_.QueryNearestPointByPosition(
966 preview_point.path_point().x(), preview_point.path_point().y());
967
968 const double dx = preview_point.path_point().x() - matched_point.path_point().x();
969 const double dy = preview_point.path_point().y() - matched_point.path_point().y();
970
971 const double cos_matched_theta = std::cos(matched_point.path_point().theta());
972 const double sin_matched_theta = std::sin(matched_point.path_point().theta());
973 const double preview_d_error = cos_matched_theta * dy - sin_matched_theta * dx;
974
975 matrix_state_(basic_state_size_ + i, 0) = preview_d_error;
976 }
977
978 const auto &track_com
979 = vehicle_state->ComputeCOMPosition(current_lat_based_lqr_plus_controller_conf_.track_com_length());
980 debug_info->mutable_lat_track_com_position()->set_x(track_com.x());
981 debug_info->mutable_lat_track_com_position()->set_y(track_com.y());
982
983 if (is_lat_turbulence_) {
985 track_com.x(),
986 track_com.y(),
988 vehicle_state->linear_velocity(),
990 control::ChooseRefTrajectoryPoint::USE_LAT_MATCH_LOCAL,
991 debug_info);
992 } else {
994 track_com.x(),
995 track_com.y(),
997 vehicle_state->linear_velocity(),
1000 debug_info);
1001 }
1002
1003 if (current_lat_based_lqr_plus_controller_conf_.use_continous_errors_check()
1006 debug_info->lateral_error_track_com(),
1007 current_lat_based_lqr_plus_controller_conf_.lat_continous_err_threshold(),
1009 &current_sign_)) {
1010 if (current_sign_ > 0) {
1011 ADEBUG << "Current vehicle is left of trajectory";
1012 // idenfy turn left
1013 if (chassis->steering_percentage()
1014 >= current_lat_based_lqr_plus_controller_conf_.straight_steering_percentage()) {
1015 // reduce the com if turn left
1016 com_change_ = -vehicle_state->linear_velocity() * ts_
1018 ADEBUG << "reduce the com: " << com_change_ << " in turn left";
1019 } else if (
1020 chassis->steering_percentage()
1021 <= -current_lat_based_lqr_plus_controller_conf_.straight_steering_percentage()) {
1022 // idenfy turn right
1023 // increase the com if turn right
1024 com_change_ = vehicle_state->linear_velocity() * ts_
1026 ADEBUG << "increase the com: " << com_change_ << " in turn right";
1027 } else {
1029 }
1030 ADEBUG << "Current com_length is " << debug_info->com_length();
1031 choose_ref_point_ = control::ChooseRefTrajectoryPoint::USE_LAT_MATCH_COM;
1032 } else if (current_sign_ < 0) {
1033 ADEBUG << "Current vehicle is right of trajectory";
1034 // idenfy turn left
1035 if (chassis->steering_percentage()
1036 >= current_lat_based_lqr_plus_controller_conf_.straight_steering_percentage()) {
1037 // increase the com if turn left
1038 com_change_ = vehicle_state->linear_velocity() * ts_
1040 ADEBUG << "increase the com: " << com_change_ << " in turn left";
1041 } else if (
1042 chassis->steering_percentage()
1043 <= -current_lat_based_lqr_plus_controller_conf_.straight_steering_percentage()) {
1044 // idenfy turn right
1045 // reduce the com if turn right
1046 com_change_ = -vehicle_state->linear_velocity() * ts_
1048 ADEBUG << "reduce the com: " << com_change_ << " in turn right";
1049 } else {
1051 }
1052 ADEBUG << "Current com_length is " << debug_info->com_length();
1053 choose_ref_point_ = control::ChooseRefTrajectoryPoint::USE_LAT_MATCH_COM;
1054 } else {
1055 com_change_ = 0;
1056 }
1060 -(lr_ + current_lat_based_lqr_plus_controller_conf_.lat_err_position_add()),
1061 (lr_ - current_lat_based_lqr_plus_controller_conf_.lat_err_position_add()));
1062 ADEBUG << "com_change_add_ is " << com_change_add_;
1063 ADEBUG << "com_change_ is " << com_change_;
1064 ADEBUG << "current_sign_ is " << current_sign_;
1065 } else {
1067 }
1068
1069 // check cuvature, lat_error, heading_error changing turbulence
1070 if (current_lat_based_lqr_plus_controller_conf_.use_turbulence_check()
1071 && (std::fabs(debug_info->lateral_error_lqr_input_change())
1072 > current_lat_based_lqr_plus_controller_conf_.lateral_error_turbulence_threshold()
1073 && std::fabs(debug_info->heading_error_lqr_input_change())
1074 > current_lat_based_lqr_plus_controller_conf_.heading_error_turbulence_threshold())) {
1075 AINFO << "Into turbulence condition";
1076 is_lat_turbulence_ = true;
1077 choose_ref_point_ = control::ChooseRefTrajectoryPoint::USE_LAT_ABSOLUTE_LOCAL;
1079 } else {
1080 ADEBUG << "Quit turbulence condition";
1081 is_lat_turbulence_ = false;
1082 }
1083
1084 // check quit turbulence and into long straight condition
1085
1086 for (size_t i = 0; i < lateral_lr_errors_.size(); i++) {
1087 debug_info->add_continous_lateral_errors(lateral_lr_errors_[i]);
1088 }
1089 debug_info->set_current_sign(current_sign_);
1090 debug_info->set_com_change(com_change_);
1091 debug_info->set_current_choose_point(choose_ref_point_);
1092}
1093
1095 auto vehicle_state = injector_->vehicle_state();
1096 if (com_change_add_ < -1e-3) {
1097 com_change_reset_ = vehicle_state->linear_velocity() * ts_
1099 } else if (com_change_add_ > 1e-3) {
1100 com_change_reset_ = -std::fabs(vehicle_state->linear_velocity()) * ts_
1102 } else {
1104 }
1106 ADEBUG << "com_change_add_ is " << com_change_add_;
1107 ADEBUG << "com_change_reset_ is " << com_change_reset_;
1108}
1109
1111 ADEBUG << "Into ResetComLengthFromTurbulence";
1112 auto vehicle_state = injector_->vehicle_state();
1113 com_turbulence_change_ = vehicle_state->linear_velocity() * ts_
1114 * current_lat_based_lqr_plus_controller_conf_.com_quit_turbulence_change_rate();
1118}
1119
1121 const uint8_t window_size,
1122 const double error,
1123 const double threshold,
1124 std::vector<double> *arr,
1125 int32_t *current_sign) {
1126 arr->push_back(error);
1127
1128 if (arr->size() < window_size) {
1129 AERROR << "Not enough elements in the array.";
1130 return false;
1131 }
1132
1133 if (arr->size() > window_size) {
1134 arr->erase(arr->begin(), arr->begin() + (arr->size() - window_size));
1135 }
1136
1137 int8_t currentIndex = arr->size() - 1;
1138 int32_t current_direction = 0;
1139 for (int i = currentIndex; i > currentIndex - window_size; --i) {
1140 current_direction = ((*arr)[i] >= threshold) ? 1 : ((*arr)[i] <= -threshold) ? -1 : 0;
1141 ADEBUG << "current_direction is " << current_direction << " with: " << (*arr)[i] << " " << i;
1142 double current_error_abs = std::fabs((*arr)[i]);
1143 // &&(prev_abs_ >= current_error_abs && current_lat_based_lqr_plus_controller_conf.use_monotonicity_check())
1144 if (prev_sign_ != 0 && current_direction != 0 && prev_sign_ != current_direction) {
1145 ADEBUG << "Elements at positions " << i << " and " << i - 1 << " do not satisfy the condition.";
1146 current_direction = 0;
1147 *current_sign = current_direction;
1148 ADEBUG << "current_sign is " << *current_sign;
1149 return false;
1150 }
1151 prev_sign_ = current_direction;
1152 prev_abs_ = current_error_abs;
1153 }
1154 *current_sign = current_direction;
1155 ADEBUG << "current_sign is " << *current_sign;
1156 return true;
1157}
1158
1160 double v = 0.01;
1161 // At reverse driving, replace the lateral translational motion dynamics with
1162 // the corresponding kinematic models
1163 if (!IsForwardModel() && !current_lat_based_lqr_plus_controller_conf_.reverse_use_dynamic_model()) {
1164 v = std::min(injector_->vehicle_state()->linear_velocity(), -minimum_speed_protection_);
1165 matrix_a_(0, 2) = matrix_a_coeff_(0, 2) * v;
1166 } else {
1167 v = std::max(injector_->vehicle_state()->linear_velocity(), minimum_speed_protection_);
1168 matrix_a_(0, 2) = 0.0;
1169 }
1170 matrix_a_(1, 1) = matrix_a_coeff_(1, 1) / v;
1171 matrix_a_(1, 3) = matrix_a_coeff_(1, 3) / v;
1172 matrix_a_(3, 1) = matrix_a_coeff_(3, 1) / v;
1173 matrix_a_(3, 3) = matrix_a_coeff_(3, 3) / v;
1174 Matrix matrix_i = Matrix::Identity(matrix_a_.cols(), matrix_a_.cols());
1175 matrix_ad_ = (matrix_i - ts_ * 0.5 * matrix_a_).inverse() * (matrix_i + ts_ * 0.5 * matrix_a_);
1176}
1177
1179 // Initialize preview matrix
1181 matrix_bdc_.block(0, 0, basic_state_size_, 1) = matrix_bd_;
1182 if (preview_window_ > 0) {
1183 matrix_bdc_(matrix_bdc_.rows() - 1, 0) = 1;
1184 // Update A matrix;
1185 for (int i = 0; i < preview_window_ - 1; ++i) {
1187 }
1188 }
1189}
1190
1191double LatPlusController::ComputeFeedForward(double ref_curvature) {
1192 const double kv = lr_ * mass_ / 2 / cf_ / wheelbase_ - lf_ * mass_ / 2 / cr_ / wheelbase_;
1193
1194 // Calculate the feedforward term of the lateral controller; then change it
1195 // from rad to %
1196 const double v = injector_->vehicle_state()->linear_velocity();
1197 double steer_angle_feedforwardterm = 0.0;
1198 if (!IsForwardModel() && !current_lat_based_lqr_plus_controller_conf_.reverse_use_dynamic_model()) {
1199 steer_angle_feedforwardterm = current_lat_based_lqr_plus_controller_conf_.reverse_feedforward_ratio()
1200 * wheelbase_ * ref_curvature * 180 / M_PI * steer_ratio_ / steer_single_direction_max_degree_ * 100;
1201 } else {
1202 steer_angle_feedforwardterm
1203 = (wheelbase_ * ref_curvature + kv * v * v * ref_curvature
1204 - matrix_k_(0, 2)
1205 * (lr_ * ref_curvature - lf_ * mass_ * v * v * ref_curvature / 2 / cr_ / wheelbase_))
1206 * 180 / M_PI * steer_ratio_ / steer_single_direction_max_degree_ * 100;
1207 }
1208
1209 return steer_angle_feedforwardterm;
1210}
1211
1213 const double x,
1214 const double y,
1215 const double theta,
1216 const double linear_v,
1217 const TrajectoryAnalyzerExtend &trajectory_analyzer,
1218 const enum ChooseRefTrajectoryPoint &choose_point,
1219 SimpleLateralPlusDebug *lat_debug) {
1220 double lateral_error = 0.0;
1221 double heading_error = 0.0;
1222 double curvature = 0.0;
1223 PathPoint matched_track_point_com;
1224 switch (choose_point) {
1225 case control::ChooseRefTrajectoryPoint::USE_LAT_MATCH_LR: {
1226 matched_track_point_com.set_x(lat_debug->target_point_lr().path_point().x());
1227 matched_track_point_com.set_y(lat_debug->target_point_lr().path_point().y());
1228 lateral_error = lat_debug->lateral_error_target_lr();
1229 heading_error = lat_debug->heading_error_target_lr();
1230 break;
1231 }
1232 case control::ChooseRefTrajectoryPoint::USE_LAT_MATCH_LOCAL: {
1233 matched_track_point_com.set_x(lat_debug->matched_point_local().path_point().x());
1234 matched_track_point_com.set_y(lat_debug->matched_point_local().path_point().y());
1235 lateral_error = lat_debug->lateral_error_match_local();
1236 heading_error = lat_debug->heading_error_match_local();
1237 break;
1238 }
1239 case control::ChooseRefTrajectoryPoint::USE_LAT_ABSOLUTE_LOCAL: {
1240 matched_track_point_com.set_x(lat_debug->absolute_point_local().path_point().x());
1241 matched_track_point_com.set_y(lat_debug->absolute_point_local().path_point().y());
1242 lateral_error = lat_debug->lateral_error_absolute_local();
1243 heading_error = lat_debug->heading_error_absolute_local();
1244 break;
1245 }
1246 case control::ChooseRefTrajectoryPoint::USE_LAT_TRACK_COM: {
1247 // match_track_com
1248 matched_track_point_com = trajectory_analyzer.QueryMatchedPathPoint(x, y);
1249 double s_track_com, s_dot_track_com, d_track_com, d_dot_track_com;
1250 trajectory_analyzer.ToTrajectoryFrame(
1251 x,
1252 y,
1253 theta,
1254 linear_v,
1255 matched_track_point_com,
1256 &s_track_com,
1257 &s_dot_track_com,
1258 &d_track_com,
1259 &d_dot_track_com);
1260
1261 lateral_error = d_track_com;
1262 heading_error = common::math::NormalizeAngle(theta - matched_track_point_com.theta());
1263 break;
1264 }
1265 default: {
1266 // match_track_com
1267 matched_track_point_com = trajectory_analyzer.QueryMatchedPathPoint(x, y);
1268 double s_track_com, s_dot_track_com, d_track_com, d_dot_track_com;
1269 trajectory_analyzer.ToTrajectoryFrame(
1270 x,
1271 y,
1272 theta,
1273 linear_v,
1274 matched_track_point_com,
1275 &s_track_com,
1276 &s_dot_track_com,
1277 &d_track_com,
1278 &d_dot_track_com);
1279
1280 lateral_error = d_track_com;
1281 heading_error = common::math::NormalizeAngle(theta - matched_track_point_com.theta());
1282 break;
1283 }
1284 }
1285 lat_debug->mutable_track_point_com()->mutable_path_point()->set_x(matched_track_point_com.x());
1286 lat_debug->mutable_track_point_com()->mutable_path_point()->set_y(matched_track_point_com.y());
1287 lat_debug->set_lateral_error_track_com(lateral_error);
1288 lat_debug->set_heading_error_track_com(heading_error);
1289}
1290
1292 const double x,
1293 const double y,
1294 const double theta,
1295 const double linear_v,
1296 const double angular_v,
1297 const double linear_a,
1298 const TrajectoryAnalyzerExtend &trajectory_analyzer,
1299 const canbus::Chassis *chassis,
1300 const enum ChooseRefTrajectoryPoint &choose_point,
1301 SimpleLateralDebug *debug,
1302 SimpleLateralPlusDebug *lat_debug) {
1303 TrajectoryPoint target_point;
1304
1305 if (current_lat_based_lqr_plus_controller_conf_.query_time_nearest_point_only()) {
1306 target_point
1308 } else {
1309 if (FLAGS_use_navigation_mode
1310 && !current_lat_based_lqr_plus_controller_conf_.enable_navigation_mode_position_update()) {
1311 target_point
1313 } else {
1314 target_point = trajectory_analyzer.QueryNearestPointByPosition(x, y);
1315 }
1316 }
1317 ADEBUG << "x point: " << x << " y point: " << y;
1318 ADEBUG << "match trajectory point information : " << target_point.ShortDebugString();
1319
1320 auto vehicle_state = injector_->vehicle_state();
1321
1322 // target_lr
1323 const auto &com_lr = vehicle_state->ComputeCOMPosition(lr_);
1324 lat_debug->set_lr(lr_);
1325 lat_debug->mutable_lat_lr_position()->set_x(com_lr.x());
1326 lat_debug->mutable_lat_lr_position()->set_y(com_lr.y());
1327 auto target_point_lr = trajectory_analyzer.QueryNearestPointByPosition(com_lr.x(), com_lr.y());
1328 lat_debug->mutable_target_point_lr()->mutable_path_point()->set_x(target_point_lr.path_point().x());
1329 lat_debug->mutable_target_point_lr()->mutable_path_point()->set_y(target_point_lr.path_point().y());
1330 double s_target_lr, s_dot_target_lr, d_target_lr, d_dot_target_lr;
1331 trajectory_analyzer.ToTrajectoryFrame(
1332 com_lr.x(),
1333 com_lr.y(),
1334 vehicle_state->heading(),
1335 linear_v,
1336 target_point.path_point(),
1337 &s_target_lr,
1338 &s_dot_target_lr,
1339 &d_target_lr,
1340 &d_dot_target_lr);
1341 debug->set_ref_heading(target_point_lr.path_point().theta());
1342 lat_debug->set_curvature_target_lr(target_point_lr.path_point().kappa());
1343 lat_debug->set_lateral_error_target_lr(d_target_lr);
1344 lat_debug->set_heading_error_target_lr(common::math::NormalizeAngle(theta - target_point_lr.path_point().theta()));
1345
1346 // target_com
1347 target_point = trajectory_analyzer.QueryNearestPointByPosition(x, y);
1348 debug->mutable_current_target_point()->mutable_path_point()->set_x(target_point.path_point().x());
1349 debug->mutable_current_target_point()->mutable_path_point()->set_y(target_point.path_point().y());
1350 double s_target_com, s_dot_target_com, d_target_com, d_dot_target_com;
1351 trajectory_analyzer.ToTrajectoryFrame(
1352 x,
1353 y,
1354 vehicle_state->heading(),
1355 linear_v,
1356 target_point.path_point(),
1357 &s_target_com,
1358 &s_dot_target_com,
1359 &d_target_com,
1360 &d_dot_target_com);
1361 debug->set_ref_heading(target_point.path_point().theta());
1362 lat_debug->set_curvature_target_com(target_point.path_point().kappa());
1363 lat_debug->set_lateral_error_target_com(d_target_com);
1364 lat_debug->set_heading_error_target_com(common::math::NormalizeAngle(theta - target_point.path_point().theta()));
1365
1366 // match_com
1367 auto matched_point_com = trajectory_analyzer.QueryMatchedPathPoint(x, y);
1368 lat_debug->mutable_matched_point_com()->mutable_path_point()->set_x(matched_point_com.x());
1369 lat_debug->mutable_matched_point_com()->mutable_path_point()->set_y(matched_point_com.y());
1370 double s_match_com, s_dot_match_com, d_match_com, d_dot_match_com;
1371 trajectory_analyzer.ToTrajectoryFrame(
1372 x, y, theta, linear_v, matched_point_com, &s_match_com, &s_dot_match_com, &d_match_com, &d_dot_match_com);
1373 debug->set_ref_heading(matched_point_com.theta());
1374 lat_debug->set_curvature_match_com(matched_point_com.kappa());
1375 lat_debug->set_lateral_error_match_com(d_match_com);
1376 lat_debug->set_heading_error_match_com(common::math::NormalizeAngle(theta - matched_point_com.theta()));
1377
1378 // match_local
1379 auto matched_point_local = trajectory_analyzer.QueryMatchedPathPoint(vehicle_state->x(), vehicle_state->y());
1380 lat_debug->mutable_matched_point_local()->mutable_path_point()->set_x(matched_point_local.x());
1381 lat_debug->mutable_matched_point_local()->mutable_path_point()->set_y(matched_point_local.y());
1382 double s_match_local, s_dot_match_local, d_match_local, d_dot_match_local;
1383 trajectory_analyzer.ToTrajectoryFrame(
1384 vehicle_state->x(),
1385 vehicle_state->y(),
1386 theta,
1387 linear_v,
1388 matched_point_local,
1389 &s_match_local,
1390 &s_dot_match_local,
1391 &d_match_local,
1392 &d_dot_match_local);
1393 debug->set_ref_heading(matched_point_local.theta());
1394 lat_debug->set_curvature_match_local(matched_point_local.kappa());
1395 lat_debug->set_lateral_error_match_local(d_match_local);
1396 lat_debug->set_heading_error_match_local(common::math::NormalizeAngle(theta - matched_point_local.theta()));
1397
1398 // absolute_local
1399 double current_absolute_time = FLAGS_sim_by_record
1402 auto absolute_point_local = trajectory_analyzer.QueryNearestPointByAbsoluteTime(current_absolute_time);
1403 lat_debug->mutable_absolute_point_local()->mutable_path_point()->set_x(absolute_point_local.path_point().x());
1404 lat_debug->mutable_absolute_point_local()->mutable_path_point()->set_y(absolute_point_local.path_point().y());
1405 double s_absolute_local, s_dot_absolute_local, d_absolute_local, d_dot_absolute_local;
1406 trajectory_analyzer.ToTrajectoryFrame(
1407 vehicle_state->x(),
1408 vehicle_state->y(),
1409 theta,
1410 linear_v,
1411 absolute_point_local.path_point(),
1412 &s_absolute_local,
1413 &s_dot_absolute_local,
1414 &d_absolute_local,
1415 &d_dot_absolute_local);
1416 debug->set_ref_heading(absolute_point_local.path_point().theta());
1417 lat_debug->set_curvature_absolute_local(absolute_point_local.path_point().kappa());
1418 lat_debug->set_lateral_error_absolute_local(d_absolute_local);
1419 lat_debug->set_heading_error_absolute_local(
1420 common::math::NormalizeAngle(theta - absolute_point_local.path_point().theta()));
1421
1422 double lateral_error = 0.0;
1423 double heading_error = 0.0;
1424 double curvature = 0.0;
1425
1426 switch (choose_point) {
1427 case control::ChooseRefTrajectoryPoint::USE_LAT_TARGET_COM: {
1428 lateral_error = lat_debug->lateral_error_target_com();
1429 heading_error = lat_debug->heading_error_target_com();
1430 curvature = lat_debug->curvature_target_com();
1431 break;
1432 }
1433 case control::ChooseRefTrajectoryPoint::USE_LAT_MATCH_COM: {
1434 lateral_error = lat_debug->lateral_error_match_com();
1435 heading_error = lat_debug->heading_error_match_com();
1436 curvature = lat_debug->curvature_match_com();
1437 break;
1438 }
1439 case control::ChooseRefTrajectoryPoint::USE_LAT_MATCH_LOCAL: {
1440 lateral_error = lat_debug->lateral_error_match_local();
1441 heading_error = lat_debug->heading_error_match_local();
1442 curvature = lat_debug->curvature_match_local();
1443 break;
1444 }
1445 case control::ChooseRefTrajectoryPoint::USE_LAT_ABSOLUTE_LOCAL: {
1446 lateral_error = lat_debug->lateral_error_absolute_local();
1447 heading_error = lat_debug->heading_error_absolute_local();
1448 curvature = lat_debug->curvature_absolute_local();
1449 break;
1450 }
1451 default: {
1452 const double dx = com_lr.x() - target_point.path_point().x();
1453 const double dy = com_lr.y() - target_point.path_point().y();
1454 const double cos_target_heading = std::cos(target_point.path_point().theta());
1455 const double sin_target_heading = std::sin(target_point.path_point().theta());
1456
1457 double lateral_error = cos_target_heading * dy - sin_target_heading * dx;
1458 if (current_lat_based_lqr_plus_controller_conf_.enable_navigation_mode_error_filter()) {
1459 lateral_error = lateral_error_filter_.Update(lateral_error);
1460 }
1461 debug->set_ref_heading(target_point.path_point().theta());
1462 heading_error = common::math::NormalizeAngle(theta - debug->ref_heading());
1463 curvature = target_point.path_point().kappa();
1464 break;
1465 }
1466 }
1467
1468 // Set curvature
1469 debug->set_curvature(curvature);
1470 lat_debug->set_curvature_change(debug->curvature() - ref_curvature_last_);
1471 ref_curvature_last_ = debug->curvature();
1472
1473 // Set lateral error and heading error origin
1474 if (std::fabs(lat_debug->lateral_error_match_com()) <= std::fabs(lat_debug->lateral_error_match_local())) {
1475 debug->set_lateral_error(lat_debug->lateral_error_match_com());
1476 lat_debug->set_current_min_error_point(control::ChooseRefTrajectoryPoint::USE_LAT_MATCH_COM);
1477 } else {
1478 debug->set_lateral_error(lat_debug->lateral_error_match_local());
1479 lat_debug->set_current_min_error_point(control::ChooseRefTrajectoryPoint::USE_LAT_MATCH_LOCAL);
1480 }
1481 if (std::fabs(lat_debug->heading_error_match_com()) <= std::fabs(lat_debug->heading_error_match_local())) {
1482 debug->set_heading_error(lat_debug->heading_error_match_com());
1483 } else {
1484 debug->set_heading_error(lat_debug->heading_error_match_local());
1485 }
1486
1487 // Set the lateral error lqr input
1488 lat_debug->set_lateral_error_lqr_input(lateral_error);
1489 lat_debug->set_lateral_error_lqr_input_change(
1492
1493 // set heading error
1494 lat_debug->set_heading_error_by_ref(heading_error);
1495 if (current_lat_based_lqr_plus_controller_conf_.enable_navigation_mode_error_filter()) {
1496 heading_error = heading_error_filter_.Update(heading_error);
1497 }
1498 // the car may have inherent steer error, the method below can handle this
1499 // error
1500 if (current_lat_based_lqr_plus_controller_conf_.use_heading_auto_compensation()) {
1501 double compensation_output_value = CalculateTempAHCValue(linear_v);
1502 heading_error -= compensation_output_value;
1503 lat_debug->set_heading_error_by_auto_compensation(heading_error);
1504 injector_->mutable_control_debug_info()
1505 ->mutable_simple_lat_debug()
1506 ->mutable_ahc_value()
1507 ->set_compensation_output_value(compensation_output_value);
1508 if (IsDrivingStraight(chassis, target_point_lr.path_point().kappa())) {
1509 UpdateAHCParam(heading_error, injector_->vehicle_state()->linear_velocity());
1510 } else {
1511 AHCClear();
1512 }
1513 }
1514 // Set the heading error lqr input
1515 lat_debug->set_heading_error_lqr_input(heading_error);
1516 lat_debug->set_heading_error_lqr_input_change(
1519
1520 // Within the low-high speed transition window, linerly interplolate the
1521 // lookahead/lookback station for "soft" prediction window switch
1522 double lookahead_station = 0.0;
1523 double lookback_station = 0.0;
1524 if (std::fabs(linear_v) >= low_speed_bound_) {
1525 lookahead_station = lookahead_station_high_speed_;
1526 lookback_station = lookback_station_high_speed_;
1527 } else if (std::fabs(linear_v) < low_speed_bound_ - low_speed_window_) {
1528 lookahead_station = lookahead_station_low_speed_;
1529 lookback_station = lookback_station_low_speed_;
1530 } else {
1531 lookahead_station = common::math::lerp(
1536 std::fabs(linear_v));
1537 lookback_station = common::math::lerp(
1542 std::fabs(linear_v));
1543 }
1544 lat_debug->set_lookahead_station(lookahead_station);
1545 lat_debug->set_lookback_station(lookback_station);
1546
1547 // update lookforward point error
1548 switch (choose_point) {
1549 case control::ChooseRefTrajectoryPoint::USE_LAT_TARGET_COM: {
1551 lookahead_station,
1552 lookback_station,
1553 x,
1554 y,
1555 theta,
1556 linear_v,
1557 target_point,
1558 trajectory_analyzer,
1559 debug,
1560 lat_debug);
1561 break;
1562 }
1563 case control::ChooseRefTrajectoryPoint::USE_LAT_MATCH_COM: {
1565 lookahead_station,
1566 lookback_station,
1567 x,
1568 y,
1569 theta,
1570 linear_v,
1571 target_point,
1572 trajectory_analyzer,
1573 debug,
1574 lat_debug);
1575 break;
1576 }
1577 case control::ChooseRefTrajectoryPoint::USE_LAT_MATCH_LOCAL: {
1579 lookahead_station,
1580 lookback_station,
1581 vehicle_state->x(),
1582 vehicle_state->y(),
1583 theta,
1584 linear_v,
1585 absolute_point_local,
1586 trajectory_analyzer,
1587 debug,
1588 lat_debug);
1589 break;
1590 }
1591 case control::ChooseRefTrajectoryPoint::USE_LAT_ABSOLUTE_LOCAL: {
1593 lookahead_station,
1594 lookback_station,
1595 vehicle_state->x(),
1596 vehicle_state->y(),
1597 theta,
1598 linear_v,
1599 absolute_point_local,
1600 trajectory_analyzer,
1601 debug,
1602 lat_debug);
1603 break;
1604 }
1605 default: {
1607 lookahead_station,
1608 lookback_station,
1609 com_lr.x(),
1610 com_lr.y(),
1611 theta,
1612 linear_v,
1613 target_point_lr,
1614 trajectory_analyzer,
1615 debug,
1616 lat_debug);
1617 break;
1618 }
1619 }
1620
1621 LateralSafetyCheck(debug, lat_debug);
1622
1623 auto lateral_error_dot = linear_v * std::sin(heading_error);
1624 auto lateral_error_dot_dot = linear_a * std::sin(heading_error);
1625 if (FLAGS_reverse_heading_control) {
1626 if (!IsForwardModel()) {
1627 lateral_error_dot = -lateral_error_dot;
1628 lateral_error_dot_dot = -lateral_error_dot_dot;
1629 }
1630 }
1631 auto centripetal_acceleration = linear_v * linear_v / wheelbase_
1632 * std::tan(chassis->steering_percentage() / 100 * vehicle_param_.max_steer_angle() / steer_ratio_);
1633 debug->set_lateral_error_rate(lateral_error_dot);
1634 debug->set_lateral_acceleration(lateral_error_dot_dot);
1635 debug->set_lateral_centripetal_acceleration(centripetal_acceleration);
1636 debug->set_lateral_jerk((debug->lateral_acceleration() - previous_lateral_acceleration_) / ts_);
1638
1639 if (!IsForwardModel()) {
1640 debug->set_heading_rate(-angular_v);
1641 } else {
1642 debug->set_heading_rate(angular_v);
1643 }
1644 debug->set_ref_heading_rate(target_point.path_point().kappa() * target_point.v());
1645 debug->set_heading_error_rate(debug->heading_rate() - debug->ref_heading_rate());
1646
1647 debug->set_heading_acceleration((debug->heading_rate() - previous_heading_rate_) / ts_);
1648 debug->set_ref_heading_acceleration((debug->ref_heading_rate() - previous_ref_heading_rate_) / ts_);
1649 debug->set_heading_error_acceleration(debug->heading_acceleration() - debug->ref_heading_acceleration());
1652
1653 debug->set_heading_jerk((debug->heading_acceleration() - previous_heading_acceleration_) / ts_);
1654 debug->set_ref_heading_jerk((debug->ref_heading_acceleration() - previous_ref_heading_acceleration_) / ts_);
1655 debug->set_heading_error_jerk(debug->heading_jerk() - debug->ref_heading_jerk());
1658}
1659
1661 const double lookahead_station,
1662 const double lookback_station,
1663 const double pose_x,
1664 const double pose_y,
1665 const double theta,
1666 const double linear_v,
1667 const common::TrajectoryPoint &ref_point,
1668 const TrajectoryAnalyzerExtend &trajectory_analyzer,
1669 SimpleLateralDebug *debug,
1670 SimpleLateralPlusDebug *debug_info) {
1671 auto lookahead_point_new = trajectory_analyzer.QueryNearestPointByRelativeStation(ref_point, lookahead_station);
1672 debug_info->mutable_lookahead_point_new()->CopyFrom(lookahead_point_new);
1673
1674 auto lookback_point_new = trajectory_analyzer.QueryNearestPointByRelativeStation(ref_point, -lookback_station);
1675 debug_info->mutable_lookback_point_new()->CopyFrom(lookback_point_new);
1676
1677 auto lookahead_point = trajectory_analyzer.QueryNearestPointByRelativeTime(
1678 ref_point.relative_time()
1679 + lookahead_station / (std::max(std::fabs(linear_v), 0.1) * std::cos(debug->heading())));
1680
1681 debug_info->set_lookahead_time(ref_point.relative_time());
1682 debug_info->set_lookahead_station_s_diff(lookahead_station);
1683
1684 // Estimate the heading error with look-ahead/look-back windows as feedback
1685 // signal for special driving scenarios
1686 // Calculate heading error feedback
1687 double heading_error_feedback = 0.0;
1688 double heading_error_feedback_new = 0.0;
1689 double lookahead_time_new = 0.0;
1690 double lookahead_station_s_diff_new = 0.0;
1691 double lookback_time_new = 0.0;
1692 double lookback_station_s_diff_new = 0.0;
1693
1694 if (!IsForwardModel()) {
1695 heading_error_feedback = debug_info->heading_error_lqr_input();
1696 heading_error_feedback_new = common::math::NormalizeAngle(theta - lookback_point_new.path_point().theta());
1697 lookback_time_new = lookahead_point_new.relative_time() - ref_point.relative_time();
1698 lookback_station_s_diff_new = lookahead_point_new.path_point().s() - ref_point.path_point().s();
1699 } else {
1700 heading_error_feedback = common::math::NormalizeAngle(
1701 debug_info->heading_error_lqr_input() + ref_point.path_point().theta()
1702 - lookahead_point.path_point().theta());
1703 heading_error_feedback_new = common::math::NormalizeAngle(theta - lookahead_point_new.path_point().theta());
1704 lookahead_time_new = lookahead_point_new.relative_time() - ref_point.relative_time();
1705 lookahead_station_s_diff_new = lookahead_point_new.path_point().s() - ref_point.path_point().s();
1706 }
1707 debug_info->set_lookahead_time_new(lookahead_time_new);
1708 debug_info->set_lookahead_station_s_diff_new(lookahead_station_s_diff_new);
1709 debug_info->set_lookback_time_new(lookback_time_new);
1710 debug_info->set_lookback_station_s_diff_new(lookback_station_s_diff_new);
1711
1712 debug_info->set_lookahead_curvature(lookahead_point.path_point().kappa());
1713 debug_info->set_lookahead_curvature_new(lookahead_point_new.path_point().kappa());
1714 debug_info->set_lookback_curvature_new(lookback_point_new.path_point().kappa());
1715
1716 debug->set_heading_error_feedback(heading_error_feedback);
1717 debug_info->set_heading_error_feedback_new(heading_error_feedback_new);
1718
1719 // Estimate the lateral error with look-ahead/look-back windows as feedback
1720 // signal for special driving scenarios
1721 // Calculate lateral error feedback
1722 double lateral_error_feedback = 0.0;
1723 double lateral_error_feedback_new = 0.0;
1724 if (!IsForwardModel()) {
1725 lateral_error_feedback = debug_info->lateral_error_lqr_input() - lookback_station * std::sin(debug->heading());
1726 const double dx = pose_x - lookback_point_new.path_point().x();
1727 const double dy = pose_y - lookback_point_new.path_point().y();
1728 const double cos_target_heading = std::cos(lookback_point_new.path_point().theta());
1729 const double sin_target_heading = std::sin(lookback_point_new.path_point().theta());
1730 lateral_error_feedback_new = cos_target_heading * dy - sin_target_heading * dx;
1731 } else {
1732 lateral_error_feedback = debug_info->lateral_error_lqr_input() + lookahead_station * std::sin(debug->heading());
1733 const double dx = pose_x - lookahead_point_new.path_point().x();
1734 const double dy = pose_y - lookahead_point_new.path_point().y();
1735 const double cos_target_heading = std::cos(lookahead_point_new.path_point().theta());
1736 const double sin_target_heading = std::sin(lookahead_point_new.path_point().theta());
1737 lateral_error_feedback_new = cos_target_heading * dy - sin_target_heading * dx;
1738 }
1739 debug->set_lateral_error_feedback(lateral_error_feedback);
1740 debug_info->set_lateral_error_feedback_new(lateral_error_feedback_new);
1741
1742 ADEBUG << "lateral_error_feedback: " << lateral_error_feedback
1743 << ", lateral_error_feedback_new: " << lateral_error_feedback_new;
1744}
1745
1747 auto vehicle_state = injector_->vehicle_state();
1748 driving_orientation_ = vehicle_state->heading();
1750 // Reverse the driving direction if the vehicle is in reverse mode
1751 if (FLAGS_reverse_heading_control) {
1752 if (!IsForwardModel()) {
1754 // Update Matrix_b for reverse mode
1756 ADEBUG << "Matrix_b changed due to gear direction";
1757 }
1758 }
1759}
1760
1761bool LatPlusController::IsDrivingStraight(const canbus::Chassis *chassis, const double ref_curvature) {
1762 // steer < 1.0, v > 0.5, curvature < 0.01
1763 if (fabs(chassis->steering_percentage())
1764 < current_lat_based_lqr_plus_controller_conf_.straight_steering_percentage()
1765 && fabs(injector_->vehicle_state()->linear_velocity())
1766 > current_lat_based_lqr_plus_controller_conf_.straight_min_velocity()
1767 && fabs(ref_curvature) < current_lat_based_lqr_plus_controller_conf_.straight_max_ref_cur()) {
1768 return true;
1769 } else {
1770 return false;
1771 }
1772}
1773
1774void LatPlusController::UpdateAHCParam(const double &heading_err, const double &speed) {
1776 AHC_container_.clear();
1777 AHC_sum_ = 0.0;
1781 current_lat_based_lqr_plus_controller_conf_.ahc_mean_value_low_threshold(),
1782 current_lat_based_lqr_plus_controller_conf_.ahc_mean_value_high_threshold());
1783 return;
1784 }
1785
1786 if (AHC_container_.size() < current_lat_based_lqr_plus_controller_conf_.ahc_container_size()) {
1787 AHC_container_.push_back(heading_err);
1788 AHC_sum_ += heading_err;
1789 }
1790
1791 AHC_sum_ += heading_err - AHC_container_.front();
1793 AHC_peak_ = *std::max_element(AHC_container_.begin(), AHC_container_.end())
1794 - *std::min_element(AHC_container_.begin(), AHC_container_.end());
1795 AHC_container_.pop_front();
1796 AHC_container_.push_back(heading_err);
1797
1798 if (std::fabs(AHC_mean_) > std::fabs(current_lat_based_lqr_plus_controller_conf_.ahc_mean_value_low_threshold())
1799 && std::fabs(AHC_mean_) < std::fabs(current_lat_based_lqr_plus_controller_conf_.ahc_mean_value_high_threshold())
1800 && std::fabs(AHC_peak_) < std::fabs(current_lat_based_lqr_plus_controller_conf_.ahc_peak_value_threshold())) {
1801 AHC_is_compensating_ = true;
1803 }
1804
1805 // set debug info
1806 injector_->mutable_control_debug_info()->mutable_simple_lat_debug()->mutable_ahc_value()->set_ahc_sum(AHC_sum_);
1807 injector_->mutable_control_debug_info()->mutable_simple_lat_debug()->mutable_ahc_value()->set_ahc_mean(AHC_mean_);
1808 injector_->mutable_control_debug_info()->mutable_simple_lat_debug()->mutable_ahc_value()->set_ahc_peak(AHC_peak_);
1809 injector_->mutable_control_debug_info()
1810 ->mutable_simple_lat_debug()
1811 ->mutable_ahc_value()
1812 ->set_ahc_compensating_value(AHC_compensating_value_);
1813 injector_->mutable_control_debug_info()->mutable_simple_lat_debug()->mutable_ahc_value()->set_ahc_compensated_value(
1815 injector_->mutable_control_debug_info()->mutable_simple_lat_debug()->mutable_ahc_value()->set_ahc_is_compensating(
1817}
1818
1819double LatPlusController::CalculateTempAHCValue(const double &speed) {
1821 double change_limit = current_lat_based_lqr_plus_controller_conf_.ts()
1823 speed,
1826 diff = common::math::Clamp(diff, -change_limit, change_limit);
1827 double output_value = AHC_prev_output_value_ + diff;
1828 AHC_prev_output_value_ = output_value;
1829 return output_value;
1830}
1831
1833 if (AHC_mean_ > 0) {
1836 speed,
1839 } else {
1842 speed,
1845 }
1846
1847 // when finish compensating process, update compensated_value
1848 if (std::fabs(AHC_compensating_value_) > std::fabs(AHC_mean_)) {
1849 AHC_is_compensating_ = false;
1852 }
1853
1855}
1856
1858 AHC_container_.clear();
1859 AHC_sum_ = 0.0;
1860 AHC_peak_ = 0.0;
1861 AHC_mean_ = 0.0;
1862}
1863
1865 const double lateral_error,
1866 const double heading_error,
1867 const planning::ADCTrajectory *planning_published_trajectory,
1868 const SimpleLongitudinalDebug *previous_lon_debug,
1869 SimpleLateralDebug *debug,
1870 SimpleLateralPlusDebug *debug_info) {
1871 if (injector_->vehicle_state()->gear() == canbus::Chassis::GEAR_REVERSE) {
1872 ADEBUG << "[AL new reverse]" << "count_ = " << reverse_handle_count_;
1873 ADEBUG << "[AL new reverse]" << "heading err = " << debug_info->heading_error_lqr_input();
1874 ADEBUG << "[AL new reverse]" << "lat err = " << debug_info->lateral_error_lqr_input();
1875 if (now_reverse_stage_ == ReverseLogicStage::NO_REVERSE) {
1876 ADEBUG << "[AL new reverse]" << "first in reverse";
1877 now_reverse_stage_ = ReverseLogicStage::FIRST_HEADING_HANDLE_STAGE;
1878 } else if (now_reverse_stage_ == ReverseLogicStage::FIRST_HEADING_HANDLE_STAGE) {
1880 ADEBUG << "[AL new reverse]" << "in 000000000000 stage damagely change heading ";
1881 // quit satuation
1882 if (reverse_handle_count_ >= current_lat_based_lqr_plus_controller_conf_.first_handle_heading_window()
1883 || debug_info->heading_error_lqr_input()
1884 < current_lat_based_lqr_plus_controller_conf_.heading_err_threshold()) {
1885 ADEBUG << "[AL new reverse]" << "quit 00000000000 stage==============";
1886 now_reverse_stage_ = ReverseLogicStage::QUIT_FIRST_HEADING_HANDLE_STAGE;
1888 efai_rate_ = 1.0;
1889 ed_date_ = 1.0;
1890 } else {
1891 efai_rate_ = current_lat_based_lqr_plus_controller_conf_.first_handle_heading_stage_prarm();
1892 ed_date_ = 1.0;
1893 }
1894
1895 } else if (now_reverse_stage_ == ReverseLogicStage::QUIT_FIRST_HEADING_HANDLE_STAGE) {
1896 ADEBUG << "[AL new reverse]" << "in 1111111111111 clear stage";
1899 >= current_lat_based_lqr_plus_controller_conf_.out_first_handle_heading_window()) {
1900 ADEBUG << "[AL new reverse]" << "quit 111111111 stage==============";
1901 now_reverse_stage_ = ReverseLogicStage::HANDLE_LAT_ERR_STAGE;
1903 efai_rate_ = 1.0;
1904 ed_date_ = 1.0;
1905 }
1906
1907 } else if (now_reverse_stage_ == ReverseLogicStage::HANDLE_LAT_ERR_STAGE) {
1908 ADEBUG << "[AL new reverse]" << "in 222222222 lat err stage";
1911 || (std::fabs(debug_info->lateral_error_lqr_input())
1912 < current_lat_based_lqr_plus_controller_conf_.lat_err_threshold())
1913 || (std::fabs(debug->curvature())
1914 < current_lat_based_lqr_plus_controller_conf_.openspace_enhance_curv())
1915 || (std::fabs(previous_lon_debug->path_remain())
1916 < current_lat_based_lqr_plus_controller_conf_.reverse_final_heading_check_path())) {
1917 ADEBUG << "[AL new reverse]" << "quit 222222222 stage==============";
1918 now_reverse_stage_ = ReverseLogicStage::HANDLE_HEADING_ERR_STAGE;
1920 efai_rate_ = 1.0;
1921 ed_date_ = 1.0;
1922 } else if (
1923 (pre_steer_angle_ <= (-1) * current_lat_based_lqr_plus_controller_conf_.reverse_dead_steer_left())
1924 && (debug_info->heading_error_lqr_input()
1925 > current_lat_based_lqr_plus_controller_conf_.reverse_too_big_heading_err())
1926 && (debug_info->lateral_error_lqr_input()
1927 > current_lat_based_lqr_plus_controller_conf_.reverse_too_big_lat_err())) {
1928 // right behind steer
1929 AINFO << "[STEERDEAD quit ,right behind ]" << "quit lat stage=======";
1930 now_reverse_stage_ = ReverseLogicStage::HANDLE_HEADING_ERR_STAGE;
1932 efai_rate_ = 1.0;
1933 ed_date_ = 1.0;
1934 } else if (
1936 && (debug_info->heading_error_lqr_input()
1937 < (-1) * current_lat_based_lqr_plus_controller_conf_.reverse_too_big_heading_err())
1938 && (debug_info->lateral_error_lqr_input()
1939 < (-1) * current_lat_based_lqr_plus_controller_conf_.reverse_too_big_lat_err())) {
1940 // left behind steer
1941 AINFO << "[STEERDEAD quit ,left behind ]" << "quit lat stage=======";
1942 now_reverse_stage_ = ReverseLogicStage::HANDLE_HEADING_ERR_STAGE;
1944 efai_rate_ = 1.0;
1945 ed_date_ = 1.0;
1946 } else {
1947 efai_rate_ = current_lat_based_lqr_plus_controller_conf_.handle_lat_err_prarm_ignore();
1948 ed_date_ = current_lat_based_lqr_plus_controller_conf_.handle_lat_err_prarm_domain();
1949 }
1950
1951 } else if (now_reverse_stage_ == ReverseLogicStage::HANDLE_HEADING_ERR_STAGE) {
1952 ADEBUG << "[AL new reverse]" << "in 33333333333 heading err stage";
1955 || std::fabs(debug_info->heading_error_lqr_input())
1956 < current_lat_based_lqr_plus_controller_conf_.heading_err_threshold()
1957 || std::fabs(debug->curvature())
1958 < current_lat_based_lqr_plus_controller_conf_.openspace_enhance_curv()) {
1959 ADEBUG << "[AL new reverse]" << "quit 333333333 stage==============";
1960 now_reverse_stage_ = ReverseLogicStage::HANDLE_LAT_ERR_STAGE;
1962 efai_rate_ = 1.0;
1963 ed_date_ = 1.0;
1964 } else {
1965 efai_rate_ = current_lat_based_lqr_plus_controller_conf_.handle_heading_err_parm_domain();
1966 ed_date_ = current_lat_based_lqr_plus_controller_conf_.handle_heading_err_parm_ignore();
1967 }
1968 } else {
1969 ADEBUG << "[AL new reverse]" << "wrong!!!!! don't change any param";
1970 }
1971 }
1972 if (injector_->vehicle_state()->gear() != canbus::Chassis::GEAR_REVERSE) {
1973 if (now_reverse_stage_ != ReverseLogicStage::NO_REVERSE) {
1974 ADEBUG << "[AL new reverse]" << "quit reverse ,clear all marks";
1975 now_reverse_stage_ = ReverseLogicStage::NO_REVERSE;
1977 efai_rate_ = 1.0;
1978 ed_date_ = 1.0;
1979 }
1980 }
1981
1982 if ((injector_->vehicle_state()->gear() == canbus::Chassis::GEAR_REVERSE)
1983 && (std::fabs(previous_lon_debug->path_remain())
1984 < current_lat_based_lqr_plus_controller_conf_.reverse_final_heading_check_path())
1985 && (std::fabs(debug_info->heading_error_lqr_input())
1986 > current_lat_based_lqr_plus_controller_conf_.reverse_final_heading_check_heading())
1987 && (planning_published_trajectory->trajectory_type() == ADCTrajectory::OPEN_SPACE)) {
1988 ADEBUG << "[FINALCHECK]final check in reverse park";
1989 efai_rate_ = current_lat_based_lqr_plus_controller_conf_.handle_heading_err_parm_domain();
1990 ed_date_ = current_lat_based_lqr_plus_controller_conf_.handle_heading_err_parm_ignore();
1991 }
1992
1993 debug_info->set_now_reverse_stage(now_reverse_stage_);
1994}
1995
1997 u_int32_t max_uint32 = std::numeric_limits<uint32_t>::max();
1998 auto check_conf = current_lat_based_lqr_plus_controller_conf_.lat_safety_check_conf();
1999 auto lat_check_debug = debug_info->mutable_lat_control_check_debug();
2000 // lateral error check
2001 double lateral_error
2003 ControlCheckStatus lateral_error_failed = ControlChecker::check_lateral_error(check_conf, &lateral_error);
2004 if (lateral_error_failed == WARNING) {
2007 lat_check_debug->set_lateral_error_w(lateral_error);
2008 } else {
2009 lat_check_debug->set_lateral_error_w(0.0);
2010 }
2011
2012 if (lateral_error_failed == ERROR) {
2015 lat_check_debug->set_lateral_error_e(lateral_error);
2016 } else {
2017 lat_check_debug->set_lateral_error_e(0.0);
2018 }
2019 lat_check_debug->set_lateral_error_check_result(lateral_error_failed);
2020 lat_check_debug->set_lateral_error_check_e_count(lateral_error_e_count_);
2021 lat_check_debug->set_lateral_error_check_w_count(lateral_error_w_count_);
2022
2023 if (current_lat_based_lqr_plus_controller_conf_.use_safety_check_output()) {
2025 debug->set_lateral_error_feedback(lateral_error);
2026 } else {
2027 debug_info->set_lateral_error_lqr_input(lateral_error);
2028 }
2029 }
2030}
2031
2036
2037} // namespace control
2038} // namespace apollo
void set_coefficients(const std::vector< double > &denominators, const std::vector< double > &numerators)
set denominators and numerators
double Filter(const double x_insert)
Processes a new measurement with the filter.
The MeanFilter class is used to smoothen a series of noisy numbers, such as sensor data or the output...
Definition mean_filter.h:45
double Update(const double measurement)
Processes a new measurement in amortized constant time.
A general class to denote the return status of an API call.
Definition status.h:43
static Status OK()
generate a success status.
Definition status.h:60
static ControlCheckStatus check_lateral_error(const SafetyCheckConf &conf, double *lateral_error)
bool IsLargeCurvature(const double ref_curvature, const double min_large_ref_curvature, bool *is_in_large_curvature)
bool VehicleStatusIdentificationUpdate(const localization::LocalizationEstimate *localization, const canbus::Chassis *chassis, const planning::ADCTrajectory *trajectory)
bool IsLeftCurvature(const double ref_curvature)
static double interpolation_1d(const double &value, const google::protobuf::RepeatedField< double > &input_vector, const google::protobuf::RepeatedField< double > &output_vector)
void LateralSafetyCheck(SimpleLateralDebug *debug, SimpleLateralPlusDebug *debug_info)
LatBaseLqrPlusControllerConf current_lat_based_lqr_plus_controller_conf_
void UpdateState(SimpleLateralDebug *debug, SimpleLateralPlusDebug *debug_info, const canbus::Chassis *chassis)
void UpdateLookForwardPointError(const double lookahead_station, const double lookback_station, const double pose_x, const double pose_y, const double theta, const double linear_v, const common::TrajectoryPoint &ref_point, const TrajectoryAnalyzerExtend &trajectory_analyzer, SimpleLateralDebug *debug, SimpleLateralPlusDebug *debug_info)
bool InitControlConf(const LatBaseLqrPlusControllerConf &current_lat_based_lqr_plus_controller_conf)
void ComputeTrackLateralErrors(const double x, const double y, const double theta, const double linear_v, const TrajectoryAnalyzerExtend &trajectory_analyzer, const enum ChooseRefTrajectoryPoint &choose_track_point, SimpleLateralPlusDebug *lat_debug)
std::vector< std::pair< std::string, LatBaseLqrPlusControllerConf > > params_list_
double CalculateTempAHCValue(const double &speed)
ReverseLogicStage::ReverseStageType now_reverse_stage_
bool LoadParams(ParamsPipeline *params_pipeline)
void EnhanceQParamsAlternate(const double lateral_error, const double heading_error, const planning::ADCTrajectory *planning_published_trajectory, const SimpleLongitudinalDebug *previous_lon_debug, SimpleLateralDebug *debug, SimpleLateralPlusDebug *debug_info)
TrajectoryAnalyzerExtend trajectory_analyzer_
void ProcessLogs(const SimpleLateralDebug *debug, const canbus::Chassis *chassis)
double ComputeFeedForward(double ref_curvature)
bool ChooseCurrentParam(LatBaseLqrPlusControllerConf &current_lat_based_lqr_plus_controller_conf, const planning::ADCTrajectory *planning_published_trajectory)
common::Status Init(std::shared_ptr< DependencyInjector > injector) override
initialize Lateral Controller
double AutoCompensatedHeadingValue(const double &speed)
bool SetCurrentParam(const std::string param_config_name, LatBaseLqrPlusControllerConf &current_lat_based_lqr_plus_controller_conf)
bool IsDrivingStraight(const canbus::Chassis *chassis, double ref_curvature)
void UpdateAHCParam(const double &heading_err, const double &speed)
std::shared_ptr< DependencyInjector > injector_
bool UpdateControlConf(const LatBaseLqrPlusControllerConf &current_lat_based_lqr_plus_controller_conf)
bool CheckContinousErrors(const uint8_t window_size, const double error, const double threshold, std::vector< double > *arr, int32_t *current_sign)
void Stop() override
stop Lateral controller
enum ChooseRefTrajectoryPoint choose_ref_point_
std::string Name() const override
Lateral controller name
void ComputeLateralErrors(const double x, const double y, const double theta, const double linear_v, const double angular_v, const double linear_a, const TrajectoryAnalyzerExtend &trajectory_analyzer, const canbus::Chassis *chassis, const enum ChooseRefTrajectoryPoint &choose_point, SimpleLateralDebug *debug, SimpleLateralPlusDebug *lat_debug)
common::Status Reset() override
reset Lateral Controller
LatBaseLqrPlusControllerConf lat_based_lqr_plus_controller_conf_
common::Status ComputeControlCommand(const localization::LocalizationEstimate *localization, const canbus::Chassis *chassis, const planning::ADCTrajectory *trajectory, ControlCommand *cmd) override
compute steering target based on current vehicle status and target trajectory
virtual double Control(const double error, const double dt)
compute control value based on the error
void SetLeadlagConf(const LeadlagConf &leadlag_conf)
alpha, beta and tau
void InitLeadlag()
initialize lead/lag controller
void SetInputAdaptionRate(const double ratio_input)
set convergence ratio for input components in adaptive dynamics
Eigen::MatrixXd CurrentInputAdaptionGain() const
get current input adaptive gain for mrac control
virtual double Control(const double command, const Eigen::MatrixXd state, const double input_limit, const double input_rate_limit)
compute control value based on the original command
void Init(const MracConf &mrac_conf, const common::LatencyParam &latency_param, const double dt)
initialize mrac controller
int ReferenceSaturationStatus() const
get saturation status for reference system
void Reset()
reset all the variables (including all the states, gains and externally-setting control parameters) f...
int ControlSaturationStatus() const
get saturation status for control system
void SetStateAdaptionRate(const double ratio_state)
set convergence ratio for state components in adaptive dynamics
Eigen::MatrixXd CurrentReferenceState() const
get current state for reference system
Eigen::MatrixXd CurrentStateAdaptionGain() const
get current state adaptive gain for mrac control
process point query and conversion related to trajectory
common::TrajectoryPoint QueryNearestPointByRelativeStation(const common::TrajectoryPoint &ref_point, const double &relative_station) const
query a point of trajectory that its s distance for reference trajectory point is closest to the give...
common::TrajectoryPoint QueryNearestPointByPosition(const double x, const double y) const
query a point of trajectory that its position is closest to the given position.
void TrajectoryTransformToCOM(const double rear_to_com_distance)
Transform the current trajectory points to the center of mass(COM) of the vehicle,...
common::PathPoint QueryMatchedPathPoint(const double x, const double y) const
query a point on trajectory that its position is closest to the given position.
common::TrajectoryPoint QueryNearestPointByAbsoluteTime(const double t) const
query a point of trajectory that its absolute time is closest to the give time.
void ToTrajectoryFrame(const double x, const double y, const double theta, const double v, const common::PathPoint &matched_point, double *ptr_s, double *ptr_s_dot, double *ptr_d, double *ptr_d_dot) const
convert a position with theta and speed to trajectory frame,
common::TrajectoryPoint QueryNearestPointByRelativeTime(const double t) const
query a point of trajectory that its relative time is closest to the give time.
a singleton clock that can be used to get the current timestamp.
Definition clock.h:39
static double NowInSeconds()
gets the current time in second.
Definition clock.cc:56
std::string GetPluginConfPath(const std::string &class_name, const std::string &conf_name)
get plugin configuration file location
static PluginManager * Instance()
get singleton instance of PluginManager
Math-related util functions.
Defines the LatPlusController class.
Linear interpolation functions.
Solver for discrete-time linear quadratic problem.
#define ADEBUG
Definition log.h:41
#define AERROR
Definition log.h:44
#define AINFO
Definition log.h:42
T lerp(const T &x0, const double t0, const T &x1, const double t1, const double t)
Linear interpolation between two points of type T.
void SolveLQRProblem(const Matrix &A, const Matrix &B, const Matrix &Q, const Matrix &R, const Matrix &M, const double tolerance, const uint max_num_iteration, Matrix *ptr_K, uint *iterate_num, double *result_diff)
T Clamp(const T value, T bound1, T bound2)
Clamp a value between two bounds.
Definition math_utils.h:155
double QuaternionToHeading(const double qw, const double qx, const double qy, const double qz)
Definition quaternion.h:56
double NormalizeAngle(const double angle)
Normalize angle to [-PI, PI).
Definition math_utils.cc:53
void LpfCoefficients(const double ts, const double cutoff_freq, std::vector< double > *denominators, std::vector< double > *numerators)
Get low-pass coefficients for digital filter.
bool GetProtoFromFile(const std::string &file_name, google::protobuf::Message *message)
Parses the content of the file specified by the file_name as a representation of protobufs,...
Definition file.cc:132
class register implement
Definition arena_queue.h:37
Contains a number of helper functions related to quaternions.
optional apollo::common::Header header
optional DrivingMode driving_mode
optional float steering_percentage
Definition chassis.proto:88
optional double timestamp_sec
Definition header.proto:9
optional LatencyParam steering_latency_param
optional double steer_angle_lateral_rate_contribution
optional double steer_angle_heading_rate_contribution
optional apollo::common::TrajectoryPoint absolute_point_local
optional apollo::common::TrajectoryPoint target_point_lr
optional apollo::common::TrajectoryPoint matched_point_local
optional apollo::localization::Pose pose
optional apollo::common::Quaternion orientation
Definition pose.proto:31
optional double heading
Definition pose.proto:48
optional apollo::common::PointENU position
Definition pose.proto:26
optional TrajectoryType trajectory_type
optional apollo::common::Header header
optional apollo::planning_internal::Debug debug