Skip to content

Commit 0715615

Browse files
feat(lane_change): using frenet planner to generate lane change path when ego near terminal (#9767)
* frenet planner Signed-off-by: Zulfaqar Azmi <zulfaqar.azmi@tier4.jp> * minor refactoring Signed-off-by: Zulfaqar Azmi <zulfaqar.azmi@tier4.jp> * adding parameter Signed-off-by: Zulfaqar Azmi <zulfaqar.azmi@tier4.jp> * Add diff th param Signed-off-by: Zulfaqar Azmi <zulfaqar.azmi@tier4.jp> * limit curvature for prepare segment Signed-off-by: Zulfaqar Azmi <zulfaqar.azmi@tier4.jp> * minor refactoring Signed-off-by: Zulfaqar Azmi <zulfaqar.azmi@tier4.jp> * print average curvature Signed-off-by: Zulfaqar Azmi <zulfaqar.azmi@tier4.jp> * refactor Signed-off-by: Zulfaqar Azmi <zulfaqar.azmi@tier4.jp> * filter the path directly Signed-off-by: Zulfaqar Azmi <zulfaqar.azmi@tier4.jp> * fix some conflicts Signed-off-by: Zulfaqar Azmi <zulfaqar.azmi@tier4.jp> * include curvature smoothing Signed-off-by: Zulfaqar Azmi <zulfaqar.azmi@tier4.jp> * document Signed-off-by: Zulfaqar Azmi <zulfaqar.azmi@tier4.jp> * fix image folder Signed-off-by: Zulfaqar Azmi <zulfaqar.azmi@tier4.jp> * image size Signed-off-by: Zulfaqar Azmi <zulfaqar.azmi@tier4.jp> * doxygen Signed-off-by: Zulfaqar Azmi <zulfaqar.azmi@tier4.jp> * add debug for state Signed-off-by: Zulfaqar Azmi <zulfaqar.azmi@tier4.jp> * use sign function instead Signed-off-by: Zulfaqar Azmi <zulfaqar.azmi@tier4.jp> * rename argument Signed-off-by: Zulfaqar Azmi <zulfaqar.azmi@tier4.jp> * readme Signed-off-by: Zulfaqar Azmi <zulfaqar.azmi@tier4.jp> * fix failed test due to empty value Signed-off-by: Zulfaqar Azmi <zulfaqar.azmi@tier4.jp> * add additional note Signed-off-by: Zulfaqar Azmi <zulfaqar.azmi@tier4.jp> * fix conflict Signed-off-by: Zulfaqar Azmi <zulfaqar.azmi@tier4.jp> --------- Signed-off-by: Zulfaqar Azmi <zulfaqar.azmi@tier4.jp>
1 parent b5005b6 commit 0715615

File tree

22 files changed

+991
-54
lines changed

22 files changed

+991
-54
lines changed

planning/behavior_path_planner/autoware_behavior_path_lane_change_module/README.md

+58
Original file line numberDiff line numberDiff line change
@@ -787,6 +787,51 @@ Depending on the space configuration around the Ego vehicle, it is possible that
787787

788788
Additionally if terminal path feature is enabled and path is computed, stop point placement can be configured to be at the edge of the current lane instead of at the `terminal_start` position, as indicated by the dashed red line in the image above.
789789

790+
## Generating Path Using Frenet Planner
791+
792+
!!! warning
793+
794+
Generating path using Frenet planner applies only when ego is near terminal start
795+
796+
If the ego vehicle is far from the terminal, the lane change module defaults to using the [path shifter](https://autowarefoundation.github.io/autoware.universe/main/planning/behavior_path_planner/autoware_behavior_path_planner_common/docs/behavior_path_planner_path_generation_design/). This ensures that the lane change is completed while the target lane remains a neighbor of the current lane. However, this approach may result in high curvature paths near the terminal, potentially causing long vehicles to deviate from the lane.
797+
798+
To address this, the lane change module provides an option to choose between the path shifter and the [Frenet planner](https://autowarefoundation.github.io/autoware.universe/main/planning/sampling_based_planner/autoware_frenet_planner/). The Frenet planner allows for some flexibility in the lane change endpoint, extending the lane changing end point slightly beyond the current lane's neighbors.
799+
800+
The following table provides comparisons between the planners
801+
802+
<div align="center">
803+
<table>
804+
<tr>
805+
<td align="center">With Path Shifter</td>
806+
<td align="center">With Frenet Planner</td>
807+
</tr>
808+
<tr>
809+
<td><img src="./images/terminal_straight_path_shifter.png" alt="Path shifter result at straight lanelets" width="450"></a></td>
810+
<td><img src="./images/terminal_straight_frenet.png" alt="Frenet planner result at straight lanelets" width="450"></a></td>
811+
</tr>
812+
<tr>
813+
<td><img src="./images/terminal_branched_path_shifter.png" alt="Path shifter result at branching lanelets" width="450"></a></td>
814+
<td><img src="./images/terminal_branched_frenet.png" alt="Frenet planner result at branching lanelets" width="450"></a></td>
815+
</tr>
816+
<tr>
817+
<td><img src="./images/terminal_curved_path_shifter.png" alt="Path shifter result at curved lanelets" width="450"></a></td>
818+
<td><img src="./images/terminal_curved_frenet.png" alt="Frenet planner result at curved lanelets" width="450"></a></td>
819+
</tr>
820+
</table>
821+
</div>
822+
823+
!!! note
824+
825+
The planner can be enabled or disabled using the `frenet.enable` flag.
826+
827+
!!! note
828+
829+
Since only a segment of the target lane is used as input to generate the lane change path, the end pose of the lane change segment may not smoothly connect to the target lane centerline. To address this, increase the value of `frenet.th_curvature_smoothing` to improve the smoothness.
830+
831+
!!! note
832+
833+
The yaw difference threshold (`frenet.th_yaw_diff`) limits the maximum curvature difference between the end of the prepare segment and the lane change segment. This threshold might prevent the generation of a lane change path when the lane curvature is high. In such cases, you can increase the frenet.th_yaw_diff value. However, note that if the prepare path was initially shifted by other modules, the resultant steering may not be continuous.
834+
790835
## Aborting a Previously Approved Lane Change
791836

792837
Once the lane change path is approved, there are several situations where we may need to abort the maneuver. The abort process is triggered when any of the following conditions is met
@@ -1008,6 +1053,7 @@ The following parameters are configurable in [lane_change.param.yaml](https://gi
10081053
| `trajectory.max_longitudinal_acc` | [m/s2] | double | maximum longitudinal acceleration for lane change | 1.0 |
10091054
| `trajectory.min_longitudinal_acc` | [m/s2] | double | maximum longitudinal deceleration for lane change | -1.0 |
10101055
| `trajectory.lane_changing_decel_factor` | [-] | double | longitudinal deceleration factor during lane changing phase | 0.5 |
1056+
| `trajectory.th_prepare_curvature` | [-] | double | If the maximum curvature of the prepare segment exceeds the threshold, the prepare segment is invalid. | 0.03 |
10111057
| `min_length_for_turn_signal_activation` | [m] | double | Turn signal will be activated if the ego vehicle approaches to this length from minimum lane change length | 10.0 |
10121058
| `lateral_acceleration.velocity` | [m/s] | double | Reference velocity for lateral acceleration calculation (look up table) | [0.0, 4.0, 10.0] |
10131059
| `lateral_acceleration.min_values` | [m/s2] | double | Min lateral acceleration values corresponding to velocity (look up table) | [0.4, 0.4, 0.4] |
@@ -1057,6 +1103,18 @@ The following parameters are used to configure terminal lane change path feature
10571103
| `terminal_path.disable_near_goal` | [-] | bool | Flag to disable terminal path feature if ego is near goal | true |
10581104
| `terminal_path.stop_at_boundary` | [-] | bool | If true, ego will stop at current lane boundary instead of middle of lane | false |
10591105

1106+
### Generating Lane Changing Path using Frenet Planner
1107+
1108+
!!! warning
1109+
1110+
Only applicable when ego is near terminal start
1111+
1112+
| Name | Unit | Type | Description | Default value |
1113+
| :------------------------------ | ----- | ------ | --------------------------------------------------------------------------------------------------------------------------------------------------- | ------------- |
1114+
| `frenet.enable` | [-] | bool | Flag to enable/disable frenet planner when ego is near terminal start. | true |
1115+
| `frenet.th_yaw_diff` | [deg] | double | If the yaw diff between of the prepare segment's end and lane changing segment's start exceed the threshold , the lane changing segment is invalid. | 10.0 |
1116+
| `frenet.th_curvature_smoothing` | [-] | double | Filters and appends target path points with curvature below the threshold to candidate path. | 0.1 |
1117+
10601118
### Collision checks
10611119

10621120
#### Target Objects

planning/behavior_path_planner/autoware_behavior_path_lane_change_module/config/lane_change.param.yaml

+7
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
lon_acc_sampling_num: 5
3030
lat_acc_sampling_num: 3
3131
lane_changing_decel_factor: 0.5
32+
th_prepare_curvature: 0.03 # [/]
3233

3334
# delay lane change
3435
delay_lane_change:
@@ -37,6 +38,12 @@
3738
min_road_shoulder_width: 0.5 # [m]
3839
th_parked_vehicle_shift_ratio: 0.6
3940

41+
# trajectory generation near terminal using frenet planner
42+
frenet:
43+
enable: true
44+
th_yaw_diff: 10.0 # [deg]
45+
th_curvature_smoothing: 0.1 # [/]
46+
4047
# safety check
4148
safety_check:
4249
allow_loose_check_for_cancel: true

planning/behavior_path_planner/autoware_behavior_path_lane_change_module/include/autoware/behavior_path_lane_change_module/scene.hpp

+12
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,18 @@ class NormalLaneChange : public LaneChangeBase
140140

141141
bool get_lane_change_paths(LaneChangePaths & candidate_paths) const;
142142

143+
bool get_path_using_frenet(
144+
const std::vector<LaneChangePhaseMetrics> & prepare_metrics,
145+
const lane_change::TargetObjects & target_objects,
146+
const std::vector<std::vector<int64_t>> & sorted_lane_ids,
147+
LaneChangePaths & candidate_paths) const;
148+
149+
bool get_path_using_path_shifter(
150+
const std::vector<LaneChangePhaseMetrics> & prepare_metrics,
151+
const lane_change::TargetObjects & target_objects,
152+
const std::vector<std::vector<int64_t>> & sorted_lane_ids,
153+
LaneChangePaths & candidate_paths) const;
154+
143155
bool check_candidate_path_safety(
144156
const LaneChangePath & candidate_path, const lane_change::TargetObjects & target_objects) const;
145157

planning/behavior_path_planner/autoware_behavior_path_lane_change_module/include/autoware/behavior_path_lane_change_module/structs/data.hpp

+1
Original file line numberDiff line numberDiff line change
@@ -269,6 +269,7 @@ struct CommonData
269269
LanesPolygonPtr lanes_polygon_ptr;
270270
TransientData transient_data;
271271
PathWithLaneId current_lanes_path;
272+
PathWithLaneId target_lanes_path;
272273
ModuleType lc_type;
273274
Direction direction;
274275

planning/behavior_path_planner/autoware_behavior_path_lane_change_module/include/autoware/behavior_path_lane_change_module/structs/debug.hpp

+15
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,20 @@ struct MetricsDebug
3939
double max_lane_changing_length;
4040
};
4141

42+
struct FrenetStateDebug
43+
{
44+
LaneChangePhaseMetrics prep_metric;
45+
frenet_planner::SamplingParameter sampling_parameter;
46+
double max_lane_changing_length;
47+
48+
FrenetStateDebug(
49+
LaneChangePhaseMetrics prep_metric, frenet_planner::SamplingParameter sampling_param,
50+
const double max_len)
51+
: prep_metric(prep_metric), sampling_parameter(sampling_param), max_lane_changing_length(max_len)
52+
{
53+
}
54+
};
55+
4256
struct Debug
4357
{
4458
std::string module_type;
@@ -52,6 +66,7 @@ struct Debug
5266
lanelet::ConstLanelets target_lanes;
5367
lanelet::ConstLanelets target_backward_lanes;
5468
std::vector<MetricsDebug> lane_change_metrics;
69+
std::vector<FrenetStateDebug> frenet_states;
5570
double collision_check_object_debug_lifetime{0.0};
5671
double distance_to_end_of_current_lane{std::numeric_limits<double>::max()};
5772
double distance_to_lane_change_finished{std::numeric_limits<double>::max()};

planning/behavior_path_planner/autoware_behavior_path_lane_change_module/include/autoware/behavior_path_lane_change_module/structs/parameters.hpp

+9
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,13 @@ struct SafetyParameters
113113
CollisionCheckParameters collision_check{};
114114
};
115115

116+
struct FrenetPlannerParameters
117+
{
118+
bool enable{true};
119+
double th_yaw_diff_deg{10.0};
120+
double th_curvature_smoothing{0.1};
121+
};
122+
116123
struct TrajectoryParameters
117124
{
118125
double max_prepare_duration{4.0};
@@ -124,6 +131,7 @@ struct TrajectoryParameters
124131
double th_lane_changing_length_diff{0.5};
125132
double min_lane_changing_velocity{5.6};
126133
double lane_changing_decel_factor{0.5};
134+
double th_prepare_curvature{0.03};
127135
int lon_acc_sampling_num{10};
128136
int lat_acc_sampling_num{10};
129137
LateralAccelerationMap lat_acc_map{};
@@ -151,6 +159,7 @@ struct Parameters
151159
CancelParameters cancel{};
152160
DelayParameters delay{};
153161
TerminalPathParameters terminal_path{};
162+
FrenetPlannerParameters frenet{};
154163

155164
// lane change parameters
156165
double backward_lane_length{200.0};

planning/behavior_path_planner/autoware_behavior_path_lane_change_module/include/autoware/behavior_path_lane_change_module/structs/path.hpp

+35-2
Original file line numberDiff line numberDiff line change
@@ -19,27 +19,60 @@
1919
#include "autoware/behavior_path_planner_common/turn_signal_decider.hpp"
2020
#include "autoware/behavior_path_planner_common/utils/path_shifter/path_shifter.hpp"
2121

22+
#include <autoware_frenet_planner/structures.hpp>
23+
2224
#include <tier4_planning_msgs/msg/path_with_lane_id.hpp>
2325

26+
#include <utility>
2427
#include <vector>
2528

2629
namespace autoware::behavior_path_planner::lane_change
2730
{
31+
enum class PathType { ConstantJerk = 0, FrenetPlanner };
32+
2833
using autoware::behavior_path_planner::TurnSignalInfo;
2934
using tier4_planning_msgs::msg::PathWithLaneId;
35+
struct TrajectoryGroup
36+
{
37+
PathWithLaneId prepare;
38+
PathWithLaneId target_lane_ref_path;
39+
std::vector<double> target_lane_ref_path_dist;
40+
LaneChangePhaseMetrics prepare_metric;
41+
frenet_planner::Trajectory lane_changing;
42+
frenet_planner::FrenetState initial_state;
43+
double max_lane_changing_length{0.0};
44+
45+
TrajectoryGroup() = default;
46+
TrajectoryGroup(
47+
PathWithLaneId prepare, PathWithLaneId target_lane_ref_path,
48+
std::vector<double> target_lane_ref_path_dist, LaneChangePhaseMetrics prepare_metric,
49+
frenet_planner::Trajectory lane_changing, frenet_planner::FrenetState initial_state,
50+
const double max_lane_changing_length)
51+
: prepare(std::move(prepare)),
52+
target_lane_ref_path(std::move(target_lane_ref_path)),
53+
target_lane_ref_path_dist(std::move(target_lane_ref_path_dist)),
54+
prepare_metric(prepare_metric),
55+
lane_changing(std::move(lane_changing)),
56+
initial_state(initial_state),
57+
max_lane_changing_length(max_lane_changing_length)
58+
{
59+
}
60+
};
61+
3062
struct Path
3163
{
64+
Info info;
3265
PathWithLaneId path;
3366
ShiftedPath shifted_path;
34-
Info info;
67+
TrajectoryGroup frenet_path;
68+
PathType type = PathType::ConstantJerk;
3569
};
3670

3771
struct Status
3872
{
3973
Path lane_change_path;
4074
bool is_safe{false};
4175
bool is_valid_path{false};
42-
double start_distance{0.0};
4376
};
4477
} // namespace autoware::behavior_path_planner::lane_change
4578

planning/behavior_path_planner/autoware_behavior_path_lane_change_module/include/autoware/behavior_path_lane_change_module/utils/path.hpp

+61-1
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@
1111
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1212
// See the License for the specific language governing permissions and
1313
// limitations under the License.
14-
1514
#ifndef AUTOWARE__BEHAVIOR_PATH_LANE_CHANGE_MODULE__UTILS__PATH_HPP_
1615
#define AUTOWARE__BEHAVIOR_PATH_LANE_CHANGE_MODULE__UTILS__PATH_HPP_
1716

@@ -26,6 +25,7 @@ namespace autoware::behavior_path_planner::utils::lane_change
2625
{
2726
using behavior_path_planner::LaneChangePath;
2827
using behavior_path_planner::lane_change::CommonDataPtr;
28+
using behavior_path_planner::lane_change::TrajectoryGroup;
2929

3030
/**
3131
* @brief Generates a prepare segment for a lane change maneuver.
@@ -98,5 +98,65 @@ LaneChangePath construct_candidate_path(
9898
const LaneChangeInfo & lane_change_info, const PathWithLaneId & prepare_segment,
9999
const PathWithLaneId & target_lane_reference_path,
100100
const std::vector<std::vector<int64_t>> & sorted_lane_ids);
101+
102+
/**
103+
* @brief Generates candidate trajectories in the Frenet frame for a lane change maneuver.
104+
*
105+
* This function computes a set of candidate trajectories for the ego vehicle in the Frenet frame,
106+
* based on the provided metrics, target lane reference path, and preparation segments. It ensures
107+
* that the generated trajectories adhere to specified constraints, such as lane boundaries and
108+
* velocity limits, while optimizing for smoothness and curvature.
109+
*
110+
* @param common_data_ptr Shared pointer to CommonData containing route, lane, and transient
111+
* information.
112+
* @param prev_module_path The previous module's path used as a base for preparation segments.
113+
* @param prep_metric Metrics for the preparation phase, including path length and velocity.
114+
*
115+
* @return std::vector<lane_change::TrajectoryGroup> A vector of trajectory groups representing
116+
* valid lane change candidates, each containing the prepare segment, target reference path, and
117+
* Frenet trajectory.
118+
*/
119+
std::vector<lane_change::TrajectoryGroup> generate_frenet_candidates(
120+
const CommonDataPtr & common_data_ptr, const PathWithLaneId & prev_module_path,
121+
const std::vector<LaneChangePhaseMetrics> & prep_metrics);
122+
123+
/**
124+
* @brief Constructs a lane change path candidate based on a Frenet trajectory group.
125+
*
126+
* This function generates a candidate lane change path by converting a Frenet trajectory group
127+
* into a shifted path and combining it with a prepare segment. It validates the path's feasibility
128+
* by ensuring yaw differences are within allowable thresholds and calculates lane change
129+
* information, such as acceleration, velocity, and duration.
130+
*
131+
* @param trajectory_group A Frenet trajectory group containing the prepared path and Frenet
132+
* trajectory data.
133+
* @param common_data_ptr Shared pointer to CommonData providing parameters and constraints for lane
134+
* changes.
135+
* @param sorted_lane_ids A vector of sorted lane IDs used to update the lane IDs in the path.
136+
*
137+
* @return std::optional<LaneChangePath> The constructed candidate lane change path if valid, or
138+
* std::nullopt if the path is not feasible.
139+
*
140+
* @throws std::logic_error If the yaw difference exceeds the threshold, or other critical errors
141+
* occur.
142+
*/
143+
std::optional<LaneChangePath> get_candidate_path(
144+
const TrajectoryGroup & trajectory_group, const CommonDataPtr & common_data_ptr,
145+
const std::vector<std::vector<int64_t>> & sorted_lane_ids);
146+
147+
/**
148+
* @brief Appends the target lane reference path to the candidate lane change path.
149+
*
150+
* This function extends the lane change candidate path by appending points from the
151+
* target lane reference path beyond the lane change end position. The appending process
152+
* is constrained by a curvature threshold to ensure smooth transitions and avoid sharp turns.
153+
*
154+
* @param frenet_candidate The candidate lane change path to which the target reference path is
155+
* appended. This includes the lane change path and associated Frenet trajectory data.
156+
* @param th_curvature_smoothing A threshold for the allowable curvature during the extension
157+
* process. Points with curvature exceeding this threshold are excluded.
158+
*/
159+
void append_target_ref_to_candidate(LaneChangePath & frenet_candidate, const double th_curvature);
101160
} // namespace autoware::behavior_path_planner::utils::lane_change
161+
102162
#endif // AUTOWARE__BEHAVIOR_PATH_LANE_CHANGE_MODULE__UTILS__PATH_HPP_

0 commit comments

Comments
 (0)