Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(intersection): fix topological sort for complicated intersection #8520

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,16 @@ target_link_libraries(${PROJECT_NAME}

ament_auto_package(INSTALL_TO_SHARE config)

if(BUILD_TESTING)
find_package(ament_lint_auto REQUIRED)
ament_lint_auto_find_test_dependencies()
file(GLOB_RECURSE TEST_SOURCES test/*.cpp)
ament_add_ros_isolated_gtest(test_${PROJECT_NAME}
${TEST_SOURCES}
)
target_link_libraries(test_${PROJECT_NAME} ${PROJECT_NAME})
endif()

install(PROGRAMS
scripts/ttc.py
DESTINATION lib/${PROJECT_NAME}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
<depend>autoware_planning_msgs</depend>
<depend>autoware_route_handler</depend>
<depend>autoware_rtc_interface</depend>
<depend>autoware_test_utils</depend>
<depend>autoware_universe_utils</depend>
<depend>autoware_vehicle_info_utils</depend>
<depend>fmt</depend>
Expand All @@ -40,6 +41,7 @@
<depend>tier4_planning_msgs</depend>
<depend>visualization_msgs</depend>

<test_depend>ament_cmake_ros</test_depend>
<test_depend>ament_lint_auto</test_depend>
<test_depend>autoware_lint_common</test_depend>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -590,7 +590,8 @@ class IntersectionModule : public SceneModuleInterface
* @brief generate discretized detection lane linestring.
*/
std::vector<lanelet::ConstLineString3d> generateDetectionLaneDivisions(
lanelet::ConstLanelets detection_lanelets_all,
const lanelet::ConstLanelets & occlusion_detection_lanelets,
const lanelet::ConstLanelets & conflicting_detection_lanelets,
const lanelet::routing::RoutingGraphPtr routing_graph_ptr, const double resolution) const;
/** @} */

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright 2024 Tier IV, Inc.

Check notice on line 1 in planning/behavior_velocity_planner/autoware_behavior_velocity_intersection_module/src/scene_intersection_prepare_data.cpp

View check run for this annotation

CodeScene Delta Analysis / CodeScene Cloud Delta Analysis (main)

✅ Getting better: Overall Code Complexity

The mean cyclomatic complexity decreases from 12.91 to 12.08, threshold = 4. This file has many conditional statements (e.g. if, for, while) across its implementation, leading to lower code health. Avoid adding more conditionals.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -266,8 +266,8 @@

if (!occlusion_attention_divisions_) {
occlusion_attention_divisions_ = generateDetectionLaneDivisions(
intersection_lanelets.occlusion_attention(), routing_graph_ptr,
planner_data_->occupancy_grid->info.resolution);
intersection_lanelets.occlusion_attention(), intersection_lanelets.attention_non_preceding(),
routing_graph_ptr, planner_data_->occupancy_grid->info.resolution);

Check warning on line 270 in planning/behavior_velocity_planner/autoware_behavior_velocity_intersection_module/src/scene_intersection_prepare_data.cpp

View check run for this annotation

Codecov / codecov/patch

planning/behavior_velocity_planner/autoware_behavior_velocity_intersection_module/src/scene_intersection_prepare_data.cpp#L270

Added line #L270 was not covered by tests
}

if (has_traffic_light_) {
Expand Down Expand Up @@ -577,6 +577,73 @@
return intersection_stoplines;
}

static std::vector<std::deque<lanelet::ConstLanelet>> getPrecedingLaneletsUptoIntersectionRecursive(

Check warning on line 580 in planning/behavior_velocity_planner/autoware_behavior_velocity_intersection_module/src/scene_intersection_prepare_data.cpp

View check run for this annotation

Codecov / codecov/patch

planning/behavior_velocity_planner/autoware_behavior_velocity_intersection_module/src/scene_intersection_prepare_data.cpp#L580

Added line #L580 was not covered by tests
const lanelet::routing::RoutingGraphPtr & graph, const lanelet::ConstLanelet & lanelet,
const double length, const lanelet::ConstLanelets & exclude_lanelets)
{
std::vector<std::deque<lanelet::ConstLanelet>> preceding_lanelet_sequences;

const auto prev_lanelets = graph->previous(lanelet);
const double lanelet_length = lanelet::utils::getLaneletLength3d(lanelet);

// end condition of the recursive function
if (prev_lanelets.empty() || lanelet_length >= length) {
preceding_lanelet_sequences.push_back({lanelet});
return preceding_lanelet_sequences;

Check warning on line 592 in planning/behavior_velocity_planner/autoware_behavior_velocity_intersection_module/src/scene_intersection_prepare_data.cpp

View check run for this annotation

Codecov / codecov/patch

planning/behavior_velocity_planner/autoware_behavior_velocity_intersection_module/src/scene_intersection_prepare_data.cpp#L592

Added line #L592 was not covered by tests
}

for (const auto & prev_lanelet : prev_lanelets) {
if (lanelet::utils::contains(exclude_lanelets, prev_lanelet)) {
// if prev_lanelet is included in exclude_lanelets,
// remove prev_lanelet from preceding_lanelet_sequences
continue;

Check warning on line 599 in planning/behavior_velocity_planner/autoware_behavior_velocity_intersection_module/src/scene_intersection_prepare_data.cpp

View check run for this annotation

Codecov / codecov/patch

planning/behavior_velocity_planner/autoware_behavior_velocity_intersection_module/src/scene_intersection_prepare_data.cpp#L599

Added line #L599 was not covered by tests
}
if (const std::string turn_direction = prev_lanelet.attributeOr("turn_direction", "else");
turn_direction == "left" || turn_direction == "right") {
continue;
}

// get lanelet sequence after prev_lanelet
auto tmp_lanelet_sequences = getPrecedingLaneletsUptoIntersectionRecursive(
graph, prev_lanelet, length - lanelet_length, exclude_lanelets);
for (auto & tmp_lanelet_sequence : tmp_lanelet_sequences) {
tmp_lanelet_sequence.push_back(lanelet);
preceding_lanelet_sequences.push_back(tmp_lanelet_sequence);
}
}

if (preceding_lanelet_sequences.empty()) {
preceding_lanelet_sequences.push_back({lanelet});
}
return preceding_lanelet_sequences;
}

Check warning on line 619 in planning/behavior_velocity_planner/autoware_behavior_velocity_intersection_module/src/scene_intersection_prepare_data.cpp

View check run for this annotation

CodeScene Delta Analysis / CodeScene Cloud Delta Analysis (main)

❌ New issue: Complex Method

getPrecedingLaneletsUptoIntersectionRecursive has a cyclomatic complexity of 11, threshold = 9. This function has many conditional statements (e.g. if, for, while), leading to lower code health. Avoid adding more conditionals and code to it without refactoring.

static std::vector<lanelet::ConstLanelets> getPrecedingLaneletsUptoIntersection(

Check warning on line 621 in planning/behavior_velocity_planner/autoware_behavior_velocity_intersection_module/src/scene_intersection_prepare_data.cpp

View check run for this annotation

Codecov / codecov/patch

planning/behavior_velocity_planner/autoware_behavior_velocity_intersection_module/src/scene_intersection_prepare_data.cpp#L621

Added line #L621 was not covered by tests
const lanelet::routing::RoutingGraphPtr & graph, const lanelet::ConstLanelet & lanelet,
const double length, const lanelet::ConstLanelets & exclude_lanelets)
{
std::vector<lanelet::ConstLanelets> lanelet_sequences_vec;
const auto prev_lanelets = graph->previous(lanelet);
for (const auto & prev_lanelet : prev_lanelets) {
if (lanelet::utils::contains(exclude_lanelets, prev_lanelet)) {
// if prev_lanelet is included in exclude_lanelets,
// remove prev_lanelet from preceding_lanelet_sequences
continue;

Check warning on line 631 in planning/behavior_velocity_planner/autoware_behavior_velocity_intersection_module/src/scene_intersection_prepare_data.cpp

View check run for this annotation

Codecov / codecov/patch

planning/behavior_velocity_planner/autoware_behavior_velocity_intersection_module/src/scene_intersection_prepare_data.cpp#L631

Added line #L631 was not covered by tests
}
if (const std::string turn_direction = prev_lanelet.attributeOr("turn_direction", "else");
turn_direction == "left" || turn_direction == "right") {
continue;
}
// convert deque into vector
const auto lanelet_sequences_deq =
getPrecedingLaneletsUptoIntersectionRecursive(graph, prev_lanelet, length, exclude_lanelets);
for (const auto & lanelet_sequence : lanelet_sequences_deq) {
lanelet_sequences_vec.emplace_back(lanelet_sequence.begin(), lanelet_sequence.end());
}
}
return lanelet_sequences_vec;

Check warning on line 644 in planning/behavior_velocity_planner/autoware_behavior_velocity_intersection_module/src/scene_intersection_prepare_data.cpp

View check run for this annotation

Codecov / codecov/patch

planning/behavior_velocity_planner/autoware_behavior_velocity_intersection_module/src/scene_intersection_prepare_data.cpp#L644

Added line #L644 was not covered by tests
}

IntersectionLanelets IntersectionModule::generateObjectiveLanelets(
lanelet::LaneletMapConstPtr lanelet_map_ptr, lanelet::routing::RoutingGraphPtr routing_graph_ptr,
const lanelet::ConstLanelet assigned_lanelet) const
Expand Down Expand Up @@ -706,66 +773,58 @@
if (inserted.second) occlusion_detection_and_preceding_lanelets.push_back(ll);
// get preceding lanelets without ego_lanelets
// to prevent the detection area from including the ego lanes and its' preceding lanes.
const auto lanelet_sequences = lanelet::utils::query::getPrecedingLaneletSequences(
routing_graph_ptr, ll, length, ego_lanelets);
const auto lanelet_sequences =
getPrecedingLaneletsUptoIntersection(routing_graph_ptr, ll, length, ego_lanelets);
for (const auto & ls : lanelet_sequences) {
for (const auto & l : ls) {
const auto & inner_inserted = detection_ids.insert(l.id());
if (inner_inserted.second) occlusion_detection_and_preceding_lanelets.push_back(l);
}
}
}
}
lanelet::ConstLanelets occlusion_detection_and_preceding_lanelets_wo_turn_direction;
for (const auto & ll : occlusion_detection_and_preceding_lanelets) {
const std::string turn_direction = ll.attributeOr("turn_direction", "else");
if (turn_direction == "left" || turn_direction == "right") {
continue;
}
occlusion_detection_and_preceding_lanelets_wo_turn_direction.push_back(ll);
}

auto [attention_lanelets, original_attention_lanelet_sequences] =
util::mergeLaneletsByTopologicalSort(detection_and_preceding_lanelets, routing_graph_ptr);
util::mergeLaneletsByTopologicalSort(
detection_and_preceding_lanelets, detection_lanelets, routing_graph_ptr);

IntersectionLanelets result;
result.attention_ = std::move(attention_lanelets);
for (const auto & original_attention_lanelet_seq : original_attention_lanelet_sequences) {
// NOTE: in mergeLaneletsByTopologicalSort(), sub_ids are empty checked, so it is ensured that
// back() exists.
std::optional<lanelet::ConstLineString3d> stopline{std::nullopt};
for (auto it = original_attention_lanelet_seq.rbegin();
it != original_attention_lanelet_seq.rend(); ++it) {
const auto traffic_lights = it->regulatoryElementsAs<lanelet::TrafficLight>();
for (const auto & traffic_light : traffic_lights) {
const auto stopline_opt = traffic_light->stopLine();
if (!stopline_opt) continue;
stopline = stopline_opt.get();
break;
}
if (stopline) break;
}
result.attention_stoplines_.push_back(stopline);
}
result.attention_non_preceding_ = std::move(detection_lanelets);
for (unsigned i = 0; i < result.attention_non_preceding_.size(); ++i) {
std::optional<lanelet::ConstLineString3d> stopline = std::nullopt;
const auto & ll = result.attention_non_preceding_.at(i);
const auto traffic_lights = ll.regulatoryElementsAs<lanelet::TrafficLight>();
for (const auto & traffic_light : traffic_lights) {
const auto stopline_opt = traffic_light->stopLine();
if (!stopline_opt) continue;
stopline = stopline_opt.get();
}
result.attention_non_preceding_stoplines_.push_back(stopline);
}
result.conflicting_ = std::move(conflicting_ex_ego_lanelets);
result.adjacent_ = planning_utils::getConstLaneletsFromIds(lanelet_map_ptr, associative_ids_);
// NOTE: occlusion_attention is not inverted here
// TODO(Mamoru Sobue): apply mergeLaneletsByTopologicalSort for occlusion lanelets as well and
// then trim part of them based on curvature threshold
result.occlusion_attention_ =
std::move(occlusion_detection_and_preceding_lanelets_wo_turn_direction);
result.occlusion_attention_ = std::move(occlusion_detection_and_preceding_lanelets);

Check notice on line 827 in planning/behavior_velocity_planner/autoware_behavior_velocity_intersection_module/src/scene_intersection_prepare_data.cpp

View check run for this annotation

CodeScene Delta Analysis / CodeScene Cloud Delta Analysis (main)

✅ Getting better: Complex Method

IntersectionModule::generateObjectiveLanelets decreases in cyclomatic complexity from 52 to 48, threshold = 9. This function has many conditional statements (e.g. if, for, while), leading to lower code health. Avoid adding more conditionals and code to it without refactoring.

Check notice on line 827 in planning/behavior_velocity_planner/autoware_behavior_velocity_intersection_module/src/scene_intersection_prepare_data.cpp

View check run for this annotation

CodeScene Delta Analysis / CodeScene Cloud Delta Analysis (main)

✅ Getting better: Bumpy Road Ahead

IntersectionModule::generateObjectiveLanelets decreases from 13 to 12 logical blocks with deeply nested code, threshold is one single block per function. The Bumpy Road code smell is a function that contains multiple chunks of nested conditional logic. The deeper the nesting and the more bumps, the lower the code health.

Check warning on line 827 in planning/behavior_velocity_planner/autoware_behavior_velocity_intersection_module/src/scene_intersection_prepare_data.cpp

View check run for this annotation

Codecov / codecov/patch

planning/behavior_velocity_planner/autoware_behavior_velocity_intersection_module/src/scene_intersection_prepare_data.cpp#L827

Added line #L827 was not covered by tests

// NOTE: to properly update(), each element in conflicting_/conflicting_area_,
// attention_non_preceding_/attention_non_preceding_area_ need to be matched
Expand Down Expand Up @@ -851,7 +910,8 @@
}

std::vector<lanelet::ConstLineString3d> IntersectionModule::generateDetectionLaneDivisions(
lanelet::ConstLanelets detection_lanelets_all,
const lanelet::ConstLanelets & occlusion_detection_lanelets,
const lanelet::ConstLanelets & conflicting_detection_lanelets,
const lanelet::routing::RoutingGraphPtr routing_graph_ptr, const double resolution) const
{
const double curvature_threshold =
Expand All @@ -861,9 +921,9 @@

using lanelet::utils::getCenterlineWithOffset;

// (0) remove left/right lanelet
// (0) remove curved
lanelet::ConstLanelets detection_lanelets;
for (const auto & detection_lanelet : detection_lanelets_all) {
for (const auto & detection_lanelet : occlusion_detection_lanelets) {
// TODO(Mamoru Sobue): instead of ignoring, only trim straight part of lanelet
const auto fine_centerline =
lanelet::utils::generateFineCenterline(detection_lanelet, curvature_calculation_ds);
Expand All @@ -875,8 +935,8 @@
}

// (1) tsort detection_lanelets
const auto [merged_detection_lanelets, originals] =
util::mergeLaneletsByTopologicalSort(detection_lanelets, routing_graph_ptr);
const auto [merged_detection_lanelets, originals] = util::mergeLaneletsByTopologicalSort(
detection_lanelets, conflicting_detection_lanelets, routing_graph_ptr);

// (2) merge each branch to one lanelet
// NOTE: somehow bg::area() for merged lanelet does not work, so calculate it here
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright 2020 Tier IV, Inc.

Check notice on line 1 in planning/behavior_velocity_planner/autoware_behavior_velocity_intersection_module/src/util.cpp

View check run for this annotation

CodeScene Delta Analysis / CodeScene Cloud Delta Analysis (main)

✅ Getting better: Overall Code Complexity

The mean cyclomatic complexity decreases from 4.80 to 4.44, threshold = 4. This file has many conditional statements (e.g. if, for, while) across its implementation, leading to lower code health. Avoid adding more conditionals.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -32,12 +32,10 @@

#include <algorithm>
#include <cmath>
#include <limits>
#include <map>
#include <memory>
#include <set>
#include <string>
#include <unordered_map>
#include <unordered_set>
#include <vector>

namespace autoware::behavior_velocity_planner::util
Expand Down Expand Up @@ -214,98 +212,106 @@
}
return std::nullopt;
}
std::vector<std::vector<size_t>> retrievePathsBackward(
const std::vector<std::vector<bool>> & adjacency, size_t start_node)
{
std::vector<std::vector<size_t>> paths;
std::vector<size_t> current_path;
std::unordered_set<size_t> visited;

std::function<void(size_t)> retrieve_paths_backward_impl = [&](size_t src_ind) {
current_path.push_back(src_ind);
visited.insert(src_ind);

bool is_terminal = true;
const auto & nexts = adjacency[src_ind];

Check warning on line 227 in planning/behavior_velocity_planner/autoware_behavior_velocity_intersection_module/src/util.cpp

View workflow job for this annotation

GitHub Actions / spell-check-differential

Unknown word (nexts)

for (size_t next = 0; next < nexts.size(); ++next) {

Check warning on line 229 in planning/behavior_velocity_planner/autoware_behavior_velocity_intersection_module/src/util.cpp

View workflow job for this annotation

GitHub Actions / spell-check-differential

Unknown word (nexts)
if (nexts[next]) {

Check warning on line 230 in planning/behavior_velocity_planner/autoware_behavior_velocity_intersection_module/src/util.cpp

View workflow job for this annotation

GitHub Actions / spell-check-differential

Unknown word (nexts)
is_terminal = false;
if (visited.find(next) == visited.end()) {
retrieve_paths_backward_impl(next);
} else {
// Loop detected
paths.push_back(current_path);
}
}
}

if (is_terminal) {
paths.push_back(current_path);
}

current_path.pop_back();
visited.erase(src_ind);
};

retrieve_paths_backward_impl(start_node);
return paths;
}

std::pair<lanelet::ConstLanelets, std::vector<lanelet::ConstLanelets>>
mergeLaneletsByTopologicalSort(
const lanelet::ConstLanelets & lanelets,
const lanelet::ConstLanelets & lanelets, const lanelet::ConstLanelets & terminal_lanelets,
const lanelet::routing::RoutingGraphPtr routing_graph_ptr)
{
const int n_node = lanelets.size();
std::vector<std::vector<int>> adjacency(n_node);
for (int dst = 0; dst < n_node; ++dst) {
adjacency[dst].resize(n_node);
for (int src = 0; src < n_node; ++src) {
adjacency[dst][src] = false;
}
}
std::set<lanelet::Id> lanelet_ids;
std::unordered_map<lanelet::Id, int> id2ind;
std::unordered_map<int, lanelet::Id> ind2id;
std::unordered_map<lanelet::Id, lanelet::ConstLanelet> id2lanelet;
int ind = 0;
std::set<lanelet::Id> lanelet_Ids;
std::unordered_map<lanelet::Id, size_t> Id2ind;
std::unordered_map<size_t, lanelet::Id> ind2Id;
std::unordered_map<lanelet::Id, lanelet::ConstLanelet> Id2lanelet;
for (const auto & lanelet : lanelets) {
lanelet_ids.insert(lanelet.id());
const auto id = lanelet.id();
id2ind[id] = ind;
ind2id[ind] = id;
id2lanelet[id] = lanelet;
ind++;
size_t ind = ind2Id.size();
const auto Id = lanelet.id();
lanelet_Ids.insert(Id);
Id2ind[Id] = ind;

Check warning on line 266 in planning/behavior_velocity_planner/autoware_behavior_velocity_intersection_module/src/util.cpp

View check run for this annotation

Codecov / codecov/patch

planning/behavior_velocity_planner/autoware_behavior_velocity_intersection_module/src/util.cpp#L266

Added line #L266 was not covered by tests
ind2Id[ind] = Id;
Id2lanelet[Id] = lanelet;
}
// NOTE: this function aims to traverse the detection lanelet backward from ego side to farthest
// side, so if lane B follows lane A on the routing_graph, adj[B][A] = true
std::set<size_t> terminal_inds;

Check warning on line 270 in planning/behavior_velocity_planner/autoware_behavior_velocity_intersection_module/src/util.cpp

View workflow job for this annotation

GitHub Actions / spell-check-differential

Unknown word (inds)
for (const auto & terminal_lanelet : terminal_lanelets) {
terminal_inds.insert(Id2ind[terminal_lanelet.id()]);

Check warning on line 272 in planning/behavior_velocity_planner/autoware_behavior_velocity_intersection_module/src/util.cpp

View workflow job for this annotation

GitHub Actions / spell-check-differential

Unknown word (inds)
}

// create adjacency matrix
const auto n_node = lanelets.size();
std::vector<std::vector<bool>> adjacency(n_node, std::vector<bool>(n_node, false));

// NOTE: this function aims to traverse the detection lanelet in the lane direction, so if lane B
// follows lane A on the routing_graph, adj[A][B] = true
for (const auto & lanelet : lanelets) {
const auto & followings = routing_graph_ptr->following(lanelet);
const int dst = lanelet.id();
const auto src = lanelet.id();

Check warning on line 283 in planning/behavior_velocity_planner/autoware_behavior_velocity_intersection_module/src/util.cpp

View check run for this annotation

Codecov / codecov/patch

planning/behavior_velocity_planner/autoware_behavior_velocity_intersection_module/src/util.cpp#L283

Added line #L283 was not covered by tests
for (const auto & following : followings) {
if (const int src = following.id(); lanelet_ids.find(src) != lanelet_ids.end()) {
adjacency[(id2ind[src])][(id2ind[dst])] = true;
if (const auto dst = following.id(); lanelet_Ids.find(dst) != lanelet_Ids.end()) {
adjacency[(Id2ind[dst])][(Id2ind[src])] = true;
}
}
}
// terminal node
std::map<lanelet::Id, std::vector<lanelet::Id>> branches;
auto has_no_previous = [&](const int node) {
for (int dst = 0; dst < n_node; dst++) {
if (adjacency[dst][node]) {
return false;
}
}
return true;
};
for (int src = 0; src < n_node; src++) {
if (!has_no_previous(src)) {
continue;
}
// So `src` has no previous lanelets
branches[(ind2id[src])] = std::vector<lanelet::Id>{};
auto & branch = branches[(ind2id[src])];
lanelet::Id node_iter = ind2id[src];
std::set<lanelet::Id> visited_ids;
while (true) {
const auto & destinations = adjacency[(id2ind[node_iter])];
// NOTE: assuming detection lanelets have only one "previous"(on the routing_graph) lanelet
const auto next = std::find(destinations.begin(), destinations.end(), true);
if (next == destinations.end()) {
branch.push_back(node_iter);
break;
}
if (visited_ids.find(node_iter) != visited_ids.end()) {
// loop detected
break;
}
branch.push_back(node_iter);
visited_ids.insert(node_iter);
node_iter = ind2id[std::distance(destinations.begin(), next)];
}

std::unordered_map<size_t, std::vector<std::vector<size_t>>> branches;
for (const auto & terminal_ind : terminal_inds) {

Check warning on line 292 in planning/behavior_velocity_planner/autoware_behavior_velocity_intersection_module/src/util.cpp

View workflow job for this annotation

GitHub Actions / spell-check-differential

Unknown word (inds)
branches[terminal_ind] = retrievePathsBackward(adjacency, terminal_ind);
}
for (decltype(branches)::iterator it = branches.begin(); it != branches.end(); it++) {
auto & branch = it->second;
std::reverse(branch.begin(), branch.end());

for (auto & [terminal_ind, paths] : branches) {
for (auto & path : paths) {
std::reverse(path.begin(), path.end());
}
}
lanelet::ConstLanelets merged;
std::vector<lanelet::ConstLanelets> originals;
for (const auto & [id, sub_ids] : branches) {
if (sub_ids.size() == 0) {
for (const auto & [ind, sub_branches] : branches) {
if (sub_branches.empty()) {
continue;
}
lanelet::ConstLanelets merge;
originals.push_back(lanelet::ConstLanelets({}));
auto & original = originals.back();
for (const auto sub_id : sub_ids) {
merge.push_back(id2lanelet[sub_id]);
original.push_back(id2lanelet[sub_id]);
for (const auto & sub_inds : sub_branches) {

Check warning on line 307 in planning/behavior_velocity_planner/autoware_behavior_velocity_intersection_module/src/util.cpp

View workflow job for this annotation

GitHub Actions / spell-check-differential

Unknown word (inds)
lanelet::ConstLanelets to_merge;
for (const auto & sub_ind : sub_inds) {

Check warning on line 309 in planning/behavior_velocity_planner/autoware_behavior_velocity_intersection_module/src/util.cpp

View workflow job for this annotation

GitHub Actions / spell-check-differential

Unknown word (inds)
to_merge.push_back(Id2lanelet[ind2Id[sub_ind]]);
}
originals.push_back(to_merge);
merged.push_back(lanelet::utils::combineLaneletsShape(to_merge));
}

Check notice on line 314 in planning/behavior_velocity_planner/autoware_behavior_velocity_intersection_module/src/util.cpp

View check run for this annotation

CodeScene Delta Analysis / CodeScene Cloud Delta Analysis (main)

✅ Getting better: Complex Method

mergeLaneletsByTopologicalSort decreases in cyclomatic complexity from 20 to 14, threshold = 9. This function has many conditional statements (e.g. if, for, while), leading to lower code health. Avoid adding more conditionals and code to it without refactoring.

Check notice on line 314 in planning/behavior_velocity_planner/autoware_behavior_velocity_intersection_module/src/util.cpp

View check run for this annotation

CodeScene Delta Analysis / CodeScene Cloud Delta Analysis (main)

✅ Getting better: Bumpy Road Ahead

mergeLaneletsByTopologicalSort decreases from 6 to 4 logical blocks with deeply nested code, threshold is one single block per function. The Bumpy Road code smell is a function that contains multiple chunks of nested conditional logic. The deeper the nesting and the more bumps, the lower the code health.
merged.push_back(lanelet::utils::combineLaneletsShape(merge));
}
return {merged, originals};
}
Expand Down
Loading
Loading