Carma-platform v4.2.0
CARMA Platform is built on robot operating system (ROS) and utilizes open source software (OSS) that enables Cooperative Driving Automation (CDA) features to allow Automated Driving Systems to interact and cooperate with infrastructure and other vehicles through communication.
subsystem_controllers::PluginManager Class Reference

The PluginManager serves as a component to manage CARMA Guidance Plugins via their ros2 lifecycle interfaces. More...

#include <plugin_manager.h>

Collaboration diagram for subsystem_controllers::PluginManager:
Collaboration graph

Public Member Functions

 PluginManager (const std::vector< std::string > &required_plugins, const std::vector< std::string > &auto_activated_plugins, std::shared_ptr< ros2_lifecycle_manager::LifecycleManagerInterface > plugin_lifecycle_mgr, GetParentNodeStateFunc get_parent_state_func, ServiceNamesAndTypesFunc get_service_names_and_types_func, std::chrono::nanoseconds service_timeout, std::chrono::nanoseconds call_timeout)
 Constructor for PluginManager. More...
 
bool configure ()
 
bool activate ()
 
bool deactivate ()
 
bool cleanup ()
 
bool shutdown ()
 
void update_plugin_status (carma_planning_msgs::msg::Plugin::UniquePtr msg)
 Update the status of a certain plugin. More...
 
void get_registered_plugins (SrvHeader, carma_planning_msgs::srv::PluginList::Request::SharedPtr req, carma_planning_msgs::srv::PluginList::Response::SharedPtr res)
 Returns the list of known plugins. More...
 
void get_active_plugins (SrvHeader, carma_planning_msgs::srv::PluginList::Request::SharedPtr req, carma_planning_msgs::srv::PluginList::Response::SharedPtr res)
 Get the list of currently active plugins. More...
 
void activate_plugin (SrvHeader, carma_planning_msgs::srv::PluginActivation::Request::SharedPtr req, carma_planning_msgs::srv::PluginActivation::Response::SharedPtr res)
 Activate the specified plugin. More...
 
void get_strategic_plugins_by_capability (SrvHeader, carma_planning_msgs::srv::GetPluginApi::Request::SharedPtr req, carma_planning_msgs::srv::GetPluginApi::Response::SharedPtr res)
 Get strategic plugins by capability. More...
 
void get_tactical_plugins_by_capability (SrvHeader, carma_planning_msgs::srv::GetPluginApi::Request::SharedPtr req, carma_planning_msgs::srv::GetPluginApi::Response::SharedPtr res)
 Get tactical plugins by capability. More...
 
void get_control_plugins_by_capability (SrvHeader, carma_planning_msgs::srv::GetPluginApi::Request::SharedPtr req, carma_planning_msgs::srv::GetPluginApi::Response::SharedPtr res)
 Get control plugins by capability. More...
 

Protected Member Functions

void add_plugin (const Entry &plugin)
 Add the specified entry to our plugin management This function will attempt to move the newly detected plugin to the required state based on this nodes own state. More...
 
bool matching_capability (const std::vector< std::string > &base_capability_levels, const std::vector< std::string > &compared_capability_levels)
 Returns true if the provided base capability hierarchy can achieve the requested capability hierarchy A capability hierarchy is described as a list of strings where the first string is the most generic description of the capability while the last string the is the most detailed description. More...
 
bool is_ros2_lifecycle_node (const std::string &node)
 Returns true if the specified fully qualified node name is a ROS2 lifecycle node. More...
 

Protected Attributes

std::unordered_set< std::string > required_plugins_
 Set of required plugins a failure of which necessitates system shutdown. More...
 
std::unordered_set< std::string > auto_activated_plugins_
 Set of use specified auto activated plugins which will automatically started without need for user input. More...
 
std::shared_ptr< ros2_lifecycle_manager::LifecycleManagerInterface > plugin_lifecycle_mgr_
 Lifecycle Manager which will track the plugin nodes and call their lifecycle services on request. More...
 
GetParentNodeStateFunc get_parent_state_func_
 Callback to retrieve the lifecycle state of the parent process. More...
 
ServiceNamesAndTypesFunc get_service_names_and_types_func_
 Callback to get service names and types for the given node. More...
 
EntryManager em_
 Entry manager to keep track of detected plugins. More...
 
std::chrono::nanoseconds service_timeout_
 The timeout for services to be available. More...
 
std::chrono::nanoseconds call_timeout_
 The timeout for service calls to return. More...
 
const std::string plan_maneuvers_suffix_ = "/plan_maneuvers"
 Base service name of plan_trajectory service. More...
 
const std::string plan_trajectory_suffix_ = "/plan_trajectory"
 Base service name of plan_trajectory service. More...
 
const std::string control_trajectory_suffix_ = "/plan_trajectory"
 Base topic name of control plugin trajectory input topic. More...
 

Detailed Description

The PluginManager serves as a component to manage CARMA Guidance Plugins via their ros2 lifecycle interfaces.

Definition at line 48 of file plugin_manager.h.

Constructor & Destructor Documentation

◆ PluginManager()

subsystem_controllers::PluginManager::PluginManager ( const std::vector< std::string > &  required_plugins,
const std::vector< std::string > &  auto_activated_plugins,
std::shared_ptr< ros2_lifecycle_manager::LifecycleManagerInterface >  plugin_lifecycle_mgr,
GetParentNodeStateFunc  get_parent_state_func,
ServiceNamesAndTypesFunc  get_service_names_and_types_func,
std::chrono::nanoseconds  service_timeout,
std::chrono::nanoseconds  call_timeout 
)

Constructor for PluginManager.

Parameters
required_pluginsThe set of plugins which will be treated as required. A failure in these plugins will result in an exception
auto_activated_pluginsThe set of plugins which will be automatically activated at first system activation but not treated specially after that.
plugin_lifecycle_mgrA fully initialized lifecycle manager which will be used trigger plugin transitions
get_parent_state_funcA callback which will allow this object to access the parent process lifecycle state
get_service_names_and_types_funcA callback which returns a map of service names to service types based on the provided base node name and namespace
service_timeoutThe timeout for plugin services to be available in nanoseconds
call_timeoutThe timeout for calls to plugin services to fail in nanoseconds

Definition at line 28 of file plugin_manager.cpp.

34 : required_plugins_(required_plugins.begin(), required_plugins.end()),
35 auto_activated_plugins_(auto_activated_plugins.begin(), auto_activated_plugins.end()),
36 plugin_lifecycle_mgr_(plugin_lifecycle_mgr), get_parent_state_func_(get_parent_state_func),
37 get_service_names_and_types_func_(get_service_names_and_types_func),
38 service_timeout_(service_timeout), call_timeout_(call_timeout)
39 {
40 if (!plugin_lifecycle_mgr)
41 throw std::invalid_argument("Input plugin_lifecycle_mgr to PluginManager constructor cannot be null");
42
43 // For all required and auto activated plugins add unknown entries but with
44 // user_requested_activation set to true.
45 // This will be used later to determine how to transition the plugin specified by that entry
46
47 for (const auto& p : required_plugins_) {
48 RCLCPP_INFO_STREAM(rclcpp::get_logger("subsystem_controllers"), "Added a required plugin: " << p);
49
50 Entry e(false, false, p, carma_planning_msgs::msg::Plugin::UNKNOWN, "", true);
52 plugin_lifecycle_mgr_->add_managed_node(p);
53 }
54
55 for (const auto& p : auto_activated_plugins_) {
56 RCLCPP_INFO_STREAM(rclcpp::get_logger("subsystem_controllers"), "Added an auto activated plugin: " << p);
57
58 Entry e(false, false, p, carma_planning_msgs::msg::Plugin::UNKNOWN, "", true);
60 plugin_lifecycle_mgr_->add_managed_node(p);
61 }
62 }
void update_entry(const Entry &entry)
Add a new entry if the given name does not exist. Update an existing entry if the given name exists.
std::shared_ptr< ros2_lifecycle_manager::LifecycleManagerInterface > plugin_lifecycle_mgr_
Lifecycle Manager which will track the plugin nodes and call their lifecycle services on request.
std::unordered_set< std::string > auto_activated_plugins_
Set of use specified auto activated plugins which will automatically started without need for user in...
std::unordered_set< std::string > required_plugins_
Set of required plugins a failure of which necessitates system shutdown.
std::chrono::nanoseconds call_timeout_
The timeout for service calls to return.
GetParentNodeStateFunc get_parent_state_func_
Callback to retrieve the lifecycle state of the parent process.
std::chrono::nanoseconds service_timeout_
The timeout for services to be available.
ServiceNamesAndTypesFunc get_service_names_and_types_func_
Callback to get service names and types for the given node.
EntryManager em_
Entry manager to keep track of detected plugins.

References auto_activated_plugins_, em_, plugin_lifecycle_mgr_, required_plugins_, and subsystem_controllers::EntryManager::update_entry().

Here is the call graph for this function:

Member Function Documentation

◆ activate()

bool subsystem_controllers::PluginManager::activate ( )

Definition at line 166 of file plugin_manager.cpp.

167 {
168 bool full_success = true;
169 // Bring all required or auto activated plugins to the active state
170 for (auto plugin : em_.get_entries())
171 {
172 // If this is not a plugin slated for activation then continue and leave up to user to activate manually later
173 if (!plugin.user_requested_activation_)
174 continue;
175
176 auto result_state = plugin_lifecycle_mgr_->transition_node_to_state(lifecycle_msgs::msg::State::PRIMARY_STATE_ACTIVE, plugin.name_, service_timeout_, call_timeout_);
177
178 if(result_state != lifecycle_msgs::msg::State::PRIMARY_STATE_ACTIVE)
179 {
180 // If this plugin was required then trigger exception
181 if (required_plugins_.find(plugin.name_) != required_plugins_.end())
182 {
183 throw std::runtime_error("Required plugin " + plugin.name_ + " could not be activated.");
184 }
185
186 // If this plugin was not required log an error and mark it is unavailable and deactivated
187 RCLCPP_ERROR_STREAM(rclcpp::get_logger("subsystem_controllers"), "Failed to activate newly discovered non-required plugin: "
188 << plugin.name_ << " Marking as deactivated and unavailable!");
189
190 Entry deactivated_entry = plugin;
191 deactivated_entry.active_ = false;
192 deactivated_entry.available_ = false;
193 deactivated_entry.user_requested_activation_ = false;
194 em_.update_entry(deactivated_entry);
195
196 full_success = false;
197 }
198
199 // If this was an auto activated plugin and not required then we only activate is once
200 if (auto_activated_plugins_.find(plugin.name_) != auto_activated_plugins_.end())
201 {
202 plugin.user_requested_activation_ = false;
203 }
204
205 plugin.active_ = true; // Mark plugin as active
206
207 em_.update_entry(plugin);
208
209 }
210
211 return full_success;
212 }
std::vector< Entry > get_entries() const
Get all registed entries as a list.

References subsystem_controllers::Entry::active_, auto_activated_plugins_, subsystem_controllers::Entry::available_, call_timeout_, em_, subsystem_controllers::EntryManager::get_entries(), plugin_lifecycle_mgr_, required_plugins_, service_timeout_, subsystem_controllers::EntryManager::update_entry(), and subsystem_controllers::Entry::user_requested_activation_.

Here is the call graph for this function:

◆ activate_plugin()

void subsystem_controllers::PluginManager::activate_plugin ( SrvHeader  ,
carma_planning_msgs::srv::PluginActivation::Request::SharedPtr  req,
carma_planning_msgs::srv::PluginActivation::Response::SharedPtr  res 
)

Activate the specified plugin.

Parameters
headerMiddle ware header
reqThe req details containing the plugin to activate
[out]resThe response containing the success flag

Definition at line 320 of file plugin_manager.cpp.

321 {
322 boost::optional<Entry> requested_plugin = em_.get_entry_by_name(req->plugin_name);
323
324 if(!requested_plugin) // If not a known plugin then obviously not activated. Though really it would be better to have an indication of name failure in the message
325 {
326 res->newstate = false;
327 return;
328 }
329
330 bool activated = false;
331 if (req->activated)
332 {
333 auto result_state = plugin_lifecycle_mgr_->transition_node_to_state(lifecycle_msgs::msg::State::PRIMARY_STATE_ACTIVE, requested_plugin->name_, service_timeout_, call_timeout_);
334
335 activated = (result_state == lifecycle_msgs::msg::State::PRIMARY_STATE_ACTIVE);
336 } else {
337 auto result_state = plugin_lifecycle_mgr_->transition_node_to_state(lifecycle_msgs::msg::State::PRIMARY_STATE_INACTIVE, requested_plugin->name_, service_timeout_, call_timeout_);
338
339 activated = (result_state == lifecycle_msgs::msg::State::PRIMARY_STATE_ACTIVE);
340 }
341
342 Entry updated_entry(requested_plugin->available_, activated, requested_plugin->name_, requested_plugin->type_, requested_plugin->capability_, true); // Mark as user activated
343 em_.update_entry(updated_entry);
344
345 res->newstate = activated;
346 }
boost::optional< Entry > get_entry_by_name(const std::string &name) const
Get a entry using name as the key.

References call_timeout_, em_, subsystem_controllers::EntryManager::get_entry_by_name(), plugin_lifecycle_mgr_, service_timeout_, and subsystem_controllers::EntryManager::update_entry().

Referenced by subsystem_controllers::GuidanceControllerNode::handle_on_configure().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ add_plugin()

void subsystem_controllers::PluginManager::add_plugin ( const Entry plugin)
protected

Add the specified entry to our plugin management This function will attempt to move the newly detected plugin to the required state based on this nodes own state.

Parameters
pluginThe entry representing the plugin to add
Exceptions
std::runtime_errorif this was a required plugin and it could not be transitioned as needed

Definition at line 64 of file plugin_manager.cpp.

65 {
66 plugin_lifecycle_mgr_->add_managed_node(plugin.name_);
67
68 em_.update_entry(plugin);
69
70 Entry deactivated_entry = plugin;
71
72 auto parent_node_state = get_parent_state_func_();
73
74 // If this node is not in the active or inactive states then move the plugin to unconfigured
75 if (parent_node_state != lifecycle_msgs::msg::State::PRIMARY_STATE_ACTIVE
76 && parent_node_state != lifecycle_msgs::msg::State::PRIMARY_STATE_INACTIVE)
77 {
78
79 deactivated_entry.active_ = false;
80
81 // Move plugin to match this nodes state
82 auto result_state = plugin_lifecycle_mgr_->transition_node_to_state(parent_node_state, plugin.name_, service_timeout_, call_timeout_);
83
84 if(result_state != parent_node_state)
85 {
86
87 // If this plugin was required then trigger exception
88 if (required_plugins_.find(plugin.name_) != required_plugins_.end())
89 {
90 throw std::runtime_error("Newly discovered required plugin " + plugin.name_ + " could not be brought to controller node state.");
91 }
92
93 // If this plugin was not required log an error and mark it is unavailable and deactivated
94 RCLCPP_ERROR_STREAM(rclcpp::get_logger("subsystem_controllers"), "Failed to transition newly discovered non-required plugin: "
95 << plugin.name_ << " Marking as deactivated and unavailable!");
96
97 deactivated_entry.available_ = false;
98
99 }
100
101 em_.update_entry(deactivated_entry);
102 return;
103 }
104
105
106 // If the node is active or inactive then,
107 // when adding a plugin, it should be brought to the inactive state
108 // We do not need transition it beyond inactive in this function as that will be managed by the plugin activation process via UI or parameters
109 auto result_state = plugin_lifecycle_mgr_->transition_node_to_state(lifecycle_msgs::msg::State::PRIMARY_STATE_INACTIVE, plugin.name_, service_timeout_, call_timeout_);
110
111 if(result_state != lifecycle_msgs::msg::State::PRIMARY_STATE_INACTIVE)
112 {
113 // If this plugin was required then trigger exception
114 if (required_plugins_.find(plugin.name_) != required_plugins_.end())
115 {
116 throw std::runtime_error("Newly discovered required plugin " + plugin.name_ + " could not be brought to inactive state.");
117 }
118
119 // If this plugin was not required log an error and mark it is unavailable and deactivated
120 RCLCPP_ERROR_STREAM(rclcpp::get_logger("subsystem_controllers"), "Failed to configure newly discovered non-required plugin: "
121 << plugin.name_ << " Marking as deactivated and unavailable!");
122
123 deactivated_entry.available_ = false;
124 }
125
126 deactivated_entry.active_ = false;
127 em_.update_entry(deactivated_entry);
128
129 }

References subsystem_controllers::Entry::active_, subsystem_controllers::Entry::available_, call_timeout_, em_, get_parent_state_func_, subsystem_controllers::Entry::name_, plugin_lifecycle_mgr_, required_plugins_, service_timeout_, and subsystem_controllers::EntryManager::update_entry().

Referenced by update_plugin_status().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ cleanup()

bool subsystem_controllers::PluginManager::cleanup ( )

Definition at line 248 of file plugin_manager.cpp.

249 {
250 bool full_success = true;
251 // Bring all required or auto activated plugins to the unconfigured state
252 for (auto plugin : em_.get_entries())
253 {
254 auto result_state = plugin_lifecycle_mgr_->transition_node_to_state(lifecycle_msgs::msg::State::PRIMARY_STATE_UNCONFIGURED, plugin.name_, service_timeout_, call_timeout_);
255
256 if(result_state != lifecycle_msgs::msg::State::PRIMARY_STATE_UNCONFIGURED)
257 {
258 // If this plugin was required then trigger exception
259 if (required_plugins_.find(plugin.name_) != required_plugins_.end())
260 {
261 throw std::runtime_error("Required plugin " + plugin.name_ + " could not be cleaned up.");
262 }
263
264 // If this plugin was not required log an error and mark it is unavailable and deactivated
265 RCLCPP_ERROR_STREAM(rclcpp::get_logger("subsystem_controllers"), "Failed to cleanup non-required plugin: "
266 << plugin.name_ << " Marking as deactivated and unavailable!");
267
268 Entry deactivated_entry = plugin;
269 deactivated_entry.active_ = false;
270 deactivated_entry.available_ = false;
271 deactivated_entry.user_requested_activation_ = false;
272 em_.update_entry(deactivated_entry);
273
274 full_success = false;
275 }
276
277 }
278
279 return full_success;
280 }

References subsystem_controllers::Entry::active_, subsystem_controllers::Entry::available_, call_timeout_, em_, subsystem_controllers::EntryManager::get_entries(), plugin_lifecycle_mgr_, required_plugins_, service_timeout_, subsystem_controllers::EntryManager::update_entry(), and subsystem_controllers::Entry::user_requested_activation_.

Here is the call graph for this function:

◆ configure()

bool subsystem_controllers::PluginManager::configure ( )

Below are the state transition methods which will cause this manager to trigger the corresponding state transitions in the managed plugins.

Exceptions
std::runtime_errorIf a required node could not transition successfully
Returns
True if all components transitioned successfully

Definition at line 131 of file plugin_manager.cpp.

132 {
133 bool full_success = true;
134 // Bring all known plugins to the inactive state
135 for (auto plugin : em_.get_entries())
136 {
137 auto result_state = plugin_lifecycle_mgr_->transition_node_to_state(lifecycle_msgs::msg::State::PRIMARY_STATE_INACTIVE, plugin.name_, service_timeout_, call_timeout_);
138
139 if(result_state != lifecycle_msgs::msg::State::PRIMARY_STATE_INACTIVE)
140 {
141 // If this plugin was required then trigger exception
142 if (required_plugins_.find(plugin.name_) != required_plugins_.end())
143 {
144 throw std::runtime_error("Required plugin " + plugin.name_ + " could not be configured.");
145 }
146
147 // If this plugin was not required log an error and mark it is unavailable and deactivated
148 RCLCPP_ERROR_STREAM(rclcpp::get_logger("subsystem_controllers"), "Failed to configure newly discovered non-required plugin: "
149 << plugin.name_ << " Marking as deactivated and unavailable!");
150
151 Entry deactivated_entry = plugin;
152 deactivated_entry.active_ = false;
153 deactivated_entry.available_ = false;
154 deactivated_entry.user_requested_activation_ = false;
155 em_.update_entry(deactivated_entry);
156
157 full_success = false;
158 }
159
160 }
161
162 return full_success;
163
164 }

References subsystem_controllers::Entry::active_, subsystem_controllers::Entry::available_, call_timeout_, em_, subsystem_controllers::EntryManager::get_entries(), plugin_lifecycle_mgr_, required_plugins_, service_timeout_, subsystem_controllers::EntryManager::update_entry(), and subsystem_controllers::Entry::user_requested_activation_.

Here is the call graph for this function:

◆ deactivate()

bool subsystem_controllers::PluginManager::deactivate ( )

Definition at line 214 of file plugin_manager.cpp.

215 {
216 bool full_success = true;
217 // Bring all required or auto activated plugins to the active state
218 for (auto plugin : em_.get_entries())
219 {
220 auto result_state = plugin_lifecycle_mgr_->transition_node_to_state(lifecycle_msgs::msg::State::PRIMARY_STATE_INACTIVE, plugin.name_, service_timeout_, call_timeout_);
221
222 if(result_state != lifecycle_msgs::msg::State::PRIMARY_STATE_INACTIVE)
223 {
224 // If this plugin was required then trigger exception
225 if (required_plugins_.find(plugin.name_) != required_plugins_.end())
226 {
227 throw std::runtime_error("Required plugin " + plugin.name_ + " could not be deactivated.");
228 }
229
230 // If this plugin was not required log an error and mark it is unavailable and deactivated
231 RCLCPP_ERROR_STREAM(rclcpp::get_logger("subsystem_controllers"), "Failed to deactivate non-required plugin: "
232 << plugin.name_ << " Marking as deactivated and unavailable!");
233
234 Entry deactivated_entry = plugin;
235 deactivated_entry.active_ = false;
236 deactivated_entry.available_ = false;
237 deactivated_entry.user_requested_activation_ = false;
238 em_.update_entry(deactivated_entry);
239
240 full_success = false;
241 }
242
243 }
244
245 return full_success;
246 }

References subsystem_controllers::Entry::active_, subsystem_controllers::Entry::available_, call_timeout_, em_, subsystem_controllers::EntryManager::get_entries(), plugin_lifecycle_mgr_, required_plugins_, service_timeout_, subsystem_controllers::EntryManager::update_entry(), and subsystem_controllers::Entry::user_requested_activation_.

Here is the call graph for this function:

◆ get_active_plugins()

void subsystem_controllers::PluginManager::get_active_plugins ( SrvHeader  ,
carma_planning_msgs::srv::PluginList::Request::SharedPtr  req,
carma_planning_msgs::srv::PluginList::Response::SharedPtr  res 
)

Get the list of currently active plugins.

Parameters
headerMiddle ware header
reqThe req details
[out]resThe response containing the list of active plugins

Definition at line 302 of file plugin_manager.cpp.

303 {
304 // convert to plugin list
305 for(const auto& plugin : em_.get_entries())
306 {
307 if(plugin.active_)
308 {
309 carma_planning_msgs::msg::Plugin msg;
310 msg.activated = plugin.active_;
311 msg.available = plugin.available_;
312 msg.name = plugin.name_;
313 msg.type = plugin.type_;
314 msg.capability = plugin.capability_;
315 res->plugins.push_back(msg);
316 }
317 }
318 }

References em_, and subsystem_controllers::EntryManager::get_entries().

Referenced by subsystem_controllers::GuidanceControllerNode::handle_on_configure().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ get_control_plugins_by_capability()

void subsystem_controllers::PluginManager::get_control_plugins_by_capability ( SrvHeader  ,
carma_planning_msgs::srv::GetPluginApi::Request::SharedPtr  req,
carma_planning_msgs::srv::GetPluginApi::Response::SharedPtr  res 
)

Get control plugins by capability.

Parameters
headerMiddle ware header
reqThe req which identifies which capability is required
resThe res which identifies the control plugins with the requested capability

Definition at line 375 of file plugin_manager.cpp.

376 {
377 std::vector<std::string> req_capability_levels;
378 boost::split(req_capability_levels, req->capability, boost::is_any_of("/"));
379
380 for(const auto& plugin : em_.get_entries())
381 {
382
383 std::vector<std::string> plugin_capability_levels;
384 boost::split(plugin_capability_levels, plugin.capability_, boost::is_any_of("/"));
385
386 if(plugin.type_ == carma_planning_msgs::msg::Plugin::CONTROL &&
387 (req->capability.size() == 0 || (matching_capability(plugin_capability_levels, req_capability_levels) && plugin.active_ && plugin.available_)))
388 {
389 RCLCPP_DEBUG_STREAM(rclcpp::get_logger("guidance_controller"), "discovered control plugin: " << plugin.name_);
390 res->plan_service.push_back(plugin.name_ + control_trajectory_suffix_);
391 }
392 else
393 {
394 RCLCPP_DEBUG_STREAM(rclcpp::get_logger("guidance_controller"), "not valid control plugin: " << plugin.name_);
395 }
396 }
397 }
bool matching_capability(const std::vector< std::string > &base_capability_levels, const std::vector< std::string > &compared_capability_levels)
Returns true if the provided base capability hierarchy can achieve the requested capability hierarchy...
const std::string control_trajectory_suffix_
Base topic name of control plugin trajectory input topic.

References control_trajectory_suffix_, em_, subsystem_controllers::EntryManager::get_entries(), matching_capability(), and process_traj_logs::split.

Referenced by subsystem_controllers::GuidanceControllerNode::handle_on_configure().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ get_registered_plugins()

void subsystem_controllers::PluginManager::get_registered_plugins ( SrvHeader  ,
carma_planning_msgs::srv::PluginList::Request::SharedPtr  req,
carma_planning_msgs::srv::PluginList::Response::SharedPtr  res 
)

Returns the list of known plugins.

Parameters
reqThe req details
[out]resThe response containing the list of known plugins

Definition at line 287 of file plugin_manager.cpp.

288 {
289 // convert to plugin list
290 for(const auto& plugin : em_.get_entries())
291 {
292 carma_planning_msgs::msg::Plugin msg;
293 msg.activated = plugin.active_;
294 msg.available = plugin.available_;
295 msg.name = plugin.name_;
296 msg.type = plugin.type_;
297 msg.capability = plugin.capability_;
298 res->plugins.push_back(msg);
299 }
300 }

References em_, and subsystem_controllers::EntryManager::get_entries().

Referenced by subsystem_controllers::GuidanceControllerNode::handle_on_configure().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ get_strategic_plugins_by_capability()

void subsystem_controllers::PluginManager::get_strategic_plugins_by_capability ( SrvHeader  ,
carma_planning_msgs::srv::GetPluginApi::Request::SharedPtr  req,
carma_planning_msgs::srv::GetPluginApi::Response::SharedPtr  res 
)

Get strategic plugins by capability.

Parameters
headerMiddle ware header
reqThe req which identifies which capability is required
resThe res which identifies the strategic plugins with the requested capability

Definition at line 423 of file plugin_manager.cpp.

424 {
425 std::vector<std::string> req_capability_levels;
426 boost::split(req_capability_levels, req->capability, boost::is_any_of("/"));
427
428 for(const auto& plugin : em_.get_entries())
429 {
430
431 std::vector<std::string> plugin_capability_levels;
432 boost::split(plugin_capability_levels, plugin.capability_, boost::is_any_of("/"));
433
434 if(plugin.type_ == carma_planning_msgs::msg::Plugin::STRATEGIC &&
435 (req->capability.size() == 0 || (matching_capability(plugin_capability_levels, req_capability_levels) && plugin.active_ && plugin.available_)))
436 {
437 RCLCPP_DEBUG_STREAM(rclcpp::get_logger("guidance_controller"), "discovered strategic plugin: " << plugin.name_);
438 res->plan_service.push_back(plugin.name_ + plan_maneuvers_suffix_);
439 }
440 else
441 {
442 RCLCPP_DEBUG_STREAM(rclcpp::get_logger("guidance_controller"), "not valid strategic plugin: " << plugin.name_);
443 }
444 }
445 }
const std::string plan_maneuvers_suffix_
Base service name of plan_trajectory service.

References em_, subsystem_controllers::EntryManager::get_entries(), matching_capability(), plan_maneuvers_suffix_, and process_traj_logs::split.

Referenced by subsystem_controllers::GuidanceControllerNode::handle_on_configure().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ get_tactical_plugins_by_capability()

void subsystem_controllers::PluginManager::get_tactical_plugins_by_capability ( SrvHeader  ,
carma_planning_msgs::srv::GetPluginApi::Request::SharedPtr  req,
carma_planning_msgs::srv::GetPluginApi::Response::SharedPtr  res 
)

Get tactical plugins by capability.

Parameters
headerMiddle ware header
reqThe req which identifies which capability is required
resThe res which identifies the tactical plugins with the requested capability

Definition at line 399 of file plugin_manager.cpp.

400 {
401 std::vector<std::string> req_capability_levels;
402 boost::split(req_capability_levels, req->capability, boost::is_any_of("/"));
403
404 for(const auto& plugin : em_.get_entries())
405 {
406
407 std::vector<std::string> plugin_capability_levels;
408 boost::split(plugin_capability_levels, plugin.capability_, boost::is_any_of("/"));
409
410 if(plugin.type_ == carma_planning_msgs::msg::Plugin::TACTICAL &&
411 (req->capability.size() == 0 || (matching_capability(plugin_capability_levels, req_capability_levels) && plugin.active_ && plugin.available_)))
412 {
413 RCLCPP_DEBUG_STREAM(rclcpp::get_logger("guidance_controller"), "discovered tactical plugin: " << plugin.name_);
414 res->plan_service.push_back(plugin.name_ + plan_trajectory_suffix_);
415 }
416 else
417 {
418 RCLCPP_DEBUG_STREAM(rclcpp::get_logger("guidance_controller"), "not valid tactical plugin: " << plugin.name_);
419 }
420 }
421 }
const std::string plan_trajectory_suffix_
Base service name of plan_trajectory service.

References em_, subsystem_controllers::EntryManager::get_entries(), matching_capability(), plan_trajectory_suffix_, and process_traj_logs::split.

Referenced by subsystem_controllers::GuidanceControllerNode::handle_on_configure().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ is_ros2_lifecycle_node()

bool subsystem_controllers::PluginManager::is_ros2_lifecycle_node ( const std::string &  node)
protected

Returns true if the specified fully qualified node name is a ROS2 lifecycle node.

Parameters
nodeThe fully specified name of the node to evaluate
Returns
True if ros2 lifecycle node. False otherwise

◆ matching_capability()

bool subsystem_controllers::PluginManager::matching_capability ( const std::vector< std::string > &  base_capability_levels,
const std::vector< std::string > &  compared_capability_levels 
)
protected

Returns true if the provided base capability hierarchy can achieve the requested capability hierarchy A capability hierarchy is described as a list of strings where the first string is the most generic description of the capability while the last string the is the most detailed description.

For example the capability "tactical_plan/plan_trajectory" would be described as ["tactical_plan", "plan_trajectory"] if the user wanted to match this to "tactical_plan/plan_trajectory/platooning_trajectory" then the compared_capability_levels would be ["tactical_plan", "plan_trajectory", "compared_capability_levels"] Matching those two inputs as ( ["tactical_plan", "plan_trajectory"], ["tactical_plan", "plan_trajectory", "compared_capability_levels"]) would be false because the compared_capability_levels is more detailed than the base. By contrast, matching ( ["tactical_plan", "plan_trajectory", "compared_capability_levels"], ["tactical_plan", "plan_trajectory"] ) would be true since the base is more generic then the request

// TODO check with Kyle on this because it maybe should be the reverse since a more specific capability may require specific meta data.

Parameters
base_capability_levelsThe base hierarchy to check for compatability
compared_capability_levelsThe compared_capability_levels which are being checked against the base
Returns
True if base_capability_levels supports compared_capability_levels

Definition at line 364 of file plugin_manager.cpp.

365 {
366 for (size_t i=0; i < base_capability_levels.size() && i < compared_capability_levels.size(); i++)
367 {
368 if (compared_capability_levels[i].compare(base_capability_levels[i]) != 0)
369 return false;
370 }
371
372 return true;
373 }

References process_bag::i.

Referenced by get_control_plugins_by_capability(), get_strategic_plugins_by_capability(), and get_tactical_plugins_by_capability().

Here is the caller graph for this function:

◆ shutdown()

bool subsystem_controllers::PluginManager::shutdown ( )

Definition at line 282 of file plugin_manager.cpp.

283 {
284 return plugin_lifecycle_mgr_->shutdown(service_timeout_, call_timeout_, false, em_.get_entry_names()).empty();
285 }
std::vector< std::string > get_entry_names() const
Get all entry names as a list.

References call_timeout_, em_, subsystem_controllers::EntryManager::get_entry_names(), plugin_lifecycle_mgr_, and service_timeout_.

Here is the call graph for this function:

◆ update_plugin_status()

void subsystem_controllers::PluginManager::update_plugin_status ( carma_planning_msgs::msg::Plugin::UniquePtr  msg)

Update the status of a certain plugin.

Parameters
msgA plugin status message

Definition at line 348 of file plugin_manager.cpp.

349 {
350 boost::optional<Entry> requested_plugin = em_.get_entry_by_name(msg->name);
351
352 if (!requested_plugin) // This is a new plugin so we need to add it
353 {
354 Entry plugin(msg->available, msg->activated, msg->name, msg->type, msg->capability, false);
355 add_plugin(plugin);
356 return;
357 }
358
359 Entry plugin(msg->available, msg->activated, msg->name, msg->type, msg->capability, requested_plugin->user_requested_activation_);
360
361 em_.update_entry(plugin);
362 }
void add_plugin(const Entry &plugin)
Add the specified entry to our plugin management This function will attempt to move the newly detecte...

References add_plugin(), em_, subsystem_controllers::EntryManager::get_entry_by_name(), and subsystem_controllers::EntryManager::update_entry().

Referenced by subsystem_controllers::GuidanceControllerNode::handle_on_configure().

Here is the call graph for this function:
Here is the caller graph for this function:

Member Data Documentation

◆ auto_activated_plugins_

std::unordered_set<std::string> subsystem_controllers::PluginManager::auto_activated_plugins_
protected

Set of use specified auto activated plugins which will automatically started without need for user input.

Definition at line 194 of file plugin_manager.h.

Referenced by PluginManager(), and activate().

◆ call_timeout_

std::chrono::nanoseconds subsystem_controllers::PluginManager::call_timeout_
protected

The timeout for service calls to return.

Definition at line 212 of file plugin_manager.h.

Referenced by activate(), activate_plugin(), add_plugin(), cleanup(), configure(), deactivate(), and shutdown().

◆ control_trajectory_suffix_

const std::string subsystem_controllers::PluginManager::control_trajectory_suffix_ = "/plan_trajectory"
protected

Base topic name of control plugin trajectory input topic.

Definition at line 221 of file plugin_manager.h.

Referenced by get_control_plugins_by_capability().

◆ em_

◆ get_parent_state_func_

GetParentNodeStateFunc subsystem_controllers::PluginManager::get_parent_state_func_
protected

Callback to retrieve the lifecycle state of the parent process.

Definition at line 200 of file plugin_manager.h.

Referenced by add_plugin().

◆ get_service_names_and_types_func_

ServiceNamesAndTypesFunc subsystem_controllers::PluginManager::get_service_names_and_types_func_
protected

Callback to get service names and types for the given node.

Definition at line 203 of file plugin_manager.h.

◆ plan_maneuvers_suffix_

const std::string subsystem_controllers::PluginManager::plan_maneuvers_suffix_ = "/plan_maneuvers"
protected

Base service name of plan_trajectory service.

Definition at line 215 of file plugin_manager.h.

Referenced by get_strategic_plugins_by_capability().

◆ plan_trajectory_suffix_

const std::string subsystem_controllers::PluginManager::plan_trajectory_suffix_ = "/plan_trajectory"
protected

Base service name of plan_trajectory service.

Definition at line 218 of file plugin_manager.h.

Referenced by get_tactical_plugins_by_capability().

◆ plugin_lifecycle_mgr_

std::shared_ptr<ros2_lifecycle_manager::LifecycleManagerInterface> subsystem_controllers::PluginManager::plugin_lifecycle_mgr_
protected

Lifecycle Manager which will track the plugin nodes and call their lifecycle services on request.

Definition at line 197 of file plugin_manager.h.

Referenced by PluginManager(), activate(), activate_plugin(), add_plugin(), cleanup(), configure(), deactivate(), and shutdown().

◆ required_plugins_

std::unordered_set<std::string> subsystem_controllers::PluginManager::required_plugins_
protected

Set of required plugins a failure of which necessitates system shutdown.

Definition at line 190 of file plugin_manager.h.

Referenced by PluginManager(), activate(), add_plugin(), cleanup(), configure(), and deactivate().

◆ service_timeout_

std::chrono::nanoseconds subsystem_controllers::PluginManager::service_timeout_
protected

The timeout for services to be available.

Definition at line 209 of file plugin_manager.h.

Referenced by activate(), activate_plugin(), add_plugin(), cleanup(), configure(), deactivate(), and shutdown().


The documentation for this class was generated from the following files: