Apollo 10.0
自动驾驶开放平台
on_lane_planning.cc
浏览该文件的文档.
1/******************************************************************************
2 * Copyright 2018 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 <limits>
21#include <list>
22#include <utility>
23
24#include "gtest/gtest_prod.h"
25
26#include "absl/strings/str_cat.h"
27
28#include "modules/common_msgs/planning_msgs/planning_internal.pb.h"
29#include "modules/common_msgs/routing_msgs/routing.pb.h"
30#include "modules/planning/planning_base/proto/planning_semantic_map_config.pb.h"
31
32#include "cyber/common/file.h"
33#include "cyber/common/log.h"
34#include "cyber/time/clock.h"
48
49namespace apollo {
50namespace planning {
65void SetChartminmax(apollo::dreamview::Chart* chart, std::string label_name_x,
66 std::string label_name_y) {
67 auto* options = chart->mutable_options();
68 double xmin(std::numeric_limits<double>::max()),
69 xmax(std::numeric_limits<double>::lowest()),
70 ymin(std::numeric_limits<double>::max()),
71 ymax(std::numeric_limits<double>::lowest());
72 for (int i = 0; i < chart->line_size(); i++) {
73 auto* line = chart->mutable_line(i);
74 for (auto& pt : line->point()) {
75 xmin = std::min(xmin, pt.x());
76 ymin = std::min(ymin, pt.y());
77 xmax = std::max(xmax, pt.x());
78 ymax = std::max(ymax, pt.y());
79 }
80 auto* properties = line->mutable_properties();
81 (*properties)["borderWidth"] = "2";
82 (*properties)["pointRadius"] = "0";
83 (*properties)["lineTension"] = "0";
84 (*properties)["fill"] = "false";
85 (*properties)["showLine"] = "true";
86 }
87 options->mutable_x()->set_min(xmin);
88 options->mutable_x()->set_max(xmax);
89 options->mutable_x()->set_label_string(label_name_x);
90 options->mutable_y()->set_min(ymin);
91 options->mutable_y()->set_max(ymax);
92 options->mutable_y()->set_label_string(label_name_y);
93 // Set chartJS's dataset properties
94}
96 if (reference_line_provider_) {
97 reference_line_provider_->Stop();
98 }
99 planner_->Stop();
100 injector_->frame_history()->Clear();
101 injector_->history()->Clear();
102 injector_->planning_context()->mutable_planning_status()->Clear();
103 last_command_.Clear();
104 injector_->ego_info()->Clear();
105}
106
107std::string OnLanePlanning::Name() const { return "on_lane_planning"; }
108
110 if (!CheckPlanningConfig(config)) {
111 return Status(ErrorCode::PLANNING_ERROR,
112 "planning config error: " + config.DebugString());
113 }
114
115 PlanningBase::Init(config);
116
117 // clear planning history
118 injector_->history()->Clear();
119
120 // clear planning status
121 injector_->planning_context()->mutable_planning_status()->Clear();
122
123 // load map
125 ACHECK(hdmap_) << "Failed to load map";
126
127 // instantiate reference line provider
128 const ReferenceLineConfig* reference_line_config = nullptr;
129 if (config_.has_reference_line_config()) {
130 reference_line_config = &config_.reference_line_config();
131 }
132 reference_line_provider_ = std::make_unique<ReferenceLineProvider>(
133 injector_->vehicle_state(), reference_line_config);
134 reference_line_provider_->Start();
135
136 // dispatch planner
137 LoadPlanner();
138 if (!planner_) {
139 return Status(
140 ErrorCode::PLANNING_ERROR,
141 "planning is not initialized with config : " + config_.DebugString());
142 }
143
145 PlanningSemanticMapConfig renderer_config;
147 FLAGS_planning_birdview_img_feature_renderer_config_file,
148 &renderer_config))
149 << "Failed to load renderer config"
150 << FLAGS_planning_birdview_img_feature_renderer_config_file;
151
152 BirdviewImgFeatureRenderer::Instance()->Init(renderer_config);
153 }
154
156
158 return planner_->Init(injector_, FLAGS_planner_config_path);
159}
160
161Status OnLanePlanning::InitFrame(const uint32_t sequence_num,
162 const TrajectoryPoint& planning_start_point,
163 const VehicleState& vehicle_state) {
164 frame_.reset(new Frame(sequence_num, local_view_, planning_start_point,
165 vehicle_state, reference_line_provider_.get()));
166
167 if (frame_ == nullptr) {
168 return Status(ErrorCode::PLANNING_ERROR, "Fail to init frame: nullptr.");
169 }
170
171 std::list<ReferenceLine> reference_lines;
172 std::list<hdmap::RouteSegments> segments;
173 reference_line_provider_->GetReferenceLines(&reference_lines, &segments);
174 DCHECK_EQ(reference_lines.size(), segments.size());
175
177 vehicle_state.linear_velocity());
178
179 for (auto& ref_line : reference_lines) {
180 ref_line.SetEgoPosition(Vec2d(vehicle_state.x(), vehicle_state.y()));
181 if (!ref_line.Segment(Vec2d(vehicle_state.x(), vehicle_state.y()),
182 planning::FLAGS_look_backward_distance,
183 forward_limit)) {
184 const std::string msg = "Fail to shrink reference line.";
185 AERROR << msg;
186 return Status(ErrorCode::PLANNING_ERROR, msg);
187 }
188 }
189 for (auto& seg : segments) {
190 if (!seg.Shrink(Vec2d(vehicle_state.x(), vehicle_state.y()),
191 planning::FLAGS_look_backward_distance, forward_limit)) {
192 const std::string msg = "Fail to shrink routing segments.";
193 AERROR << msg;
194 return Status(ErrorCode::PLANNING_ERROR, msg);
195 }
196 }
197
198 auto status = frame_->Init(
199 injector_->vehicle_state(), reference_lines, segments,
200 reference_line_provider_->FutureRouteWaypoints(), injector_->ego_info());
201 if (!status.ok()) {
202 AERROR << "failed to init frame:" << status.ToString();
203 return status;
204 }
205 return Status::OK();
206}
207
208// TODO(all): fix this! this will cause unexpected behavior from controller
209void OnLanePlanning::GenerateStopTrajectory(ADCTrajectory* ptr_trajectory_pb) {
210 ptr_trajectory_pb->clear_trajectory_point();
211
212 const auto& vehicle_state = injector_->vehicle_state()->vehicle_state();
213 const double max_t = FLAGS_fallback_total_time;
214 const double unit_t = FLAGS_fallback_time_unit;
215
216 TrajectoryPoint tp;
217 auto* path_point = tp.mutable_path_point();
218 path_point->set_x(vehicle_state.x());
219 path_point->set_y(vehicle_state.y());
220 path_point->set_theta(vehicle_state.heading());
221 path_point->set_s(0.0);
222 tp.set_v(0.0);
223 tp.set_a(0.0);
224 for (double t = 0.0; t < max_t; t += unit_t) {
225 tp.set_relative_time(t);
226 auto next_point = ptr_trajectory_pb->add_trajectory_point();
227 next_point->CopyFrom(tp);
228 }
229}
230
232 ADCTrajectory* const ptr_trajectory_pb) {
233 // when rerouting, reference line might not be updated. In this case, planning
234 // module maintains not-ready until be restarted.
236 const double start_timestamp = Clock::NowInSeconds();
237 const double start_system_timestamp =
238 std::chrono::duration<double>(
239 std::chrono::system_clock::now().time_since_epoch())
240 .count();
241
242 // localization
243 ADEBUG << "Get localization:"
244 << local_view_.localization_estimate->DebugString();
245
246 // chassis
247 ADEBUG << "Get chassis:" << local_view_.chassis->DebugString();
248
249 Status status = injector_->vehicle_state()->Update(
251
252 VehicleState vehicle_state = injector_->vehicle_state()->vehicle_state();
253 const double vehicle_state_timestamp = vehicle_state.timestamp();
254 DCHECK_GE(start_timestamp, vehicle_state_timestamp)
255 << "start_timestamp is behind vehicle_state_timestamp by "
256 << start_timestamp - vehicle_state_timestamp << " secs";
257
258 if (!status.ok() || !util::IsVehicleStateValid(vehicle_state)) {
259 const std::string msg =
260 "Update VehicleStateProvider failed "
261 "or the vehicle state is out dated.";
262 AERROR << msg;
263 ptr_trajectory_pb->mutable_decision()
264 ->mutable_main_decision()
265 ->mutable_not_ready()
266 ->set_reason(msg);
267 status.Save(ptr_trajectory_pb->mutable_header()->mutable_status());
268 // TODO(all): integrate reverse gear
269 ptr_trajectory_pb->set_gear(canbus::Chassis::GEAR_DRIVE);
270 FillPlanningPb(start_timestamp, ptr_trajectory_pb);
271 GenerateStopTrajectory(ptr_trajectory_pb);
272 return;
273 }
274
275 if (start_timestamp + 1e-6 < vehicle_state_timestamp) {
276 common::monitor::MonitorLogBuffer monitor_logger_buffer(
278 monitor_logger_buffer.ERROR("ego system time is behind GPS time");
279 }
280
281 if (start_timestamp - vehicle_state_timestamp <
282 FLAGS_message_latency_threshold) {
283 vehicle_state = AlignTimeStamp(vehicle_state, start_timestamp);
284 }
285
286 // Update reference line provider and reset scenario if new routing
287 reference_line_provider_->UpdateVehicleState(vehicle_state);
288 if (local_view_.planning_command->is_motion_command() &&
290 last_command_ = *local_view_.planning_command;
291 // AINFO << "new_command:" << last_command_.DebugString();
292 reference_line_provider_->Reset();
293 injector_->history()->Clear();
294 injector_->planning_context()->mutable_planning_status()->Clear();
295 reference_line_provider_->UpdatePlanningCommand(
297 planner_->Reset(frame_.get());
298 }
299 // Get end lane way point.
300 reference_line_provider_->GetEndLaneWayPoint(local_view_.end_lane_way_point);
301
302 // planning is triggered by prediction data, but we can still use an estimated
303 // cycle time for stitching
304 const double planning_cycle_time =
305 1.0 / static_cast<double>(FLAGS_planning_loop_rate);
306
307 std::string replan_reason;
308 std::vector<TrajectoryPoint> stitching_trajectory =
310 *(local_view_.chassis), vehicle_state, start_timestamp,
311 planning_cycle_time, FLAGS_trajectory_stitching_preserved_length,
312 true, last_publishable_trajectory_.get(), &replan_reason,
314
315 injector_->ego_info()->Update(stitching_trajectory.back(), vehicle_state);
316 const uint32_t frame_num = static_cast<uint32_t>(seq_num_++);
317 AINFO << "Planning start frame sequence id = [" << frame_num << "]";
318 status = InitFrame(frame_num, stitching_trajectory.back(), vehicle_state);
319 if (status.ok()) {
320 injector_->ego_info()->CalculateFrontObstacleClearDistance(
321 frame_->obstacles());
322 injector_->ego_info()->CalculateCurrentRouteInfo(
323 reference_line_provider_.get());
324 }
325
326 if (FLAGS_enable_record_debug) {
327 frame_->RecordInputDebug(ptr_trajectory_pb->mutable_debug());
328 }
329 ptr_trajectory_pb->mutable_latency_stats()->set_init_frame_time_ms(
330 Clock::NowInSeconds() - start_timestamp);
331
332 if (!status.ok()) {
333 AERROR << status.ToString();
334 if (FLAGS_publish_estop) {
335 // "estop" signal check in function "Control::ProduceControlCommand()"
336 // estop_ = estop_ || local_view_.trajectory.estop().is_estop();
337 // we should add more information to ensure the estop being triggered.
338 ADCTrajectory estop_trajectory;
339 EStop* estop = estop_trajectory.mutable_estop();
340 estop->set_is_estop(true);
341 estop->set_reason(status.error_message());
342 status.Save(estop_trajectory.mutable_header()->mutable_status());
343 ptr_trajectory_pb->CopyFrom(estop_trajectory);
344 } else {
345 ptr_trajectory_pb->mutable_decision()
346 ->mutable_main_decision()
347 ->mutable_not_ready()
348 ->set_reason(status.ToString());
349 status.Save(ptr_trajectory_pb->mutable_header()->mutable_status());
350 GenerateStopTrajectory(ptr_trajectory_pb);
351 }
352 // TODO(all): integrate reverse gear
353 ptr_trajectory_pb->set_gear(canbus::Chassis::GEAR_DRIVE);
354 FillPlanningPb(start_timestamp, ptr_trajectory_pb);
355 frame_->set_current_frame_planned_trajectory(*ptr_trajectory_pb);
356 const uint32_t n = frame_->SequenceNum();
357 injector_->frame_history()->Add(n, std::move(frame_));
358 return;
359 }
360
361 for (auto& ref_line_info : *frame_->mutable_reference_line_info()) {
362 auto traffic_status =
363 traffic_decider_.Execute(frame_.get(), &ref_line_info);
364 if (!traffic_status.ok() || !ref_line_info.IsDrivable()) {
365 ref_line_info.SetDrivable(false);
366 AWARN << "Reference line " << ref_line_info.Lanes().Id()
367 << " traffic decider failed";
368 }
369 }
370
371 status = Plan(start_timestamp, stitching_trajectory, ptr_trajectory_pb);
372
373 // print trajxy
374 PrintCurves trajectory_print_curve;
375 for (const auto& p : ptr_trajectory_pb->trajectory_point()) {
376 trajectory_print_curve.AddPoint("trajxy", p.path_point().x(),
377 p.path_point().y());
378 }
379 trajectory_print_curve.PrintToLog();
380
381 // print obstacle polygon
382 for (const auto& obstacle : frame_->obstacles()) {
383 obstacle->PrintPolygonCurve();
384 }
385 // print ego box
386 PrintBox print_box("ego_box");
387 print_box.AddAdcBox(vehicle_state.x(), vehicle_state.y(),
388 vehicle_state.heading(), true);
389 print_box.PrintToLog();
390
391 const auto end_system_timestamp =
392 std::chrono::duration<double>(
393 std::chrono::system_clock::now().time_since_epoch())
394 .count();
395 const auto time_diff_ms =
396 (end_system_timestamp - start_system_timestamp) * 1000;
397 ADEBUG << "total planning time spend: " << time_diff_ms << " ms.";
398
399 ptr_trajectory_pb->mutable_latency_stats()->set_total_time_ms(time_diff_ms);
400 ADEBUG << "Planning latency: "
401 << ptr_trajectory_pb->latency_stats().DebugString();
402
403 if (!status.ok()) {
404 status.Save(ptr_trajectory_pb->mutable_header()->mutable_status());
405 AERROR << "Planning failed:" << status.ToString();
406 if (FLAGS_publish_estop) {
407 AERROR << "Planning failed and set estop";
408 // "estop" signal check in function "Control::ProduceControlCommand()"
409 // estop_ = estop_ || local_view_.trajectory.estop().is_estop();
410 // we should add more information to ensure the estop being triggered.
411 EStop* estop = ptr_trajectory_pb->mutable_estop();
412 estop->set_is_estop(true);
413 estop->set_reason(status.error_message());
414 }
415 }
416
417 ptr_trajectory_pb->set_is_replan(stitching_trajectory.size() == 1);
418 if (ptr_trajectory_pb->is_replan()) {
419 ptr_trajectory_pb->set_replan_reason(replan_reason);
420 }
421
422 if (frame_->open_space_info().is_on_open_space_trajectory()) {
423 FillPlanningPb(start_timestamp, ptr_trajectory_pb);
424 ADEBUG << "Planning pb:" << ptr_trajectory_pb->header().DebugString();
425 frame_->set_current_frame_planned_trajectory(*ptr_trajectory_pb);
426 } else {
427 auto* ref_line_task =
428 ptr_trajectory_pb->mutable_latency_stats()->add_task_stats();
429 ref_line_task->set_time_ms(reference_line_provider_->LastTimeDelay() *
430 1000.0);
431 ref_line_task->set_name("ReferenceLineProvider");
432
433 FillPlanningPb(start_timestamp, ptr_trajectory_pb);
434 ADEBUG << "Planning pb:" << ptr_trajectory_pb->header().DebugString();
435
436 frame_->set_current_frame_planned_trajectory(*ptr_trajectory_pb);
437 if (FLAGS_enable_planning_smoother) {
438 planning_smoother_.Smooth(injector_->frame_history(), frame_.get(),
439 ptr_trajectory_pb);
440 }
441 }
442
443 const auto end_planning_perf_timestamp =
444 std::chrono::duration<double>(
445 std::chrono::system_clock::now().time_since_epoch())
446 .count();
447 const auto plnning_perf_ms =
448 (end_planning_perf_timestamp - start_system_timestamp) * 1000;
449 AINFO << "Planning Perf: planning name [" << Name() << "], "
450 << plnning_perf_ms << " ms.";
451 AINFO << "Planning end frame sequence id = [" << frame_num << "]";
452 injector_->frame_history()->Add(frame_num, std::move(frame_));
453}
454
455void OnLanePlanning::ExportReferenceLineDebug(planning_internal::Debug* debug) {
456 if (!FLAGS_enable_record_debug) {
457 return;
458 }
459 for (auto& reference_line_info : *frame_->mutable_reference_line_info()) {
460 auto rl_debug = debug->mutable_planning_data()->add_reference_line();
461 rl_debug->set_id(reference_line_info.Lanes().Id());
462 rl_debug->set_length(reference_line_info.reference_line().Length());
463 rl_debug->set_cost(reference_line_info.Cost());
464 rl_debug->set_is_change_lane_path(reference_line_info.IsChangeLanePath());
465 rl_debug->set_is_drivable(reference_line_info.IsDrivable());
466 rl_debug->set_is_protected(reference_line_info.GetRightOfWayStatus() ==
468
469 // store kappa and dkappa for performance evaluation
470 const auto& reference_points =
471 reference_line_info.reference_line().reference_points();
472 double kappa_rms = 0.0;
473 double dkappa_rms = 0.0;
474 double kappa_max_abs = std::numeric_limits<double>::lowest();
475 double dkappa_max_abs = std::numeric_limits<double>::lowest();
476 for (const auto& reference_point : reference_points) {
477 double kappa_sq = reference_point.kappa() * reference_point.kappa();
478 double dkappa_sq = reference_point.dkappa() * reference_point.dkappa();
479 kappa_rms += kappa_sq;
480 dkappa_rms += dkappa_sq;
481 kappa_max_abs = kappa_max_abs < kappa_sq ? kappa_sq : kappa_max_abs;
482 dkappa_max_abs = dkappa_max_abs < dkappa_sq ? dkappa_sq : dkappa_max_abs;
483 }
484 double reference_points_size = static_cast<double>(reference_points.size());
485 kappa_rms /= reference_points_size;
486 dkappa_rms /= reference_points_size;
487 kappa_rms = std::sqrt(kappa_rms);
488 dkappa_rms = std::sqrt(dkappa_rms);
489 rl_debug->set_kappa_rms(kappa_rms);
490 rl_debug->set_dkappa_rms(dkappa_rms);
491 rl_debug->set_kappa_max_abs(kappa_max_abs);
492 rl_debug->set_dkappa_max_abs(dkappa_max_abs);
493
494 bool is_off_road = false;
495 double minimum_boundary = std::numeric_limits<double>::infinity();
496
497 const double adc_half_width =
499 const auto& reference_line_path =
500 reference_line_info.reference_line().GetMapPath();
501 const auto sample_s = 0.1;
502 const auto reference_line_length =
503 reference_line_info.reference_line().Length();
504 double average_offset = 0.0;
505 double sample_count = 0.0;
506 for (double s = 0.0; s < reference_line_length; s += sample_s) {
507 double left_width = reference_line_path.GetLaneLeftWidth(s);
508 double right_width = reference_line_path.GetLaneRightWidth(s);
509 average_offset += 0.5 * std::abs(left_width - right_width);
510 if (left_width < adc_half_width || right_width < adc_half_width) {
511 is_off_road = true;
512 }
513 if (left_width < minimum_boundary) {
514 minimum_boundary = left_width;
515 }
516 if (right_width < minimum_boundary) {
517 minimum_boundary = right_width;
518 }
519 ++sample_count;
520 }
521 rl_debug->set_is_offroad(is_off_road);
522 rl_debug->set_minimum_boundary(minimum_boundary);
523 rl_debug->set_average_offset(average_offset / sample_count);
524 }
525}
526
528 const double current_time_stamp,
529 const std::vector<TrajectoryPoint>& stitching_trajectory,
530 ADCTrajectory* const ptr_trajectory_pb) {
531 auto* ptr_debug = ptr_trajectory_pb->mutable_debug();
532 if (FLAGS_enable_record_debug) {
533 ptr_debug->mutable_planning_data()->mutable_init_point()->CopyFrom(
534 stitching_trajectory.back());
535 frame_->mutable_open_space_info()->set_debug(ptr_debug);
536 frame_->mutable_open_space_info()->sync_debug_instance();
537 }
538
539 auto status = planner_->Plan(stitching_trajectory.back(), frame_.get(),
540 ptr_trajectory_pb);
541
542 ptr_debug->mutable_planning_data()->set_front_clear_distance(
543 injector_->ego_info()->front_clear_distance());
544
545 if (frame_->open_space_info().is_on_open_space_trajectory()) {
546 frame_->mutable_open_space_info()->sync_debug_instance();
547 const auto& publishable_trajectory =
548 frame_->open_space_info().publishable_trajectory_data().first;
549 const auto& publishable_trajectory_gear =
550 frame_->open_space_info().publishable_trajectory_data().second;
551 const auto& trajectory_type = frame_->open_space_info().trajectory_type();
552 const auto& is_collision = frame_->open_space_info().is_collision();
553 publishable_trajectory.PopulateTrajectoryProtobuf(ptr_trajectory_pb);
554 ptr_trajectory_pb->set_gear(publishable_trajectory_gear);
555 ptr_trajectory_pb->set_trajectory_type(trajectory_type);
556 ptr_trajectory_pb->set_is_collision(is_collision);
557 // TODO(QiL): refine engage advice in open space trajectory optimizer.
558 auto* engage_advice = ptr_trajectory_pb->mutable_engage_advice();
559
560 // enable start auto from open_space planner.
561 if (injector_->vehicle_state()->vehicle_state().driving_mode() !=
562 Chassis::DrivingMode::Chassis_DrivingMode_COMPLETE_AUTO_DRIVE) {
563 engage_advice->set_advice(EngageAdvice::READY_TO_ENGAGE);
564 engage_advice->set_reason(
565 "Ready to engage when staring with OPEN_SPACE_PLANNER");
566 } else {
567 engage_advice->set_advice(EngageAdvice::KEEP_ENGAGED);
568 engage_advice->set_reason("Keep engage while in parking");
569 }
570 // TODO(QiL): refine the export decision in open space info
571 ptr_trajectory_pb->mutable_decision()
572 ->mutable_main_decision()
573 ->mutable_parking()
574 ->set_status(MainParking::IN_PARKING);
575
576 if (FLAGS_enable_record_debug) {
577 // ptr_debug->MergeFrom(frame_->open_space_info().debug_instance());
578 frame_->mutable_open_space_info()->RecordDebug(ptr_debug);
579 ADEBUG << "Open space debug information added!";
580 // call open space info load debug
581 // TODO(Runxin): create a new flag to enable openspace chart
582 ExportOpenSpaceChart(ptr_trajectory_pb->debug(), *ptr_trajectory_pb,
583 ptr_debug);
584 }
585 } else {
586 const auto* best_ref_info = frame_->FindDriveReferenceLineInfo();
587 const auto* target_ref_info = frame_->FindTargetReferenceLineInfo();
588 if (!best_ref_info) {
589 const std::string msg = "planner failed to make a driving plan";
590 AERROR << msg;
593 }
594 return Status(ErrorCode::PLANNING_ERROR, msg);
595 }
596 // Store current frame stitched path for possible speed fallback in next
597 // frames
598 DiscretizedPath current_frame_planned_path;
599 for (const auto& trajectory_point : stitching_trajectory) {
600 current_frame_planned_path.push_back(trajectory_point.path_point());
601 }
602 const auto& best_ref_path = best_ref_info->path_data().discretized_path();
603 std::copy(best_ref_path.begin() + 1, best_ref_path.end(),
604 std::back_inserter(current_frame_planned_path));
605 frame_->set_current_frame_planned_path(current_frame_planned_path);
606
607 ptr_debug->MergeFrom(best_ref_info->debug());
608 if (FLAGS_export_chart) {
609 ExportOnLaneChart(best_ref_info->debug(), ptr_debug);
610 } else {
611 ExportReferenceLineDebug(ptr_debug);
612 // Export additional ST-chart for failed lane-change speed planning
613 const auto* failed_ref_info = frame_->FindFailedReferenceLineInfo();
614 if (failed_ref_info) {
615 ExportFailedLaneChangeSTChart(failed_ref_info->debug(), ptr_debug);
616 }
617 }
618 ptr_trajectory_pb->mutable_latency_stats()->MergeFrom(
619 best_ref_info->latency_stats());
620 // set right of way status
621 ptr_trajectory_pb->set_right_of_way_status(
622 best_ref_info->GetRightOfWayStatus());
623
624 for (const auto& id : best_ref_info->TargetLaneId()) {
625 ptr_trajectory_pb->add_lane_id()->CopyFrom(id);
626 }
627
628 for (const auto& id : target_ref_info->TargetLaneId()) {
629 ptr_trajectory_pb->add_target_lane_id()->CopyFrom(id);
630 }
631
632 ptr_trajectory_pb->set_trajectory_type(best_ref_info->trajectory_type());
633
634 if (FLAGS_enable_rss_info) {
635 *ptr_trajectory_pb->mutable_rss_info() = best_ref_info->rss_info();
636 }
637
638 best_ref_info->ExportDecision(ptr_trajectory_pb->mutable_decision(),
639 injector_->planning_context());
640
641 // Add debug information.
642 if (FLAGS_enable_record_debug) {
643 auto* reference_line = ptr_debug->mutable_planning_data()->add_path();
644 reference_line->set_name("planning_reference_line");
645 const auto& reference_points =
646 best_ref_info->reference_line().reference_points();
647 double s = 0.0;
648 double prev_x = 0.0;
649 double prev_y = 0.0;
650 bool empty_path = true;
651 for (const auto& reference_point : reference_points) {
652 auto* path_point = reference_line->add_path_point();
653 path_point->set_x(reference_point.x());
654 path_point->set_y(reference_point.y());
655 path_point->set_theta(reference_point.heading());
656 path_point->set_kappa(reference_point.kappa());
657 path_point->set_dkappa(reference_point.dkappa());
658 if (empty_path) {
659 path_point->set_s(0.0);
660 empty_path = false;
661 } else {
662 double dx = reference_point.x() - prev_x;
663 double dy = reference_point.y() - prev_y;
664 s += std::hypot(dx, dy);
665 path_point->set_s(s);
666 }
667 prev_x = reference_point.x();
668 prev_y = reference_point.y();
669 }
670 }
671
673 current_time_stamp, best_ref_info->trajectory()));
674 PrintCurves debug_traj;
675 for (size_t i = 0; i < last_publishable_trajectory_->size(); i++) {
676 auto& traj_pt = last_publishable_trajectory_->at(i);
677 debug_traj.AddPoint("traj_sv", traj_pt.path_point().s(), traj_pt.v());
678 debug_traj.AddPoint("traj_sa", traj_pt.path_point().s(), traj_pt.a());
679 debug_traj.AddPoint("traj_sk", traj_pt.path_point().s(),
680 traj_pt.path_point().kappa());
681 }
682 // debug_traj.PrintToLog();
683 ADEBUG << "current_time_stamp: " << current_time_stamp;
684
685 last_publishable_trajectory_->PrependTrajectoryPoints(
686 std::vector<TrajectoryPoint>(stitching_trajectory.begin(),
687 stitching_trajectory.end() - 1));
688
689 last_publishable_trajectory_->PopulateTrajectoryProtobuf(ptr_trajectory_pb);
690
691 best_ref_info->ExportEngageAdvice(
692 ptr_trajectory_pb->mutable_engage_advice(),
693 injector_->planning_context());
694 }
695
696 return status;
697}
698
699bool OnLanePlanning::CheckPlanningConfig(const PlanningConfig& config) {
700 // TODO(All): check other config params
701 return true;
702}
703
704void PopulateChartOptions(double x_min, double x_max, std::string x_label,
705 double y_min, double y_max, std::string y_label,
706 bool display, Chart* chart) {
707 auto* options = chart->mutable_options();
708 options->mutable_x()->set_min(x_min);
709 options->mutable_x()->set_max(x_max);
710 options->mutable_y()->set_min(y_min);
711 options->mutable_y()->set_max(y_max);
712 options->mutable_x()->set_label_string(x_label);
713 options->mutable_y()->set_label_string(y_label);
714 options->set_legend_display(display);
715}
716
717void AddSTGraph(const STGraphDebug& st_graph, Chart* chart) {
718 if (st_graph.name() == "DP_ST_SPEED_OPTIMIZER") {
719 chart->set_title("Speed Heuristic");
720 } else {
721 chart->set_title("Planning S-T Graph");
722 }
723 PopulateChartOptions(-2.0, 10.0, "t (second)", -10.0, 220.0, "s (meter)",
724 false, chart);
725
726 for (const auto& boundary : st_graph.boundary()) {
727 // from 'ST_BOUNDARY_TYPE_' to the end
728 std::string type =
729 StGraphBoundaryDebug_StBoundaryType_Name(boundary.type()).substr(17);
730
731 auto* boundary_chart = chart->add_polygon();
732 auto* properties = boundary_chart->mutable_properties();
733 (*properties)["borderWidth"] = "2";
734 (*properties)["pointRadius"] = "0";
735 (*properties)["lineTension"] = "0";
736 (*properties)["cubicInterpolationMode"] = "monotone";
737 (*properties)["showLine"] = "true";
738 (*properties)["showText"] = "true";
739 (*properties)["fill"] = "false";
740
741 if (type == "DRIVABLE_REGION") {
742 (*properties)["color"] = "\"rgba(0, 255, 0, 0.5)\"";
743 } else {
744 (*properties)["color"] = "\"rgba(255, 0, 0, 0.8)\"";
745 }
746
747 boundary_chart->set_label(boundary.name() + "_" + type);
748 for (const auto& point : boundary.point()) {
749 auto* point_debug = boundary_chart->add_point();
750 point_debug->set_x(point.t());
751 point_debug->set_y(point.s());
752 }
753 }
754
755 auto* speed_profile = chart->add_line();
756 auto* properties = speed_profile->mutable_properties();
757 (*properties)["color"] = "\"rgba(255, 255, 255, 0.5)\"";
758 for (const auto& point : st_graph.speed_profile()) {
759 auto* point_debug = speed_profile->add_point();
760 point_debug->set_x(point.t());
761 point_debug->set_y(point.s());
762 }
763}
764
765void AddSLFrame(const SLFrameDebug& sl_frame, Chart* chart) {
766 chart->set_title(sl_frame.name());
767 PopulateChartOptions(0.0, 80.0, "s (meter)", -8.0, 8.0, "l (meter)", false,
768 chart);
769 auto* sl_line = chart->add_line();
770 sl_line->set_label("SL Path");
771 for (const auto& sl_point : sl_frame.sl_path()) {
772 auto* point_debug = sl_line->add_point();
773 point_debug->set_x(sl_point.s());
774 point_debug->set_x(sl_point.l());
775 }
776}
777
779 const ::google::protobuf::RepeatedPtrField<SpeedPlan>& speed_plans,
780 Chart* chart) {
781 chart->set_title("Speed Plan");
782 PopulateChartOptions(0.0, 80.0, "s (meter)", 0.0, 50.0, "v (m/s)", false,
783 chart);
784
785 for (const auto& speed_plan : speed_plans) {
786 auto* line = chart->add_line();
787 line->set_label(speed_plan.name());
788 for (const auto& point : speed_plan.speed_point()) {
789 auto* point_debug = line->add_point();
790 point_debug->set_x(point.s());
791 point_debug->set_y(point.v());
792 }
793
794 // Set chartJS's dataset properties
795 auto* properties = line->mutable_properties();
796 (*properties)["borderWidth"] = "2";
797 (*properties)["pointRadius"] = "0";
798 (*properties)["fill"] = "false";
799 (*properties)["showLine"] = "true";
800 if (speed_plan.name() == "DpStSpeedOptimizer") {
801 (*properties)["color"] = "\"rgba(27, 249, 105, 0.5)\"";
802 } else if (speed_plan.name() == "QpSplineStSpeedOptimizer") {
803 (*properties)["color"] = "\"rgba(54, 162, 235, 1)\"";
804 }
805 }
806}
807
808void OnLanePlanning::ExportFailedLaneChangeSTChart(
809 const planning_internal::Debug& debug_info,
810 planning_internal::Debug* debug_chart) {
811 const auto& src_data = debug_info.planning_data();
812 auto* dst_data = debug_chart->mutable_planning_data();
813 for (const auto& st_graph : src_data.st_graph()) {
814 AddSTGraph(st_graph, dst_data->add_chart());
815 }
816}
817
818void OnLanePlanning::ExportOnLaneChart(
819 const planning_internal::Debug& debug_info,
820 planning_internal::Debug* debug_chart) {
821 const auto& src_data = debug_info.planning_data();
822 auto* dst_data = debug_chart->mutable_planning_data();
823 for (const auto& st_graph : src_data.st_graph()) {
824 AddSTGraph(st_graph, dst_data->add_chart());
825 }
826 for (const auto& sl_frame : src_data.sl_frame()) {
827 AddSLFrame(sl_frame, dst_data->add_chart());
828 }
829 AddSpeedPlan(src_data.speed_plan(), dst_data->add_chart());
830}
831
832void OnLanePlanning::ExportOpenSpaceChart(
833 const planning_internal::Debug& debug_info,
834 const ADCTrajectory& trajectory_pb, planning_internal::Debug* debug_chart) {
835 // Export Trajectory Visualization Chart.
836 if (FLAGS_enable_record_debug) {
837 AddOpenSpaceOptimizerResult(debug_info, debug_chart);
838 AddPartitionedTrajectory(debug_info, debug_chart);
839 AddStitchSpeedProfile(debug_chart);
840 AddPublishedSpeed(trajectory_pb, debug_chart);
841 AddPublishedAcceleration(trajectory_pb, debug_chart);
842 // AddFallbackTrajectory(debug_info, debug_chart);
843 }
844}
845
846void OnLanePlanning::AddOpenSpaceOptimizerResult(
847 const planning_internal::Debug& debug_info,
848 planning_internal::Debug* debug_chart) {
849 // if open space info provider success run
850 if (!frame_->open_space_info().open_space_provider_success()) {
851 return;
852 }
853
854 auto chart = debug_chart->mutable_planning_data()->add_chart();
855 auto open_space_debug = debug_info.planning_data().open_space();
856
857 chart->set_title("Open Space Trajectory Optimizer Visualization");
858 PopulateChartOptions(open_space_debug.xy_boundary(0) - 1.0,
859 open_space_debug.xy_boundary(1) + 1.0, "x (meter)",
860 open_space_debug.xy_boundary(2) - 1.0,
861 open_space_debug.xy_boundary(3) + 1.0, "y (meter)", true,
862 chart);
863
864 chart->mutable_options()->set_sync_xy_window_size(true);
865 chart->mutable_options()->set_aspect_ratio(0.9);
866 int obstacle_index = 1;
867 for (const auto& obstacle : open_space_debug.obstacles()) {
868 auto* obstacle_outline = chart->add_line();
869 obstacle_outline->set_label(absl::StrCat("Bdr", obstacle_index));
870 obstacle_index += 1;
871 for (int vertice_index = 0;
872 vertice_index < obstacle.vertices_x_coords_size(); vertice_index++) {
873 auto* point_debug = obstacle_outline->add_point();
874 point_debug->set_x(obstacle.vertices_x_coords(vertice_index));
875 point_debug->set_y(obstacle.vertices_y_coords(vertice_index));
876 }
877 // Set chartJS's dataset properties
878 auto* obstacle_properties = obstacle_outline->mutable_properties();
879 (*obstacle_properties)["borderWidth"] = "2";
880 (*obstacle_properties)["pointRadius"] = "0";
881 (*obstacle_properties)["lineTension"] = "0";
882 (*obstacle_properties)["fill"] = "false";
883 (*obstacle_properties)["showLine"] = "true";
884 }
885
886 auto smoothed_trajectory = open_space_debug.smoothed_trajectory();
887 auto* smoothed_line = chart->add_line();
888 smoothed_line->set_label("Smooth");
889 // size_t adc_label = 0;
890 for (int i = 0; i < smoothed_trajectory.vehicle_motion_point_size() / 2;
891 i++) {
892 auto& point = smoothed_trajectory.vehicle_motion_point(i);
893 const auto x = point.trajectory_point().path_point().x();
894 const auto y = point.trajectory_point().path_point().y();
895 // const auto heading = point.trajectory_point().path_point().theta();
896 /*
897 // Draw vehicle shape along the trajectory
898 auto* adc_shape = chart->add_car();
899 adc_shape->set_x(x);
900 adc_shape->set_y(y);
901 adc_shape->set_heading(heading);
902 adc_shape->set_color("rgba(54, 162, 235, 1)");
903 adc_shape->set_label(std::to_string(adc_label));
904 adc_shape->set_hide_label_in_legend(true);
905 ++adc_label;
906 */
907 // Draw vehicle trajectory points
908 auto* point_debug = smoothed_line->add_point();
909 point_debug->set_x(x);
910 point_debug->set_y(y);
911 }
912
913 // Set chartJS's dataset properties
914 auto* smoothed_properties = smoothed_line->mutable_properties();
915 (*smoothed_properties)["borderWidth"] = "2";
916 (*smoothed_properties)["pointRadius"] = "0";
917 (*smoothed_properties)["lineTension"] = "0";
918 (*smoothed_properties)["fill"] = "false";
919 (*smoothed_properties)["showLine"] = "true";
920
921 auto warm_start_trajectory = open_space_debug.warm_start_trajectory();
922 auto* warm_start_line = chart->add_line();
923 warm_start_line->set_label("WarmStart");
924 for (int i = 0; i < warm_start_trajectory.vehicle_motion_point_size() / 2;
925 i++) {
926 auto* point_debug = warm_start_line->add_point();
927 auto& point = warm_start_trajectory.vehicle_motion_point(i);
928 point_debug->set_x(point.trajectory_point().path_point().x());
929 point_debug->set_y(point.trajectory_point().path_point().y());
930 }
931 // Set chartJS's dataset properties
932 auto* warm_start_properties = warm_start_line->mutable_properties();
933 (*warm_start_properties)["borderWidth"] = "2";
934 (*warm_start_properties)["pointRadius"] = "0";
935 (*warm_start_properties)["lineTension"] = "0";
936 (*warm_start_properties)["fill"] = "false";
937 (*warm_start_properties)["showLine"] = "true";
938}
939
940void OnLanePlanning::AddPartitionedTrajectory(
941 const planning_internal::Debug& debug_info,
942 planning_internal::Debug* debug_chart) {
943 // if open space info provider success run
944 if (!frame_->open_space_info().open_space_provider_success()) {
945 return;
946 }
947
948 const auto& open_space_debug = debug_info.planning_data().open_space();
949 const auto& chosen_trajectories =
950 open_space_debug.chosen_trajectory().trajectory();
951 if (chosen_trajectories.empty() ||
952 chosen_trajectories[0].trajectory_point().empty()) {
953 return;
954 }
955
956 const auto& vehicle_state = frame_->vehicle_state();
957 auto chart = debug_chart->mutable_planning_data()->add_chart();
958 auto chart_kappa = debug_chart->mutable_planning_data()->add_chart();
959 auto chart_theta = debug_chart->mutable_planning_data()->add_chart();
960 chart->set_title("Open Space Partitioned Trajectory");
961 chart_kappa->set_title("total kappa");
962 chart_theta->set_title("total theta");
963 auto* options = chart->mutable_options();
964 options->mutable_x()->set_label_string("x (meter)");
965 options->mutable_y()->set_label_string("y (meter)");
966 options->set_sync_xy_window_size(true);
967 options->set_aspect_ratio(0.9);
968
969 // Draw vehicle state
970 auto* adc_shape = chart->add_car();
971 adc_shape->set_x(vehicle_state.x());
972 adc_shape->set_y(vehicle_state.y());
973 adc_shape->set_heading(vehicle_state.heading());
974 adc_shape->set_label("ADV");
975 adc_shape->set_color("rgba(54, 162, 235, 1)");
976
977 // Draw the chosen trajectories
978 const auto& chosen_trajectory = chosen_trajectories[0];
979 auto* chosen_line = chart->add_line();
980 chosen_line->set_label("Chosen");
981 for (const auto& point : chosen_trajectory.trajectory_point()) {
982 auto* point_debug = chosen_line->add_point();
983 point_debug->set_x(point.path_point().x());
984 point_debug->set_y(point.path_point().y());
985 }
986 auto* chosen_properties = chosen_line->mutable_properties();
987 (*chosen_properties)["borderWidth"] = "2";
988 (*chosen_properties)["pointRadius"] = "0";
989 (*chosen_properties)["lineTension"] = "0";
990 (*chosen_properties)["fill"] = "false";
991 (*chosen_properties)["showLine"] = "true";
992 auto* theta_line = chart_theta->add_line();
993 auto* kappa_line = chart_kappa->add_line();
994 // Draw partitioned trajectories
995 size_t partitioned_trajectory_label = 0;
996 for (const auto& partitioned_trajectory :
997 open_space_debug.partitioned_trajectories().trajectory()) {
998 auto* partition_line = chart->add_line();
999 partition_line->set_label(
1000 absl::StrCat("Partitioned ", partitioned_trajectory_label));
1001 ++partitioned_trajectory_label;
1002 for (const auto& point : partitioned_trajectory.trajectory_point()) {
1003 auto* point_debug = partition_line->add_point();
1004 auto* point_theta = theta_line->add_point();
1005 auto* point_kappa = kappa_line->add_point();
1006 point_debug->set_x(point.path_point().x());
1007 point_debug->set_y(point.path_point().y());
1008 point_theta->set_x(point.relative_time());
1009 point_kappa->set_x(point.relative_time());
1010 point_theta->set_y(point.path_point().theta());
1011 point_kappa->set_y(point.path_point().kappa());
1012 }
1013
1014 auto* partition_properties = partition_line->mutable_properties();
1015 (*partition_properties)["borderWidth"] = "2";
1016 (*partition_properties)["pointRadius"] = "0";
1017 (*partition_properties)["lineTension"] = "0";
1018 (*partition_properties)["fill"] = "false";
1019 (*partition_properties)["showLine"] = "true";
1020 SetChartminmax(chart_kappa, "time", "total kappa");
1021 SetChartminmax(chart_theta, "time", "total theta");
1022 }
1023
1024 // Draw trajectory stitching point (line with only one point)
1025 // auto* stitching_line = chart->add_line();
1026 // stitching_line->set_label("TrajectoryStitchingPoint");
1027 // auto* trajectory_stitching_point = stitching_line->add_point();
1028 // trajectory_stitching_point->set_x(
1029 // open_space_debug.trajectory_stitching_point().path_point().x());
1030 // trajectory_stitching_point->set_y(
1031 // open_space_debug.trajectory_stitching_point().path_point().y());
1032 // // Set chartJS's dataset properties
1033 // auto* stitching_properties = stitching_line->mutable_properties();
1034 // (*stitching_properties)["borderWidth"] = "3";
1035 // (*stitching_properties)["pointRadius"] = "5";
1036 // (*stitching_properties)["lineTension"] = "0";
1037 // (*stitching_properties)["fill"] = "true";
1038 // (*stitching_properties)["showLine"] = "true";
1039
1040 // Draw fallback trajectory compared with the partitioned and potential
1041 // collision_point (line with only one point)
1042 // if (open_space_debug.is_fallback_trajectory()) {
1043 // auto* collision_line = chart->add_line();
1044 // collision_line->set_label("FutureCollisionPoint");
1045 // auto* future_collision_point = collision_line->add_point();
1046 // future_collision_point->set_x(
1047 // open_space_debug.future_collision_point().path_point().x());
1048 // future_collision_point->set_y(
1049 // open_space_debug.future_collision_point().path_point().y());
1050 // // Set chartJS's dataset properties
1051 // auto* collision_properties = collision_line->mutable_properties();
1052 // (*collision_properties)["borderWidth"] = "3";
1053 // (*collision_properties)["pointRadius"] = "8";
1054 // (*collision_properties)["lineTension"] = "0";
1055 // (*collision_properties)["fill"] = "true";
1056 // (*stitching_properties)["showLine"] = "true";
1057 // (*stitching_properties)["pointStyle"] = "cross";
1058
1059 // const auto& fallback_trajectories =
1060 // open_space_debug.fallback_trajectory().trajectory();
1061 // if (fallback_trajectories.empty() ||
1062 // fallback_trajectories[0].trajectory_point().empty()) {
1063 // return;
1064 // }
1065 // const auto& fallback_trajectory = fallback_trajectories[0];
1066 // // has to define chart boundary first
1067 // auto* fallback_line = chart->add_line();
1068 // fallback_line->set_label("Fallback");
1069 // for (const auto& point : fallback_trajectory.trajectory_point()) {
1070 // auto* point_debug = fallback_line->add_point();
1071 // point_debug->set_x(point.path_point().x());
1072 // point_debug->set_y(point.path_point().y());
1073 // }
1074 // // Set chartJS's dataset properties
1075 // auto* fallback_properties = fallback_line->mutable_properties();
1076 // (*fallback_properties)["borderWidth"] = "3";
1077 // (*fallback_properties)["pointRadius"] = "2";
1078 // (*fallback_properties)["lineTension"] = "0";
1079 // (*fallback_properties)["fill"] = "false";
1080 // (*fallback_properties)["showLine"] = "true";
1081 // }
1082}
1083
1084void OnLanePlanning::AddStitchSpeedProfile(
1085 planning_internal::Debug* debug_chart) {
1086 if (!injector_->frame_history()->Latest()) {
1087 AINFO << "Planning frame is empty!";
1088 return;
1089 }
1090
1091 // if open space info provider success run
1092 if (!frame_->open_space_info().open_space_provider_success()) {
1093 return;
1094 }
1095
1096 auto chart = debug_chart->mutable_planning_data()->add_chart();
1097 chart->set_title("Open Space Speed Plan Visualization");
1098 auto* options = chart->mutable_options();
1099 // options->mutable_x()->set_mid_value(Clock::NowInSeconds());
1100 double xmin(std::numeric_limits<double>::max()),
1101 xmax(std::numeric_limits<double>::lowest()),
1102 ymin(std::numeric_limits<double>::max()),
1103 ymax(std::numeric_limits<double>::lowest());
1104 // auto smoothed_trajectory = open_space_debug.smoothed_trajectory();
1105 auto* speed_profile = chart->add_line();
1106 speed_profile->set_label("Speed Profile");
1107 const auto& last_trajectory =
1108 injector_->frame_history()->Latest()->current_frame_planned_trajectory();
1109 for (const auto& point : last_trajectory.trajectory_point()) {
1110 auto* point_debug = speed_profile->add_point();
1111 point_debug->set_x(point.relative_time() +
1112 last_trajectory.header().timestamp_sec());
1113 point_debug->set_y(point.v());
1114 if (point_debug->x() > xmax) xmax = point_debug->x();
1115 if (point_debug->x() < xmin) xmin = point_debug->x();
1116 if (point_debug->y() > ymax) ymax = point_debug->y();
1117 if (point_debug->y() < ymin) ymin = point_debug->y();
1118 }
1119 options->mutable_x()->set_window_size(xmax - xmin);
1120 options->mutable_x()->set_label_string("time (s)");
1121 options->mutable_y()->set_min(ymin);
1122 options->mutable_y()->set_max(ymax);
1123 options->mutable_y()->set_label_string("speed (m/s)");
1124 // Set chartJS's dataset properties
1125 auto* speed_profile_properties = speed_profile->mutable_properties();
1126 (*speed_profile_properties)["borderWidth"] = "2";
1127 (*speed_profile_properties)["pointRadius"] = "0";
1128 (*speed_profile_properties)["lineTension"] = "0";
1129 (*speed_profile_properties)["fill"] = "false";
1130 (*speed_profile_properties)["showLine"] = "true";
1131}
1132
1133void OnLanePlanning::AddPublishedSpeed(const ADCTrajectory& trajectory_pb,
1134 planning_internal::Debug* debug_chart) {
1135 // if open space info provider success run
1136 if (!frame_->open_space_info().open_space_provider_success()) {
1137 return;
1138 }
1139
1140 auto chart = debug_chart->mutable_planning_data()->add_chart();
1141 chart->set_title("Speed Partition Visualization");
1142 auto* options = chart->mutable_options();
1143 // options->mutable_x()->set_mid_value(Clock::NowInSeconds());
1144 // auto smoothed_trajectory = open_space_debug.smoothed_trajectory();
1145 auto* speed_profile = chart->add_line();
1146 speed_profile->set_label("Speed Profile");
1147 double xmin(std::numeric_limits<double>::max()),
1148 xmax(std::numeric_limits<double>::lowest()),
1149 ymin(std::numeric_limits<double>::max()),
1150 ymax(std::numeric_limits<double>::lowest());
1151 for (const auto& point : trajectory_pb.trajectory_point()) {
1152 auto* point_debug = speed_profile->add_point();
1153 point_debug->set_x(point.relative_time() +
1154 trajectory_pb.header().timestamp_sec());
1155 if (trajectory_pb.gear() == canbus::Chassis::GEAR_DRIVE) {
1156 point_debug->set_y(point.v());
1157 }
1158 if (trajectory_pb.gear() == canbus::Chassis::GEAR_REVERSE) {
1159 point_debug->set_y(-point.v());
1160 }
1161 if (point_debug->x() > xmax) xmax = point_debug->x();
1162 if (point_debug->x() < xmin) xmin = point_debug->x();
1163 if (point_debug->y() > ymax) ymax = point_debug->y();
1164 if (point_debug->y() < ymin) ymin = point_debug->y();
1165 }
1166 options->mutable_x()->set_window_size(xmax - xmin);
1167 options->mutable_x()->set_label_string("time (s)");
1168 options->mutable_y()->set_min(ymin);
1169 options->mutable_y()->set_max(ymax);
1170 options->mutable_y()->set_label_string("speed (m/s)");
1171 // Set chartJS's dataset properties
1172 auto* speed_profile_properties = speed_profile->mutable_properties();
1173 (*speed_profile_properties)["borderWidth"] = "2";
1174 (*speed_profile_properties)["pointRadius"] = "0";
1175 (*speed_profile_properties)["lineTension"] = "0";
1176 (*speed_profile_properties)["fill"] = "false";
1177 (*speed_profile_properties)["showLine"] = "true";
1178
1179 auto* sliding_line = chart->add_line();
1180 sliding_line->set_label("Time");
1181
1182 auto* point_debug_up = sliding_line->add_point();
1183 point_debug_up->set_x(Clock::NowInSeconds());
1184 point_debug_up->set_y(2.1);
1185 auto* point_debug_down = sliding_line->add_point();
1186 point_debug_down->set_x(Clock::NowInSeconds());
1187 point_debug_down->set_y(-1.1);
1188
1189 // Set chartJS's dataset properties
1190 auto* sliding_line_properties = sliding_line->mutable_properties();
1191 (*sliding_line_properties)["borderWidth"] = "2";
1192 (*sliding_line_properties)["pointRadius"] = "0";
1193 (*sliding_line_properties)["lineTension"] = "0";
1194 (*sliding_line_properties)["fill"] = "false";
1195 (*sliding_line_properties)["showLine"] = "true";
1196}
1197
1198VehicleState OnLanePlanning::AlignTimeStamp(const VehicleState& vehicle_state,
1199 const double curr_timestamp) const {
1200 // TODO(Jinyun): use the same method in trajectory stitching
1201 // for forward prediction
1202 auto future_xy = injector_->vehicle_state()->EstimateFuturePosition(
1203 curr_timestamp - vehicle_state.timestamp());
1204
1205 VehicleState aligned_vehicle_state = vehicle_state;
1206 aligned_vehicle_state.set_x(future_xy.x());
1207 aligned_vehicle_state.set_y(future_xy.y());
1208 aligned_vehicle_state.set_timestamp(curr_timestamp);
1209 return aligned_vehicle_state;
1210}
1211
1212void OnLanePlanning::AddPublishedAcceleration(
1213 const ADCTrajectory& trajectory_pb, planning_internal::Debug* debug) {
1214 // if open space info provider success run
1215 if (!frame_->open_space_info().open_space_provider_success()) {
1216 return;
1217 }
1218 double xmin(std::numeric_limits<double>::max()),
1219 xmax(std::numeric_limits<double>::lowest()),
1220 ymin(std::numeric_limits<double>::max()),
1221 ymax(std::numeric_limits<double>::lowest());
1222 auto chart = debug->mutable_planning_data()->add_chart();
1223 chart->set_title("Acceleration Partition Visualization");
1224 auto* options = chart->mutable_options();
1225 // options->mutable_x()->set_mid_value(Clock::NowInSeconds());
1226
1227 auto* acceleration_profile = chart->add_line();
1228 acceleration_profile->set_label("Acceleration Profile");
1229 for (const auto& point : trajectory_pb.trajectory_point()) {
1230 auto* point_debug = acceleration_profile->add_point();
1231 point_debug->set_x(point.relative_time() +
1232 trajectory_pb.header().timestamp_sec());
1233 if (trajectory_pb.gear() == canbus::Chassis::GEAR_DRIVE)
1234 point_debug->set_y(point.a());
1235 if (trajectory_pb.gear() == canbus::Chassis::GEAR_REVERSE)
1236 point_debug->set_y(-point.a());
1237 if (point_debug->x() > xmax) xmax = point_debug->x();
1238 if (point_debug->x() < xmin) xmin = point_debug->x();
1239 if (point_debug->y() > ymax) ymax = point_debug->y();
1240 if (point_debug->y() < ymin) ymin = point_debug->y();
1241 }
1242 options->mutable_x()->set_window_size(xmax - xmin);
1243 options->mutable_x()->set_label_string("time (s)");
1244 options->mutable_y()->set_min(ymin);
1245 options->mutable_y()->set_max(ymax);
1246 options->mutable_y()->set_label_string("acceleration (m/s)");
1247 // Set chartJS's dataset properties
1248 auto* acceleration_profile_properties =
1249 acceleration_profile->mutable_properties();
1250 (*acceleration_profile_properties)["borderWidth"] = "2";
1251 (*acceleration_profile_properties)["pointRadius"] = "0";
1252 (*acceleration_profile_properties)["lineTension"] = "0";
1253 (*acceleration_profile_properties)["fill"] = "false";
1254 (*acceleration_profile_properties)["showLine"] = "true";
1255
1256 auto* sliding_line = chart->add_line();
1257 sliding_line->set_label("Time");
1258
1259 auto* point_debug_up = sliding_line->add_point();
1260 point_debug_up->set_x(Clock::NowInSeconds());
1261 point_debug_up->set_y(2.1);
1262 auto* point_debug_down = sliding_line->add_point();
1263 point_debug_down->set_x(Clock::NowInSeconds());
1264 point_debug_down->set_y(-1.1);
1265
1266 // Set chartJS's dataset properties
1267 auto* sliding_line_properties = sliding_line->mutable_properties();
1268 (*sliding_line_properties)["borderWidth"] = "2";
1269 (*sliding_line_properties)["pointRadius"] = "0";
1270 (*sliding_line_properties)["lineTension"] = "0";
1271 (*sliding_line_properties)["fill"] = "false";
1272 (*sliding_line_properties)["showLine"] = "true";
1273}
1274
1275} // namespace planning
1276} // namespace apollo
Define the birdview img feature renderer class
A general class to denote the return status of an API call.
Definition status.h:43
bool ok() const
check whether the return status is OK.
Definition status.h:67
const std::string & error_message() const
returns the error message of the status, empty if the status is OK.
Definition status.h:91
std::string ToString() const
returns a string representation in a readable format.
Definition status.h:98
void Save(StatusPb *status_pb)
save the error_code and error message to protobuf
Definition status.h:109
static Status OK()
generate a success status.
Definition status.h:60
static const VehicleConfig & GetConfig()
Get the current vehicle configuration.
Implements a class of 2-dimensional vectors.
Definition vec2d.h:42
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
static const HDMap * BaseMapPtr()
Frame holds all data for one planning cycle.
Definition frame.h:62
common::Status Plan(const double current_time_stamp, const std::vector< common::TrajectoryPoint > &stitching_trajectory, ADCTrajectory *const trajectory) override
Plan the trajectory given current vehicle state
void RunOnce(const LocalView &local_view, ADCTrajectory *const ptr_trajectory_pb) override
main logic of the planning module, runs periodically triggered by timer.
common::Status Init(const PlanningConfig &config) override
module initialization function
std::string Name() const override
Planning name.
virtual apollo::common::Status Init(const PlanningConfig &config)
std::unique_ptr< Frame > frame_
virtual void FillPlanningPb(const double timestamp, ADCTrajectory *const trajectory_pb)
std::unique_ptr< PublishableTrajectory > last_publishable_trajectory_
const hdmap::HDMap * hdmap_
std::shared_ptr< Planner > planner_
std::shared_ptr< DependencyInjector > injector_
static double LookForwardDistance(const double velocity)
void AddAdcBox(double x, double y, double heading, bool is_rear_axle_point=true)
void AddPoint(std::string key, double x, double y)
add point to curve key
apollo::common::Status Smooth(const FrameHistory *frame_history, const Frame *current_frame, ADCTrajectory *const current_trajectory_pb)
Definition smoother.cc:55
apollo::common::Status Execute(Frame *frame, ReferenceLineInfo *reference_line_info)
bool Init(const std::shared_ptr< DependencyInjector > &injector)
static std::vector< common::TrajectoryPoint > ComputeStitchingTrajectory(const canbus::Chassis &vehicle_chassis, const common::VehicleState &vehicle_state, const double current_timestamp, const double planning_cycle_time, const size_t preserved_points_num, const bool replan_by_offset, const PublishableTrajectory *prev_trajectory, std::string *replan_reason, const control::ControlInteractiveMsg &control_interactive_msg)
Planning module main class.
#define ACHECK(cond)
Definition log.h:80
#define ADEBUG
Definition log.h:41
#define AERROR
Definition log.h:44
#define AINFO
Definition log.h:42
#define AWARN
Definition log.h:43
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
bool IsVehicleStateValid(const VehicleState &vehicle_state)
Definition util.cc:35
bool IsDifferentRouting(const PlanningCommand &first, const PlanningCommand &second)
Definition util.cc:46
void SetChartminmax(apollo::dreamview::Chart *chart, std::string label_name_x, std::string label_name_y)
void AddSpeedPlan(const ::google::protobuf::RepeatedPtrField< SpeedPlan > &speed_plans, Chart *chart)
void AddSTGraph(const STGraphDebug &st_graph, Chart *chart)
void PopulateChartOptions(double x_min, double x_max, std::string x_label, double y_min, double y_max, std::string y_label, bool display, Chart *chart)
void AddSLFrame(const SLFrameDebug &sl_frame, Chart *chart)
class register implement
Definition arena_queue.h:37
Contains a number of helper functions related to quaternions.
Declaration of the class ReferenceLineProvider.
optional VehicleParam vehicle_param
optional LatencyStats latency_stats
repeated apollo::common::TrajectoryPoint trajectory_point
optional TrajectoryType trajectory_type
optional apollo::common::Header header
optional apollo::planning_internal::Debug debug
std::shared_ptr< routing::LaneWaypoint > end_lane_way_point
Definition local_view.h:49
std::shared_ptr< localization::LocalizationEstimate > localization_estimate
Definition local_view.h:43
std::shared_ptr< PlanningCommand > planning_command
Definition local_view.h:48
std::shared_ptr< control::ControlInteractiveMsg > control_interactive_msg
Definition local_view.h:50
std::shared_ptr< canbus::Chassis > chassis
Definition local_view.h:42
optional ReferenceLineConfig reference_line_config
optional PlanningLearningMode learning_mode
repeated apollo::common::SLPoint sl_path
repeated apollo::common::SpeedPoint speed_profile
LocalView contains all necessary data as planning input