Skip to content

Commit 2465bbf

Browse files
authored
feat(avoidance): improve stop behavior under decel/jerk constraints option (#3978)
* feat(avoidance): add option to decel within constraints Signed-off-by: satoshi-ota <satoshi.ota928@gmail.com> * chore(avoidance): add comments Signed-off-by: satoshi-ota <satoshi.ota928@gmail.com> * refactor(utils): merge similar functions Signed-off-by: satoshi-ota <satoshi.ota928@gmail.com> --------- Signed-off-by: satoshi-ota <satoshi.ota928@gmail.com>
1 parent bcc93c1 commit 2465bbf

File tree

6 files changed

+103
-50
lines changed

6 files changed

+103
-50
lines changed

planning/behavior_path_planner/include/behavior_path_planner/scene_module/avoidance/avoidance_module.hpp

+1-2
Original file line numberDiff line numberDiff line change
@@ -231,10 +231,9 @@ class AvoidanceModule : public SceneModuleInterface
231231

232232
/**
233233
* @brief insert stop point in output path.
234-
* @param flag. if it is true, the ego decelerates within accel/jerk constraints.
235234
* @param target path.
236235
*/
237-
void insertPrepareVelocity(const bool avoidable, ShiftedPath & shifted_path) const;
236+
void insertPrepareVelocity(ShiftedPath & shifted_path) const;
238237

239238
/**
240239
* @brief insert decel point in output path in order to yield. the ego decelerates within

planning/behavior_path_planner/include/behavior_path_planner/utils/avoidance/avoidance_module_data.hpp

+9-3
Original file line numberDiff line numberDiff line change
@@ -349,15 +349,21 @@ struct ObjectData // avoidance target
349349
// to intersection
350350
double to_stop_factor_distance{std::numeric_limits<double>::infinity()};
351351

352+
// to stop line distance
353+
double to_stop_line{std::numeric_limits<double>::infinity()};
354+
352355
// if lateral margin is NOT enough, the ego must avoid the object.
353356
bool avoid_required{false};
354357

355-
// unavoidable reason
356-
std::string reason{""};
357-
358358
// is avoidable by behavior module
359359
bool is_avoidable{false};
360360

361+
// is stoppable under the constraints
362+
bool is_stoppable{false};
363+
364+
// unavoidable reason
365+
std::string reason{""};
366+
361367
// lateral avoid margin
362368
// NOTE: If margin is less than the minimum margin threshold, boost::none will be set.
363369
boost::optional<double> avoid_margin{boost::none};

planning/behavior_path_planner/include/behavior_path_planner/utils/avoidance/helper.hpp

+19-12
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
#include <motion_utils/distance/distance.hpp>
2222

2323
#include <algorithm>
24+
#include <limits>
2425
#include <memory>
2526

2627
namespace behavior_path_planner::helper::avoidance
@@ -39,6 +40,13 @@ class AvoidanceHelper
3940
{
4041
}
4142

43+
AvoidanceHelper(
44+
const std::shared_ptr<const PlannerData> & data,
45+
const std::shared_ptr<AvoidanceParameters> & parameters)
46+
: data_{data}, parameters_{parameters}
47+
{
48+
}
49+
4250
void validate() const
4351
{
4452
const auto reference_points_size = prev_reference_path_.points.size();
@@ -190,22 +198,21 @@ class AvoidanceHelper
190198
return *itr;
191199
}
192200

193-
boost::optional<double> getFeasibleDecelDistance(const double target_velocity) const
201+
double getFeasibleDecelDistance(
202+
const double target_velocity, const bool use_hard_constraints = true) const
194203
{
204+
const auto & p = parameters_;
195205
const auto & a_now = data_->self_acceleration->accel.accel.linear.x;
196-
const auto & a_lim = parameters_->max_deceleration;
197-
const auto & j_lim = parameters_->max_jerk;
198-
return calcDecelDistWithJerkAndAccConstraints(
206+
const auto & a_lim = use_hard_constraints ? p->max_deceleration : p->nominal_deceleration;
207+
const auto & j_lim = use_hard_constraints ? p->max_jerk : p->nominal_jerk;
208+
const auto ret = calcDecelDistWithJerkAndAccConstraints(
199209
getEgoSpeed(), target_velocity, a_now, a_lim, j_lim, -1.0 * j_lim);
200-
}
201210

202-
boost::optional<double> getMildDecelDistance(const double target_velocity) const
203-
{
204-
const auto & a_now = data_->self_acceleration->accel.accel.linear.x;
205-
const auto & a_lim = parameters_->nominal_deceleration;
206-
const auto & j_lim = parameters_->nominal_jerk;
207-
return calcDecelDistWithJerkAndAccConstraints(
208-
getEgoSpeed(), target_velocity, a_now, a_lim, j_lim, -1.0 * j_lim);
211+
if (!!ret) {
212+
return ret.get();
213+
}
214+
215+
return std::numeric_limits<double>::max();
209216
}
210217

211218
bool isInitialized() const

planning/behavior_path_planner/include/behavior_path_planner/utils/avoidance/utils.hpp

+4
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,10 @@ void fillAvoidanceNecessity(
9898
ObjectData & object_data, const ObjectDataArray & registered_objects, const double vehicle_width,
9999
const std::shared_ptr<AvoidanceParameters> & parameters);
100100

101+
void fillObjectStoppableJudge(
102+
ObjectData & object_data, const ObjectDataArray & registered_objects,
103+
const double feasible_stop_distance, const std::shared_ptr<AvoidanceParameters> & parameters);
104+
101105
void updateRegisteredObject(
102106
ObjectDataArray & registered_objects, const ObjectDataArray & now_objects,
103107
const std::shared_ptr<AvoidanceParameters> & parameters);

planning/behavior_path_planner/src/scene_module/avoidance/avoidance_module.cpp

+43-33
Original file line numberDiff line numberDiff line change
@@ -318,7 +318,12 @@ AvoidancePlanningData AvoidanceModule::calcAvoidancePlanningData(DebugData & deb
318318
void AvoidanceModule::fillAvoidanceTargetObjects(
319319
AvoidancePlanningData & data, DebugData & debug) const
320320
{
321-
const auto expanded_lanelets = utils::avoidance::getTargetLanelets(
321+
using utils::avoidance::fillObjectStoppableJudge;
322+
using utils::avoidance::filterTargetObjects;
323+
using utils::avoidance::getTargetLanelets;
324+
325+
// Separate dynamic objects based on whether they are inside or outside of the expanded lanelets.
326+
const auto expanded_lanelets = getTargetLanelets(
322327
planner_data_, data.current_lanelets, parameters_->detection_area_left_expand_dist,
323328
parameters_->detection_area_right_expand_dist * (-1.0));
324329

@@ -337,7 +342,18 @@ void AvoidanceModule::fillAvoidanceTargetObjects(
337342
objects.push_back(createObjectData(data, object));
338343
}
339344

340-
utils::avoidance::filterTargetObjects(objects, data, debug, planner_data_, parameters_);
345+
// Filter out the objects to determine the ones to be avoided.
346+
filterTargetObjects(objects, data, debug, planner_data_, parameters_);
347+
348+
// Calculate the distance needed to safely decelerate the ego vehicle to a stop line.
349+
// TODO(Satoshi OTA) use helper_ after the manager transition
350+
helper::avoidance::AvoidanceHelper helper(planner_data_, parameters_);
351+
352+
const auto feasible_stop_distance = helper.getFeasibleDecelDistance(0.0);
353+
std::for_each(data.target_objects.begin(), data.target_objects.end(), [&, this](auto & o) {
354+
o.to_stop_line = calcDistanceToStopLine(o);
355+
fillObjectStoppableJudge(o, registered_objects_, feasible_stop_distance, parameters_);
356+
});
341357

342358
// debug
343359
{
@@ -355,9 +371,7 @@ void AvoidanceModule::fillAvoidanceTargetObjects(
355371
debug_info_array.push_back(debug_info);
356372
};
357373

358-
for (const auto & o : objects) {
359-
append(o);
360-
}
374+
std::for_each(objects.begin(), objects.end(), [&](const auto & o) { append(o); });
361375

362376
updateAvoidanceDebugData(debug_info_array);
363377
}
@@ -516,7 +530,7 @@ void AvoidanceModule::fillEgoStatus(
516530
if (o.avoid_required && enough_space) {
517531
data.avoid_required = true;
518532
data.stop_target_object = o;
519-
data.to_stop_line = calcDistanceToStopLine(o);
533+
data.to_stop_line = o.to_stop_line;
520534
break;
521535
}
522536
}
@@ -660,17 +674,16 @@ void AvoidanceModule::updateEgoBehavior(const AvoidancePlanningData & data, Shif
660674
break;
661675
}
662676
case AvoidanceState::AVOID_PATH_NOT_READY: {
663-
insertPrepareVelocity(false, path);
677+
insertPrepareVelocity(path);
664678
insertWaitPoint(parameters_->use_constraints_for_decel, path);
665679
break;
666680
}
667681
case AvoidanceState::AVOID_PATH_READY: {
668-
insertPrepareVelocity(true, path);
669682
insertWaitPoint(parameters_->use_constraints_for_decel, path);
670683
break;
671684
}
672685
case AvoidanceState::AVOID_EXECUTE: {
673-
insertStopPoint(true, path);
686+
insertStopPoint(parameters_->use_constraints_for_decel, path);
674687
break;
675688
}
676689
default:
@@ -3290,18 +3303,26 @@ void AvoidanceModule::insertWaitPoint(
32903303
return;
32913304
}
32923305

3306+
// If we don't need to consider deceleration constraints, insert a deceleration point
3307+
// and return immediately
32933308
if (!use_constraints_for_decel) {
32943309
utils::avoidance::insertDecelPoint(
32953310
getEgoPosition(), data.to_stop_line, 0.0, shifted_path.path, stop_pose_);
32963311
return;
32973312
}
32983313

3299-
const auto stop_distance = helper_.getMildDecelDistance(0.0);
3300-
if (stop_distance) {
3301-
const auto insert_distance = std::max(data.to_stop_line, *stop_distance);
3314+
// If target object can be stopped for, insert a deceleration point and return
3315+
if (data.stop_target_object.get().is_stoppable) {
33023316
utils::avoidance::insertDecelPoint(
3303-
getEgoPosition(), insert_distance, 0.0, shifted_path.path, stop_pose_);
3317+
getEgoPosition(), data.to_stop_line, 0.0, shifted_path.path, stop_pose_);
3318+
return;
33043319
}
3320+
3321+
// If the object cannot be stopped for, calculate a "mild" deceleration distance
3322+
// and insert a deceleration point at that distance
3323+
const auto stop_distance = helper_.getFeasibleDecelDistance(0.0, false);
3324+
utils::avoidance::insertDecelPoint(
3325+
getEgoPosition(), stop_distance, 0.0, shifted_path.path, stop_pose_);
33053326
}
33063327

33073328
void AvoidanceModule::insertStopPoint(
@@ -3333,19 +3354,16 @@ void AvoidanceModule::insertStopPoint(
33333354
const auto stop_distance =
33343355
calcSignedArcLength(shifted_path.path.points, getEgoPosition(), stop_idx);
33353356

3336-
// Insert deceleration point at stop distance without deceleration if use_constraints_for_decel is
3337-
// false
3357+
// If we don't need to consider deceleration constraints, insert a deceleration point
3358+
// and return immediately
33383359
if (!use_constraints_for_decel) {
33393360
utils::avoidance::insertDecelPoint(
33403361
getEgoPosition(), stop_distance, 0.0, shifted_path.path, stop_pose_);
33413362
return;
33423363
}
33433364

33443365
// Otherwise, consider deceleration constraints before inserting deceleration point
3345-
const auto decel_distance = helper_.getMildDecelDistance(0.0);
3346-
if (!decel_distance) {
3347-
return;
3348-
}
3366+
const auto decel_distance = helper_.getFeasibleDecelDistance(0.0, false);
33493367
if (stop_distance < decel_distance) {
33503368
return;
33513369
}
@@ -3368,14 +3386,12 @@ void AvoidanceModule::insertYieldVelocity(ShiftedPath & shifted_path) const
33683386
return;
33693387
}
33703388

3371-
const auto decel_distance = helper_.getMildDecelDistance(p->yield_velocity);
3372-
if (decel_distance) {
3373-
utils::avoidance::insertDecelPoint(
3374-
getEgoPosition(), *decel_distance, p->yield_velocity, shifted_path.path, slow_pose_);
3375-
}
3389+
const auto decel_distance = helper_.getFeasibleDecelDistance(p->yield_velocity, false);
3390+
utils::avoidance::insertDecelPoint(
3391+
getEgoPosition(), decel_distance, p->yield_velocity, shifted_path.path, slow_pose_);
33763392
}
33773393

3378-
void AvoidanceModule::insertPrepareVelocity(const bool avoidable, ShiftedPath & shifted_path) const
3394+
void AvoidanceModule::insertPrepareVelocity(ShiftedPath & shifted_path) const
33793395
{
33803396
const auto & data = avoidance_data_;
33813397

@@ -3393,15 +3409,9 @@ void AvoidanceModule::insertPrepareVelocity(const bool avoidable, ShiftedPath &
33933409
return;
33943410
}
33953411

3396-
if (avoidable) {
3397-
return;
3398-
}
3399-
34003412
const auto decel_distance = helper_.getFeasibleDecelDistance(0.0);
3401-
if (decel_distance) {
3402-
utils::avoidance::insertDecelPoint(
3403-
getEgoPosition(), *decel_distance, 0.0, shifted_path.path, slow_pose_);
3404-
}
3413+
utils::avoidance::insertDecelPoint(
3414+
getEgoPosition(), decel_distance, 0.0, shifted_path.path, slow_pose_);
34053415
}
34063416

34073417
std::shared_ptr<AvoidanceDebugMsgArray> AvoidanceModule::get_debug_msg_array() const

planning/behavior_path_planner/src/utils/avoidance/utils.cpp

+27
Original file line numberDiff line numberDiff line change
@@ -600,6 +600,33 @@ void fillAvoidanceNecessity(
600600
object_data.avoid_required = check_necessity(parameters->safety_check_hysteresis_factor);
601601
}
602602

603+
void fillObjectStoppableJudge(
604+
ObjectData & object_data, const ObjectDataArray & registered_objects,
605+
const double feasible_stop_distance, const std::shared_ptr<AvoidanceParameters> & parameters)
606+
{
607+
if (!parameters->use_constraints_for_decel) {
608+
object_data.is_stoppable = true;
609+
}
610+
611+
const auto id = object_data.object.object_id;
612+
const auto same_id_obj = std::find_if(
613+
registered_objects.begin(), registered_objects.end(),
614+
[&id](const auto & o) { return o.object.object_id == id; });
615+
616+
const auto is_stoppable = object_data.to_stop_line > feasible_stop_distance;
617+
if (is_stoppable) {
618+
object_data.is_stoppable = true;
619+
return;
620+
}
621+
622+
if (same_id_obj == registered_objects.end()) {
623+
object_data.is_stoppable = false;
624+
return;
625+
}
626+
627+
object_data.is_stoppable = same_id_obj->is_stoppable;
628+
}
629+
603630
void updateRegisteredObject(
604631
ObjectDataArray & registered_objects, const ObjectDataArray & now_objects,
605632
const std::shared_ptr<AvoidanceParameters> & parameters)

0 commit comments

Comments
 (0)