C++ YASMIN (Yet Another State MachINe)
Loading...
Searching...
No Matches
monitor_state.hpp
Go to the documentation of this file.
1// Copyright (C) 2023 Miguel Ángel González Santamarta
2//
3// This program is free software: you can redistribute it and/or modify
4// it under the terms of the GNU General Public License as published by
5// the Free Software Foundation, either version 3 of the License, or
6// (at your option) any later version.
7//
8// This program is distributed in the hope that it will be useful,
9// but WITHOUT ANY WARRANTY; without even the implied warranty of
10// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11// GNU General Public License for more details.
12//
13// You should have received a copy of the GNU General Public License
14// along with this program. If not, see <https://www.gnu.org/licenses/>.
15
16#ifndef YASMIN_ROS__MONITOR_STATE_HPP_
17#define YASMIN_ROS__MONITOR_STATE_HPP_
18
19#include <chrono>
20#include <condition_variable>
21#include <functional>
22#include <memory>
23#include <string>
24#include <vector>
25
26#include <rclcpp/rclcpp.hpp>
27
28#include "yasmin/blackboard.hpp"
29#include "yasmin/logs.hpp"
30#include "yasmin/state.hpp"
31#include "yasmin/types.hpp"
34
35using std::placeholders::_1;
36
37namespace yasmin_ros {
38
48template <typename MsgT> class MonitorState : public yasmin::State {
49
51 using MonitorHandler = std::function<std::string(
52 yasmin::Blackboard::SharedPtr, std::shared_ptr<MsgT>)>;
53
54public:
59
60
73 MonitorState(const std::string &topic_name, const yasmin::Outcomes &outcomes,
74 MonitorHandler monitor_handler, rclcpp::QoS qos = 10,
75 int msg_queue = 10, int timeout = -1, int maximum_retry = 3)
77 nullptr, msg_queue, timeout, maximum_retry) {}
78
95 MonitorHandler monitor_handler, rclcpp::QoS qos = 10,
96 rclcpp::CallbackGroup::SharedPtr callback_group = nullptr,
97 int msg_queue = 10, int timeout = -1, int maximum_retry = 3)
99 callback_group, msg_queue, timeout, maximum_retry) {}
100
115 MonitorState(const rclcpp::Node::SharedPtr &node,
116 const std::string &topic_name, const yasmin::Outcomes &outcomes,
117 MonitorHandler monitor_handler, rclcpp::QoS qos = 10,
118 rclcpp::CallbackGroup::SharedPtr callback_group = nullptr,
119 int msg_queue = 10, int timeout = -1, int maximum_retry = 3)
123
124 // Set outcomes
125 if (timeout > 0) {
126 this->outcomes.insert(basic_outcomes::TIMEOUT);
129 "No message received from topic in the specified timeout");
130 }
131 this->outcomes.insert(basic_outcomes::CANCEL);
133 "The monitor was canceled");
134
135 if (outcomes.size() > 0) {
136 for (const std::string &outcome : outcomes) {
137 this->outcomes.insert(outcome);
138 }
139 }
140
141 if (node == nullptr) {
143 } else {
144 this->node_ = node;
145 }
146
147 // Create subscription
148 rclcpp::SubscriptionOptions options;
149 options.callback_group = callback_group;
150 this->sub = this->node_->create_subscription<MsgT>(
151 this->topic_name, this->qos,
152 std::bind(&MonitorState::callback, this, _1), options);
153 }
154
162 std::string execute(yasmin::Blackboard::SharedPtr blackboard) override {
163 int retry_count = 0;
164 std::unique_lock<std::mutex> lock(this->msg_mutex);
165 std::cv_status wait_status = std::cv_status::no_timeout;
166
167 while (this->msg_list.empty()) {
168
169 if (this->timeout > 0) {
170 wait_status =
171 this->msg_cond.wait_for(lock, std::chrono::seconds(this->timeout));
172 } else {
173 this->msg_cond.wait(lock);
174 }
175
176 if (this->is_canceled()) {
178 }
179
180 while (this->timeout > 0 && wait_status == std::cv_status::timeout) {
181 YASMIN_LOG_WARN("Timeout reached, topic '%s' is not available",
182 this->topic_name.c_str());
183
184 if (retry_count < this->maximum_retry) {
185 retry_count++;
186 YASMIN_LOG_WARN("Retrying to wait for topic '%s' (%d/%d)",
187 this->topic_name.c_str(), retry_count,
188 this->maximum_retry);
189 wait_status = this->msg_cond.wait_for(
190 lock, std::chrono::seconds(this->timeout));
191 } else {
193 }
194
195 if (this->is_canceled()) {
197 }
198 }
199 }
200
201 YASMIN_LOG_INFO("Processing msg from topic '%s'", this->topic_name.c_str());
202 std::string outcome =
203 this->monitor_handler(blackboard, this->msg_list.at(0));
204 this->msg_list.erase(this->msg_list.begin());
205
206 return outcome;
207 }
208
214 void cancel_state() override {
215 this->msg_cond.notify_one();
217 }
218
219protected:
221 rclcpp::Node::SharedPtr node_;
222
223private:
225 std::shared_ptr<rclcpp::Subscription<MsgT>> sub;
226
228 std::string topic_name;
230 rclcpp::QoS qos;
231
233 std::vector<std::shared_ptr<MsgT>> msg_list;
242
244 std::condition_variable msg_cond;
246 std::mutex msg_mutex;
247
256 void callback(const typename MsgT::SharedPtr msg) {
257
258 this->msg_list.push_back(msg);
259
260 if ((int)this->msg_list.size() > this->msg_queue) {
261 this->msg_list.erase(this->msg_list.begin());
262 }
263
264 this->msg_cond.notify_one();
265 }
266};
267
268} // namespace yasmin_ros
269
270#endif // YASMIN_ROS__MONITOR_STATE_HPP_
std::shared_ptr< Blackboard > SharedPtr
Shared pointer type for Blackboard.
Definition blackboard.hpp:100
Represents a state in a state machine.
Definition state.hpp:49
Outcomes outcomes
The possible outcomes of this state.
Definition state.hpp:53
State(const Outcomes &outcomes)
Shared pointer type for State.
Definition state.cpp:64
bool is_canceled() const noexcept
Checks if the state has been canceled.
Definition state.cpp:89
virtual void cancel_state()
Cancels the current state execution.
Definition state.hpp:172
void set_outcome_description(const std::string &outcome, const std::string &description)
Sets a human-readable description for an outcome.
Definition state.cpp:164
std::vector< std::shared_ptr< MsgT > > msg_list
List to store queued messages.
Definition monitor_state.hpp:233
void cancel_state() override
Cancel the current monitor state.
Definition monitor_state.hpp:214
rclcpp::Node::SharedPtr node_
Shared pointer to the ROS 2 node.
Definition monitor_state.hpp:221
std::function< std::string( yasmin::Blackboard::SharedPtr, std::shared_ptr< MsgT >)> MonitorHandler
Function type for handling messages from topic.
Definition monitor_state.hpp:51
MonitorState(const std::string &topic_name, const yasmin::Outcomes &outcomes, MonitorHandler monitor_handler, rclcpp::QoS qos=10, int msg_queue=10, int timeout=-1, int maximum_retry=3)
Shared pointer type for MonitorState.
Definition monitor_state.hpp:73
rclcpp::QoS qos
Quality of Service settings for the topic.
Definition monitor_state.hpp:230
int timeout
Timeout in seconds for message reception.
Definition monitor_state.hpp:239
MonitorHandler monitor_handler
Callback function to handle incoming messages.
Definition monitor_state.hpp:235
int maximum_retry
Maximum number of retries.
Definition monitor_state.hpp:241
std::string topic_name
Name of the topic to monitor.
Definition monitor_state.hpp:228
std::shared_ptr< rclcpp::Subscription< MsgT > > sub
Subscription to the ROS 2 topic.
Definition monitor_state.hpp:225
std::string execute(yasmin::Blackboard::SharedPtr blackboard) override
Execute the monitoring operation and process the first received message.
Definition monitor_state.hpp:162
MonitorState(const std::string &topic_name, const yasmin::Outcomes &outcomes, MonitorHandler monitor_handler, rclcpp::QoS qos=10, rclcpp::CallbackGroup::SharedPtr callback_group=nullptr, int msg_queue=10, int timeout=-1, int maximum_retry=3)
Construct a new MonitorState with specific QoS, message queue, and timeout.
Definition monitor_state.hpp:94
std::mutex msg_mutex
Mutex for protecting action completion.
Definition monitor_state.hpp:246
void callback(const typename MsgT::SharedPtr msg)
Callback function for receiving messages from the subscribed topic.
Definition monitor_state.hpp:256
std::condition_variable msg_cond
Condition variable for action completion.
Definition monitor_state.hpp:244
int msg_queue
Maximum number of messages to queue.
Definition monitor_state.hpp:237
MonitorState(const rclcpp::Node::SharedPtr &node, const std::string &topic_name, const yasmin::Outcomes &outcomes, MonitorHandler monitor_handler, rclcpp::QoS qos=10, rclcpp::CallbackGroup::SharedPtr callback_group=nullptr, int msg_queue=10, int timeout=-1, int maximum_retry=3)
Construct a new MonitorState with ROS 2 node, specific QoS, message queue, and timeout.
Definition monitor_state.hpp:115
static YasminNode::SharedPtr get_instance()
Provides access to the singleton instance of YasminNode.
Definition yasmin_node.cpp:58
#define YASMIN_LOG_INFO(text,...)
Definition logs.hpp:169
#define YASMIN_LOG_WARN(text,...)
Definition logs.hpp:164
constexpr char CANCEL[]
Constant representing a canceled action outcome.
Definition basic_outcomes.hpp:63
constexpr char TIMEOUT[]
Constant representing a timed-out action outcome.
Definition basic_outcomes.hpp:71
Definition action_state.hpp:37
Definition blackboard.hpp:34
StringSet Outcomes
Set of possible outcomes for states.
Definition types.hpp:77
#define YASMIN_PTR_ALIASES(ClassName)
Macro to define all pointer aliases for a class.
Definition types.hpp:52