Closed jilinzhou closed 5 years ago
@lianglia-apollo
The l value are very large (~170). Are you trying to project obstacles near to the reference line?
The l value are very large (~170). Are you trying to project obstacles near to the reference line?
@lianglia-apollo Thanks for the quick reply. I did not modify any logic of the code. You are right. The 'l' value are very large which mean the DEST obstacle is far away from the reference line.
In the following function,
PathObstacle* ReferenceLineInfo::AddObstacle(const Obstacle* obstacle) {
...
SLBoundary perception_sl;
if (!reference_line_.GetSLBoundary(obstacle->PerceptionBoundingBox(),
&perception_sl)) {
AERROR << "Failed to get sl boundary for obstacle: " << obstacle->Id();
return path_obstacle;
}
path_obstacle->SetPerceptionSlBoundary(perception_sl);
...
}
The obstacle's SL boundary is computed by calling ReferenceLine::GetSLBoundary(). The 'l' value is not checked for lateralDecision at this stage. Then later on, in the following function:
bool PathDecider::MakeStaticObstacleDecision(const PathData &path_data, PathDecision *const path_decision) {
DCHECK_NOTNULL(path_decision);
const auto &frenet_path = path_data.frenet_frame_path();
const auto &frenet_points = frenet_path.points();
if (frenet_points.empty()) {
AERROR << "Path is empty.";
return false;
}
const double half_width =
common::VehicleConfigHelper::GetConfig().vehicle_param().width() / 2.0;
const double lateral_radius = half_width + FLAGS_lateral_ignore_buffer;
const double lateral_stop_radius =
half_width + FLAGS_static_decision_nudge_l_buffer;
for (const auto *path_obstacle : path_decision->path_obstacles().Items()) {
const auto &obstacle = *path_obstacle->obstacle();
if (!obstacle.IsStatic()) {
continue;
}
if (path_obstacle->HasLongitudinalDecision() &&
path_obstacle->LongitudinalDecision().has_ignore() &&
path_obstacle->HasLateralDecision() &&
path_obstacle->LateralDecision().has_ignore()) {
continue;
}
if (path_obstacle->HasLongitudinalDecision() &&
path_obstacle->LongitudinalDecision().has_stop()) {
continue;
}
if (path_obstacle->st_boundary().boundary_type() ==
StBoundary::BoundaryType::KEEP_CLEAR) {
continue;
}
// IGNORE by default
ObjectDecisionType object_decision;
object_decision.mutable_ignore();
const auto &sl_boundary = path_obstacle->PerceptionSLBoundary();
//************************No lateral distance check yet*********************************************
if (sl_boundary.end_s() < frenet_points.front().s() ||
sl_boundary.start_s() > frenet_points.back().s()) {
path_decision->AddLongitudinalDecision("PathDecider/not-in-s",
obstacle.Id(), object_decision);
path_decision->AddLateralDecision("PathDecider/not-in-s", obstacle.Id(),
object_decision);
continue;
}
// if (sl_boundary.start_s() < 0.0) {
AWARN << "obstacle start s: " <<sl_boundary.start_s() << " Id: " << path_obstacle->Id();
// }
//****************************Failed in the following call***********************************************
const auto frenet_point = frenet_path.EvaluateByS(sl_boundary.start_s());
....
}
The problem is the discontinuity of projection of 2d box onto reference line. I have attached a picture which might explain when this occurs. One corner of DEST box is projected to other side of the reference line (s = 173.743 in our debugging output) while other three corners are projected to the other side of ref line ((-35.6943 , -32.1497, -35.6238).
We also noticed this issue. We are fixing it by cutting the reference line if the curvature is too large. The new code will be released soon. We made some modifications on pnc_map to cut a segment of routing lane segment if we found the curvature is greater than some threshold.
I am thinking that maybe we don't need to check for DEST obstacle when it is very far away, which will cause some mapping issues. We are able to find the destination from routing, and extract the distance from ego vehicle to the destination point.
@lianglia-apollo : Yes, for DEST obstacle, it can be ruled out using routing info. For general static objects, projecting each corner of 2d box onto reference line might be computationally too expensive. How about build a few layers (coarse to fine) of axis aligned 2d boxes (lane width can be used here) for the reference line and then does the collision detection in between the bounding box of obstacle and the ref line? At the top layer, the reference line is represented a big 2d AABox. If there is no collision in between them, we are done. If there is a collision, check the collision to the 2nd layer AABox of ref line. If there is no collision, we are done again, otherwise go to 3rd layer. Repeat the process till the final decision can be made.
@lianglia-apollo @jilinzhou Could you please tell me what exactly you do to solve this problem since I still have the same issue. My situation is a dynamic moving obstacle. I found the start_s of the obstacle just changed suddenly since the projection of one corner of the obstacle just changes. Logically there is nothing wrong with the projection since the nearest point on the reference line changes. But in reality, it seems a little bit weird that something changed while the obstacle remains.
Describe the bug
I added some printout at the end of mappath.GetProjection() as the following:
Here is the output for the last two frames before the planning crashes for this DESTINATION static obstacle:
I think the extra lane segments appended in the last frame's reference line causes the issue. It just happens that one of those appended segments is the closest to the DESTINATION obstacle's third corner.
I have not figured a nice way to fix the issue. Intuitively, it may be better to check collision in between the 2d box as a whole against each LaneSegment instead of checking each corner independently.