1717#include " autoware/boundary_departure_checker/conversion.hpp"
1818#include " autoware/boundary_departure_checker/utils.hpp"
1919
20+ #include < autoware/motion_utils/trajectory/interpolation.hpp>
2021#include < autoware/motion_utils/trajectory/trajectory.hpp>
2122#include < autoware/trajectory/trajectory_point.hpp>
2223#include < autoware/trajectory/utils/closest.hpp>
24+ #include < autoware/universe_utils/geometry/geometry.hpp>
2325#include < autoware_utils_math/normalization.hpp>
2426#include < autoware_utils_math/unit_conversion.hpp>
2527#include < autoware_utils_system/stop_watch.hpp>
3032
3133#include < boost/geometry.hpp>
3234
33- #include < fmt/format.h>
3435#include < lanelet2_core/geometry/Polygon.h>
3536
3637#include < algorithm>
@@ -112,19 +113,35 @@ bool is_segment_within_ego_height(
112113 std::abs (boundary_segment.second .z () - ego_z_position));
113114 return height_diff < ego_height;
114115}
116+
117+ bool has_critical_departure (
118+ const std::vector<autoware::boundary_departure_checker::ClosestProjectionToBound> &
119+ closest_projections)
120+ {
121+ const auto is_critical_departure_type = [](const auto & pt) {
122+ return pt.departure_type ==
123+ autoware::boundary_departure_checker::DepartureType::CRITICAL_DEPARTURE;
124+ };
125+ return std::any_of (
126+ closest_projections.rbegin (), closest_projections.rend (), is_critical_departure_type);
127+ }
115128} // namespace
116129
117130namespace autoware ::boundary_departure_checker
118131{
119132UncrossableBoundaryDepartureChecker::UncrossableBoundaryDepartureChecker (
120- lanelet::LaneletMapPtr lanelet_map_ptr, const VehicleInfo & vehicle_info, const Param & param,
133+ const rclcpp::Clock::SharedPtr clock_ptr, lanelet::LaneletMapPtr lanelet_map_ptr,
134+ const VehicleInfo & vehicle_info, Param param,
121135 std::shared_ptr<autoware_utils_debug::TimeKeeper> time_keeper)
122- : param_(param),
123- lanelet_map_ptr_ (lanelet_map_ptr),
136+ : param_(std::move( param) ),
137+ lanelet_map_ptr_ (std::move( lanelet_map_ptr) ),
124138 vehicle_info_ptr_(std::make_shared<VehicleInfo>(vehicle_info)),
139+ last_no_critical_dpt_time_(clock_ptr->now ().seconds()),
140+ last_found_critical_dpt_time_(clock_ptr->now ().seconds()),
141+ clock_ptr_(clock_ptr),
125142 time_keeper_(std::move(time_keeper))
126143{
127- auto try_uncrossable_boundaries_rtree = build_uncrossable_boundaries_tree (lanelet_map_ptr );
144+ auto try_uncrossable_boundaries_rtree = build_uncrossable_boundaries_tree (lanelet_map_ptr_ );
128145
129146 if (!try_uncrossable_boundaries_rtree) {
130147 throw std::runtime_error (try_uncrossable_boundaries_rtree.error ());
@@ -134,6 +151,134 @@ UncrossableBoundaryDepartureChecker::UncrossableBoundaryDepartureChecker(
134151 std::make_unique<UncrossableBoundRTree>(*try_uncrossable_boundaries_rtree);
135152}
136153
154+ void UncrossableBoundaryDepartureChecker::update_critical_departure_points (
155+ const std::vector<TrajectoryPoint> & raw_ref_traj, const double offset_from_ego,
156+ const Side<DeparturePoints> & new_departure_points,
157+ const ClosestProjectionsToBound & closest_projections_to_bound)
158+ {
159+ if (!is_critical_departure_persist (closest_projections_to_bound)) {
160+ critical_departure_points_.clear ();
161+ }
162+
163+ for (auto & crit_dpt_pt_mut : critical_departure_points_) {
164+ crit_dpt_pt_mut.ego_dist_on_ref_traj = autoware::motion_utils::calcSignedArcLength (
165+ raw_ref_traj, 0UL , crit_dpt_pt_mut.pose_on_current_ref_traj .position );
166+
167+ if (crit_dpt_pt_mut.ego_dist_on_ref_traj < offset_from_ego) {
168+ crit_dpt_pt_mut.can_be_removed = true ;
169+ continue ;
170+ }
171+
172+ const auto updated_pose =
173+ motion_utils::calcInterpolatedPose (raw_ref_traj, crit_dpt_pt_mut.ego_dist_on_ref_traj );
174+ if (
175+ const auto is_shifted_opt = utils::is_point_shifted (
176+ crit_dpt_pt_mut.pose_on_current_ref_traj , updated_pose, param_.th_pt_shift_dist_m ,
177+ param_.th_pt_shift_angle_rad )) {
178+ crit_dpt_pt_mut.can_be_removed = true ;
179+ }
180+ }
181+
182+ auto remove_itr = std::remove_if (
183+ critical_departure_points_.begin (), critical_departure_points_.end (),
184+ [](const DeparturePoint & pt) { return pt.can_be_removed ; });
185+
186+ critical_departure_points_.erase (remove_itr, critical_departure_points_.end ());
187+
188+ if (!is_continuous_critical_departure (closest_projections_to_bound)) {
189+ return ;
190+ }
191+
192+ auto new_critical_departure_point = find_new_critical_departure_points (
193+ new_departure_points, critical_departure_points_, raw_ref_traj,
194+ param_.th_point_merge_distance_m );
195+
196+ if (new_critical_departure_point.empty ()) {
197+ return ;
198+ }
199+
200+ std::move (
201+ new_critical_departure_point.begin (), new_critical_departure_point.end (),
202+ std::back_inserter (critical_departure_points_));
203+
204+ std::sort (critical_departure_points_.begin (), critical_departure_points_.end ());
205+ }
206+
207+ bool is_critical_departure (const ClosestProjectionsToBound & closest_projections_to_bound)
208+ {
209+ const auto check_side_for_critical_departure = [&](const auto side_key) {
210+ const auto & closest_projections = closest_projections_to_bound[side_key];
211+ return has_critical_departure (closest_projections);
212+ };
213+
214+ return std::any_of (g_side_keys.begin (), g_side_keys.end (), check_side_for_critical_departure);
215+ }
216+
217+ bool UncrossableBoundaryDepartureChecker::is_continuous_critical_departure (
218+ const ClosestProjectionsToBound & closest_projections_to_bound)
219+ {
220+ const auto is_critical_departure_detected = is_critical_departure (closest_projections_to_bound);
221+
222+ if (!is_critical_departure_detected) {
223+ last_no_critical_dpt_time_ = clock_ptr_->now ().seconds ();
224+ return false ;
225+ }
226+
227+ const auto t_diff = clock_ptr_->now ().seconds () - last_no_critical_dpt_time_;
228+ return t_diff >= param_.critical_departure_on_time_buffer_s ;
229+ }
230+
231+ bool UncrossableBoundaryDepartureChecker::is_critical_departure_persist (
232+ const ClosestProjectionsToBound & closest_projections_to_bound)
233+ {
234+ const auto is_critical_departure_detected =
235+ is_critical_departure (closest_projections_to_bound) && !critical_departure_points_.empty ();
236+
237+ if (is_critical_departure_detected) {
238+ last_found_critical_dpt_time_ = clock_ptr_->now ().seconds ();
239+ return true ;
240+ }
241+
242+ const auto t_diff = clock_ptr_->now ().seconds () - last_found_critical_dpt_time_;
243+ return t_diff >= param_.critical_departure_off_time_buffer_s ;
244+ }
245+
246+ CriticalDeparturePoints UncrossableBoundaryDepartureChecker::find_new_critical_departure_points (
247+ const Side<DeparturePoints> & new_departure_points,
248+ const CriticalDeparturePoints & critical_departure_points,
249+ const std::vector<TrajectoryPoint> & raw_ref_traj, const double th_point_merge_distance_m)
250+ {
251+ CriticalDeparturePoints new_critical_departure_points;
252+ for (const auto side_key : g_side_keys) {
253+ for (const auto & dpt_pt : new_departure_points[side_key]) {
254+ if (dpt_pt.departure_type != DepartureType::CRITICAL_DEPARTURE) {
255+ continue ;
256+ }
257+
258+ if (dpt_pt.can_be_removed ) {
259+ continue ;
260+ }
261+
262+ const auto is_near_curr_pts = std::any_of (
263+ critical_departure_points.begin (), critical_departure_points.end (),
264+ [&](const CriticalDeparturePoint & crit_pt) {
265+ return std::abs (dpt_pt.ego_dist_on_ref_traj - crit_pt.ego_dist_on_ref_traj ) <
266+ th_point_merge_distance_m;
267+ });
268+
269+ if (is_near_curr_pts) {
270+ continue ;
271+ }
272+
273+ CriticalDeparturePoint crit_pt (dpt_pt);
274+ crit_pt.pose_on_current_ref_traj =
275+ motion_utils::calcInterpolatedPose (raw_ref_traj, crit_pt.ego_dist_on_ref_traj );
276+ new_critical_departure_points.push_back (crit_pt);
277+ }
278+ }
279+ return new_critical_departure_points;
280+ }
281+
137282tl::expected<AbnormalitiesData, std::string>
138283UncrossableBoundaryDepartureChecker::get_abnormalities_data (
139284 const TrajectoryPoints & trajectory_points, const TrajectoryPoints & predicted_traj,
@@ -180,14 +325,14 @@ UncrossableBoundaryDepartureChecker::get_abnormalities_data(
180325 abnormalities_data.footprints_sides [abnormality_type]);
181326 }
182327
183- auto closest_projections_to_bound = get_closest_projections_to_boundaries (
328+ auto closest_projections_to_bound_opt = get_closest_projections_to_boundaries (
184329 abnormalities_data.projections_to_bound , curr_vel, curr_acc);
185330
186- if (!closest_projections_to_bound ) {
187- return tl::make_unexpected (closest_projections_to_bound .error ());
331+ if (!closest_projections_to_bound_opt ) {
332+ return tl::make_unexpected (closest_projections_to_bound_opt .error ());
188333 }
189334
190- abnormalities_data.closest_projections_to_bound = std::move (*closest_projections_to_bound );
335+ abnormalities_data.closest_projections_to_bound = std::move (*closest_projections_to_bound_opt );
191336
192337 std::vector<double > pred_traj_idx_to_ref_traj_lon_dist;
193338 pred_traj_idx_to_ref_traj_lon_dist.reserve (predicted_traj.size ());
@@ -199,6 +344,15 @@ UncrossableBoundaryDepartureChecker::get_abnormalities_data(
199344 abnormalities_data.departure_points = get_departure_points (
200345 abnormalities_data.closest_projections_to_bound , pred_traj_idx_to_ref_traj_lon_dist);
201346
347+ const auto ego_dist_on_traj_m =
348+ motion_utils::calcSignedArcLength (trajectory_points, 0UL , curr_pose_with_cov.pose .position );
349+
350+ update_critical_departure_points (
351+ trajectory_points, ego_dist_on_traj_m, abnormalities_data.departure_points ,
352+ abnormalities_data.closest_projections_to_bound );
353+
354+ abnormalities_data.critical_departure_points = critical_departure_points_;
355+
202356 return abnormalities_data;
203357}
204358
0 commit comments