|
19 | 19 | #ifndef CONTROLLER_MANAGER__CONTROLLER_SPEC_HPP_
|
20 | 20 | #define CONTROLLER_MANAGER__CONTROLLER_SPEC_HPP_
|
21 | 21 |
|
| 22 | +#include <algorithm> |
22 | 23 | #include <memory>
|
23 | 24 | #include <string>
|
| 25 | +#include <unordered_map> |
| 26 | +#include <unordered_set> |
24 | 27 | #include <vector>
|
| 28 | + |
25 | 29 | #include "controller_interface/controller_interface_base.hpp"
|
26 | 30 | #include "hardware_interface/controller_info.hpp"
|
| 31 | +#include "hardware_interface/helpers.hpp" |
27 | 32 | #include "hardware_interface/types/statistics_types.hpp"
|
28 | 33 |
|
29 | 34 | namespace controller_manager
|
@@ -57,5 +62,79 @@ struct ControllerChainSpec
|
57 | 62 | std::vector<std::string> following_controllers;
|
58 | 63 | std::vector<std::string> preceding_controllers;
|
59 | 64 | };
|
| 65 | + |
| 66 | +class ControllerChainDependencyGraph |
| 67 | +{ |
| 68 | +public: |
| 69 | + void add_dependency(const std::string & predecessor, const std::string & successor) |
| 70 | + { |
| 71 | + if (predecessors.count(predecessor) == 0) |
| 72 | + { |
| 73 | + predecessors[predecessor] = {}; |
| 74 | + } |
| 75 | + if (successors.count(successor) == 0) |
| 76 | + { |
| 77 | + successors[successor] = {}; |
| 78 | + } |
| 79 | + |
| 80 | + ros2_control::add_item(predecessors[successor], predecessor); |
| 81 | + ros2_control::add_item(successors[predecessor], successor); |
| 82 | + } |
| 83 | + |
| 84 | + void remove_controller(const std::string & controller_name) |
| 85 | + { |
| 86 | + predecessors.erase(controller_name); |
| 87 | + successors.erase(controller_name); |
| 88 | + for (auto & [_, succ] : predecessors) |
| 89 | + { |
| 90 | + succ.erase(std::remove(succ.begin(), succ.end(), controller_name), succ.end()); |
| 91 | + } |
| 92 | + for (auto & [_, preds] : successors) |
| 93 | + { |
| 94 | + preds.erase(std::remove(preds.begin(), preds.end(), controller_name), preds.end()); |
| 95 | + } |
| 96 | + } |
| 97 | + |
| 98 | + void depth_first_search( |
| 99 | + const std::string & controller_name, std::unordered_set<std::string> & visited, |
| 100 | + std::unordered_map<std::string, std::vector<std::string>> & graph) |
| 101 | + { |
| 102 | + if (visited.find(controller_name) != visited.end()) |
| 103 | + { |
| 104 | + return; |
| 105 | + } |
| 106 | + visited.insert(controller_name); |
| 107 | + for (const auto & neighbor : graph[controller_name]) |
| 108 | + { |
| 109 | + if (visited.find(neighbor) == visited.end()) |
| 110 | + { |
| 111 | + depth_first_search(neighbor, visited, graph); |
| 112 | + } |
| 113 | + } |
| 114 | + } |
| 115 | + |
| 116 | + std::vector<std::string> get_all_predecessors(const std::string & controller_name) |
| 117 | + { |
| 118 | + std::unordered_set<std::string> visited; |
| 119 | + depth_first_search(controller_name, visited, predecessors); |
| 120 | + std::vector<std::string> predecessors_list; |
| 121 | + std::copy(visited.begin(), visited.end(), std::back_inserter(predecessors_list)); |
| 122 | + return predecessors_list; |
| 123 | + } |
| 124 | + |
| 125 | + std::vector<std::string> get_all_successors(const std::string & controller_name) |
| 126 | + { |
| 127 | + std::unordered_set<std::string> visited; |
| 128 | + depth_first_search(controller_name, visited, successors); |
| 129 | + std::vector<std::string> successors_list; |
| 130 | + std::copy(visited.begin(), visited.end(), std::back_inserter(successors_list)); |
| 131 | + return successors_list; |
| 132 | + } |
| 133 | + |
| 134 | +private: |
| 135 | + std::unordered_map<std::string, std::vector<std::string>> predecessors = {}; |
| 136 | + std::unordered_map<std::string, std::vector<std::string>> successors = {}; |
| 137 | +}; |
| 138 | + |
60 | 139 | } // namespace controller_manager
|
61 | 140 | #endif // CONTROLLER_MANAGER__CONTROLLER_SPEC_HPP_
|
0 commit comments