-
Notifications
You must be signed in to change notification settings - Fork 21
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* Make default initial distance of vertex equal to float max * Implement BGL depth first search * Updated DFS solver to use Visitors template * Updated test library to create solver factories for the various BGL DFS solvers * Updated unit test with DFS solvers * Updated benchmarks with DFS solvers * Updated Dijkstra solver documentation * Revised explicit template instantiation of BGL solvers * Removed visitors template from BGL solver partial implementations * Added macro for explicitly instantiating a template class for a sequence of types; revised explicit template instantiation of BGL solver partial implementations * Updated unit test template parameter to be the solver itself instead of the factory Co-authored-by: Michael Ripperger <michael.ripperger@swri.org> Co-authored-by: ctlewis <colin.lewis@swri.org>
- Loading branch information
1 parent
d56038b
commit 9c9d0e5
Showing
13 changed files
with
468 additions
and
93 deletions.
There are no files selected for viewing
71 changes: 71 additions & 0 deletions
71
descartes_light/solvers/include/descartes_light/solvers/bgl/bgl_dfs_solver.h
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,71 @@ | ||
/* | ||
* Software License Agreement (Apache License) | ||
* | ||
* Copyright (c) 2021, Southwest Research Institute | ||
* | ||
* 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. | ||
*/ | ||
#ifndef DESCARTES_LIGHT_SOLVERS_BGL_BGL_DFS_SOLVER_H | ||
#define DESCARTES_LIGHT_SOLVERS_BGL_BGL_DFS_SOLVER_H | ||
|
||
#include <descartes_light/solvers/bgl/bgl_solver.h> | ||
#include <descartes_light/solvers/bgl/event_visitors.h> | ||
|
||
namespace descartes_light | ||
{ | ||
/** | ||
* @brief BGL solver implementation that constructs vertices and edges in the build function and uses a depth first | ||
* search with a specifiable visitor to search the graph | ||
* @details Note: the solver internally creates event visitors for recording predecessors and vertex distances. | ||
* Therefore, these event visitors do not need to be specified as template parameters | ||
*/ | ||
template <typename FloatType, typename Visitors> | ||
class BGLDepthFirstSVSESolver : public BGLSolverBaseSVSE<FloatType> | ||
{ | ||
public: | ||
BGLDepthFirstSVSESolver(Visitors event_visitors, unsigned num_threads = std::thread::hardware_concurrency()); | ||
SearchResult<FloatType> search() override; | ||
|
||
protected: | ||
/** @brief Event visitors for custom behavior in the search */ | ||
Visitors event_visitors_; | ||
}; | ||
|
||
using BGLDepthFirstSVSESolverF = BGLDepthFirstSVSESolver<float, early_terminator<boost::on_discover_vertex>>; | ||
using BGLDepthFirstSVSESolverD = BGLDepthFirstSVSESolver<double, early_terminator<boost::on_discover_vertex>>; | ||
|
||
/** | ||
* @brief BGL solver implementation that constructs vertices build function and uses a depth first search | ||
* with an edge-adding visitor to search the graph | ||
* @details Note: the solver internally creates event visitors for recording predecessors and vertex distances and for | ||
* adding edges dynamically to the graph. Therefore, these event visitors do not need to be specified as template | ||
* parameters | ||
*/ | ||
template <typename FloatType, typename Visitors> | ||
class BGLDepthFirstSVDESolver : public BGLSolverBaseSVDE<FloatType> | ||
{ | ||
public: | ||
BGLDepthFirstSVDESolver(Visitors event_visitors, unsigned num_threads = std::thread::hardware_concurrency()); | ||
SearchResult<FloatType> search() override; | ||
|
||
protected: | ||
/** @brief Event visitors for custom behavior in the search */ | ||
Visitors event_visitors_; | ||
}; | ||
|
||
using BGLDepthFirstSVDESolverF = BGLDepthFirstSVDESolver<float, early_terminator<boost::on_discover_vertex>>; | ||
using BGLDepthFirstSVDESolverD = BGLDepthFirstSVDESolver<double, early_terminator<boost::on_discover_vertex>>; | ||
|
||
} // namespace descartes_light | ||
|
||
#endif // DESCARTES_LIGHT_SOLVERS_BGL_BGL_DFS_SOLVER_H |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
156 changes: 156 additions & 0 deletions
156
descartes_light/solvers/include/descartes_light/solvers/bgl/impl/bgl_dfs_solver.hpp
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,156 @@ | ||
/* | ||
* Software License Agreement (Apache License) | ||
* | ||
* Copyright (c) 2021, Southwest Research Institute | ||
* | ||
* 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. | ||
*/ | ||
#ifndef DESCARTES_LIGHT_SOLVERS_BGL_IMPL_DFS_SOLVER_HPP | ||
#define DESCARTES_LIGHT_SOLVERS_BGL_IMPL_DFS_SOLVER_HPP | ||
|
||
#include <descartes_light/solvers/bgl/bgl_dfs_solver.h> | ||
#include <descartes_light/solvers/bgl/impl/event_visitors.hpp> | ||
|
||
#include <descartes_light/descartes_macros.h> | ||
DESCARTES_IGNORE_WARNINGS_PUSH | ||
#include <boost/graph/depth_first_search.hpp> | ||
DESCARTES_IGNORE_WARNINGS_POP | ||
|
||
namespace descartes_light | ||
{ | ||
template <typename FloatType, typename Visitors> | ||
static VertexDesc<FloatType> solveDFS(BGLGraph<FloatType>& graph, | ||
const VertexDesc<FloatType>& source, | ||
const Visitors& event_visitors, | ||
const std::vector<std::vector<VertexDesc<FloatType>>>& ladder_rungs) | ||
{ | ||
auto color_prop_map = boost::get(&Vertex<FloatType>::color, graph); | ||
auto visitor = boost::make_dfs_visitor(event_visitors); | ||
|
||
try | ||
{ | ||
graph[source].distance = 0.0; | ||
boost::depth_first_search(graph, visitor, color_prop_map, source); | ||
|
||
// In the case that the visitor does not throw the target vertex descriptor, find the lowest cost vertex in last | ||
// rung of the ladder graph | ||
auto target = std::min_element(ladder_rungs.back().begin(), | ||
ladder_rungs.back().end(), | ||
[&](const VertexDesc<FloatType>& a, const VertexDesc<FloatType>& b) { | ||
return graph[a].distance < graph[b].distance; | ||
}); | ||
|
||
// Check that the identified lowest cost vertex is valid and has a cost less than inf | ||
if (target != ladder_rungs.back().end() && graph[*target].distance < std::numeric_limits<FloatType>::max()) | ||
throw *target; | ||
} | ||
catch (const VertexDesc<FloatType>& target) | ||
{ | ||
return target; | ||
} | ||
|
||
throw std::runtime_error("DFS search failed to encounter a vertex in the last rung of the plan graph"); | ||
} | ||
|
||
template <typename FloatType, typename Visitors> | ||
BGLDepthFirstSVSESolver<FloatType, Visitors>::BGLDepthFirstSVSESolver(Visitors event_visitors, unsigned num_threads) | ||
: BGLSolverBaseSVSE<FloatType>(num_threads), event_visitors_(std::move(event_visitors)) | ||
{ | ||
} | ||
|
||
template <typename FloatType, typename Visitors> | ||
SearchResult<FloatType> BGLDepthFirstSVSESolver<FloatType, Visitors>::search() | ||
{ | ||
// Internal properties | ||
auto& graph_ = BGLSolverBase<FloatType>::graph_; | ||
const auto& source_ = BGLSolverBase<FloatType>::source_; | ||
auto& predecessors_ = BGLSolverBase<FloatType>::predecessors_; | ||
const auto& ladder_rungs_ = BGLSolverBase<FloatType>::ladder_rungs_; | ||
|
||
// Resize the container of predecessors to match the number of vertices | ||
// Assign the initial values as a vertex descriptor that is definitely not in the graph to avoid mistakes in the | ||
// future reconstructing the path | ||
predecessors_.resize(boost::num_vertices(graph_), std::numeric_limits<VertexDesc<FloatType>>::max()); | ||
|
||
// Assign the predecessor of the source node to itself since the BGL DFS will not do it | ||
predecessors_.at(source_) = source_; | ||
|
||
// Create an event visitor that combines the internally specified visitors with ones that record predecessors and | ||
// vertex costs (i.e. distances) | ||
auto visitor = std::make_pair(boost::record_predecessors(predecessors_.data(), boost::on_tree_edge()), | ||
std::make_pair(cost_recorder(), event_visitors_)); | ||
|
||
const VertexDesc<FloatType> target = solveDFS(graph_, source_, visitor, ladder_rungs_); | ||
|
||
SearchResult<FloatType> result; | ||
|
||
// Reconstruct the path from the predecesor map; remove the artificial start state | ||
const auto vd_path = BGLSolverBase<FloatType>::reconstructPath(source_, target); | ||
result.trajectory = BGLSolverBase<FloatType>::toStates(vd_path); | ||
result.trajectory.erase(result.trajectory.begin()); | ||
|
||
result.cost = graph_[target].distance; | ||
|
||
return result; | ||
} | ||
|
||
template <typename FloatType, typename Visitors> | ||
BGLDepthFirstSVDESolver<FloatType, Visitors>::BGLDepthFirstSVDESolver(Visitors event_visitors, unsigned num_threads) | ||
: BGLSolverBaseSVDE<FloatType>(num_threads), event_visitors_(std::move(event_visitors)) | ||
{ | ||
} | ||
|
||
template <typename FloatType, typename Visitors> | ||
SearchResult<FloatType> BGLDepthFirstSVDESolver<FloatType, Visitors>::search() | ||
{ | ||
// Internal properties | ||
auto& graph_ = BGLSolverBase<FloatType>::graph_; | ||
const auto& source_ = BGLSolverBase<FloatType>::source_; | ||
auto& predecessors_ = BGLSolverBase<FloatType>::predecessors_; | ||
const auto& ladder_rungs_ = BGLSolverBase<FloatType>::ladder_rungs_; | ||
|
||
// Resize the container of predecessors to match the number of vertices | ||
// Assign the initial values as a vertex descriptor that is definitely not in the graph to avoid mistakes in the | ||
// future reconstructing the path | ||
predecessors_.resize(boost::num_vertices(graph_), std::numeric_limits<VertexDesc<FloatType>>::max()); | ||
|
||
// Assign the predecessor of the source node to itself since the BGL DFS will not do it | ||
predecessors_.at(source_) = source_; | ||
|
||
// Make a visitor that combines the internally specified event visitors with ones that add all edges dynamically and | ||
// record predecessors and vertex costs (i.e. distances) | ||
const auto& edge_eval_ = BGLSolverBaseSVDE<FloatType>::edge_eval_; | ||
auto visitor = std::make_pair( | ||
boost::record_predecessors(predecessors_.data(), boost::on_tree_edge()), | ||
std::make_pair( | ||
cost_recorder(), | ||
std::make_pair(add_all_edges_dynamically<FloatType, boost::on_discover_vertex>(edge_eval_, ladder_rungs_), | ||
event_visitors_))); | ||
|
||
const VertexDesc<FloatType> target = solveDFS(graph_, source_, visitor, ladder_rungs_); | ||
|
||
SearchResult<FloatType> result; | ||
|
||
// Reconstruct the path from the predecesor map; remove the artificial start state | ||
const auto vd_path = BGLSolverBase<FloatType>::reconstructPath(source_, target); | ||
result.trajectory = BGLSolverBase<FloatType>::toStates(vd_path); | ||
result.trajectory.erase(result.trajectory.begin()); | ||
|
||
result.cost = graph_[target].distance; | ||
|
||
return result; | ||
} | ||
|
||
} // namespace descartes_light | ||
|
||
#endif // DESCARTES_LIGHT_SOLVERS_BGL_IMPL_DFS_SOLVER_HPP |
Oops, something went wrong.