Skip to content

Commit

Permalink
Merge branch 'beta/v0.19.1' into feature/add-mrm-pull-over-for-v0.19.1
Browse files Browse the repository at this point in the history
  • Loading branch information
mkuri authored Apr 9, 2024
2 parents 14c6021 + 7503f42 commit b349d7a
Show file tree
Hide file tree
Showing 24 changed files with 600 additions and 177 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
#include <boost/geometry/core/cs.hpp>
#include <boost/geometry/geometries/geometries.hpp>
#include <boost/geometry/geometries/register/point.hpp>
#include <boost/geometry/geometries/register/ring.hpp>

#define EIGEN_MPL2_ONLY
#include <Eigen/Core>
Expand Down Expand Up @@ -98,5 +99,6 @@ BOOST_GEOMETRY_REGISTER_POINT_2D( // NOLIN
tier4_autoware_utils::Point2d, double, cs::cartesian, x(), y()) // NOLINT
BOOST_GEOMETRY_REGISTER_POINT_3D( // NOLINT
tier4_autoware_utils::Point3d, double, cs::cartesian, x(), y(), z()) // NOLINT
BOOST_GEOMETRY_REGISTER_RING(tier4_autoware_utils::LinearRing2d) // NOLINT

#endif // TIER4_AUTOWARE_UTILS__GEOMETRY__BOOST_GEOMETRY_HPP_
Original file line number Diff line number Diff line change
Expand Up @@ -29,14 +29,20 @@
#include <geometry_msgs/msg/twist_stamped.hpp>
#include <nav_msgs/msg/odometry.hpp>

#include <boost/geometry/algorithms/envelope.hpp>
#include <boost/geometry/algorithms/union.hpp>
#include <boost/geometry/index/rtree.hpp>
#include <boost/optional.hpp>

#include <lanelet2_core/LaneletMap.h>
#include <lanelet2_core/geometry/BoundingBox.h>
#include <lanelet2_core/geometry/LaneletMap.h>
#include <lanelet2_core/geometry/LineString.h>
#include <lanelet2_core/geometry/Polygon.h>

#include <map>
#include <memory>
#include <string>
#include <utility>
#include <vector>

namespace lane_departure_checker
Expand Down Expand Up @@ -112,6 +118,19 @@ class LaneDepartureChecker
bool checkPathWillLeaveLane(
const lanelet::ConstLanelets & lanelets, const PathWithLaneId & path) const;

std::vector<std::pair<double, lanelet::Lanelet>> getLaneletsFromPath(
const lanelet::LaneletMapPtr lanelet_map_ptr, const PathWithLaneId & path) const;

std::optional<tier4_autoware_utils::Polygon2d> getFusedLaneletPolygonForPath(
const lanelet::LaneletMapPtr lanelet_map_ptr, const PathWithLaneId & path) const;

bool checkPathWillLeaveLane(
const lanelet::LaneletMapPtr lanelet_map_ptr, const PathWithLaneId & path) const;

PathWithLaneId cropPointsOutsideOfLanes(
const lanelet::LaneletMapPtr lanelet_map_ptr, const PathWithLaneId & path,
const size_t end_index);

static bool isOutOfLane(
const lanelet::ConstLanelets & candidate_lanelets, const LinearRing2d & vehicle_footprint);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ using motion_utils::calcArcLength;
using tier4_autoware_utils::LinearRing2d;
using tier4_autoware_utils::LineString2d;
using tier4_autoware_utils::MultiPoint2d;
using tier4_autoware_utils::MultiPolygon2d;
using tier4_autoware_utils::Point2d;

namespace
Expand Down Expand Up @@ -92,6 +93,7 @@ lanelet::ConstLanelets getCandidateLanelets(

return candidate_lanelets;
}

} // namespace

namespace lane_departure_checker
Expand Down Expand Up @@ -298,6 +300,98 @@ bool LaneDepartureChecker::willLeaveLane(
return false;
}

std::vector<std::pair<double, lanelet::Lanelet>> LaneDepartureChecker::getLaneletsFromPath(
const lanelet::LaneletMapPtr lanelet_map_ptr, const PathWithLaneId & path) const
{
// Get Footprint Hull basic polygon
std::vector<LinearRing2d> vehicle_footprints = createVehicleFootprints(path);
LinearRing2d footprint_hull = createHullFromFootprints(vehicle_footprints);
auto to_basic_polygon = [](const LinearRing2d & footprint_hull) -> lanelet::BasicPolygon2d {
lanelet::BasicPolygon2d basic_polygon;
for (const auto & point : footprint_hull) {
Eigen::Vector2d p(point.x(), point.y());
basic_polygon.push_back(p);
}
return basic_polygon;
};
lanelet::BasicPolygon2d footprint_hull_basic_polygon = to_basic_polygon(footprint_hull);

// Find all lanelets that intersect the footprint hull
return lanelet::geometry::findWithin2d(
lanelet_map_ptr->laneletLayer, footprint_hull_basic_polygon, 0.0);
}

std::optional<tier4_autoware_utils::Polygon2d> LaneDepartureChecker::getFusedLaneletPolygonForPath(
const lanelet::LaneletMapPtr lanelet_map_ptr, const PathWithLaneId & path) const
{
const auto lanelets_distance_pair = getLaneletsFromPath(lanelet_map_ptr, path);
auto to_polygon2d = [](const lanelet::BasicPolygon2d & poly) -> tier4_autoware_utils::Polygon2d {
tier4_autoware_utils::Polygon2d p;
auto & outer = p.outer();

for (const auto & p : poly) {
tier4_autoware_utils::Point2d p2d(p.x(), p.y());
outer.push_back(p2d);
}
boost::geometry::correct(p);
return p;
};

// Fuse lanelets into a single BasicPolygon2d
auto fused_lanelets = [&]() -> std::optional<tier4_autoware_utils::Polygon2d> {
if (lanelets_distance_pair.empty()) return std::nullopt;
tier4_autoware_utils::MultiPolygon2d lanelet_unions;
tier4_autoware_utils::MultiPolygon2d result;

for (size_t i = 0; i < lanelets_distance_pair.size(); ++i) {
const auto & route_lanelet = lanelets_distance_pair.at(i).second;
const auto & p = route_lanelet.polygon2d().basicPolygon();
tier4_autoware_utils::Polygon2d poly = to_polygon2d(p);
boost::geometry::union_(lanelet_unions, poly, result);
lanelet_unions = result;
result.clear();
}

if (lanelet_unions.empty()) return std::nullopt;
return lanelet_unions.front();
}();

return fused_lanelets;
}

bool LaneDepartureChecker::checkPathWillLeaveLane(
const lanelet::LaneletMapPtr lanelet_map_ptr, const PathWithLaneId & path) const
{
// check if the footprint is not fully contained within the fused lanelets polygon
const std::vector<LinearRing2d> vehicle_footprints = createVehicleFootprints(path);
const auto fused_lanelets_polygon = getFusedLaneletPolygonForPath(lanelet_map_ptr, path);
if (!fused_lanelets_polygon) return true;
return !std::all_of(
vehicle_footprints.begin(), vehicle_footprints.end(),
[&fused_lanelets_polygon](const auto & footprint) {
return boost::geometry::within(footprint, fused_lanelets_polygon.value());
});
}

PathWithLaneId LaneDepartureChecker::cropPointsOutsideOfLanes(
const lanelet::LaneletMapPtr lanelet_map_ptr, const PathWithLaneId & path, const size_t end_index)
{
PathWithLaneId temp_path;
const auto fused_lanelets_polygon = getFusedLaneletPolygonForPath(lanelet_map_ptr, path);
if (path.points.empty() || !fused_lanelets_polygon) return temp_path;
const auto vehicle_footprints = createVehicleFootprints(path);
size_t idx = 0;
std::for_each(vehicle_footprints.begin(), vehicle_footprints.end(), [&](const auto & footprint) {
if (idx > end_index || boost::geometry::within(footprint, fused_lanelets_polygon.value())) {
temp_path.points.push_back(path.points.at(idx));
}
++idx;
});
PathWithLaneId cropped_path = path;
cropped_path.points = temp_path.points;
return cropped_path;
}

bool LaneDepartureChecker::isOutOfLane(
const lanelet::ConstLanelets & candidate_lanelets, const LinearRing2d & vehicle_footprint)
{
Expand Down Expand Up @@ -364,4 +458,5 @@ bool LaneDepartureChecker::willCrossBoundary(
}
return false;
}

} // namespace lane_departure_checker
Original file line number Diff line number Diff line change
Expand Up @@ -122,11 +122,6 @@ class AvoidanceModule : public SceneModuleInterface
calcSignedArcLength(path.points, ego_position, left_shift.finish_pose.position);
rtc_interface_ptr_map_.at("left")->updateCooperateStatus(
left_shift.uuid, true, start_distance, finish_distance, clock_->now());
if (finish_distance > -1.0e-03) {
steering_factor_interface_ptr_->updateSteeringFactor(
{left_shift.start_pose, left_shift.finish_pose}, {start_distance, finish_distance},
PlanningBehavior::AVOIDANCE, SteeringFactor::LEFT, SteeringFactor::TURNING, "");
}
}

for (const auto & right_shift : right_shift_array_) {
Expand All @@ -136,11 +131,6 @@ class AvoidanceModule : public SceneModuleInterface
calcSignedArcLength(path.points, ego_position, right_shift.finish_pose.position);
rtc_interface_ptr_map_.at("right")->updateCooperateStatus(
right_shift.uuid, true, start_distance, finish_distance, clock_->now());
if (finish_distance > -1.0e-03) {
steering_factor_interface_ptr_->updateSteeringFactor(
{right_shift.start_pose, right_shift.finish_pose}, {start_distance, finish_distance},
PlanningBehavior::AVOIDANCE, SteeringFactor::RIGHT, SteeringFactor::TURNING, "");
}
}
}

Expand Down Expand Up @@ -417,6 +407,10 @@ class AvoidanceModule : public SceneModuleInterface

bool safe_{true};

bool is_recording_{false};

bool is_record_necessary_{false};

std::shared_ptr<AvoidanceHelper> helper_;

std::shared_ptr<AvoidanceParameters> parameters_;
Expand Down
78 changes: 70 additions & 8 deletions planning/behavior_path_avoidance_module/src/scene.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,34 @@ lanelet::BasicLineString3d toLineString3d(const std::vector<Point> & bound)
bound.begin(), bound.end(), [&](const auto & p) { ret.emplace_back(p.x, p.y, p.z); });
return ret;
}

bool straddleRoadBound(
const ShiftedPath & path, const lanelet::ConstLanelets & lanes,
const vehicle_info_util::VehicleInfo & vehicle_info)
{
using boost::geometry::intersects;
using tier4_autoware_utils::pose2transform;
using tier4_autoware_utils::transformVector;

const auto footprint = vehicle_info.createFootprint();

for (const auto & lane : lanes) {
for (const auto & p : path.path.points) {
const auto transform = pose2transform(p.point.pose);
const auto shifted_vehicle_footprint = transformVector(footprint, transform);

if (intersects(lane.leftBound2d().basicLineString(), shifted_vehicle_footprint)) {
return true;
}

if (intersects(lane.rightBound2d().basicLineString(), shifted_vehicle_footprint)) {
return true;
}
}
}

return false;
}
} // namespace

AvoidanceModule::AvoidanceModule(
Expand Down Expand Up @@ -894,6 +922,48 @@ BehaviorModuleOutput AvoidanceModule::plan()
planner_data_->parameters.ego_nearest_yaw_threshold);
}

// check if the ego straddles lane border
if (!is_recording_) {
is_record_necessary_ = straddleRoadBound(
spline_shift_path, data.current_lanelets, planner_data_->parameters.vehicle_info);
}

if (!path_shifter_.getShiftLines().empty()) {
const auto front_shift_line = path_shifter_.getShiftLines().front();
const double start_distance = calcSignedArcLength(
data.reference_path.points, getEgoPosition(), front_shift_line.start.position);
const double finish_distance = calcSignedArcLength(
data.reference_path.points, getEgoPosition(), front_shift_line.end.position);

const auto record_start_time = !is_recording_ && is_record_necessary_ && helper_->isShifted();
const auto record_end_time = is_recording_ && !helper_->isShifted();
const auto relative_shift_length = front_shift_line.end_shift_length - helper_->getEgoShift();
const auto steering_direction =
relative_shift_length > 0.0 ? SteeringFactor::LEFT : SteeringFactor::RIGHT;
const auto steering_status = [&]() {
if (record_start_time) {
is_recording_ = true;
RCLCPP_ERROR(getLogger(), "start right avoidance maneuver. get time stamp.");
return uint16_t(100);
}

if (record_end_time) {
is_recording_ = false;
is_record_necessary_ = false;
RCLCPP_ERROR(getLogger(), "end avoidance maneuver. get time stamp.");
return uint16_t(200);
}

return helper_->isShifted() ? SteeringFactor::TURNING : SteeringFactor::APPROACHING;
}();

if (finish_distance > -1.0e-03) {
steering_factor_interface_ptr_->updateSteeringFactor(
{front_shift_line.start, front_shift_line.end}, {start_distance, finish_distance},
PlanningBehavior::AVOIDANCE, steering_direction, steering_status, "");
}
}

// sparse resampling for computational cost
{
spline_shift_path.path = utils::resamplePathWithSpline(
Expand Down Expand Up @@ -974,14 +1044,6 @@ CandidateOutput AvoidanceModule::planCandidate() const
output.start_distance_to_path_change = sl_front.start_longitudinal;
output.finish_distance_to_path_change = sl_back.end_longitudinal;

const uint16_t steering_factor_direction = std::invoke([&output]() {
return output.lateral_shift > 0.0 ? SteeringFactor::LEFT : SteeringFactor::RIGHT;
});
steering_factor_interface_ptr_->updateSteeringFactor(
{sl_front.start, sl_back.end},
{output.start_distance_to_path_change, output.finish_distance_to_path_change},
PlanningBehavior::AVOIDANCE, steering_factor_direction, SteeringFactor::APPROACHING, "");

output.path_candidate = shifted_path.path;
return output;
}
Expand Down
10 changes: 10 additions & 0 deletions planning/behavior_path_lane_change_module/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -409,6 +409,16 @@ The following parameters are configurable in `behavior_path_planner.param.yaml`
| `safety_check.stuck.check_objects_on_other_lanes` | [-] | boolean | If true, the lane change module include objects on other lanes. | true |
| `safety_check.stuck.use_all_predicted_path` | [-] | boolean | If false, use only the predicted path that has the maximum confidence. | true |

| Name | Unit | Type | Description | Default value |
| :------------------------------------------------------- | ----- | ------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------- |
| `enable_collision_check_for_prepare_phase.general_lanes` | [-] | boolean | Perform collision check starting from the prepare phase for situations not explicitly covered by other settings (e.g., intersections). If `false`, collision check only evaluated for lane changing phase. | false |
| `enable_collision_check_for_prepare_phase.intersection` | [-] | boolean | Perform collision check starting from prepare phase when ego is in intersection. If `false`, collision check only evaluated for lane changing phase. | true |
| `enable_collision_check_for_prepare_phase.turns` | [-] | boolean | Perform collision check starting from prepare phase when ego is in lanelet with turn direction tags. If `false`, collision check only evaluated for lane changing phase. | true |
| `prepare_phase_ignore_target_speed_thresh` | [m/s] | double | Ignore collision check in prepare phase of object speed that is lesser that the configured value. `enable_collision_check_at_prepare_phase` must be `true` | 0.1 |
| `check_objects_on_current_lanes` | [-] | boolean | If true, the lane change module check objects on current lanes when performing collision assessment. | false |
| `check_objects_on_other_lanes` | [-] | boolean | If true, the lane change module include objects on other lanes. when performing collision assessment | false |
| `use_all_predicted_path` | [-] | boolean | If false, use only the predicted path that has the maximum confidence. | true |

(\*1) the value must be negative.

### Abort lane change
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,10 @@
stop_time: 3.0 # [s]

# collision check
enable_prepare_segment_collision_check: true
enable_collision_check_for_prepare_phase:
general_lanes: false
intersection: true
turns: true
prepare_segment_ignore_object_velocity_thresh: 0.1 # [m/s]
check_objects_on_current_lanes: true
check_objects_on_other_lanes: true
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,8 @@ class NormalLaneChange : public LaneChangeBase

bool isVehicleStuck(const lanelet::ConstLanelets & current_lanes) const;

bool check_prepare_phase() const;

double calcMaximumLaneChangeLength(
const lanelet::ConstLanelet & current_terminal_lanelet, const double max_acc) const;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,9 @@ struct LaneChangeParameters
double max_longitudinal_acc{1.0};

// collision check
bool enable_prepare_segment_collision_check{true};
bool enable_collision_check_for_prepare_phase_in_general_lanes{false};
bool enable_collision_check_for_prepare_phase_in_intersection{true};
bool enable_collision_check_for_prepare_phase_in_turns{true};
double prepare_segment_ignore_object_velocity_thresh{0.1};
bool check_objects_on_current_lanes{true};
bool check_objects_on_other_lanes{true};
Expand Down
Loading

0 comments on commit b349d7a

Please sign in to comment.