1#include "modulo_components/LifecycleComponent.hpp"
4using namespace rclcpp_lifecycle;
9 : LifecycleNode(modulo_utils::parsing::parse_node_name(node_options, fallback_name), node_options),
10 ComponentInterface(std::make_shared<rclcpp::node_interfaces::NodeInterfaces<ALL_RCLCPP_NODE_INTERFACES>>(
11 LifecycleNode::get_node_base_interface(), LifecycleNode::get_node_clock_interface(),
12 LifecycleNode::get_node_graph_interface(), LifecycleNode::get_node_logging_interface(),
13 LifecycleNode::get_node_parameters_interface(), LifecycleNode::get_node_services_interface(),
14 LifecycleNode::get_node_time_source_interface(), LifecycleNode::get_node_timers_interface(),
15 LifecycleNode::get_node_topics_interface(), LifecycleNode::get_node_type_descriptions_interface(),
16 LifecycleNode::get_node_waitables_interface())),
19std::shared_ptr<state_representation::ParameterInterface>
24void LifecycleComponent::step() {
27 this->evaluate_periodic_callbacks();
29 this->publish_outputs();
31 this->publish_predicates();
32 }
catch (
const std::exception&
ex) {
38node_interfaces::LifecycleNodeInterface::CallbackReturn LifecycleComponent::on_configure(
const State& previous_state) {
39 RCLCPP_DEBUG(this->
get_logger(),
"on_configure called from previous state %s", previous_state.label().c_str());
40 if (
previous_state.id() != lifecycle_msgs::msg::State::PRIMARY_STATE_UNCONFIGURED) {
42 return node_interfaces::LifecycleNodeInterface::CallbackReturn::FAILURE;
44 if (!this->handle_configure()) {
47 if (this->handle_cleanup()) {
48 return node_interfaces::LifecycleNodeInterface::CallbackReturn::FAILURE;
52 "Could not revert to the unconfigured state! Entering into the error processing transition state.");
53 return node_interfaces::LifecycleNodeInterface::CallbackReturn::ERROR;
56 return node_interfaces::LifecycleNodeInterface::CallbackReturn::SUCCESS;
59bool LifecycleComponent::handle_configure() {
63 }
catch (
const std::exception&
ex) {
67 return result && this->configure_outputs();
74node_interfaces::LifecycleNodeInterface::CallbackReturn LifecycleComponent::on_cleanup(
const State& previous_state) {
75 RCLCPP_DEBUG(this->
get_logger(),
"on_cleanup called from previous state %s", previous_state.label().c_str());
76 if (
previous_state.id() != lifecycle_msgs::msg::State::PRIMARY_STATE_INACTIVE) {
78 return node_interfaces::LifecycleNodeInterface::CallbackReturn::FAILURE;
80 if (!this->handle_cleanup()) {
82 return node_interfaces::LifecycleNodeInterface::CallbackReturn::ERROR;
84 return node_interfaces::LifecycleNodeInterface::CallbackReturn::SUCCESS;
87bool LifecycleComponent::handle_cleanup() {
90 }
catch (
const std::exception&
ex) {
100node_interfaces::LifecycleNodeInterface::CallbackReturn LifecycleComponent::on_activate(
const State& previous_state) {
101 RCLCPP_DEBUG(this->
get_logger(),
"on_activate called from previous state %s", previous_state.label().c_str());
102 if (
previous_state.id() != lifecycle_msgs::msg::State::PRIMARY_STATE_INACTIVE) {
104 return node_interfaces::LifecycleNodeInterface::CallbackReturn::FAILURE;
106 if (!this->handle_activate()) {
109 if (this->handle_deactivate()) {
110 return node_interfaces::LifecycleNodeInterface::CallbackReturn::FAILURE;
113 get_logger(),
"Could not revert to the inactive state! Entering into the error processing transition state.");
114 return node_interfaces::LifecycleNodeInterface::CallbackReturn::ERROR;
117 return node_interfaces::LifecycleNodeInterface::CallbackReturn::SUCCESS;
120bool LifecycleComponent::handle_activate() {
124 }
catch (
const std::exception&
ex) {
128 return result && this->activate_outputs();
135node_interfaces::LifecycleNodeInterface::CallbackReturn LifecycleComponent::on_deactivate(
const State& previous_state) {
136 RCLCPP_DEBUG(this->
get_logger(),
"on_deactivate called from previous state %s", previous_state.label().c_str());
137 if (
previous_state.id() != lifecycle_msgs::msg::State::PRIMARY_STATE_ACTIVE) {
139 return node_interfaces::LifecycleNodeInterface::CallbackReturn::FAILURE;
141 if (!this->handle_deactivate()) {
143 return node_interfaces::LifecycleNodeInterface::CallbackReturn::ERROR;
145 return node_interfaces::LifecycleNodeInterface::CallbackReturn::SUCCESS;
148bool LifecycleComponent::handle_deactivate() {
149 auto result = this->deactivate_outputs();
152 }
catch (
const std::exception&
ex) {
162node_interfaces::LifecycleNodeInterface::CallbackReturn LifecycleComponent::on_shutdown(
const State& previous_state) {
163 RCLCPP_DEBUG(this->
get_logger(),
"on_shutdown called from previous state %s", previous_state.label().c_str());
164 if (!this->has_error_) {
166 case lifecycle_msgs::msg::State::PRIMARY_STATE_FINALIZED:
167 return node_interfaces::LifecycleNodeInterface::CallbackReturn::SUCCESS;
168 case lifecycle_msgs::msg::State::PRIMARY_STATE_ACTIVE:
169 if (!this->handle_deactivate()) {
174 case lifecycle_msgs::msg::State::PRIMARY_STATE_INACTIVE:
175 if (!this->handle_cleanup()) {
180 case lifecycle_msgs::msg::State::PRIMARY_STATE_UNCONFIGURED:
181 if (!this->handle_shutdown()) {
184 this->finalize_interfaces();
185 return node_interfaces::LifecycleNodeInterface::CallbackReturn::SUCCESS;
192 return node_interfaces::LifecycleNodeInterface::CallbackReturn::ERROR;
195bool LifecycleComponent::handle_shutdown() {
199 }
catch (
const std::exception&
ex) {
210node_interfaces::LifecycleNodeInterface::CallbackReturn LifecycleComponent::on_error(
const State& previous_state) {
211 RCLCPP_DEBUG(this->
get_logger(),
"on_error called from previous state %s", previous_state.label().c_str());
215 }
catch (
const std::exception&
ex) {
221 this->finalize_interfaces();
222 return node_interfaces::LifecycleNodeInterface::CallbackReturn::ERROR;
224 this->has_error_ =
false;
225 return node_interfaces::LifecycleNodeInterface::CallbackReturn::SUCCESS;
228bool LifecycleComponent::handle_error() {
236bool LifecycleComponent::configure_outputs() {
245 case MessageType::BOOL: {
248 PublisherType::LIFECYCLE_PUBLISHER, publisher)
249 ->create_publisher_interface(message_pair);
252 case MessageType::FLOAT64: {
253 auto publisher = this->create_publisher<std_msgs::msg::Float64>(topic_name, this->get_qos());
255 std::make_shared<
PublisherHandler<LifecyclePublisher<std_msgs::msg::Float64>, std_msgs::msg::Float64>>(
256 PublisherType::LIFECYCLE_PUBLISHER, publisher)
257 ->create_publisher_interface(message_pair);
260 case MessageType::FLOAT64_MULTI_ARRAY: {
261 auto publisher = this->create_publisher<std_msgs::msg::Float64MultiArray>(topic_name, this->get_qos());
263 LifecyclePublisher<std_msgs::msg::Float64MultiArray>, std_msgs::msg::Float64MultiArray>>(
264 PublisherType::LIFECYCLE_PUBLISHER, publisher)
265 ->create_publisher_interface(message_pair);
268 case MessageType::INT32: {
269 auto publisher = this->create_publisher<std_msgs::msg::Int32>(topic_name, this->get_qos());
271 std::make_shared<
PublisherHandler<LifecyclePublisher<std_msgs::msg::Int32>, std_msgs::msg::Int32>>(
272 PublisherType::LIFECYCLE_PUBLISHER, publisher)
273 ->create_publisher_interface(message_pair);
276 case MessageType::STRING: {
277 auto publisher = this->create_publisher<std_msgs::msg::String>(topic_name, this->get_qos());
279 std::make_shared<
PublisherHandler<LifecyclePublisher<std_msgs::msg::String>, std_msgs::msg::String>>(
280 PublisherType::LIFECYCLE_PUBLISHER, publisher)
281 ->create_publisher_interface(message_pair);
284 case MessageType::ENCODED_STATE: {
285 auto publisher = this->create_publisher<modulo_core::EncodedState>(topic_name, this->get_qos());
286 interface = std::make_shared<
288 PublisherType::LIFECYCLE_PUBLISHER, publisher)
289 ->create_publisher_interface(message_pair);
292 case MessageType::CUSTOM_MESSAGE: {
293 interface = this->custom_output_configuration_callables_.at(name)(topic_name);
299 RCLCPP_ERROR_STREAM(this->get_logger(),
"Failed to configure output '" << name <<
"': " << ex.what());
305bool LifecycleComponent::activate_outputs() {
307 for (
auto const& [name, interface] : this->outputs_) {
309 interface->activate();
312 RCLCPP_ERROR_STREAM(this->get_logger(),
"Failed to activate output '" << name <<
"': " << ex.what());
315 RCLCPP_DEBUG(this->get_logger(),
"All outputs activated.");
319bool LifecycleComponent::deactivate_outputs() {
321 for (
auto const& [name, interface] : this->outputs_) {
323 interface->deactivate();
326 RCLCPP_ERROR_STREAM(this->get_logger(),
"Failed to deactivate output '" << name <<
"': " << ex.what());
329 RCLCPP_DEBUG(this->get_logger(),
"All outputs deactivated.");
333rclcpp_lifecycle::State LifecycleComponent::get_lifecycle_state()
const {
334 return this->get_current_state();
337void LifecycleComponent::raise_error() {
338 ComponentInterface::raise_error();
339 this->has_error_ =
true;
340 if (get_current_state().
id() == lifecycle_msgs::msg::State::PRIMARY_STATE_UNCONFIGURED) {
341 this->trigger_transition(lifecycle_msgs::msg::Transition::TRANSITION_UNCONFIGURED_SHUTDOWN);
342 }
else if (get_current_state().
id() == lifecycle_msgs::msg::State::PRIMARY_STATE_INACTIVE) {
343 this->trigger_transition(lifecycle_msgs::msg::Transition::TRANSITION_INACTIVE_SHUTDOWN);
344 }
else if (get_current_state().
id() == lifecycle_msgs::msg::State::PRIMARY_STATE_ACTIVE) {
345 this->trigger_transition(lifecycle_msgs::msg::Transition::TRANSITION_ACTIVE_SHUTDOWN);
Base interface class for modulo components to wrap a ROS Node with custom behaviour.
std::shared_ptr< state_representation::ParameterInterface > get_parameter(const std::string &name) const
Get a parameter by name.
T get_parameter_value(const std::string &name) const
Get a parameter value by name.
virtual void on_step_callback()
Steps to execute periodically. To be redefined by derived Component classes.
rclcpp::QoS get_qos() const
Getter of the Quality of Service attribute.
void raise_error() override
Trigger the shutdown and error transitions.
virtual bool on_shutdown_callback()
Steps to execute when shutting down the component.
virtual bool on_deactivate_callback()
Steps to execute when deactivating the component.
std::shared_ptr< state_representation::ParameterInterface > get_parameter(const std::string &name) const
Get a parameter by name.
virtual bool on_activate_callback()
Steps to execute when activating the component.
virtual bool on_cleanup_callback()
Steps to execute when cleaning up the component.
LifecycleComponent(const rclcpp::NodeOptions &node_options, const std::string &fallback_name="LifecycleComponent")
Constructor from node options.
virtual bool on_error_callback()
Steps to execute when handling errors.
virtual bool on_configure_callback()
Steps to execute when configuring the component.
rclcpp_lifecycle::State get_lifecycle_state() const
Get the current lifecycle state of the component.
The PublisherHandler handles different types of ROS publishers to activate, deactivate and publish da...
A base class for all core exceptions.
Modulo Core communication module for handling messages on publication and subscription interfaces.