SMACC2
Loading...
Searching...
No Matches
smacc_state_machine.hpp
Go to the documentation of this file.
1// Copyright 2025 Robosoft Inc.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15/*****************************************************************************************************************
16 *
17 * Authors: Pablo Inigo Blasco, Brett Aldrich
18 *
19 ******************************************************************************************************************/
20#pragma once
21
22#include <boost/any.hpp>
23#include <map>
24#include <mutex>
25
26#include <smacc2/common.hpp>
31
32#include <smacc2_msgs/msg/smacc_state_machine.hpp>
33#include <smacc2_msgs/msg/smacc_status.hpp>
34#include <smacc2_msgs/msg/smacc_transition_log_entry.hpp>
35#include <smacc2_msgs/srv/smacc_get_transition_history.hpp>
36
40
41namespace smacc2
42{
43using namespace smacc2::introspection;
44
45enum class EventLifeTime
46{
48 CURRENT_STATE /*events are discarded if we are leaving the state it were created. I is used for client behaviors whose lifetime is associated to state*/
49};
50
59
60// This class describes the concept of Smacc State Machine in an abastract way.
61// The SmaccStateMachineBase inherits from this state machine and from
62// statechart::StateMachine<> (via multiple inheritance)
64{
65public:
67 std::string stateMachineName, SignalDetector * signalDetector,
68 rclcpp::NodeOptions nodeOptions = rclcpp::NodeOptions());
69
70 virtual ~ISmaccStateMachine();
71
72 virtual void reset();
73
74 virtual void stop();
75
76 virtual void eStop();
77
78 template <typename TOrthogonal>
79 TOrthogonal * getOrthogonal();
80
81 // gets the client behavior in a given orthogonal
82 // the index is used to distinguish between multiple client behaviors of the same type
83 template <typename TOrthogonal, typename TClientBehavior>
84 inline TClientBehavior * getClientBehavior(int index = 0)
85 {
86 auto orthogonal = this->template getOrthogonal<TOrthogonal>();
87
88 return orthogonal->template getClientBehavior<TClientBehavior>(index);
89 }
90
91 const std::map<std::string, std::shared_ptr<smacc2::ISmaccOrthogonal>> & getOrthogonals() const;
92
93 template <typename SmaccComponentType>
94 void requiresComponent(SmaccComponentType *& storage, ComponentRequirement requirementType);
95
96 template <typename EventType>
97 void postEvent(EventType * ev, EventLifeTime evlifetime = EventLifeTime::ABSOLUTE);
98
99 template <typename EventType>
101
102 // gets data from the state machine blackboard
103 template <typename T>
104 bool getGlobalSMData(std::string name, T & ret);
105
106 // sets data in the state machine blackboard
107 template <typename T>
108 void setGlobalSMData(std::string name, T value);
109
110 //template <typename StateField, typename BehaviorType>
111 //void mapBehavior();
112
113 std::string getStateMachineName();
114
116
117 inline std::shared_ptr<SmaccStateInfo> getCurrentStateInfo() { return currentStateInfo_; }
118
119 void publishTransition(const SmaccTransitionInfo & transitionInfo);
120
122 virtual void onInitialize();
123
125 const std::shared_ptr<rmw_request_id_t> request_header,
126 const std::shared_ptr<smacc2_msgs::srv::SmaccGetTransitionHistory::Request> req,
127 std::shared_ptr<smacc2_msgs::srv::SmaccGetTransitionHistory::Response> res);
128
129 template <typename TSmaccSignal, typename TMemberFunctionPrototype, typename TSmaccObjectType>
131 TSmaccSignal & signal, TMemberFunctionPrototype callback, TSmaccObjectType * object);
132
133 void disconnectSmaccSignalObject(void * object);
134
135 template <typename StateType>
136 void notifyOnStateEntryStart(StateType * state);
137
138 template <typename StateType>
139 void notifyOnStateEntryEnd(StateType * state);
140
141 template <typename StateType>
142 void notifyOnRuntimeConfigured(StateType * state);
143
144 template <typename StateType>
145 void notifyOnStateExitting(StateType * state);
146
147 template <typename StateType>
148 void notifyOnStateExited(StateType * state);
149
150 template <typename StateType>
151 void notifyOnRuntimeConfigurationFinished(StateType * state);
152
153 inline int64_t getCurrentStateCounter() const;
154
155 inline ISmaccState * getCurrentState() const;
156
158
159 template <typename InitialStateType>
161
162 rclcpp::Node::SharedPtr getNode();
163
164 inline rclcpp::Logger getLogger() { return nh_->get_logger(); }
165
166 inline std::recursive_mutex & getMutex() { return this->m_mutex_; }
167
168protected:
170
171 void initializeROS(std::string smshortname);
172
173 void onInitialized();
174
175 template <typename TOrthogonal>
176 void createOrthogonal();
177
178 // The node handle for this state
179 rclcpp::Node::SharedPtr nh_;
180
181 rclcpp::TimerBase::SharedPtr timer_;
182 rclcpp::Publisher<smacc2_msgs::msg::SmaccStateMachine>::SharedPtr stateMachinePub_;
183 rclcpp::Publisher<smacc2_msgs::msg::SmaccStatus>::SharedPtr stateMachineStatusPub_;
184 rclcpp::Publisher<smacc2_msgs::msg::SmaccTransitionLogEntry>::SharedPtr transitionLogPub_;
185
186 rclcpp::Publisher<smacc2_msgs::msg::SmaccEvent>::SharedPtr eventsLogPub_;
187
188 rclcpp::Service<smacc2_msgs::srv::SmaccGetTransitionHistory>::SharedPtr transitionHistoryService_;
189
190 // if it is null, you may be located in a transition. There is a small gap of time where internally
191 // this currentState_ is null. This may change in the future.
192 std::vector<ISmaccState *> currentState_;
193
194 std::shared_ptr<SmaccStateInfo> currentStateInfo_;
195
196 smacc2_msgs::msg::SmaccStatus status_msg_;
197
198 // orthogonals
199 std::map<std::string, std::shared_ptr<smacc2::ISmaccOrthogonal>> orthogonals_;
200
201protected:
202 std::shared_ptr<SmaccStateMachineInfo> stateMachineInfo_;
203
204private:
205 std::recursive_mutex m_mutex_;
206 std::recursive_mutex eventQueueMutex_;
207
209
210 std::map<void *, std::shared_ptr<CallbackCounterSemaphore>> stateCallbackConnections;
211
212 // shared variables
213 std::map<std::string, std::pair<std::function<std::string()>, boost::any>> globalData_;
214
215 // contains the whole history of transitions of the state machine
216 std::vector<smacc2_msgs::msg::SmaccTransitionLogEntry> transitionLogHistory_;
217
219
220 // Event to notify to the signaldetection thread that a request has been created...
222
224
225 void lockStateMachine(std::string msg);
226
227 void unlockStateMachine(std::string msg);
228
229 template <typename EventType>
230 void propagateEventToStateReactors(ISmaccState * st, EventType * ev);
231
232 void updateStatusMessage();
233
234 friend class ISmaccState;
235 friend class SignalDetector;
236};
237} // namespace smacc2
238
std::map< std::string, std::shared_ptr< smacc2::ISmaccOrthogonal > > orthogonals_
std::vector< ISmaccState * > currentState_
std::recursive_mutex eventQueueMutex_
bool getGlobalSMData(std::string name, T &ret)
void publishTransition(const SmaccTransitionInfo &transitionInfo)
StateMachineInternalAction stateMachineCurrentAction
rclcpp::Publisher< smacc2_msgs::msg::SmaccStateMachine >::SharedPtr stateMachinePub_
std::shared_ptr< SmaccStateInfo > currentStateInfo_
TClientBehavior * getClientBehavior(int index=0)
rclcpp::Node::SharedPtr getNode()
std::map< std::string, std::pair< std::function< std::string()>, boost::any > > globalData_
void requiresComponent(SmaccComponentType *&storage, ComponentRequirement requirementType)
void notifyOnStateExitting(StateType *state)
rclcpp::Service< smacc2_msgs::srv::SmaccGetTransitionHistory >::SharedPtr transitionHistoryService_
void setGlobalSMData(std::string name, T value)
virtual void onInitialize()
this function should be implemented by the user to create the orthogonals
std::vector< smacc2_msgs::msg::SmaccTransitionLogEntry > transitionLogHistory_
void notifyOnRuntimeConfigurationFinished(StateType *state)
smacc2::SmaccSignalConnection createSignalConnection(TSmaccSignal &signal, TMemberFunctionPrototype callback, TSmaccObjectType *object)
const std::map< std::string, std::shared_ptr< smacc2::ISmaccOrthogonal > > & getOrthogonals() const
rclcpp::Publisher< smacc2_msgs::msg::SmaccStatus >::SharedPtr stateMachineStatusPub_
ISmaccStateMachine(std::string stateMachineName, SignalDetector *signalDetector, rclcpp::NodeOptions nodeOptions=rclcpp::NodeOptions())
void notifyOnStateExited(StateType *state)
void lockStateMachine(std::string msg)
void notifyOnStateEntryEnd(StateType *state)
void propagateEventToStateReactors(ISmaccState *st, EventType *ev)
void disconnectSmaccSignalObject(void *object)
const SmaccStateMachineInfo & getStateMachineInfo()
std::shared_ptr< SmaccStateInfo > getCurrentStateInfo()
void unlockStateMachine(std::string msg)
rclcpp::TimerBase::SharedPtr timer_
rclcpp::Publisher< smacc2_msgs::msg::SmaccTransitionLogEntry >::SharedPtr transitionLogPub_
std::map< void *, std::shared_ptr< CallbackCounterSemaphore > > stateCallbackConnections
void notifyOnRuntimeConfigured(StateType *state)
void initializeROS(std::string smshortname)
smacc2_msgs::msg::SmaccStatus status_msg_
std::shared_ptr< SmaccStateMachineInfo > stateMachineInfo_
void postEvent(EventType *ev, EventLifeTime evlifetime=EventLifeTime::ABSOLUTE)
rclcpp::Publisher< smacc2_msgs::msg::SmaccEvent >::SharedPtr eventsLogPub_
std::recursive_mutex & getMutex()
void getTransitionLogHistory(const std::shared_ptr< rmw_request_id_t > request_header, const std::shared_ptr< smacc2_msgs::srv::SmaccGetTransitionHistory::Request > req, std::shared_ptr< smacc2_msgs::srv::SmaccGetTransitionHistory::Response > res)
void notifyOnStateEntryStart(StateType *state)
boost::signals2::connection SmaccSignalConnection
SMRunMode
Definition common.hpp:68
ComponentRequirement
Definition common.hpp:74