17#include <boost/algorithm/string.hpp>
18#include <lifecycle_msgs/msg/state.hpp>
19#include <rclcpp/logger.hpp>
20#include <rclcpp/logging.hpp>
29 const std::vector<std::string>& auto_activated_plugins,
30 std::shared_ptr<ros2_lifecycle_manager::LifecycleManagerInterface> plugin_lifecycle_mgr,
33 std::chrono::nanoseconds service_timeout, std::chrono::nanoseconds call_timeout)
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)
40 if (!plugin_lifecycle_mgr)
41 throw std::invalid_argument(
"Input plugin_lifecycle_mgr to PluginManager constructor cannot be null");
48 RCLCPP_INFO_STREAM(rclcpp::get_logger(
"subsystem_controllers"),
"Added a required plugin: " << p);
50 Entry e(
false,
false, p, carma_planning_msgs::msg::Plugin::UNKNOWN,
"",
true);
56 RCLCPP_INFO_STREAM(rclcpp::get_logger(
"subsystem_controllers"),
"Added an auto activated plugin: " << p);
58 Entry e(
false,
false, p, carma_planning_msgs::msg::Plugin::UNKNOWN,
"",
true);
70 Entry deactivated_entry = plugin;
75 if (parent_node_state != lifecycle_msgs::msg::State::PRIMARY_STATE_ACTIVE
76 && parent_node_state != lifecycle_msgs::msg::State::PRIMARY_STATE_INACTIVE)
79 deactivated_entry.
active_ =
false;
84 if(result_state != parent_node_state)
90 throw std::runtime_error(
"Newly discovered required plugin " + plugin.
name_ +
" could not be brought to controller node state.");
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!");
111 if(result_state != lifecycle_msgs::msg::State::PRIMARY_STATE_INACTIVE)
116 throw std::runtime_error(
"Newly discovered required plugin " + plugin.
name_ +
" could not be brought to inactive state.");
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!");
126 deactivated_entry.
active_ =
false;
133 bool full_success =
true;
139 if(result_state != lifecycle_msgs::msg::State::PRIMARY_STATE_INACTIVE)
144 throw std::runtime_error(
"Required plugin " + plugin.name_ +
" could not be configured.");
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!");
151 Entry deactivated_entry = plugin;
152 deactivated_entry.
active_ =
false;
157 full_success =
false;
168 bool full_success =
true;
173 if (!plugin.user_requested_activation_)
178 if(result_state != lifecycle_msgs::msg::State::PRIMARY_STATE_ACTIVE)
183 throw std::runtime_error(
"Required plugin " + plugin.name_ +
" could not be activated.");
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!");
190 Entry deactivated_entry = plugin;
191 deactivated_entry.
active_ =
false;
196 full_success =
false;
202 plugin.user_requested_activation_ =
false;
205 plugin.active_ =
true;
216 bool full_success =
true;
222 if(result_state != lifecycle_msgs::msg::State::PRIMARY_STATE_INACTIVE)
227 throw std::runtime_error(
"Required plugin " + plugin.name_ +
" could not be deactivated.");
231 RCLCPP_ERROR_STREAM(rclcpp::get_logger(
"subsystem_controllers"),
"Failed to deactivate non-required plugin: "
232 << plugin.name_ <<
" Marking as deactivated and unavailable!");
234 Entry deactivated_entry = plugin;
235 deactivated_entry.
active_ =
false;
240 full_success =
false;
250 bool full_success =
true;
256 if(result_state != lifecycle_msgs::msg::State::PRIMARY_STATE_UNCONFIGURED)
261 throw std::runtime_error(
"Required plugin " + plugin.name_ +
" could not be cleaned up.");
265 RCLCPP_ERROR_STREAM(rclcpp::get_logger(
"subsystem_controllers"),
"Failed to cleanup non-required plugin: "
266 << plugin.name_ <<
" Marking as deactivated and unavailable!");
268 Entry deactivated_entry = plugin;
269 deactivated_entry.
active_ =
false;
274 full_success =
false;
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);
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);
324 if(!requested_plugin)
326 res->newstate =
false;
330 bool activated =
false;
335 activated = (result_state == lifecycle_msgs::msg::State::PRIMARY_STATE_ACTIVE);
339 activated = (result_state == lifecycle_msgs::msg::State::PRIMARY_STATE_ACTIVE);
342 Entry updated_entry(requested_plugin->available_, activated, requested_plugin->name_, requested_plugin->type_, requested_plugin->capability_,
true);
345 res->newstate = activated;
352 if (!requested_plugin)
354 Entry plugin(msg->available, msg->activated, msg->name, msg->type, msg->capability,
false);
359 Entry plugin(msg->available, msg->activated, msg->name, msg->type, msg->capability, requested_plugin->user_requested_activation_);
366 for (
size_t i=0;
i < base_capability_levels.size() &&
i < compared_capability_levels.size();
i++)
368 if (compared_capability_levels[
i].compare(base_capability_levels[
i]) != 0)
377 std::vector<std::string> req_capability_levels;
378 boost::split(req_capability_levels, req->capability, boost::is_any_of(
"/"));
383 std::vector<std::string> plugin_capability_levels;
384 boost::split(plugin_capability_levels, plugin.capability_, boost::is_any_of(
"/"));
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_)))
389 RCLCPP_DEBUG_STREAM(rclcpp::get_logger(
"guidance_controller"),
"discovered control plugin: " << plugin.name_);
394 RCLCPP_DEBUG_STREAM(rclcpp::get_logger(
"guidance_controller"),
"not valid control plugin: " << plugin.name_);
401 std::vector<std::string> req_capability_levels;
402 boost::split(req_capability_levels, req->capability, boost::is_any_of(
"/"));
407 std::vector<std::string> plugin_capability_levels;
408 boost::split(plugin_capability_levels, plugin.capability_, boost::is_any_of(
"/"));
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_)))
413 RCLCPP_DEBUG_STREAM(rclcpp::get_logger(
"guidance_controller"),
"discovered tactical plugin: " << plugin.name_);
418 RCLCPP_DEBUG_STREAM(rclcpp::get_logger(
"guidance_controller"),
"not valid tactical plugin: " << plugin.name_);
425 std::vector<std::string> req_capability_levels;
426 boost::split(req_capability_levels, req->capability, boost::is_any_of(
"/"));
431 std::vector<std::string> plugin_capability_levels;
432 boost::split(plugin_capability_levels, plugin.capability_, boost::is_any_of(
"/"));
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_)))
437 RCLCPP_DEBUG_STREAM(rclcpp::get_logger(
"guidance_controller"),
"discovered strategic plugin: " << plugin.name_);
442 RCLCPP_DEBUG_STREAM(rclcpp::get_logger(
"guidance_controller"),
"not valid strategic plugin: " << plugin.name_);
std::chrono::milliseconds std_msec
std::vector< std::string > get_entry_names() const
Get all entry names as a list.
boost::optional< Entry > get_entry_by_name(const std::string &name) const
Get a entry using name as the key.
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::vector< Entry > get_entries() const
Get all entries as a list.
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.
void add_plugin(const Entry &plugin)
Add the specified entry to our plugin management This function will attempt to move the newly detecte...
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.
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.
std::unordered_set< std::string > auto_activated_plugins_
Set of use specified auto activated plugins which will automatically started without need for user in...
const std::string plan_trajectory_suffix_
Base service name of plan_trajectory service.
std::unordered_set< std::string > required_plugins_
Set of required plugins a failure of which necessitates system shutdown.
const std::string plan_maneuvers_suffix_
Base service name of plan_trajectory service.
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...
std::chrono::nanoseconds call_timeout_
The timeout for service calls to return.
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.
GetParentNodeStateFunc get_parent_state_func_
Callback to retrieve the lifecycle state of the parent process.
void update_plugin_status(carma_planning_msgs::msg::Plugin::UniquePtr msg)
Update the status of a certain plugin.
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.
std::chrono::nanoseconds service_timeout_
The timeout for services to be available.
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.
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.
void activate_plugin(SrvHeader, carma_planning_msgs::srv::PluginActivation::Request::SharedPtr req, carma_planning_msgs::srv::PluginActivation::Response::SharedPtr res)
Activate the specified plugin.
EntryManager em_
Entry manager to keep track of detected plugins.
const std::string control_trajectory_suffix_
Base topic name of control plugin trajectory input topic.
std::function< uint8_t()> GetParentNodeStateFunc
std::function< std::map< std::string, std::vector< std::string, std::allocator< std::string > > >(const std::string &, const std::string &)> ServiceNamesAndTypesFunc
Function which will return a map of service names and their message types based on the provided base ...
const std::shared_ptr< rmw_request_id_t > SrvHeader
An entry represents a driver details for the purposes of tracking.
bool available_
Availability flag of a driver.
std::string name_
Fully specified node name of a driver.
bool user_requested_activation_
Flag indicating if the user requested this plugin be activated.
bool active_
Activation flag of a plugin.