From e13c57de7384cd0f0659a607510af924f9cdf538 Mon Sep 17 00:00:00 2001 From: BuddhiGamage Date: Mon, 16 Sep 2024 13:27:35 +1000 Subject: [PATCH 1/5] listen runner initialized --- .../listen_runner.hpp | 70 +++++++++++++++---- 1 file changed, 57 insertions(+), 13 deletions(-) diff --git a/capabilities2_runner_audio/include/capabilities2_runner_audio/listen_runner.hpp b/capabilities2_runner_audio/include/capabilities2_runner_audio/listen_runner.hpp index f53b1da..e9904cd 100644 --- a/capabilities2_runner_audio/include/capabilities2_runner_audio/listen_runner.hpp +++ b/capabilities2_runner_audio/include/capabilities2_runner_audio/listen_runner.hpp @@ -1,24 +1,68 @@ #pragma once +#include #include +#include +#include +#include +#include -namespace capabilities2_runner_audio +namespace capabilities2_runner { -class ListenRunner : public capabilities2_runner::ActionRunner + +/** + * @brief action runner base class + * + * Class to run VoiceListener action based capability + * + */ +class VoiceListenerRunner : public ActionRunner { public: - ListenRunner(/* args */); - ~ListenRunner(); + VoiceListenerRunner() : ActionRunner() + { + } -private: -}; + /** + * @brief Starter function for starting the action runner + * + * @param node shared pointer to the capabilities node. Allows to use ros node related functionalities + * @param run_config runner configuration loaded from the yaml file + * @param on_started function pointer to trigger at the start of the action client in the runner + * @param on_terminated function pointer to trigger at the termination of the action client in the runner + */ + virtual void start(rclcpp::Node::SharedPtr node, const runner_opts& run_config, + std::function on_started = nullptr, + std::function on_terminated = nullptr) override + { + init_action(node, run_config, "speech_to_text", on_started, on_terminated); + } -ListenRunner::ListenRunner(/* args */) -{ -} + /** + * @brief trigger the runner + * + @param parameters XMLElement that contains parameters in the format '' + */ + virtual void trigger(std::shared_ptr parameters = nullptr) + { + tinyxml2::XMLElement* parametersElement = parameters->FirstChildElement("speech_to_text"); -ListenRunner::~ListenRunner() -{ -} + hri_audio_msgs::action::SpeechToText::Goal goal_msg; + + + + + // launch runner using action client + action_client_->async_send_goal(goal_msg, send_goal_options_); + } + + + +protected: + std::string global_frame_; /**The global frame of the robot*/ + std::string robot_base_frame_; /**The frame of the robot base*/ + + double x, y; /**Coordinate frame parameters*/ +}; -} // namespace capabilities2_runner_audio +} // namespace capabilities2_runner From 4fd63379e879d8a669dc33dbdd359a278457af21 Mon Sep 17 00:00:00 2001 From: Kalana Ratnayake Date: Mon, 16 Sep 2024 14:37:22 +1000 Subject: [PATCH 2/5] minor change --- .../include/capabilities2_runner_nav2/waypoint_runner.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/capabilities2_runner_nav2/include/capabilities2_runner_nav2/waypoint_runner.hpp b/capabilities2_runner_nav2/include/capabilities2_runner_nav2/waypoint_runner.hpp index ac09fe2..0b32171 100644 --- a/capabilities2_runner_nav2/include/capabilities2_runner_nav2/waypoint_runner.hpp +++ b/capabilities2_runner_nav2/include/capabilities2_runner_nav2/waypoint_runner.hpp @@ -36,7 +36,7 @@ class WayPointRunner : public ActionRunner std::function on_started = nullptr, std::function on_terminated = nullptr) override { - init_action(node, run_config, "WaypointFollower", on_started, on_terminated); + init_action(node, run_config, "follow_waypoints", on_started, on_terminated); } /** From 98f7e4f64742adf6da498d44aeea40ef4c952872 Mon Sep 17 00:00:00 2001 From: Kalana Ratnayake Date: Tue, 17 Sep 2024 01:51:04 +1000 Subject: [PATCH 3/5] added ActionClientManager to handle multple actions in a single runner --- .../action_client_manager.hpp | 201 ++++++++++++ .../capabilities2_runner/action_runner.hpp | 294 +++++++----------- .../capabilities2_runner/launch_runner.hpp | 5 +- .../multi_action_runner.hpp | 94 ++++++ .../capabilities2_runner/runner_base.hpp | 34 +- capabilities2_runner_audio/CMakeLists.txt | 66 +++- .../listen_runner.hpp | 32 +- capabilities2_runner_audio/package.xml | 11 + capabilities2_runner_audio/plugins.xml | 9 +- .../src/audio_runners.cpp | 11 + .../waypoint_runner.hpp | 89 +++--- capabilities2_runner_nav2/plugins.xml | 4 +- .../capabilities2_server/runner_cache.hpp | 4 +- 13 files changed, 593 insertions(+), 261 deletions(-) create mode 100644 capabilities2_runner/include/capabilities2_runner/action_client_manager.hpp create mode 100644 capabilities2_runner/include/capabilities2_runner/multi_action_runner.hpp create mode 100644 capabilities2_runner_audio/src/audio_runners.cpp diff --git a/capabilities2_runner/include/capabilities2_runner/action_client_manager.hpp b/capabilities2_runner/include/capabilities2_runner/action_client_manager.hpp new file mode 100644 index 0000000..fff84fe --- /dev/null +++ b/capabilities2_runner/include/capabilities2_runner/action_client_manager.hpp @@ -0,0 +1,201 @@ +#pragma once + +#include +#include +#include +#include +#include + +#include +#include +#include + +namespace capabilities2_runner +{ + +template +struct ActionClientBundle +{ + std::shared_ptr> action_client; + typename rclcpp_action::Client::SendGoalOptions send_goal_options; + typename rclcpp_action::ClientGoalHandle::SharedPtr goal_handle; +}; + +/** + * @brief action manager that control multiple action clients + */ +class ActionClientManager +{ +public: + /** + * @brief Constructor of the action client manager + * + * @param node shared pointer to the capabilities node. Allows to use ros node related functionalities + * @param run_config runner configuration loaded from the yaml file + * @param on_started function pointer to trigger at the start of the action client in the runner + * @param on_terminated function pointer to trigger at the termination of the action client in the runner + * @param on_stopped function pointer to trigger at the termination of the action client by the server + */ + ActionClientManager(rclcpp::Node::SharedPtr node, const runner_opts& run_config, + std::function on_started = nullptr, + std::function on_terminated = nullptr, + std::function on_stopped = nullptr) + { + node_ = node; + run_config_ = run_config; + on_started_ = on_started; + on_terminated_ = on_terminated; + on_stopped_ = on_stopped; + } + + /** + * @brief Initializer function for initializing the action runner in place of constructor due to plugin semantics + * + * @param action_name action name used in the yaml file, used to load specific configuration from the run_config + */ + template + void init_action(const std::string& action_name) + { + typename rclcpp_action::Client::SendGoalOptions goal_options_; + typename rclcpp_action::ClientGoalHandle::SharedPtr goal_handle_; + + auto client_ = rclcpp_action::create_client(node_, action_name); + + // wait for action server + RCLCPP_INFO(node_->get_logger(), "%s waiting for action: %s", run_config_.interface.c_str(), action_name.c_str()); + + if (!client_->wait_for_action_server(std::chrono::seconds(3))) + { + RCLCPP_ERROR(node_->get_logger(), "%s failed to connect to action: %s", run_config_.interface.c_str(), action_name.c_str()); + throw runner_exception("failed to connect to action server"); + } + + // send goal options + // goal response callback + goal_options_.goal_response_callback = [this, &goal_handle_](const typename rclcpp_action::ClientGoalHandle::SharedPtr& goal_handle) + { + // store goal handle to be used with stop funtion + goal_handle_ = goal_handle; + }; + + // result callback + goal_options_.result_callback = [this](const typename rclcpp_action::ClientGoalHandle::WrappedResult& wrapped_result) + { + if (wrapped_result.code == rclcpp_action::ResultCode::SUCCEEDED) + { + // publish event + if (on_started_) on_started_(run_config_.interface); + } + else + { + // send terminated event + if (on_terminated_) on_terminated_(run_config_.interface); + } + }; + + ActionClientBundle bundle{client_, goal_options_, goal_handle_}; + + action_clients_map_[action_name] = std::make_any>(bundle); + } + + /** + * @brief Deinitializer function for stopping an the action + * + * @param action_name action name used in the yaml file, used to load specific configuration from the run_config + */ + template + void deinit_action(const std::string& action_name) + { + auto bundle = std::any_cast>(action_clients_map_[action_name]); + + // if the node pointer is empty then throw an error + // this means that the runner was not started and is being used out of order + + if (!node_) + throw runner_exception("cannot stop runner that was not started"); + + // throw an error if the action client is null + // this can happen if the runner is not able to find the action resource + + if (!bundle.action_client) + throw runner_exception("cannot stop runner action that was not started"); + + + // stop runner using action client + if (bundle.goal_handle) + { + try + { + auto cancel_future = bundle.action_client->async_cancel_goal( + bundle.goal_handle, [this](action_msgs::srv::CancelGoal_Response::SharedPtr response) { + if (response->return_code != action_msgs::srv::CancelGoal_Response::ERROR_NONE) + { + // throw runner_exception("failed to cancel runner"); + } + + // publish event + if (on_stopped_) + { + on_stopped_(run_config_.interface); + } + }); + + // wait for action to be stopped. hold the thread for 2 seconds to help keep callbacks in scope + rclcpp::spin_until_future_complete(node_, cancel_future, std::chrono::seconds(2)); + } + catch (const rclcpp_action::exceptions::UnknownGoalHandleError& e) + { + RCLCPP_ERROR(node_->get_logger(), "failed to cancel goal: %s", e.what()); + throw runner_exception(e.what()); + } + } + } + + /** + * @brief Trigger function for calling an the action + * + * @param action_name action name used in the yaml file, used to load specific configuration from the run_config + */ + template + void trigger_action(const std::string& action_name, typename ActionT::Goal goal_msg) + { + auto bundle = std::any_cast>(action_clients_map_[action_name]); + + // launch runner using action client + bundle.action_client->async_send_goal(goal_msg, bundle.send_goal_options); + } + +protected: + + /** + * Dictionary to hold action client bundle. The key is a string, and the value is a polymorphic bundle. + * */ + std::map action_clients_map_; + + /** + * shared pointer to the capabilities node. Allows to use ros node related functionalities + */ + rclcpp::Node::SharedPtr node_; + + /** + * runner configuration + */ + runner_opts run_config_; + + /** + * pointer to function to execute on starting the runner + */ + std::function on_started_; + + /** + * pointer to function to execute on terminating the runner + */ + std::function on_terminated_; + + /** + * pointer to function to execute on stopping the runner + */ + std::function on_stopped_; +}; + +} // namespace capabilities2_runner diff --git a/capabilities2_runner/include/capabilities2_runner/action_runner.hpp b/capabilities2_runner/include/capabilities2_runner/action_runner.hpp index 5e8fe8e..fa1e066 100644 --- a/capabilities2_runner/include/capabilities2_runner/action_runner.hpp +++ b/capabilities2_runner/include/capabilities2_runner/action_runner.hpp @@ -23,183 +23,131 @@ template class ActionRunner : public RunnerBase { public: - /** - * @brief Constructor which needs to be empty due to plugin semantics - */ - ActionRunner() : RunnerBase() - { - } - - /** - * @brief Initializer function for initializing the action runner in place of constructor due to plugin semantics - * - * @param node shared pointer to the capabilities node. Allows to use ros node related functionalities - * @param run_config runner configuration loaded from the yaml file - * @param action_name action name used in the yaml file, used to load specific configuration from the run_config - * @param on_started function pointer to trigger at the start of the action client in the runner - * @param on_terminated function pointer to trigger at the termination of the action client in the runner - */ - virtual void init_action(rclcpp::Node::SharedPtr node, const runner_opts& run_config, const std::string& action_name, - std::function on_started = nullptr, - std::function on_terminated = nullptr) - { - // initialize the runner base by storing node pointer and run config - init_base(node, run_config); - - // initialize the clock used for message timestamps - clock_ = node_->get_clock(); - - // create an action client - action_client_ = rclcpp_action::create_client(node_, action_name); - - // wait for action server - RCLCPP_INFO(node_->get_logger(), "%s waiting for action: %s", run_config_.interface.c_str(), action_name.c_str()); - - if (!action_client_->wait_for_action_server(std::chrono::seconds(3))) - { - RCLCPP_ERROR(node_->get_logger(), "%s failed to connect to action server", run_config_.interface.c_str()); - throw runner_exception("failed to connect to action server"); - } - - // send goal options - // goal response callback - send_goal_options_.goal_response_callback = - [this, on_started, - on_terminated](const typename rclcpp_action::ClientGoalHandle::SharedPtr& goal_handle) { - // store goal handle to be used with stop funtion - goal_handle_ = goal_handle; - }; - - // result callback - send_goal_options_.result_callback = - [this, on_started, - on_terminated](const typename rclcpp_action::ClientGoalHandle::WrappedResult& wrapped_result) { - if (wrapped_result.code == rclcpp_action::ResultCode::SUCCEEDED) - { - // publish event - if (on_started) - { - on_started(run_config_.interface); - } - } - else - { - // send terminated event - if (on_terminated) - { - on_terminated(run_config_.interface); - } - } - }; - } - - /** - * @brief stop function to cease functionality and shutdown - * - * @param on_stopped function pointer to trigger at the termination of the action client by the server - */ - virtual void stop(std::function on_stopped = nullptr) override - { - // if the node pointer is empty then throw an error - // this means that the runner was not started and is being used out of order - - if (!node_) - throw runner_exception("cannot stop runner that was not started"); - - // throw an error if the action client is null - // this can happen if the runner is not able to find the action resource - - if (!action_client_) - throw runner_exception("cannot stop runner action that was not started"); - - // stop runner using action client - if (goal_handle_) - { - try - { - auto cancel_future = action_client_->async_cancel_goal( - goal_handle_, [this, on_stopped](action_msgs::srv::CancelGoal_Response::SharedPtr response) { - if (response->return_code != action_msgs::srv::CancelGoal_Response::ERROR_NONE) - { - // throw runner_exception("failed to cancel runner"); - } - - // publish event - if (on_stopped) - { - on_stopped(run_config_.interface); - } - }); - - // wait for action to be stopped. hold the thread for 2 seconds to help keep callbacks in scope - rclcpp::spin_until_future_complete(node_, cancel_future, std::chrono::seconds(2)); - } - catch (const rclcpp_action::exceptions::UnknownGoalHandleError& e) - { - RCLCPP_ERROR(node_->get_logger(), "failed to cancel goal: %s", e.what()); - throw runner_exception(e.what()); - } - } - } + /** + * @brief Constructor which needs to be empty due to plugin semantics + */ + ActionRunner() : RunnerBase() + { + } + + /** + * @brief Initializer function for initializing the action runner in place of constructor due to plugin semantics + * + * @param node shared pointer to the capabilities node. Allows to use ros node related functionalities + * @param run_config runner configuration loaded from the yaml file + * @param action_name action name used in the yaml file, used to load specific configuration from the run_config + * @param on_started function pointer to trigger at the start of the action client in the runner + * @param on_terminated function pointer to trigger at the termination of the action client in the runner + * @param on_stopped function pointer to trigger at the termination of the action client by the server + */ + virtual void init_action(rclcpp::Node::SharedPtr node, const runner_opts& run_config, const std::string& action_name, + std::function on_started = nullptr, + std::function on_terminated = nullptr, + std::function on_stopped = nullptr) + { + // initialize the runner base by storing node pointer and run config + init_base(node, run_config, on_started, on_terminated, on_stopped); + + // create an action client + action_client_ = rclcpp_action::create_client(node_, action_name); + + // wait for action server + RCLCPP_INFO(node_->get_logger(), "%s waiting for action: %s", run_config_.interface.c_str(), action_name.c_str()); + + if (!action_client_->wait_for_action_server(std::chrono::seconds(3))) + { + RCLCPP_ERROR(node_->get_logger(), "%s failed to connect to action: %s", run_config_.interface.c_str(), action_name.c_str()); + throw runner_exception("failed to connect to action server"); + } + + // send goal options + // goal response callback + send_goal_options_.goal_response_callback = + [this](const typename rclcpp_action::ClientGoalHandle::SharedPtr& goal_handle) { + // store goal handle to be used with stop funtion + goal_handle_ = goal_handle; + }; + + // result callback + send_goal_options_.result_callback = + [this](const typename rclcpp_action::ClientGoalHandle::WrappedResult& wrapped_result) { + if (wrapped_result.code == rclcpp_action::ResultCode::SUCCEEDED) + { + // publish event + if (on_started_) + { + on_started_(run_config_.interface); + } + } + else + { + // send terminated event + if (on_terminated_) + { + on_terminated_(run_config_.interface); + } + } + }; + } + + /** + * @brief stop function to cease functionality and shutdown + * + */ + virtual void stop() override + { + // if the node pointer is empty then throw an error + // this means that the runner was not started and is being used out of order + + if (!node_) + throw runner_exception("cannot stop runner that was not started"); + + // throw an error if the action client is null + // this can happen if the runner is not able to find the action resource + + if (!action_client_) + throw runner_exception("cannot stop runner action that was not started"); + + // stop runner using action client + if (goal_handle_) + { + try + { + auto cancel_future = action_client_->async_cancel_goal( + goal_handle_, [this](action_msgs::srv::CancelGoal_Response::SharedPtr response) { + if (response->return_code != action_msgs::srv::CancelGoal_Response::ERROR_NONE) + { + // throw runner_exception("failed to cancel runner"); + } + + // publish event + if (on_stopped_) + { + on_stopped_(run_config_.interface); + } + }); + + // wait for action to be stopped. hold the thread for 2 seconds to help keep callbacks in scope + rclcpp::spin_until_future_complete(node_, cancel_future, std::chrono::seconds(2)); + } + catch (const rclcpp_action::exceptions::UnknownGoalHandleError& e) + { + RCLCPP_ERROR(node_->get_logger(), "failed to cancel goal: %s", e.what()); + throw runner_exception(e.what()); + } + } + } protected: - /** - * @brief Get the name of an action resource by given action type - * - * This helps to navigate remappings from the runner config - * - * @param action_type - * @return std::string - */ - std::string get_action_name_by_type(const std::string& action_type) - { - for (const auto& resource : run_config_.resources) - { - if (resource.resource_type == "action") - { - if (resource.msg_type == action_type) - { - return resource.name; - } - } - } - - throw runner_exception("no action resource found: " + action_type); - } - - /** - * @brief get first action resource name - * - * This can be used to get the name of the first action resource in the runner config - * - * @return std::string - */ - std::string get_first_action_name() - { - for (const auto& resource : run_config_.resources) - { - if (resource.resource_type == "action") - { - return resource.name; - } - } - - throw runner_exception("no action resources found for interface: " + run_config_.interface); - } + /**< action client */ + std::shared_ptr> action_client_; -protected: - /**< action client */ - std::shared_ptr> action_client_; - - /**< rclcpp clock to get time */ - rclcpp::Clock::SharedPtr clock_; - - /**< Send Goal Option struct to link result_callback, feedback_callback and goal_response_callback with action client - */ - typename rclcpp_action::Client::SendGoalOptions send_goal_options_; + /**< Send Goal Option struct to link result_callback, feedback_callback and goal_response_callback with action client + */ + typename rclcpp_action::Client::SendGoalOptions send_goal_options_; - /**< goal handle parameter to capture goal response from goal_response_callback */ - typename rclcpp_action::ClientGoalHandle::SharedPtr goal_handle_; + /**< goal handle parameter to capture goal response from goal_response_callback */ + typename rclcpp_action::ClientGoalHandle::SharedPtr goal_handle_; }; } // namespace capabilities2_runner diff --git a/capabilities2_runner/include/capabilities2_runner/launch_runner.hpp b/capabilities2_runner/include/capabilities2_runner/launch_runner.hpp index fb11ce7..7cf3c6e 100644 --- a/capabilities2_runner/include/capabilities2_runner/launch_runner.hpp +++ b/capabilities2_runner/include/capabilities2_runner/launch_runner.hpp @@ -26,10 +26,11 @@ class LaunchRunner : public ActionRunner virtual void start(rclcpp::Node::SharedPtr node, const runner_opts& run_config, std::function on_started = nullptr, - std::function on_terminated = nullptr) override + std::function on_terminated = nullptr, + std::function on_stopped = nullptr) override { // store node pointer and run_config - init_action(node, run_config, "capabilities_launch_proxy/launch", on_started, on_terminated); + init_action(node, run_config, "capabilities_launch_proxy/launch", on_started, on_terminated, on_stopped); // get the package path from environment variable std::string package_path; diff --git a/capabilities2_runner/include/capabilities2_runner/multi_action_runner.hpp b/capabilities2_runner/include/capabilities2_runner/multi_action_runner.hpp new file mode 100644 index 0000000..3a913cb --- /dev/null +++ b/capabilities2_runner/include/capabilities2_runner/multi_action_runner.hpp @@ -0,0 +1,94 @@ +#pragma once + +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include + +namespace capabilities2_runner +{ + +/** + * @brief action runner base class + * + * Create an action client to run an action based capability + */ +class MultiActionRunner : public RunnerBase +{ +public: + /** + * @brief Constructor which needs to be empty due to plugin semantics + */ + MultiActionRunner() : RunnerBase() + { + } + + /** + * @brief Initializer function for initializing the action runner in place of constructor due to plugin semantics + * + * @param node shared pointer to the capabilities node. Allows to use ros node related functionalities + * @param run_config runner configuration loaded from the yaml file + * @param on_started function pointer to trigger at the start of the action client in the runner + * @param on_terminated function pointer to trigger at the termination of the action client in the runner + */ + virtual void init_runner(rclcpp::Node::SharedPtr node, const runner_opts& run_config, + std::function on_started = nullptr, + std::function on_terminated = nullptr, + std::function on_stopped = nullptr) + { + // initialize the runner base by storing node pointer and run config + init_base(node, run_config, on_started, on_terminated, on_stopped); + + // initialize the action client manager used for manageing the actions + actionClientManager_ = std::make_shared(node, run_config, on_started, on_terminated, on_stopped); + } + + /** + * @brief Initializer function for initializing the action runner in place of constructor due to plugin semantics + * + * @param action_name action name used in the yaml file, used to load specific configuration from the run_config + */ + template + void init_action(const std::string& action_name) + { + actionClientManager_->init_action(action_name); + } + + /** + * @brief Deinitializer function for stopping an the action + * + * @param action_name action name used in the yaml file, used to load specific configuration from the run_config + */ + template + void deinit_action(const std::string& action_name) + { + actionClientManager_->deinit_action(action_name); + } + + /** + * @brief Trigger function for calling an the action + * + * @param action_name action name used in the yaml file, used to load specific configuration from the run_config + */ + template + void trigger_action(const std::string& action_name, typename ActionT::Goal goal_msg) + { + actionClientManager_->trigger_action(action_name, goal_msg); + } + +protected: + + /** Action Client Manager for handling multiple actions*/ + std::shared_ptr actionClientManager_; + +}; + +} // namespace capabilities2_runner diff --git a/capabilities2_runner/include/capabilities2_runner/runner_base.hpp b/capabilities2_runner/include/capabilities2_runner/runner_base.hpp index c44e22e..c82bae9 100644 --- a/capabilities2_runner/include/capabilities2_runner/runner_base.hpp +++ b/capabilities2_runner/include/capabilities2_runner/runner_base.hpp @@ -80,14 +80,15 @@ class RunnerBase */ virtual void start(rclcpp::Node::SharedPtr node, const runner_opts& run_config, std::function on_started = nullptr, - std::function on_terminated = nullptr) = 0; + std::function on_terminated = nullptr, + std::function on_stopped = nullptr) = 0; /** * @brief stop the runner * * @param on_stopped pointer to function to execute on stopping the runner */ - virtual void stop(std::function on_stopped = nullptr) = 0; + virtual void stop() = 0; /** * @brief trigger the runner @@ -101,12 +102,20 @@ class RunnerBase * * @param node shared pointer to the capabilities node. Allows to use ros node related functionalities * @param run_config runner configuration loaded from the yaml file + * @param on_started pointer to function to execute on starting the runner + * @param on_terminated pointer to function to execute on terminating the runner */ - void init_base(rclcpp::Node::SharedPtr node, const runner_opts& run_config) + void init_base(rclcpp::Node::SharedPtr node, const runner_opts& run_config, + std::function on_started = nullptr, + std::function on_terminated = nullptr, + std::function on_stopped = nullptr) { // store node pointer and opts - node_ = node; - run_config_ = run_config; + node_ = node; + run_config_ = run_config; + on_started_ = on_started; + on_terminated_ = on_terminated; + on_stopped_ = on_stopped; } /** @@ -159,6 +168,21 @@ class RunnerBase * @param node runner configuration */ runner_opts run_config_; + + /** + * @param node pointer to function to execute on starting the runner + */ + std::function on_started_; + + /** + * @param node pointer to function to execute on terminating the runner + */ + std::function on_terminated_; + + /** + * @param node pointer to function to execute on stopping the runner + */ + std::function on_stopped_; }; } // namespace capabilities2_runner diff --git a/capabilities2_runner_audio/CMakeLists.txt b/capabilities2_runner_audio/CMakeLists.txt index 8fe7764..15ba918 100644 --- a/capabilities2_runner_audio/CMakeLists.txt +++ b/capabilities2_runner_audio/CMakeLists.txt @@ -1,26 +1,62 @@ cmake_minimum_required(VERSION 3.8) project(capabilities2_runner_audio) +# Default to C++17 +if(NOT CMAKE_CXX_STANDARD) + set(CMAKE_CXX_STANDARD 17) +endif() + if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang") add_compile_options(-Wall -Wextra -Wpedantic) endif() # find dependencies find_package(ament_cmake REQUIRED) -# uncomment the following section in order to fill in -# further dependencies manually. -# find_package( REQUIRED) - -if(BUILD_TESTING) - find_package(ament_lint_auto REQUIRED) - # the following line skips the linter which checks for copyrights - # comment the line when a copyright and license is added to all source files - set(ament_cmake_copyright_FOUND TRUE) - # the following line skips cpplint (only works in a git repo) - # comment the line when this package is in a git repo and when - # a copyright and license is added to all source files - set(ament_cmake_cpplint_FOUND TRUE) - ament_lint_auto_find_test_dependencies() -endif() +find_package(rclcpp REQUIRED) +find_package(rclcpp_action REQUIRED) +find_package(pluginlib REQUIRED) +find_package(hri_audio_msgs REQUIRED) +find_package(capabilities2_msgs REQUIRED) +find_package(capabilities2_runner REQUIRED) +find_package(PkgConfig) +pkg_check_modules(TINYXML2 tinyxml2 REQUIRED) + +include_directories(include +${TINYXML2_INCLUDE_DIRS} +) + +add_library(${PROJECT_NAME} SHARED + src/audio_runners.cpp +) + +target_link_libraries(${PROJECT_NAME} + ${TINYXML2_LIBRARIES} +) + +ament_target_dependencies(${PROJECT_NAME} + rclcpp + rclcpp_action + pluginlib + hri_audio_msgs + capabilities2_msgs + capabilities2_runner + TINYXML2 +) + +pluginlib_export_plugin_description_file(${PROJECT_NAME} plugins.xml) + +install(TARGETS ${PROJECT_NAME} + EXPORT ${PROJECT_NAME} + ARCHIVE DESTINATION lib + LIBRARY DESTINATION lib + RUNTIME DESTINATION bin +) + +install(DIRECTORY include/ + DESTINATION include +) + +ament_export_include_directories(include) +ament_export_libraries(${PROJECT_NAME}) ament_package() diff --git a/capabilities2_runner_audio/include/capabilities2_runner_audio/listen_runner.hpp b/capabilities2_runner_audio/include/capabilities2_runner_audio/listen_runner.hpp index e9904cd..95bbe65 100644 --- a/capabilities2_runner_audio/include/capabilities2_runner_audio/listen_runner.hpp +++ b/capabilities2_runner_audio/include/capabilities2_runner_audio/listen_runner.hpp @@ -1,7 +1,7 @@ #pragma once #include -#include +#include #include #include #include @@ -16,10 +16,10 @@ namespace capabilities2_runner * Class to run VoiceListener action based capability * */ -class VoiceListenerRunner : public ActionRunner +class VoiceListenerRunner : public MultiActionRunner { public: - VoiceListenerRunner() : ActionRunner() + VoiceListenerRunner() : MultiActionRunner() { } @@ -33,27 +33,33 @@ class VoiceListenerRunner : public ActionRunner on_started = nullptr, - std::function on_terminated = nullptr) override + std::function on_terminated = nullptr, + std::function on_stopped = nullptr) override { - init_action(node, run_config, "speech_to_text", on_started, on_terminated); + init_runner(node, run_config, on_started, on_terminated, on_stopped); + + init_action("speech_to_text"); } + /** + * @brief stop function to cease functionality and shutdown + * + */ + virtual void stop() override + { + deinit_action("speech_to_text"); + } + /** * @brief trigger the runner * - @param parameters XMLElement that contains parameters in the format '' + @param parameters XMLElement */ virtual void trigger(std::shared_ptr parameters = nullptr) { - tinyxml2::XMLElement* parametersElement = parameters->FirstChildElement("speech_to_text"); - hri_audio_msgs::action::SpeechToText::Goal goal_msg; - - - - // launch runner using action client - action_client_->async_send_goal(goal_msg, send_goal_options_); + trigger_action("speech_to_text", goal_msg); } diff --git a/capabilities2_runner_audio/package.xml b/capabilities2_runner_audio/package.xml index 88563f5..cb8e743 100644 --- a/capabilities2_runner_audio/package.xml +++ b/capabilities2_runner_audio/package.xml @@ -9,6 +9,17 @@ ament_cmake + rclcpp + rclcpp_action + pluginlib + std_msgs + hri_audio_msgs + capabilities2_msgs + capabilities2_runner + + + tinyxml2 + ament_lint_auto ament_lint_common diff --git a/capabilities2_runner_audio/plugins.xml b/capabilities2_runner_audio/plugins.xml index a6ff14f..d43e9c3 100644 --- a/capabilities2_runner_audio/plugins.xml +++ b/capabilities2_runner_audio/plugins.xml @@ -1,8 +1,7 @@ - - - + + - action based nav2 stack runner + A plugin that provide speech to text capability - + \ No newline at end of file diff --git a/capabilities2_runner_audio/src/audio_runners.cpp b/capabilities2_runner_audio/src/audio_runners.cpp new file mode 100644 index 0000000..f7b73c5 --- /dev/null +++ b/capabilities2_runner_audio/src/audio_runners.cpp @@ -0,0 +1,11 @@ +#include +#include +#include + +namespace capabilities2_runner +{ + +} + +// register runner plugins +PLUGINLIB_EXPORT_CLASS(capabilities2_runner::VoiceListenerRunner, capabilities2_runner::RunnerBase) diff --git a/capabilities2_runner_nav2/include/capabilities2_runner_nav2/waypoint_runner.hpp b/capabilities2_runner_nav2/include/capabilities2_runner_nav2/waypoint_runner.hpp index 0b32171..d9f0a48 100644 --- a/capabilities2_runner_nav2/include/capabilities2_runner_nav2/waypoint_runner.hpp +++ b/capabilities2_runner_nav2/include/capabilities2_runner_nav2/waypoint_runner.hpp @@ -20,60 +20,61 @@ namespace capabilities2_runner class WayPointRunner : public ActionRunner { public: - WayPointRunner() : ActionRunner() - { - } + WayPointRunner() : ActionRunner() + { + } - /** - * @brief Starter function for starting the action runner - * - * @param node shared pointer to the capabilities node. Allows to use ros node related functionalities - * @param run_config runner configuration loaded from the yaml file - * @param on_started function pointer to trigger at the start of the action client in the runner - * @param on_terminated function pointer to trigger at the termination of the action client in the runner - */ - virtual void start(rclcpp::Node::SharedPtr node, const runner_opts& run_config, - std::function on_started = nullptr, - std::function on_terminated = nullptr) override - { - init_action(node, run_config, "follow_waypoints", on_started, on_terminated); - } + /** + * @brief Starter function for starting the action runner + * + * @param node shared pointer to the capabilities node. Allows to use ros node related functionalities + * @param run_config runner configuration loaded from the yaml file + * @param on_started function pointer to trigger at the start of the action client in the runner + * @param on_terminated function pointer to trigger at the termination of the action client in the runner + */ + virtual void start(rclcpp::Node::SharedPtr node, const runner_opts& run_config, + std::function on_started = nullptr, + std::function on_terminated = nullptr, + std::function on_stopped = nullptr) override + { + init_action(node, run_config, "follow_waypoints", on_started, on_terminated, on_stopped); + } - /** - * @brief trigger the runner - * - @param parameters XMLElement that contains parameters in the format '' - */ - virtual void trigger(std::shared_ptr parameters = nullptr) - { - tinyxml2::XMLElement* parametersElement = parameters->FirstChildElement("waypointfollower"); + /** + * @brief trigger the runner + * + @param parameters XMLElement that contains parameters in the format '' + */ + virtual void trigger(std::shared_ptr parameters = nullptr) + { + tinyxml2::XMLElement* parametersElement = parameters->FirstChildElement("waypointfollower"); - parametersElement->QueryDoubleAttribute("x", &x); - parametersElement->QueryDoubleAttribute("y", &y); + parametersElement->QueryDoubleAttribute("x", &x); + parametersElement->QueryDoubleAttribute("y", &y); - nav2_msgs::action::FollowWaypoints::Goal goal_msg; - geometry_msgs::msg::PoseStamped pose_msg; + nav2_msgs::action::FollowWaypoints::Goal goal_msg; + geometry_msgs::msg::PoseStamped pose_msg; - global_frame_ = "map"; - robot_base_frame_ = "base_link"; + global_frame_ = "map"; + robot_base_frame_ = "base_link"; - pose_msg.header.stamp = clock_->now(); - pose_msg.header.frame_id = global_frame_; - pose_msg.pose.position.x = x; - pose_msg.pose.position.y = y; - pose_msg.pose.position.z = 0.0; + pose_msg.header.stamp = node_->get_clock()->now(); + pose_msg.header.frame_id = global_frame_; + pose_msg.pose.position.x = x; + pose_msg.pose.position.y = y; + pose_msg.pose.position.z = 0.0; - goal_msg.poses.push_back(pose_msg); + goal_msg.poses.push_back(pose_msg); - // launch runner using action client - action_client_->async_send_goal(goal_msg, send_goal_options_); - } + // launch runner using action client + action_client_->async_send_goal(goal_msg, send_goal_options_); + } -protected: - std::string global_frame_; /**The global frame of the robot*/ - std::string robot_base_frame_; /**The frame of the robot base*/ + protected: + std::string global_frame_; /**The global frame of the robot*/ + std::string robot_base_frame_; /**The frame of the robot base*/ - double x, y; /**Coordinate frame parameters*/ + double x, y; /**Coordinate frame parameters*/ }; } // namespace capabilities2_runner diff --git a/capabilities2_runner_nav2/plugins.xml b/capabilities2_runner_nav2/plugins.xml index 00a0bdd..a0d5780 100644 --- a/capabilities2_runner_nav2/plugins.xml +++ b/capabilities2_runner_nav2/plugins.xml @@ -1,5 +1,5 @@ - - + + A plugin that provide nav2 waypoint navigation capability diff --git a/capabilities2_server/include/capabilities2_server/runner_cache.hpp b/capabilities2_server/include/capabilities2_server/runner_cache.hpp index 44ef907..0f6f644 100644 --- a/capabilities2_server/include/capabilities2_server/runner_cache.hpp +++ b/capabilities2_server/include/capabilities2_server/runner_cache.hpp @@ -74,7 +74,7 @@ class RunnerCache } // start the runner - runner_cache_[capability]->start(node, run_config.to_runner_opts(), on_started, on_terminated); + runner_cache_[capability]->start(node, run_config.to_runner_opts(), on_started, on_terminated, on_stopped); } /** @@ -107,7 +107,7 @@ class RunnerCache // safely stop the runner try { - runner_cache_[capability]->stop(on_stopped); + runner_cache_[capability]->stop(); } catch (const capabilities2_runner::runner_exception& e) { From 91e5c2d361b5a7e56b6b7920f587d98c98f58adf Mon Sep 17 00:00:00 2001 From: BuddhiGamage Date: Tue, 17 Sep 2024 12:55:33 +1000 Subject: [PATCH 4/5] updated listen_runner --- .../include/capabilities2_runner_audio/listen_runner.hpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/capabilities2_runner_audio/include/capabilities2_runner_audio/listen_runner.hpp b/capabilities2_runner_audio/include/capabilities2_runner_audio/listen_runner.hpp index 95bbe65..9ef9429 100644 --- a/capabilities2_runner_audio/include/capabilities2_runner_audio/listen_runner.hpp +++ b/capabilities2_runner_audio/include/capabilities2_runner_audio/listen_runner.hpp @@ -58,8 +58,16 @@ class VoiceListenerRunner : public MultiActionRunner virtual void trigger(std::shared_ptr parameters = nullptr) { hri_audio_msgs::action::SpeechToText::Goal goal_msg; + goal_msg = SpeechToText.Goal() # Create a new goal message + goal_msg.header.stamp = self.get_clock().now().to_msg() # Set the timestamp + trigger_action("speech_to_text", goal_msg); + + + + // launch runner using action client + action_client_->async_send_goal(goal_msg, send_goal_options_); } From 4dc283440922abda31d5dc218013a7d5b42e49ee Mon Sep 17 00:00:00 2001 From: BuddhiGamage Date: Tue, 17 Sep 2024 13:43:51 +1000 Subject: [PATCH 5/5] compile isuues fixed --- .../include/capabilities2_runner_audio/listen_runner.hpp | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/capabilities2_runner_audio/include/capabilities2_runner_audio/listen_runner.hpp b/capabilities2_runner_audio/include/capabilities2_runner_audio/listen_runner.hpp index 9ef9429..f04037f 100644 --- a/capabilities2_runner_audio/include/capabilities2_runner_audio/listen_runner.hpp +++ b/capabilities2_runner_audio/include/capabilities2_runner_audio/listen_runner.hpp @@ -58,16 +58,11 @@ class VoiceListenerRunner : public MultiActionRunner virtual void trigger(std::shared_ptr parameters = nullptr) { hri_audio_msgs::action::SpeechToText::Goal goal_msg; - goal_msg = SpeechToText.Goal() # Create a new goal message - goal_msg.header.stamp = self.get_clock().now().to_msg() # Set the timestamp + goal_msg.header.stamp = node_->get_clock()->now(); trigger_action("speech_to_text", goal_msg); - - - // launch runner using action client - action_client_->async_send_goal(goal_msg, send_goal_options_); }