Skip to content

Commit 3123f5a

Browse files
authored
Automatically transition lifecycle entities when node transitions (#1863)
* Automatically transition LifecyclePublisher(s) between activated and inactive Signed-off-by: Ivan Santiago Paunovic <[email protected]> * Fix: Add created publishers to the managed entities vector Signed-off-by: Ivan Santiago Paunovic <[email protected]> * enabled_ -> activated_ Signed-off-by: Ivan Santiago Paunovic <[email protected]> * Continue setting should_log_ as before Signed-off-by: Ivan Santiago Paunovic <[email protected]> * Fix visibility attributes so it works on Windows Signed-off-by: Ivan Santiago Paunovic <[email protected]>
1 parent aa18ef5 commit 3123f5a

File tree

9 files changed

+168
-47
lines changed

9 files changed

+168
-47
lines changed

rclcpp_lifecycle/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ find_package(lifecycle_msgs REQUIRED)
1919
### CPP High level library
2020
add_library(rclcpp_lifecycle
2121
src/lifecycle_node.cpp
22+
src/managed_entity.cpp
2223
src/node_interfaces/lifecycle_node_interface.cpp
2324
src/state.cpp
2425
src/transition.cpp

rclcpp_lifecycle/include/rclcpp_lifecycle/lifecycle_node.hpp

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -968,10 +968,18 @@ class LifecycleNode : public node_interfaces::LifecycleNodeInterface,
968968
bool
969969
register_on_error(std::function<LifecycleNodeInterface::CallbackReturn(const State &)> fcn);
970970

971+
RCLCPP_LIFECYCLE_PUBLIC
972+
CallbackReturn
973+
on_activate(const State & previous_state) override;
974+
975+
RCLCPP_LIFECYCLE_PUBLIC
976+
CallbackReturn
977+
on_deactivate(const State & previous_state) override;
978+
971979
protected:
972980
RCLCPP_LIFECYCLE_PUBLIC
973981
void
974-
add_publisher_handle(std::shared_ptr<rclcpp_lifecycle::LifecyclePublisherInterface> pub);
982+
add_managed_entity(std::weak_ptr<rclcpp_lifecycle::ManagedEntityInterface> managed_entity);
975983

976984
RCLCPP_LIFECYCLE_PUBLIC
977985
void

rclcpp_lifecycle/include/rclcpp_lifecycle/lifecycle_node_impl.hpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,11 +49,13 @@ LifecycleNode::create_publisher(
4949
const rclcpp::PublisherOptionsWithAllocator<AllocatorT> & options)
5050
{
5151
using PublisherT = rclcpp_lifecycle::LifecyclePublisher<MessageT, AllocatorT>;
52-
return rclcpp::create_publisher<MessageT, AllocatorT, PublisherT>(
52+
auto pub = rclcpp::create_publisher<MessageT, AllocatorT, PublisherT>(
5353
*this,
5454
topic_name,
5555
qos,
5656
options);
57+
this->add_managed_entity(pub);
58+
return pub;
5759
}
5860

5961
// TODO(karsten1987): Create LifecycleSubscriber

rclcpp_lifecycle/include/rclcpp_lifecycle/lifecycle_publisher.hpp

Lines changed: 9 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -19,35 +19,20 @@
1919
#include <string>
2020
#include <utility>
2121

22+
#include "rclcpp/logging.hpp"
2223
#include "rclcpp/publisher.hpp"
2324

24-
#include "rclcpp/logging.hpp"
25+
#include "rclcpp_lifecycle/managed_entity.hpp"
26+
2527

2628
namespace rclcpp_lifecycle
2729
{
28-
/// base class with only
29-
/**
30-
* pure virtual functions. A managed
31-
* node can then deactivate or activate
32-
* the publishing.
33-
* It is more a convenient interface class
34-
* than a necessary base class.
35-
*/
36-
class LifecyclePublisherInterface
37-
{
38-
public:
39-
virtual ~LifecyclePublisherInterface() {}
40-
virtual void on_activate() = 0;
41-
virtual void on_deactivate() = 0;
42-
virtual bool is_activated() = 0;
43-
};
44-
4530
/// brief child class of rclcpp Publisher class.
4631
/**
4732
* Overrides all publisher functions to check for enabled/disabled state.
4833
*/
4934
template<typename MessageT, typename Alloc = std::allocator<void>>
50-
class LifecyclePublisher : public LifecyclePublisherInterface,
35+
class LifecyclePublisher : public SimpleManagedEntity,
5136
public rclcpp::Publisher<MessageT, Alloc>
5237
{
5338
public:
@@ -64,7 +49,6 @@ class LifecyclePublisher : public LifecyclePublisherInterface,
6449
const rclcpp::QoS & qos,
6550
const rclcpp::PublisherOptionsWithAllocator<Alloc> & options)
6651
: rclcpp::Publisher<MessageT, Alloc>(node_base, topic, qos, options),
67-
enabled_(false),
6852
should_log_(true),
6953
logger_(rclcpp::get_logger("LifecyclePublisher"))
7054
{
@@ -81,7 +65,7 @@ class LifecyclePublisher : public LifecyclePublisherInterface,
8165
virtual void
8266
publish(std::unique_ptr<MessageT, MessageDeleter> msg)
8367
{
84-
if (!enabled_) {
68+
if (!this->is_activated()) {
8569
log_publisher_not_enabled();
8670
return;
8771
}
@@ -97,32 +81,20 @@ class LifecyclePublisher : public LifecyclePublisherInterface,
9781
virtual void
9882
publish(const MessageT & msg)
9983
{
100-
if (!enabled_) {
84+
if (!this->is_activated()) {
10185
log_publisher_not_enabled();
10286
return;
10387
}
10488
rclcpp::Publisher<MessageT, Alloc>::publish(msg);
10589
}
10690

107-
virtual void
108-
on_activate()
109-
{
110-
enabled_ = true;
111-
}
112-
113-
virtual void
114-
on_deactivate()
91+
void
92+
on_activate() override
11593
{
116-
enabled_ = false;
94+
SimpleManagedEntity::on_activate();
11795
should_log_ = true;
11896
}
11997

120-
virtual bool
121-
is_activated()
122-
{
123-
return enabled_;
124-
}
125-
12698
private:
12799
/// LifecyclePublisher log helper function
128100
/**
@@ -146,7 +118,6 @@ class LifecyclePublisher : public LifecyclePublisherInterface,
146118
should_log_ = false;
147119
}
148120

149-
bool enabled_ = false;
150121
bool should_log_ = true;
151122
rclcpp::Logger logger_;
152123
};
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
// Copyright 2022 Open Source Robotics Foundation, 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+
#ifndef RCLCPP_LIFECYCLE__MANAGED_ENTITY_HPP_
16+
#define RCLCPP_LIFECYCLE__MANAGED_ENTITY_HPP_
17+
18+
#include <atomic>
19+
20+
#include "rclcpp_lifecycle/visibility_control.h"
21+
22+
namespace rclcpp_lifecycle
23+
{
24+
25+
/// Base class for lifecycle entities, like `LifecyclePublisher`.
26+
class ManagedEntityInterface
27+
{
28+
public:
29+
RCLCPP_LIFECYCLE_PUBLIC
30+
virtual
31+
~ManagedEntityInterface() {}
32+
33+
RCLCPP_LIFECYCLE_PUBLIC
34+
virtual
35+
void
36+
on_activate() = 0;
37+
38+
RCLCPP_LIFECYCLE_PUBLIC
39+
virtual
40+
void
41+
on_deactivate() = 0;
42+
};
43+
44+
/// A simple implementation of `ManagedEntityInterface`, which toogles a flag.
45+
class SimpleManagedEntity : public ManagedEntityInterface
46+
{
47+
public:
48+
RCLCPP_LIFECYCLE_PUBLIC
49+
~SimpleManagedEntity() override = default;
50+
51+
RCLCPP_LIFECYCLE_PUBLIC
52+
void
53+
on_activate() override;
54+
55+
RCLCPP_LIFECYCLE_PUBLIC
56+
void
57+
on_deactivate() override;
58+
59+
RCLCPP_LIFECYCLE_PUBLIC
60+
bool
61+
is_activated() const;
62+
63+
private:
64+
std::atomic<bool> activated_ = false;
65+
};
66+
67+
} // namespace rclcpp_lifecycle
68+
#endif // RCLCPP_LIFECYCLE__MANAGED_ENTITY_HPP_

rclcpp_lifecycle/src/lifecycle_node.cpp

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -639,11 +639,25 @@ LifecycleNode::shutdown(LifecycleNodeInterface::CallbackReturn & cb_return_code)
639639
rcl_lifecycle_shutdown_label, cb_return_code);
640640
}
641641

642+
node_interfaces::LifecycleNodeInterface::CallbackReturn
643+
LifecycleNode::on_activate(const State &)
644+
{
645+
impl_->on_activate();
646+
return LifecycleNodeInterface::CallbackReturn::SUCCESS;
647+
}
648+
649+
node_interfaces::LifecycleNodeInterface::CallbackReturn
650+
LifecycleNode::on_deactivate(const State &)
651+
{
652+
impl_->on_deactivate();
653+
return LifecycleNodeInterface::CallbackReturn::SUCCESS;
654+
}
655+
642656
void
643-
LifecycleNode::add_publisher_handle(
644-
std::shared_ptr<rclcpp_lifecycle::LifecyclePublisherInterface> pub)
657+
LifecycleNode::add_managed_entity(
658+
std::weak_ptr<rclcpp_lifecycle::ManagedEntityInterface> managed_entity)
645659
{
646-
impl_->add_publisher_handle(pub);
660+
impl_->add_managed_entity(managed_entity);
647661
}
648662

649663
void

rclcpp_lifecycle/src/lifecycle_node_interface_impl.hpp

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -501,9 +501,9 @@ class LifecycleNode::LifecycleNodeInterfaceImpl
501501
}
502502

503503
void
504-
add_publisher_handle(std::shared_ptr<rclcpp_lifecycle::LifecyclePublisherInterface> pub)
504+
add_managed_entity(std::weak_ptr<rclcpp_lifecycle::ManagedEntityInterface> managed_entity)
505505
{
506-
weak_pubs_.push_back(pub);
506+
weak_managed_entities_.push_back(managed_entity);
507507
}
508508

509509
void
@@ -512,6 +512,28 @@ class LifecycleNode::LifecycleNodeInterfaceImpl
512512
weak_timers_.push_back(timer);
513513
}
514514

515+
void
516+
on_activate()
517+
{
518+
for (const auto & weak_entity : weak_managed_entities_) {
519+
auto entity = weak_entity.lock();
520+
if (entity) {
521+
entity->on_activate();
522+
}
523+
}
524+
}
525+
526+
void
527+
on_deactivate()
528+
{
529+
for (const auto & weak_entity : weak_managed_entities_) {
530+
auto entity = weak_entity.lock();
531+
if (entity) {
532+
entity->on_activate();
533+
}
534+
}
535+
}
536+
515537
rcl_lifecycle_state_machine_t state_machine_;
516538
State current_state_;
517539
std::map<
@@ -538,7 +560,7 @@ class LifecycleNode::LifecycleNodeInterfaceImpl
538560
GetTransitionGraphSrvPtr srv_get_transition_graph_;
539561

540562
// to controllable things
541-
std::vector<std::weak_ptr<rclcpp_lifecycle::LifecyclePublisherInterface>> weak_pubs_;
563+
std::vector<std::weak_ptr<rclcpp_lifecycle::ManagedEntityInterface>> weak_managed_entities_;
542564
std::vector<std::weak_ptr<rclcpp::TimerBase>> weak_timers_;
543565
};
544566

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
// Copyright 2022 Open Source Robotics Foundation, 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+
#include "rclcpp_lifecycle/managed_entity.hpp"
16+
17+
namespace rclcpp_lifecycle
18+
{
19+
20+
void SimpleManagedEntity::on_activate()
21+
{
22+
activated_.store(true);
23+
}
24+
25+
void SimpleManagedEntity::on_deactivate()
26+
{
27+
activated_.store(false);
28+
}
29+
30+
bool SimpleManagedEntity::is_activated() const
31+
{
32+
return activated_.load();
33+
}
34+
35+
} // namespace rclcpp_lifecycle

rclcpp_lifecycle/test/test_lifecycle_publisher.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ class EmptyLifecycleNode : public rclcpp_lifecycle::LifecycleNode
4646
publisher_ =
4747
std::make_shared<rclcpp_lifecycle::LifecyclePublisher<test_msgs::msg::Empty>>(
4848
get_node_base_interface().get(), std::string("topic"), rclcpp::QoS(10), options);
49-
add_publisher_handle(publisher_);
49+
add_managed_entity(publisher_);
5050

5151
// For coverage this is being added here
5252
auto timer = create_wall_timer(std::chrono::seconds(1), []() {});

0 commit comments

Comments
 (0)