diff --git a/src/control/src/DwaController.cpp b/src/control/src/DwaController.cpp index 1ea21774384..4e0481a027f 100644 --- a/src/control/src/DwaController.cpp +++ b/src/control/src/DwaController.cpp @@ -2,6 +2,7 @@ // Copyright 2018 Intel Corporation. All Rights Reserved. #include "control/DwaController.hpp" +#include DwaController::DwaController(const std::string & name, Robot * robot) : ControlTask(name, robot) @@ -24,4 +25,11 @@ void DwaController::workerThread() { RCLCPP_INFO(get_logger(), "DwaController::workerThread"); + + while (!stopWorkerThread_) + { + std::this_thread::sleep_for(std::chrono::milliseconds(500)); + RCLCPP_INFO(get_logger(), "DwaController::workerThread: doing work"); + } } + diff --git a/src/mission_execution/CMakeLists.txt b/src/mission_execution/CMakeLists.txt index 478ad0fb828..c0fbb9c4627 100644 --- a/src/mission_execution/CMakeLists.txt +++ b/src/mission_execution/CMakeLists.txt @@ -29,6 +29,7 @@ add_executable(mission_execution ament_target_dependencies(mission_execution rclcpp std_msgs + task ) install(TARGETS ${PROJECT_NAME} diff --git a/src/navigation/include/navigation/SimpleNavigator.hpp b/src/navigation/include/navigation/SimpleNavigator.hpp index 3803391c051..8120a3f130c 100644 --- a/src/navigation/include/navigation/SimpleNavigator.hpp +++ b/src/navigation/include/navigation/SimpleNavigator.hpp @@ -7,6 +7,7 @@ #include "navigation/NavigateToPoseTask.hpp" #include "planning/AStarPlanner.hpp" #include "control/DwaController.hpp" +#include "task/TaskClient.hpp" class SimpleNavigator : public NavigateToPoseTask { @@ -21,8 +22,11 @@ class SimpleNavigator : public NavigateToPoseTask void workerThread(); // TODO: These will be the client-side proxies (like SimpleActionClient): - AStarPlanner * planner_; - DwaController * controller_; + //AStarPlanner * planner_; + //DwaController * controller_; + + TaskClient * planner_; + TaskClient * controller_; }; #endif // NAVIGATION__SIMPLENAVIGATOR_HPP_ diff --git a/src/navigation/src/SimpleNavigator.cpp b/src/navigation/src/SimpleNavigator.cpp index 7a1b5dd8300..8cb3bf1fdd1 100644 --- a/src/navigation/src/SimpleNavigator.cpp +++ b/src/navigation/src/SimpleNavigator.cpp @@ -2,11 +2,16 @@ // Copyright 2018 Intel Corporation. All Rights Reserved. #include "navigation/SimpleNavigator.hpp" +#include SimpleNavigator::SimpleNavigator(const std::string & name, Robot * robot) -: NavigateToPoseTask(name, robot), planner_(nullptr), controller_(nullptr) +: NavigateToPoseTask(name, robot) { RCLCPP_INFO(get_logger(), "SimpleNavigator::SimpleNavigator"); + +// TODO: make into C++ smart pointers + planner_ = new TaskClient("AStarPlanner", this); + controller_ = new TaskClient("DwaController", this); } SimpleNavigator::~SimpleNavigator() @@ -24,4 +29,18 @@ void SimpleNavigator::workerThread() { RCLCPP_INFO(get_logger(), "SimpleNavigator::workerThread"); + + RCLCPP_INFO(get_logger(), "SimpleNavigator::workerThread: sending executes"); + planner_->execute(); + controller_->execute(); + + while (!stopWorkerThread_ /* && rclcpp::ok() */ ) + { + RCLCPP_INFO(get_logger(), "SimpleNavigator::workerThread: doing work"); + std::this_thread::sleep_for(std::chrono::milliseconds(500)); + } + + RCLCPP_INFO(get_logger(), "SimpleNavigator::workerThread: sending cancels"); + planner_->cancel(); + controller_->cancel(); } diff --git a/src/planning/include/planning/PlanningTask.hpp b/src/planning/include/planning/PlanningTask.hpp index 1e3e8319d13..b7a7b3b6692 100644 --- a/src/planning/include/planning/PlanningTask.hpp +++ b/src/planning/include/planning/PlanningTask.hpp @@ -4,10 +4,10 @@ #ifndef PLANNING__PLANNINGTASK_HPP_ #define PLANNING__PLANNINGTASK_HPP_ -#include "task/Task.hpp" +#include "task/TaskServer.hpp" #include "geometry_msgs/msg/pose_stamped.hpp" -class PlanningTask : public Task +class PlanningTask : public TaskServer { public: PlanningTask(const std::string & name); diff --git a/src/planning/src/AStarPlanner.cpp b/src/planning/src/AStarPlanner.cpp index b5463de7315..1a1fccf7e98 100644 --- a/src/planning/src/AStarPlanner.cpp +++ b/src/planning/src/AStarPlanner.cpp @@ -2,6 +2,7 @@ // Copyright 2018 Intel Corporation. All Rights Reserved. #include "planning/AStarPlanner.hpp" +#include AStarPlanner::AStarPlanner(const std::string & name) : PlanningTask(name) @@ -25,4 +26,11 @@ void AStarPlanner::workerThread() { RCLCPP_INFO(get_logger(), "AStarPlanner::workerThread"); + + while (!stopWorkerThread_) + { + std::this_thread::sleep_for(std::chrono::milliseconds(500)); + RCLCPP_INFO(get_logger(), "AStarPlanner::workerThread: doing work"); + } } + diff --git a/src/planning/src/PlanningTask.cpp b/src/planning/src/PlanningTask.cpp index 8982a29547d..210c416f81f 100644 --- a/src/planning/src/PlanningTask.cpp +++ b/src/planning/src/PlanningTask.cpp @@ -4,7 +4,7 @@ #include "planning/PlanningTask.hpp" PlanningTask::PlanningTask(const std::string & name) -: Task(name) +: TaskServer(name) { RCLCPP_INFO(get_logger(), "PlanningTask::PlanningTask"); } diff --git a/src/task/CMakeLists.txt b/src/task/CMakeLists.txt index d102ac691c0..db3b6c94487 100644 --- a/src/task/CMakeLists.txt +++ b/src/task/CMakeLists.txt @@ -23,7 +23,8 @@ set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY "../libs/") add_library(task STATIC src/RobotTask.cpp - src/Task.cpp + src/TaskServer.cpp + src/TaskClient.cpp ) ament_target_dependencies(task diff --git a/src/task/include/task/AStarPlanner.hpp b/src/task/include/task/AStarPlanner.hpp deleted file mode 100644 index 1566ccdf5de..00000000000 --- a/src/task/include/task/AStarPlanner.hpp +++ /dev/null @@ -1,23 +0,0 @@ -// License: Apache 2.0. See LICENSE file in root directory. -// Copyright 2018 Intel Corporation. All Rights Reserved. - -#ifndef TASK__ASTARPLANNER_HPP_ -#define TASK__ASTARPLANNER_HPP_ - -#include "task/PlanningTask.hpp" - -class AStarPlanner : public PlanningTask -{ -public: - AStarPlanner(const std::string & name); - AStarPlanner() = delete; - ~AStarPlanner(); - - void createPlan(const geometry_msgs::msg::PoseStamped & start, - const geometry_msgs::msg::PoseStamped & goal); - -protected: - void workerThread() override; -}; - -#endif // TASK__ASTARPLANNER_HPP_ diff --git a/src/task/include/task/DwaController.hpp b/src/task/include/task/DwaController.hpp deleted file mode 100644 index e245fcefb2d..00000000000 --- a/src/task/include/task/DwaController.hpp +++ /dev/null @@ -1,22 +0,0 @@ -// License: Apache 2.0. See LICENSE file in root directory. -// Copyright 2018 Intel Corporation. All Rights Reserved. - -#ifndef TASK__SPECIFICCONTROLLER_HPP_ -#define TASK__SPECIFICCONTROLLER_HPP_ - -#include "task/ControlTask.hpp" - -class DwaController : public ControlTask -{ -public: - DwaController(const std::string & name, Robot * robot); - DwaController() = delete; - ~DwaController(); - - void executePlan() override; - -protected: - void workerThread() override; -}; - -#endif // TASK__SPECIFICCONTROLLER_HPP_ diff --git a/src/task/include/task/RobotTask.hpp b/src/task/include/task/RobotTask.hpp index 8a8d30f3021..1df0050542c 100644 --- a/src/task/include/task/RobotTask.hpp +++ b/src/task/include/task/RobotTask.hpp @@ -4,10 +4,10 @@ #ifndef TASK__ROBOTTASK_HPP_ #define TASK__ROBOTTASK_HPP_ -#include "task/Task.hpp" +#include "task/TaskServer.hpp" #include "robot/Robot.hpp" -class RobotTask : public Task +class RobotTask : public TaskServer { public: RobotTask(const std::string & name, Robot * robot); diff --git a/src/task/include/task/Task.hpp b/src/task/include/task/Task.hpp deleted file mode 100644 index 6a69465e232..00000000000 --- a/src/task/include/task/Task.hpp +++ /dev/null @@ -1,33 +0,0 @@ -// License: Apache 2.0. See LICENSE file in root directory. -// Copyright 2018 Intel Corporation. All Rights Reserved. - -#ifndef TASK__TASK_HPP_ -#define TASK__TASK_HPP_ - -#include -#include -#include -#include "rclcpp/rclcpp.hpp" -#include "std_msgs/msg/string.hpp" - -class Task: public rclcpp::Node -{ -public: - Task(const std::string & name); - virtual ~Task(); - - void execute(); - void cancel(); - -protected: - virtual void workerThread() = 0; - - std::thread *workerThread_; - std::atomic stopWorkerThread_; - - void onCmdReceived(const std_msgs::msg::String::SharedPtr msg); - - rclcpp::Subscription::SharedPtr cmdSub_; -}; - -#endif // TASK__TASK_HPP_ diff --git a/src/task/include/task/TaskClient.hpp b/src/task/include/task/TaskClient.hpp new file mode 100644 index 00000000000..979b0070e6e --- /dev/null +++ b/src/task/include/task/TaskClient.hpp @@ -0,0 +1,41 @@ +// License: Apache 2.0. See LICENSE file in root directory. +// Copyright 2018 Intel Corporation. All Rights Reserved. + +#ifndef TASK__TASKCLIENT_HPP_ +#define TASK__TASKCLIENT_HPP_ + +#include +#include "rclcpp/rclcpp.hpp" +#include "std_msgs/msg/string.hpp" + +class TaskClient +{ +public: + TaskClient(const std::string & name, rclcpp::Node * node); + virtual ~TaskClient(); + + typedef std_msgs::msg::String Goal; + typedef std_msgs::msg::String GoalID; + typedef std_msgs::msg::String Result; + typedef std_msgs::msg::String Feedback; + typedef std_msgs::msg::String Status; + + void execute(); + void cancel(); + +protected: + void onResultReceived(const Result::SharedPtr msg); + void onFeedbackReceived(const Feedback::SharedPtr msg); + void onStatusReceived(const Status::SharedPtr msg); + + rclcpp::Node * node_; + + rclcpp::Publisher::SharedPtr goalPub_; + rclcpp::Publisher::SharedPtr cancelPub_; + + rclcpp::Subscription::SharedPtr resultSub_; + rclcpp::Subscription::SharedPtr feedbackSub_; + rclcpp::Subscription::SharedPtr statusSub_; +}; + +#endif // TASK__TASKCLIENT_HPP_ diff --git a/src/task/include/task/TaskServer.hpp b/src/task/include/task/TaskServer.hpp new file mode 100644 index 00000000000..b42eba7c3e7 --- /dev/null +++ b/src/task/include/task/TaskServer.hpp @@ -0,0 +1,56 @@ +// License: Apache 2.0. See LICENSE file in root directory. +// Copyright 2018 Intel Corporation. All Rights Reserved. + +#ifndef TASK__TASKSERVER_HPP_ +#define TASK__TASKSERVER_HPP_ + +#include +#include +#include +#include +#include "rclcpp/rclcpp.hpp" +#include "std_msgs/msg/string.hpp" + +class TaskServer: public rclcpp::Node +{ +public: + TaskServer(const std::string & name); + virtual ~TaskServer(); + + // Execute + typedef std::function ExecuteCallback; + + typedef std_msgs::msg::String Goal; + typedef std_msgs::msg::String GoalID; + typedef std_msgs::msg::String Result; + typedef std_msgs::msg::String Feedback; + typedef std_msgs::msg::String Status; + + // void publishStatus(); + // void publishResult(); + // void publishFeedback(); + + // Timer, status frequency + +protected: + void start(); + void stop(); + + virtual void workerThread() = 0; + + std::thread *workerThread_; + std::atomic stopWorkerThread_; + std::atomic running_; + + void onGoalReceived(const Goal::SharedPtr msg); + void onCancelReceived(const GoalID::SharedPtr msg); + + rclcpp::Subscription::SharedPtr goalSub_; + rclcpp::Subscription::SharedPtr cancelSub_; + + rclcpp::Publisher::SharedPtr resultPub_; + rclcpp::Publisher::SharedPtr feedbackPub_; + rclcpp::Publisher::SharedPtr statusPub_; +}; + +#endif // TASK__TASKSERVER_HPP_ diff --git a/src/task/src/AStarPlanner.cpp b/src/task/src/AStarPlanner.cpp deleted file mode 100644 index e9694b405db..00000000000 --- a/src/task/src/AStarPlanner.cpp +++ /dev/null @@ -1,28 +0,0 @@ -// License: Apache 2.0. See LICENSE file in root directory. -// Copyright 2018 Intel Corporation. All Rights Reserved. - -#include "task/AStarPlanner.hpp" - -AStarPlanner::AStarPlanner(const std::string & name) -: PlanningTask(name) -{ - RCLCPP_INFO(get_logger(), "AStarPlanner::AStarPlanner"); -} - -AStarPlanner::~AStarPlanner() -{ - RCLCPP_INFO(get_logger(), "AStarPlanner::~AStarPlanner"); -} - -void -AStarPlanner::createPlan(const geometry_msgs::msg::PoseStamped & start, - const geometry_msgs::msg::PoseStamped & goal) -{ - RCLCPP_INFO(get_logger(), "AStarPlanner::createPlan"); -} - -void -AStarPlanner::workerThread() -{ - RCLCPP_INFO(get_logger(), "AStarPlanner::workerThread"); -} diff --git a/src/task/src/DwaController.cpp b/src/task/src/DwaController.cpp deleted file mode 100644 index 4c7e54db03a..00000000000 --- a/src/task/src/DwaController.cpp +++ /dev/null @@ -1,27 +0,0 @@ -// License: Apache 2.0. See LICENSE file in root directory. -// Copyright 2018 Intel Corporation. All Rights Reserved. - -#include "task/DwaController.hpp" - -DwaController::DwaController(const std::string & name, Robot * robot) -: ControlTask(name, robot) -{ - RCLCPP_INFO(get_logger(), "DwaController::DwaController"); -} - -DwaController::~DwaController() -{ - RCLCPP_INFO(get_logger(), "DwaController::~DwaController"); -} - -void -DwaController::executePlan() -{ - RCLCPP_INFO(get_logger(), "DwaController::executePlan"); -} - -void -DwaController::workerThread() -{ - RCLCPP_INFO(get_logger(), "DwaController::workerThread"); -} diff --git a/src/task/src/RobotTask.cpp b/src/task/src/RobotTask.cpp index 6e32da1e922..dc6a508e087 100644 --- a/src/task/src/RobotTask.cpp +++ b/src/task/src/RobotTask.cpp @@ -4,7 +4,7 @@ #include "task/RobotTask.hpp" RobotTask::RobotTask(const std::string & name, Robot * robot) -: Task(name) +: TaskServer(name) { RCLCPP_INFO(get_logger(), "RobotTask::RobotTask"); robot = robot; diff --git a/src/task/src/Task.cpp b/src/task/src/Task.cpp deleted file mode 100644 index f957ab24da4..00000000000 --- a/src/task/src/Task.cpp +++ /dev/null @@ -1,54 +0,0 @@ -// License: Apache 2.0. See LICENSE file in root directory. -// Copyright 2018 Intel Corporation. All Rights Reserved. - -#include "task/Task.hpp" - -Task::Task(const std::string & name) -: Node(name), workerThread_(nullptr), stopWorkerThread_(false) -{ - RCLCPP_INFO(get_logger(), "Task::Task"); - - cmdSub_ = create_subscription("TaskCmd", - std::bind(&Task::onCmdReceived, this, std::placeholders::_1)); -} - -Task::~Task() -{ - RCLCPP_INFO(get_logger(), "Task::~Task"); - if (workerThread_ != nullptr) - cancel(); -} - -void -Task::execute() -{ - RCLCPP_INFO(get_logger(), "Task::execute"); - stopWorkerThread_ = false; - workerThread_ = new std::thread(&Task::workerThread, this); -} - -void -Task::cancel() -{ - RCLCPP_INFO(get_logger(), "Task::cancel"); - stopWorkerThread_ = true; - workerThread_->join(); - - delete workerThread_; - workerThread_ = nullptr; -} - -void -Task::onCmdReceived(const std_msgs::msg::String::SharedPtr msg) -{ - RCLCPP_INFO(get_logger(), "Task::onCmdReceived: \"%s\"", msg->data.c_str()) - - if (msg->data.compare("ExecuteTask") == 0) { - execute(); - } else if (msg->data.compare("CancelTask") == 0) { - cancel(); - } else { - RCLCPP_INFO(get_logger(), "Task::onCmdReceived: invalid command: \"%s\"", - msg->data.c_str()) - } -} diff --git a/src/task/src/TaskClient.cpp b/src/task/src/TaskClient.cpp new file mode 100644 index 00000000000..bc9a2995b08 --- /dev/null +++ b/src/task/src/TaskClient.cpp @@ -0,0 +1,61 @@ +// License: Apache 2.0. See LICENSE file in root directory. +// Copyright 2018 Intel Corporation. All Rights Reserved. + +#include "task/TaskClient.hpp" + +TaskClient::TaskClient(const std::string & name, rclcpp::Node * node) +: node_(node) +{ + RCLCPP_INFO(node_->get_logger(), "TaskClient::TaskClient: %s", name.c_str()); + + goalPub_ = node_->create_publisher(name + "_goal"); + cancelPub_ = node_->create_publisher(name + "_cancel"); + + resultSub_ = node_->create_subscription(name + "_result", + std::bind(&TaskClient::onResultReceived, this, std::placeholders::_1)); + + feedbackSub_ = node_->create_subscription(name + "_feedback", + std::bind(&TaskClient::onFeedbackReceived, this, std::placeholders::_1)); + + statusSub_ = node_->create_subscription(name + "_status", + std::bind(&TaskClient::onStatusReceived, this, std::placeholders::_1)); +} + +TaskClient::~TaskClient() +{ + RCLCPP_INFO(node_->get_logger(), "TaskClient::~TaskClient"); +} + +void +TaskClient::execute() +{ + std_msgs::msg::String msg; + msg.data = "Hello, World!"; + + RCLCPP_INFO(node_->get_logger(), "TaskClient::execute: goalPub_: %p", goalPub_); + goalPub_->publish(msg); +} + +void +TaskClient::cancel() +{ + std_msgs::msg::String msg; + msg.data = "Goodbye, World!"; + + cancelPub_->publish(msg); +} + +void +TaskClient::onResultReceived(const Result::SharedPtr msg) +{ +} + +void +TaskClient::onFeedbackReceived(const Feedback::SharedPtr msg) +{ +} + +void +TaskClient::onStatusReceived(const Status::SharedPtr msg) +{ +} diff --git a/src/task/src/TaskServer.cpp b/src/task/src/TaskServer.cpp new file mode 100644 index 00000000000..dc8dadaaa3d --- /dev/null +++ b/src/task/src/TaskServer.cpp @@ -0,0 +1,73 @@ +// License: Apache 2.0. See LICENSE file in root directory. +// Copyright 2018 Intel Corporation. All Rights Reserved. + +#include "task/TaskServer.hpp" + +TaskServer::TaskServer(const std::string & name) +: Node(name), workerThread_(nullptr), stopWorkerThread_(false), running_(false) +{ + RCLCPP_INFO(get_logger(), "TaskServer::TaskServer"); + + goalSub_ = create_subscription(name + "_goal", + std::bind(&TaskServer::onGoalReceived, this, std::placeholders::_1)); + + cancelSub_ = create_subscription(name + "_cancel", + std::bind(&TaskServer::onCancelReceived, this, std::placeholders::_1)); + + resultPub_ = this->create_publisher(name + "_result"); + feedbackPub_ = this->create_publisher(name + "_status"); + statusPub_ = this->create_publisher(name + "_feedback"); +} + +TaskServer::~TaskServer() +{ + RCLCPP_INFO(get_logger(), "TaskServer::~TaskServer"); + if (workerThread_ != nullptr) + stop(); +} + +void +TaskServer::start() +{ + RCLCPP_INFO(get_logger(), "TaskServer::start"); + + if (running_) { + RCLCPP_INFO(get_logger(), "TaskServer::start: thread already running"); + } else { + stopWorkerThread_ = false; + workerThread_ = new std::thread(&TaskServer::workerThread, this); + running_ = true; + } +} + +void +TaskServer::stop() +{ + RCLCPP_INFO(get_logger(), "TaskServer::stop"); + + if (!running_) { + RCLCPP_INFO(get_logger(), "TaskServer::stop: thread already stopped"); + } else { + stopWorkerThread_ = true; + workerThread_->join(); + delete workerThread_; + workerThread_ = nullptr; + running_ = false; + } +} + +void +TaskServer::onGoalReceived(const Goal::SharedPtr msg) +{ + RCLCPP_INFO(get_logger(), "TaskServer::onGoalReceived: \"%s\"", msg->data.c_str()) + + // TODO: save the msg, start the worker thread, which passes the msg to the user's callback + start(); +} + +void +TaskServer::onCancelReceived(const GoalID::SharedPtr msg) +{ + RCLCPP_INFO(get_logger(), "TaskServer::onCancelReceived: \"%s\"", msg->data.c_str()) + stop(); +}