43 homography_im2car_ = homography_im2car;
44 homography_car2im_ = homography_im2car.inverse();
49 margin_vehicle_to_lane_ =
50 (average_lane_width_in_meter_ - max_vehicle_width_in_meter_) * 0.5f;
51 single_virtual_egolane_width_in_meter_ = max_vehicle_width_in_meter_;
52 half_vehicle_width_in_meter_ = max_vehicle_width_in_meter_ * 0.5f;
53 half_virtual_egolane_width_in_meter_ =
54 single_virtual_egolane_width_in_meter_ * 0.5f;
55 old_cipv_track_id_ = -2;
62 const Eigen::Affine3d &world2camera,
68 if (motion_buffer->size() > 0) {
71 AWARN <<
"motion_buffer is empty";
77bool Cipv::DistanceFromPointToLineSegment(
const Point2Df &point,
78 const Point2Df &line_seg_start_point,
83 {line_seg_start_point(0), line_seg_start_point(1)},
84 {line_seg_end_point(0), line_seg_end_point(1)});
89 *distance =
static_cast<float>(line_seg.DistanceTo(p));
94bool Cipv::GetEgoLane(
const std::vector<base::LaneLine> &lane_objects,
95 EgoLane *egolane_image, EgoLane *egolane_ground,
96 bool *b_left_valid,
bool *b_right_valid) {
98 for (
size_t i = 0; i < lane_objects.size(); ++i) {
99 const auto &lane_object = lane_objects[i];
100 const size_t curve_image_point_size =
101 lane_object.curve_image_point_set.size();
102 const size_t curve_car_coord_point_set_size =
103 lane_object.curve_car_coord_point_set.size();
105 if (debug_level_ >= 2) {
106 AINFO <<
"[GetEgoLane]LEFT_image_lane_objects[" << i
107 <<
"].curve_image_point_set.size(): " << curve_image_point_size;
108 AINFO <<
"[GetEgoLane]LEFT_ground_lane_objects[" << i
109 <<
"].curve_car_coord_point_set_size: "
110 << curve_car_coord_point_set_size;
112 if (curve_image_point_size < min_laneline_length_for_cipv_) {
113 *b_left_valid =
false;
115 *b_left_valid =
true;
117 for (
size_t j = 0; j < curve_car_coord_point_set_size; ++j) {
119 x = lane_object.curve_car_coord_point_set[j].x;
120 y = lane_object.curve_car_coord_point_set[j].y;
121 egolane_ground->left_line.line_point.emplace_back(x, y);
123 for (
size_t j = 0; j < curve_image_point_size; ++j) {
125 x = lane_object.curve_image_point_set[j].x;
126 y = lane_object.curve_image_point_set[j].y;
127 egolane_image->left_line.line_point.emplace_back(x, y);
131 if (debug_level_ >= 2) {
132 AINFO <<
"[GetEgoLane]RIGHT_image_lane_objects[" << i
133 <<
"].curve_image_point_set.size(): " << curve_image_point_size;
134 AINFO <<
"[GetEgoLane]RIGHT_ground_lane_objects[" << i
135 <<
"].curve_car_coord_point_set_size: "
136 << curve_car_coord_point_set_size;
138 if (curve_image_point_size < min_laneline_length_for_cipv_) {
139 *b_right_valid =
false;
141 *b_right_valid =
true;
142 for (
size_t j = 0; j < curve_car_coord_point_set_size; ++j) {
144 x = lane_object.curve_car_coord_point_set[j].x;
145 y = lane_object.curve_car_coord_point_set[j].y;
146 egolane_ground->right_line.line_point.emplace_back(x, y);
148 for (
size_t j = 0; j < curve_image_point_size; ++j) {
150 x = lane_object.curve_image_point_set[j].x;
151 y = lane_object.curve_image_point_set[j].y;
152 egolane_image->right_line.line_point.emplace_back(x, y);
161bool Cipv::MakeVirtualLane(
const LaneLineSimple &ref_lane_line,
162 const float yaw_rate,
const float offset_distance,
163 LaneLineSimple *virtual_lane_line) {
166 virtual_lane_line->line_point.clear();
167 for (uint32_t i = 0; i < ref_lane_line.line_point.size(); ++i) {
168 virtual_lane_line->line_point.emplace_back(
169 ref_lane_line.line_point[i](0),
170 ref_lane_line.line_point[i](1) + offset_distance);
176 const float velocity,
const float time_unit,
177 float *x,
float *y) {
183 float adjusted_velocity = std::max(
kMinVelocity, velocity);
184 float theta =
static_cast<float>(tick) * time_unit * yaw_rate;
185 float displacement =
static_cast<float>(tick) * time_unit * adjusted_velocity;
186 *x = displacement *
static_cast<float>(cos(theta));
187 *y = displacement *
static_cast<float>(sin(theta));
197 const float velocity,
const float time_unit,
198 const float half_vehicle_width,
float *center_x,
199 float *center_y,
float *left_x,
float *left_y,
200 float *right_x,
float *right_y) {
206 float adjusted_velocity = std::max(
kMinVelocity, velocity);
207 float theta =
static_cast<float>(tick) * time_unit * yaw_rate;
208 float displacement =
static_cast<float>(tick) * time_unit * adjusted_velocity;
209 float offset = half_vehicle_width;
210 *center_x = displacement *
static_cast<float>(cos(theta));
211 *center_y = displacement *
static_cast<float>(sin(theta));
213 offset = -half_vehicle_width;
215 *left_x = (displacement + offset) *
static_cast<float>(cos(theta)) - offset;
216 *left_y = (displacement + offset) *
static_cast<float>(sin(theta)) +
218 *right_x = (displacement - offset) *
static_cast<float>(cos(theta)) + offset;
219 *right_y = (displacement - offset) *
static_cast<float>(sin(theta)) -
230 const float velocity,
231 const float offset_distance,
234 float center_x = 0.0f;
235 float center_y = 0.0f;
238 float right_x = 0.0f;
239 float right_y = 0.0f;
243 for (uint32_t i = 1; i < kMaxNumVirtualLanePoint; ++i) {
244 VehicleDynamics(i, yaw_rate, velocity, kAverageFrameRate, offset_distance,
245 ¢er_x, ¢er_y, &left_x, &left_y, &right_x, &right_y);
246 Point2Df left_point(left_x, left_y);
247 left_lane_line->
line_point.emplace_back(left_point);
248 Point2Df right_point(right_x, right_y);
249 right_lane_line->
line_point.emplace_back(right_point);
255bool Cipv::ElongateEgoLane(
const std::vector<base::LaneLine> &lane_objects,
256 const bool b_left_valid,
const bool b_right_valid,
257 const float yaw_rate,
const float velocity,
259 float offset_distance = half_virtual_egolane_width_in_meter_;
261 if (b_left_valid && b_right_valid) {
263 if (debug_level_ >= 2) {
264 AINFO <<
"Both lanes are fine";
267 }
else if (!b_left_valid && b_right_valid) {
269 offset_distance = single_virtual_egolane_width_in_meter_;
270 MakeVirtualLane(egolane_ground->
right_line, yaw_rate, offset_distance,
272 if (debug_level_ >= 2) {
273 AINFO <<
"Made left lane with offset: " << offset_distance;
277 }
else if (b_left_valid && !b_right_valid) {
279 offset_distance = -single_virtual_egolane_width_in_meter_;
280 MakeVirtualLane(egolane_ground->
left_line, yaw_rate, offset_distance,
282 if (debug_level_ >= 2) {
283 AINFO <<
"Made right lane with offset: " << offset_distance;
290bool Cipv::CreateVirtualEgoLane(
const float yaw_rate,
const float velocity,
291 EgoLane *egolane_ground) {
292 float offset_distance = half_vehicle_width_in_meter_;
295 &egolane_ground->left_line,
296 &egolane_ground->right_line);
297 if (debug_level_ >= 2) {
298 AINFO <<
"Made both lane_objects with size of "
299 << egolane_ground->left_line.line_point.size();
306bool Cipv::FindClosestObjectImage(
const std::shared_ptr<base::Object> &
object,
307 const EgoLane &egolane_image,
308 LineSegment2Df *closted_object_edge,
310 float size_x =
object->size(0);
311 float size_y =
object->size(1);
312 float size_z =
object->size(2);
314 if (size_x < 1.0e-2 && size_y < 1.0e-2 && size_z < 1.0e-2) {
321 float center_x = (
object->camera_supplement.box.xmin +
322 object->camera_supplement.box.xmin) *
324 float center_y =
object->camera_supplement.box.ymax;
326 if (debug_level_ >= 3) {
327 AINFO <<
"object->camera_supplement.box = base::RectF("
328 <<
object->camera_supplement.box.xmin <<
", "
329 <<
object->camera_supplement.box.ymin <<
", "
330 <<
object->camera_supplement.box.xmax -
331 object->camera_supplement.box.xmin
333 <<
object->camera_supplement.box.ymax -
334 object->camera_supplement.box.ymin
337 closted_object_edge->start_point(0) =
object->camera_supplement.box.xmin;
338 closted_object_edge->start_point(1) =
object->camera_supplement.box.ymax;
340 closted_object_edge->end_point(0) =
object->camera_supplement.box.xmax;
341 closted_object_edge->end_point(1) =
object->camera_supplement.box.ymax;
344 static_cast<float>(sqrt(center_x * center_x + center_y * center_y));
345 if (debug_level_ >= 2) {
346 AINFO <<
"start(" << closted_object_edge->start_point(0) <<
", "
347 << closted_object_edge->start_point(1) <<
")->";
348 AINFO <<
"end(" << closted_object_edge->end_point(0) <<
", "
349 << closted_object_edge->end_point(1) <<
")";
350 AINFO <<
"closest distance: " << *distance;
357bool Cipv::FindClosestObjectGround(
const std::shared_ptr<base::Object> &
object,
358 const EgoLane &egolane_ground,
359 const Eigen::Affine3d &world2camera,
360 LineSegment2Df *closted_object_edge,
362 if (debug_level_ >= 2) {
363 AINFO <<
"object->track_id = " <<
object->track_id;
365 float size_x =
object->size(0);
366 float size_y =
object->size(1);
367 float size_z =
object->size(2);
368 if (size_x < 1.0e-2 && size_y < 1.0e-2 && size_z < 1.0e-2) {
375 auto pos = world2camera *
object->center;
376 float center_x =
static_cast<float>(pos(2));
377 float center_y =
static_cast<float>(-pos(0));
387 double theta_ray = atan2(pos(0), pos(2));
388 double theta =
object->camera_supplement.alpha + theta_ray;
391 if (debug_level_ >= 3) {
392 AINFO <<
"object->camera_supplement.box = base::RectF("
393 <<
object->camera_supplement.box.xmin <<
", "
394 <<
object->camera_supplement.box.ymin <<
", "
395 <<
object->camera_supplement.box.xmax -
396 object->camera_supplement.box.xmin
398 <<
object->camera_supplement.box.ymax -
399 object->camera_supplement.box.ymin
402 AINFO <<
"object.center(0) = " <<
object->center(0) <<
";";
403 AINFO <<
"object.center(1) = " <<
object->center(1) <<
";";
404 AINFO <<
"object.center(2) = " <<
object->center(2) <<
";";
405 AINFO <<
"pos(0) = " << pos(0) <<
";";
406 AINFO <<
"pos(1) = " << pos(1) <<
";";
407 AINFO <<
"pos(2) = " << pos(2) <<
";";
408 AINFO <<
"object->camera_supplement.local_center(0) = "
409 <<
object->camera_supplement.local_center(0) <<
";";
410 AINFO <<
"object->camera_supplement.local_center(1) = "
411 <<
object->camera_supplement.local_center(1) <<
";";
412 AINFO <<
"object->camera_supplement.local_center(2) = "
413 <<
object->camera_supplement.local_center(2) <<
";";
414 AINFO <<
"theta_ray = " << theta_ray <<
";";
415 AINFO <<
"object->camera_supplement.alpha = "
416 <<
object->camera_supplement.alpha <<
";";
417 AINFO <<
"theta = " << theta <<
";";
418 AINFO <<
"object.anchor_point(0) = " <<
object->anchor_point(0) <<
";";
419 AINFO <<
"object.anchor_point(1) = " <<
object->anchor_point(1) <<
";";
420 AINFO <<
"object.anchor_point(2) = " <<
object->anchor_point(2) <<
";";
421 AINFO <<
"object.direction(0) = " <<
object->direction(0) <<
";";
422 AINFO <<
"object.direction(1) = " <<
object->direction(1) <<
";";
423 AINFO <<
"object.direction(2) = " <<
object->direction(2) <<
";";
424 AINFO <<
"object.size(0) = " <<
object->size(0) <<
";";
425 AINFO <<
"object.size(1) = " <<
object->size(1) <<
";";
426 AINFO <<
"object.size(2) = " <<
object->size(2) <<
";";
428 float x1 = size_x * 0.5f;
430 float y1 = size_y * 0.5f;
432 float cos_theta =
static_cast<float>(
cos(theta));
433 float sin_theta =
static_cast<float>(
sin(theta));
437 p[0](0) = x2 * cos_theta + y1 * sin_theta + center_x;
438 p[0](1) = y1 * cos_theta - x2 * sin_theta + center_y;
440 p[1](0) = x2 * cos_theta + y2 * sin_theta + center_x;
441 p[1](1) = y2 * cos_theta - x2 * sin_theta + center_y;
443 p[2](0) = x1 * cos_theta + y1 * sin_theta + center_x;
444 p[2](1) = y1 * cos_theta - x1 * sin_theta + center_y;
446 p[3](0) = x1 * cos_theta + y2 * sin_theta + center_x;
447 p[3](1) = y2 * cos_theta - x1 * sin_theta + center_y;
449 if (debug_level_ >= 2) {
450 AINFO <<
"P0(" << p[0](0) <<
", " << p[0](1) <<
")";
451 AINFO <<
"P1(" << p[1](0) <<
", " << p[1](1) <<
")";
452 AINFO <<
"P2(" << p[2](0) <<
", " << p[2](1) <<
")";
453 AINFO <<
"P3(" << p[3](0) <<
", " << p[3](1) <<
")";
459 int32_t closest_index = -1;
460 int32_t left_index = -1;
461 int32_t right_index = -1;
462 for (int32_t i = 0; i < 4; i++) {
463 if (p[i](1) <= left_y) {
467 if (p[i](1) > right_y) {
471 if (p[i](0) < closest_x) {
477 if (left_index < 0 || right_index < 0 || left_index == right_index) {
478 if (debug_level_ >= 2) {
479 AINFO <<
"left_index: " << left_index;
480 AINFO <<
"right_index: " << right_index;
485 closted_object_edge->start_point(0) = p[right_index](0);
486 closted_object_edge->start_point(1) = p[right_index](1);
488 closted_object_edge->end_point(0) = p[left_index](0);
489 closted_object_edge->end_point(1) = p[left_index](1);
492 if ((p[left_index](0) < 0 && p[right_index](0) < 0) ||
493 (p[closest_index](0) < 0)) {
498 static_cast<float>(sqrt(p[closest_index](0) * p[closest_index](0) +
499 p[closest_index](1) * p[closest_index](1)));
500 if (debug_level_ >= 2) {
501 AINFO <<
"start(" << closted_object_edge->start_point(0) <<
", "
502 << closted_object_edge->start_point(1) <<
")->";
503 AINFO <<
"end(" << closted_object_edge->end_point(0) <<
", "
504 << closted_object_edge->end_point(1) <<
")";
505 AINFO <<
"closest distance to p[" << closest_index <<
"]("
506 << p[closest_index](0) <<
", " << p[closest_index](1)
507 <<
"): " << *distance;
513bool Cipv::AreDistancesSane(
const float distance_start_point_to_right_lane,
514 const float distance_start_point_to_left_lane,
515 const float distance_end_point_to_right_lane,
516 const float distance_end_point_to_left_lane) {
517 float distance = -1.0f;
519 if (debug_level_ >= 1) {
520 AINFO <<
"distance from start to right lane("
521 << distance_start_point_to_right_lane <<
" m) is too long";
526 if (debug_level_ >= 1) {
527 AINFO <<
"distance from start to left lane("
528 << distance_start_point_to_left_lane <<
" m) is too long";
533 if (debug_level_ >= 1) {
534 AINFO <<
"distance from end to right lane("
535 << distance_end_point_to_right_lane <<
" m) is too long";
540 if (debug_level_ >= 1) {
541 AINFO <<
"distance from end to left lane("
542 << distance_end_point_to_left_lane <<
" m) is too long";
546 distance =
static_cast<float>(fabs(distance_start_point_to_right_lane -
547 distance_end_point_to_right_lane));
549 if (debug_level_ >= 1) {
550 AINFO <<
"width of vehicle (" << distance <<
" m) is too long";
555 distance =
static_cast<float>(fabs(distance_end_point_to_left_lane -
556 distance_start_point_to_left_lane));
558 if (debug_level_ >= 1) {
559 AINFO <<
"width of vehicle (" << distance <<
" m) is too long";
571bool Cipv::IsPointLeftOfLine(
const Point2Df &point,
572 const Point2Df &line_seg_start_point,
573 const Point2Df &line_seg_end_point) {
574 float cross_product = ((line_seg_end_point(0) - line_seg_start_point(0)) *
575 (point(1) - line_seg_start_point(1))) -
576 ((line_seg_end_point(1) - line_seg_start_point(1)) *
577 (point(0) - line_seg_start_point(0)));
579 if (cross_product > 0.0f) {
580 if (debug_level_ >= 2) {
581 AINFO <<
"point (" << point(0) <<
", " << point(1)
582 <<
") is left of line_segment (" << line_seg_start_point(0) <<
", "
583 << line_seg_start_point(1) <<
")->(" << line_seg_end_point(0)
584 <<
", " << line_seg_end_point(1)
585 <<
"), cross_product: " << cross_product;
589 if (debug_level_ >= 2) {
590 AINFO <<
"point (" << point(0) <<
", " << point(1)
591 <<
") is right of line_segment (" << line_seg_start_point(0) <<
", "
592 << line_seg_start_point(1) <<
")->(" << line_seg_end_point(0) <<
", "
593 << line_seg_end_point(1) <<
"), cross_product: " << cross_product;
599bool Cipv::IsObjectInTheLaneImage(
const std::shared_ptr<base::Object> &
object,
600 const EgoLane &egolane_image,
601 float *object_distance) {
602 LineSegment2Df closted_object_edge;
603 bool b_left_lane_clear =
false;
604 bool b_right_lane_clear =
false;
606 float distance = 0.0f;
608 int closest_index = -1;
610 float b_valid_object = FindClosestObjectImage(
611 object, egolane_image, &closted_object_edge, &distance);
612 if (!b_valid_object) {
613 if (debug_level_ >= 1) {
614 AINFO <<
"The closest edge of an object is not available";
618 *object_distance = distance;
620 if (debug_level_ >= 3) {
621 AINFO <<
"egolane_image.left_line.line_point.size(): "
622 << egolane_image.left_line.line_point.size();
624 if (egolane_image.left_line.line_point.size() <= 1) {
625 if (debug_level_ >= 1) {
626 AINFO <<
"No left lane";
634 for (
size_t i = 0; i + 1 < egolane_image.left_line.line_point.size(); ++i) {
637 if (DistanceFromPointToLineSegment(
638 closted_object_edge.end_point,
639 egolane_image.left_line.line_point[i],
640 egolane_image.left_line.line_point[i + 1], &distance)) {
641 if (distance < shortest_distance) {
642 closest_index =
static_cast<int>(i);
643 shortest_distance = distance;
649 if (closest_index >= 0) {
651 if (debug_level_ >= 3) {
652 AINFO <<
"[Left] closest_index: " << closest_index
653 <<
", shortest_distance: " << shortest_distance;
654 AINFO <<
"Should be left to be selected";
656 if (IsPointLeftOfLine(
657 closted_object_edge.end_point,
658 egolane_image.left_line.line_point[closest_index],
659 egolane_image.left_line.line_point[closest_index + 1])) {
660 b_left_lane_clear =
true;
661 AINFO <<
"The left lane is clear";
665 if (debug_level_ >= 3) {
666 AINFO <<
"egolane_image.right_line.line_point.size(): "
667 << egolane_image.right_line.line_point.size();
670 if (egolane_image.right_line.line_point.size() <= 1) {
671 if (debug_level_ >= 1) {
672 AINFO <<
"No right lane";
678 for (
size_t i = 0; i + 1 < egolane_image.right_line.line_point.size(); ++i) {
681 if (DistanceFromPointToLineSegment(
682 closted_object_edge.start_point,
683 egolane_image.right_line.line_point[i],
684 egolane_image.right_line.line_point[i + 1], &distance)) {
685 if (distance < shortest_distance) {
686 closest_index =
static_cast<int>(i);
687 shortest_distance = distance;
692 if (closest_index >= 0) {
693 if (debug_level_ >= 3) {
694 AINFO <<
"[right] closest_index: " << closest_index
695 <<
", shortest_distance: " << shortest_distance;
696 AINFO <<
"Should be right to be selected";
699 if (!IsPointLeftOfLine(
700 closted_object_edge.start_point,
701 egolane_image.right_line.line_point[closest_index],
702 egolane_image.right_line.line_point[closest_index + 1])) {
703 b_right_lane_clear =
true;
704 AINFO <<
"The right lane is clear";
708 if (b_left_lane_clear && b_right_lane_clear) {
709 AINFO <<
"The object is in the ego lane";
711 AINFO <<
"The object is out of the ego lane";
713 return (b_left_lane_clear && b_right_lane_clear);
724bool Cipv::IsObjectInTheLaneGround(
const std::shared_ptr<base::Object> &
object,
725 const EgoLane &egolane_ground,
726 const Eigen::Affine3d &world2camera,
727 const bool b_virtual,
728 float *object_distance) {
729 LineSegment2Df closted_object_edge;
730 bool b_left_lane_clear =
false;
731 bool b_right_lane_clear =
false;
732 float shortest_distance = 0.0f;
733 float distance = 0.0f;
734 float max_dist_object_to_lane_in_meter =
735 b_virtual ? max_dist_object_to_virtual_lane_in_meter_
736 : max_dist_object_to_lane_in_meter_;
737 int closest_index = -1;
739 float b_valid_object = FindClosestObjectGround(
740 object, egolane_ground, world2camera, &closted_object_edge, &distance);
741 if (!b_valid_object) {
742 if (debug_level_ >= 1) {
743 AINFO <<
"The closest edge of an object is not available";
747 *object_distance = distance;
749 if (debug_level_ >= 3) {
750 AINFO <<
"egolane_ground.left_line.line_point.size(): "
751 << egolane_ground.left_line.line_point.size();
753 if (egolane_ground.left_line.line_point.size() <= 1) {
754 if (debug_level_ >= 1) {
755 AINFO <<
"No left lane";
763 for (
size_t i = 0; i + 1 < egolane_ground.left_line.line_point.size(); ++i) {
766 if (DistanceFromPointToLineSegment(
767 closted_object_edge.end_point,
768 egolane_ground.left_line.line_point[i],
769 egolane_ground.left_line.line_point[i + 1], &distance)) {
770 if (distance < shortest_distance) {
771 closest_index =
static_cast<int>(i);
772 shortest_distance = distance;
778 if (closest_index >= 0) {
780 if (debug_level_ >= 3) {
781 AINFO <<
"[Left] closest_index: " << closest_index
782 <<
", shortest_distance: " << shortest_distance;
784 if (!IsPointLeftOfLine(
785 closted_object_edge.end_point,
786 egolane_ground.left_line.line_point[closest_index],
787 egolane_ground.left_line.line_point[closest_index + 1]) &&
788 shortest_distance < max_dist_object_to_lane_in_meter) {
789 b_left_lane_clear =
true;
793 if (debug_level_ >= 3) {
794 AINFO <<
"egolane_ground.right_line.line_point.size(): "
795 << egolane_ground.right_line.line_point.size();
798 if (egolane_ground.right_line.line_point.size() <= 1) {
799 if (debug_level_ >= 1) {
800 AINFO <<
"No right lane";
806 for (
size_t i = 0; i + 1 < egolane_ground.right_line.line_point.size(); ++i) {
809 if (DistanceFromPointToLineSegment(
810 closted_object_edge.start_point,
811 egolane_ground.right_line.line_point[i],
812 egolane_ground.right_line.line_point[i + 1], &distance)) {
813 if (distance < shortest_distance) {
814 closest_index =
static_cast<int>(i);
815 shortest_distance = distance;
820 if (closest_index >= 0) {
821 if (debug_level_ >= 3) {
822 AINFO <<
"[right] closest_index: " << closest_index
823 <<
", shortest_distance: " << shortest_distance;
826 if (IsPointLeftOfLine(
827 closted_object_edge.start_point,
828 egolane_ground.right_line.line_point[closest_index],
829 egolane_ground.right_line.line_point[closest_index + 1]) &&
830 shortest_distance < max_dist_object_to_lane_in_meter) {
831 b_right_lane_clear =
true;
835 return b_left_lane_clear && b_right_lane_clear;
839bool Cipv::IsObjectInTheLane(
const std::shared_ptr<base::Object> &
object,
840 const EgoLane &egolane_image,
841 const EgoLane &egolane_ground,
842 const Eigen::Affine3d &world2camera,
843 const bool b_virtual,
float *distance) {
844 if (b_image_based_cipv_) {
845 return IsObjectInTheLaneImage(
object, egolane_image, distance);
847 return IsObjectInTheLaneGround(
object, egolane_ground, world2camera,
848 b_virtual, distance);
855 const Eigen::Affine3d &world2camera,
856 std::vector<std::shared_ptr<base::Object>> *objects) {
857 if (debug_level_ >= 3) {
858 AINFO <<
"Cipv Got SensorObjects with size of " << objects->size();
859 AINFO <<
"Cipv Got lane object with size of " << lane_objects.size();
864 int32_t cipv_index = -1;
866 int32_t cipv_track_id = -1;
867 bool b_left_valid =
false;
868 bool b_right_valid =
false;
869 int32_t old_cipv_index = -1;
872 EgoLane virtual_egolane_ground;
873 egolane_ground.
left_line.line_point.clear();
875 virtual_egolane_ground.
left_line.line_point.clear();
876 virtual_egolane_ground.
right_line.line_point.clear();
879 GetEgoLane(lane_objects, &egolane_image, &egolane_ground, &b_left_valid,
881 ElongateEgoLane(lane_objects, b_left_valid, b_right_valid, options.
yaw_rate,
882 options.
velocity, &egolane_image, &egolane_ground);
885 &virtual_egolane_ground);
887 float min_distance = std::numeric_limits<float>::max();
889 for (int32_t i = 0; i < static_cast<int32_t>(objects->size()); ++i) {
890 if (debug_level_ >= 2) {
891 AINFO <<
"objects[" << i <<
"]->track_id: " << (*objects)[i]->track_id;
893 if (IsObjectInTheLane((*objects)[i], egolane_image, egolane_ground,
894 world2camera,
false, &distance) ||
895 IsObjectInTheLane((*objects)[i], egolane_image, virtual_egolane_ground,
896 world2camera,
true, &distance)) {
897 if (cipv_index < 0 || distance < min_distance) {
899 cipv_track_id = (*objects)[i]->track_id;
900 min_distance = distance;
903 if (debug_level_ >= 2) {
904 AINFO <<
"current cipv_index: " << cipv_index;
907 if ((*objects)[i]->track_id == old_cipv_track_id_) {
908 old_cipv_index = cipv_index;
911 if (debug_level_ >= 1) {
912 AINFO <<
"old_cipv_index: " << old_cipv_index;
913 AINFO <<
"old_cipv_track_id_: " << old_cipv_track_id_;
915 if (cipv_index >= 0) {
916 if (old_cipv_index >= 0 && old_cipv_index != cipv_index &&
917 old_cipv_index <
static_cast<int32_t
>(objects->size())) {
918 (*objects)[old_cipv_index]->b_cipv =
false;
920 (*objects)[cipv_index]->b_cipv =
true;
921 old_cipv_track_id_ = cipv_track_id;
924 if (debug_level_ >= 1) {
925 AINFO <<
"final cipv_index: " << cipv_index;
926 AINFO <<
"final cipv_track_id: " << cipv_track_id;
935 if (debug_level_ >= 1) {
943bool Cipv::TranformPoint(
const Eigen::VectorXf &in,
944 const Eigen::Matrix4f &motion_matrix,
945 Eigen::Vector3d *out) {
946 if (in.rows() != motion_matrix.cols()) {
947 AERROR <<
"Matrix mismatch";
949 Eigen::VectorXf trans_pt = motion_matrix * in;
954 trans_pt /= trans_pt(3);
955 *out << trans_pt(0), trans_pt(1), trans_pt(2);
960 const Eigen::Affine3d &world2camera,
961 std::vector<std::shared_ptr<base::Object>> *objects) {
962 int motion_size =
static_cast<int>(motion_buffer->size());
963 if (debug_level_ >= 2) {
964 AINFO <<
" motion_size: " << motion_size;
966 if (motion_size <= 0) {
967 ADEBUG <<
" motion_size: " << motion_size;
974 if (debug_level_ >= 2) {
975 AINFO <<
"object_trackjectories_.size(): " << object_trackjectories_.size();
977 for (
auto obj : *objects) {
978 int cur_id = obj->track_id;
979 if (debug_level_ >= 2) {
980 AINFO <<
"target ID: " << cur_id;
987 if (object_trackjectories_[cur_id].empty()) {
988 object_trackjectories_[cur_id].set_capacity(kDropsHistorySize);
991 object_id_skip_count_[cur_id] = 0;
993 auto pos = world2camera * obj->center;
994 float center_x =
static_cast<float>(pos(2));
995 float center_y =
static_cast<float>(-pos(0));
997 object_trackjectories_[cur_id].push_back(
998 std::make_pair(center_x, center_y));
1000 if (debug_level_ >= 2) {
1001 AINFO <<
"object_trackjectories_[" << cur_id
1002 <<
" ].size(): " << object_trackjectories_[cur_id].size();
1005 Eigen::Matrix4f accum_motion_buffer =
1006 motion_buffer->at(motion_size - 1).motion;
1008 for (std::size_t it = object_trackjectories_[cur_id].size() - 1, count = 0;
1010 if (count >= kDropsHistorySize || count > motion_buffer->size()) {
1013 if (
static_cast<int>(it) + 1 > motion_size) {
1016 Eigen::VectorXf pt =
1017 Eigen::VectorXf::Zero((*motion_buffer)[0].motion.cols());
1018 pt(0) = object_trackjectories_[cur_id][it].first;
1019 pt(1) = object_trackjectories_[cur_id][it].second;
1023 Eigen::Vector3d transformed_pt;
1024 accum_motion_buffer *= motion_buffer->at(motion_size - it - 1).motion;
1025 TranformPoint(pt, accum_motion_buffer, &transformed_pt);
1028 if (debug_level_ >= 3) {
1029 AINFO <<
"(*motion_buffer)[" << motion_size - it - 1 <<
"].motion:";
1030 AINFO << motion_buffer->at(motion_size - it - 1).motion;
1031 AINFO <<
"accum_motion_buffer[" << motion_size - it - 1 <<
"] =";
1032 AINFO << accum_motion_buffer;
1033 AINFO <<
"target[" << obj->track_id <<
"][" << it <<
"]: ("
1034 << transformed_pt(0) <<
", " << transformed_pt(1) <<
")";
1036 obj->drops[count] = transformed_pt;
1037 obj->drop_num = count++;
1043 for (
const auto &each_object : object_trackjectories_) {
1044 int obj_id = each_object.first;
1045 bool b_found_id =
false;
1046 for (
auto obj : *objects) {
1047 int cur_id = obj->track_id;
1048 if (obj_id == cur_id) {
1054 if (!b_found_id && object_trackjectories_[obj_id].size() > 0) {
1056 object_id_skip_count_[obj_id]++;
1057 if (debug_level_ >= 2) {
1058 AINFO <<
"object_id_skip_count_[" << obj_id
1059 <<
" ]: " << object_id_skip_count_[obj_id];
1061 if (object_id_skip_count_[obj_id] >= kMaxAllowedSkipObject) {
1062 if (debug_level_ >= 2) {
1063 AINFO <<
"Removed obsolete object " << obj_id;
1065 object_trackjectories_.erase(obj_id);
1066 object_id_skip_count_.erase(obj_id);
1070 if (debug_level_ >= 2) {
1071 for (
auto obj : *objects) {
1072 int cur_id = obj->track_id;
1073 AINFO <<
"obj->track_id: " << cur_id;
1074 AINFO <<
"obj->drop_num: " << obj->drop_num;
1080bool Cipv::image2ground(
const float image_x,
const float image_y,
1081 float *ground_x,
float *ground_y) {
1082 Eigen::Vector3d p_homo;
1084 p_homo << image_x, image_y, 1;
1085 Eigen::Vector3d p_ground;
1086 p_ground = homography_im2car_ * p_homo;
1087 if (fabs(p_ground(2)) > std::numeric_limits<double>::min()) {
1088 *ground_x =
static_cast<float>(p_ground(0) / p_ground(2));
1089 *ground_y =
static_cast<float>(p_ground(1) / p_ground(2));
1092 if (debug_level_ >= 1) {
1093 AINFO <<
"p_ground(2) too small :" << p_ground(2);
1098bool Cipv::ground2image(
const float ground_x,
const float ground_y,
1099 float *image_x,
float *image_y) {
1100 Eigen::Vector3d p_homo_ground;
1102 p_homo_ground << ground_x, ground_y, 1;
1103 Eigen::Vector3d p_image;
1104 p_image = homography_car2im_ * p_homo_ground;
1105 if (fabs(p_image(2)) > std::numeric_limits<double>::min()) {
1106 *image_x =
static_cast<float>(p_image(0) / p_image(2));
1107 *image_y =
static_cast<float>(p_image(1) / p_image(2));
1110 if (debug_level_ >= 1) {
1111 AINFO <<
"p_image(2) too small :" << p_image(2);
#define PERCEPTION_REGISTER_CIPV(name)
Implements a class of 2-dimensional vectors.
std::string Name() const override
bool DetermineCipv(const std::vector< base::LaneLine > &lane_objects, const CipvOptions &options, const Eigen::Affine3d &world2camera, std::vector< std::shared_ptr< base::Object > > *objects)
bool Process(CameraFrame *frame, const CipvOptions &options, const Eigen::Affine3d &world2camera, const base::MotionBufferPtr &motion_buffer) override
bool Init(const Eigen::Matrix3d &homography_im2car, const CipvInitOptions &options=CipvInitOptions()) override
bool CollectDrops(const base::MotionBufferPtr &motion_buffer, const Eigen::Affine3d &world2camera, std::vector< std::shared_ptr< base::Object > > *objects)
static bool MakeVirtualEgoLaneFromYawRate(const float yaw_rate, const float velocity, const float offset_distance, LaneLineSimple *left_lane_line, LaneLineSimple *right_lane_line)
static float VehicleDynamics(const uint32_t tick, const float yaw_rate, const float velocity, const float time_unit, float *x, float *y)
Define the LineSegment2d class.
std::shared_ptr< MotionBuffer > MotionBufferPtr
@ EGO_LEFT
left lane marking of the ego lane
@ EGO_RIGHT
right lane marking of the ego lane
constexpr float kMinVelocity
constexpr float kMaxDistObjectToLaneInMeter
constexpr float kMaxVehicleWidthInMeter
constexpr float kMaxFloat
constexpr float kFloatEpsilon
apollo::common::EigenVector< Point2Df > line_point
std::vector< base::LaneLine > lane_objects
std::vector< base::ObjectPtr > tracked_objects
float min_laneline_length_for_cipv
float average_lane_width_in_meter
float max_vehicle_width_in_meter