本文背景
Apollo是无人驾驶相关的开源框架,GitHub地址为https://github.com/ApolloAuto/apollo,在决策部分主要具有Perception(感知),Prediction(预测),Routing(路由寻径),Planning(轨迹规划),Control(控制)。由于最近在看Routing相关的代码,所以主要针对Routing内容的总结。
本文是对Routing策略中的AStar算法的介绍。
Astar介绍
AStar算法的具体介绍在网上搜索就能知道,看到有比较好的 堪称最好的A*算法,可以先了解一下Astar的原理。主要思路就是在dijkstra的基础上增加启发式函数,往搜索目标搜索,加快搜索速度。
Apollo的Astar策略算法源代码
/******************************************************************************
* Copyright 2017 The Apollo Authors. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*****************************************************************************/
#include <algorithm>
#include <cmath>
#include <fstream>
#include <limits>
#include <queue>
#include <modules/perception/obstacle/camera/lane_post_process/common/util.h>
#include "modules/common/log.h"
#include "modules/routing/common/routing_gflags.h"
#include "modules/routing/graph/sub_topo_graph.h"
#include "modules/routing/graph/topo_graph.h"
#include "modules/routing/graph/topo_node.h"
#include "modules/routing/strategy/a_star_strategy.h"
namespace apollo {
namespace routing {
namespace {
struct SearchNode {
const TopoNode* topo_node = nullptr;
double f = std::numeric_limits<double>::max();
SearchNode() = default;
explicit SearchNode(const TopoNode* node)
: topo_node(node), f(std::numeric_limits<double>::max()) {}
SearchNode(const SearchNode& search_node) = default;
bool operator<(const SearchNode& node) const {
// in order to let the top of priority queue is the smallest one!
return f > node.f;
}
bool operator==(const SearchNode& node) const {
return topo_node == node.topo_node;
}
};
double GetCostToNeighbor(const TopoEdge* edge) {
return (edge->Cost() + edge->ToNode()->Cost());
}
const TopoNode* GetLargestNode(const std::vector<const TopoNode*>& nodes) {
double max_range = 0.0;
const TopoNode* largest = nullptr;
for (const auto* node : nodes) {
const double temp_range = node->EndS() - node->StartS();
if (temp_range > max_range) {
max_range = temp_range;
largest = node;
}
}
return largest;
}
bool AdjustLaneChangeBackward(
std::vector<const TopoNode*>* const result_node_vec) {
for (int i = static_cast<int>(result_node_vec->size()) - 2; i > 0; --i) {
const auto* from_node = result_node_vec->at(i);
const auto* to_node = result_node_vec->at(i + 1);
const auto* base_node = result_node_vec->at(i - 1);
const auto* from_to_edge = from_node->GetOutEdgeTo(to_node);
if (from_to_edge == nullptr) {
// may need to recalculate edge,
// because only edge from origin node to subnode is saved
from_to_edge = to_node->GetInEdgeFrom(from_node);
}
if (from_to_edge == nullptr) {
AERROR << "Get null ptr to edge:" << from_node->LaneId() << " ("
<< from_node->StartS() << ", " << from_node->EndS() << ")"
<< " --> " << to_node->LaneId() << " (" << to_node->StartS()
<< ", " << to_node->EndS() << ")";
return false;
}
if (from_to_edge->Type() != TopoEdgeType::TET_FORWARD) {
if (base_node->EndS() - base_node->StartS() <
from_node->EndS() - from_node->StartS()) {
continue;
}
std::vector<const TopoNode*> candidate_set;
candidate_set.push_back(from_node);
const auto& out_edges = base_node->OutToLeftOrRightEdge();
for (const auto* edge : out_edges) {
const auto* candidate_node = edge->ToNod