20 #include "rclcpp/node_interfaces/node_base.hpp"
23 #include "rclcpp/exceptions.hpp"
24 #include "rcutils/logging_macros.h"
25 #include "rmw/validate_namespace.h"
26 #include "rmw/validate_node_name.h"
28 #include "../logging_mutex.hpp"
30 using rclcpp::exceptions::throw_from_rcl_error;
35 const std::string & node_name,
36 const std::string & namespace_,
37 rclcpp::Context::SharedPtr context,
39 bool use_intra_process_default,
40 bool enable_topic_statistics_default)
42 use_intra_process_default_(use_intra_process_default),
43 enable_topic_statistics_default_(enable_topic_statistics_default),
44 node_handle_(nullptr),
45 default_callback_group_(nullptr),
46 associated_with_executor_(false),
47 notify_guard_condition_(context),
48 notify_guard_condition_is_valid_(false)
53 std::shared_ptr<std::recursive_mutex> logging_mutex = get_global_logging_mutex();
57 std::lock_guard<std::recursive_mutex> guard(*logging_mutex);
64 node_name.c_str(), namespace_.c_str(),
65 context_->get_rcl_context().get(), &rcl_node_options);
70 int validation_result;
73 rmw_validate_node_name(node_name.c_str(), &validation_result, &invalid_index);
74 if (rmw_ret != RMW_RET_OK) {
75 if (rmw_ret == RMW_RET_INVALID_ARGUMENT) {
78 throw_from_rcl_error(
RCL_RET_ERROR,
"failed to validate node name");
81 if (validation_result != RMW_NODE_NAME_VALID) {
84 rmw_node_name_validation_result_string(validation_result),
87 throw std::runtime_error(
"valid rmw node name but invalid rcl node name");
93 int validation_result;
96 rmw_validate_namespace(namespace_.c_str(), &validation_result, &invalid_index);
97 if (rmw_ret != RMW_RET_OK) {
98 if (rmw_ret == RMW_RET_INVALID_ARGUMENT) {
101 throw_from_rcl_error(
RCL_RET_ERROR,
"failed to validate namespace");
104 if (validation_result != RMW_NAMESPACE_VALID) {
107 rmw_namespace_validation_result_string(validation_result),
110 throw std::runtime_error(
"valid rmw node namespace but invalid rcl node namespace");
113 throw_from_rcl_error(ret,
"failed to initialize rcl node");
119 std::lock_guard<std::recursive_mutex> guard(*logging_mutex);
123 if (rcl_node_fini(node) != RCL_RET_OK) {
124 RCUTILS_LOG_ERROR_NAMED(
126 "Error in destruction of rcl node handle: %s", rcl_get_error_string().str);
132 using rclcpp::CallbackGroupType;
133 default_callback_group_ = create_callback_group(CallbackGroupType::MutuallyExclusive);
136 notify_guard_condition_is_valid_ =
true;
139 NodeBase::~NodeBase()
143 std::lock_guard<std::recursive_mutex> notify_condition_lock(notify_guard_condition_mutex_);
144 notify_guard_condition_is_valid_ =
false;
166 rclcpp::Context::SharedPtr
175 return node_handle_.get();
181 return node_handle_.get();
184 std::shared_ptr<rcl_node_t>
187 return std::shared_ptr<rcl_node_t>(shared_from_this(), node_handle_.get());
190 std::shared_ptr<const rcl_node_t>
193 return std::shared_ptr<const rcl_node_t>(shared_from_this(), node_handle_.get());
196 rclcpp::CallbackGroup::SharedPtr
198 rclcpp::CallbackGroupType group_type,
199 bool automatically_add_to_executor_with_node)
201 auto group = std::make_shared<rclcpp::CallbackGroup>(
203 automatically_add_to_executor_with_node);
204 std::lock_guard<std::mutex> lock(callback_groups_mutex_);
205 callback_groups_.push_back(group);
209 rclcpp::CallbackGroup::SharedPtr
212 return default_callback_group_;
218 std::lock_guard<std::mutex> lock(callback_groups_mutex_);
219 for (
auto & weak_group : this->callback_groups_) {
220 auto cur_group = weak_group.lock();
221 if (cur_group && (cur_group == group)) {
230 std::lock_guard<std::mutex> lock(callback_groups_mutex_);
231 for (rclcpp::CallbackGroup::WeakPtr & weak_group : this->callback_groups_) {
232 rclcpp::CallbackGroup::SharedPtr group = weak_group.lock();
242 return associated_with_executor_;
248 std::lock_guard<std::recursive_mutex> notify_condition_lock(notify_guard_condition_mutex_);
249 if (!notify_guard_condition_is_valid_) {
250 throw std::runtime_error(
"failed to get notify guard condition because it is invalid");
252 return notify_guard_condition_;
258 return use_intra_process_default_;
264 return enable_topic_statistics_default_;
269 const std::string & name,
bool is_service,
bool only_expand)
const
271 char * output_cstr = NULL;
281 throw_from_rcl_error(ret,
"failed to resolve name", rcl_get_error_state());
283 std::string output{output_cstr};
284 allocator.deallocate(output_cstr, allocator.state);
#define rcl_get_default_allocator
Return a properly initialized rcl_allocator_t with default values.
A condition that can be waited on in a single wait set and asynchronously triggered.
Thrown when a node namespace is invalid.
Thrown when a node name is invalid.
Implementation of the NodeBase part of the Node API.
RCLCPP_PUBLIC const char * get_name() const override
Return the name of the node.
bool get_enable_topic_statistics_default() const override
Return the default preference for enabling topic statistics collection.
RCLCPP_PUBLIC bool get_use_intra_process_default() const override
Return the default preference for using intra process communication.
RCLCPP_PUBLIC rclcpp::CallbackGroup::SharedPtr get_default_callback_group() override
Return the default callback group.
RCLCPP_PUBLIC rclcpp::CallbackGroup::SharedPtr create_callback_group(rclcpp::CallbackGroupType group_type, bool automatically_add_to_executor_with_node=true) override
Create and return a callback group.
RCLCPP_PUBLIC rcl_node_t * get_rcl_node_handle() override
Return the rcl_node_t node handle (non-const version).
std::string resolve_topic_or_service_name(const std::string &name, bool is_service, bool only_expand=false) const override
Expand and remap a given topic or service name.
RCLCPP_PUBLIC rclcpp::GuardCondition & get_notify_guard_condition() override
Return a guard condition that should be notified when the internal node state changes.
RCLCPP_PUBLIC const char * get_namespace() const override
Return the namespace of the node.
RCLCPP_PUBLIC std::shared_ptr< rcl_node_t > get_shared_rcl_node_handle() override
Return the rcl_node_t node handle in a std::shared_ptr.
RCLCPP_PUBLIC void for_each_callback_group(const CallbackGroupFunction &func) override
Iterate over the stored callback groups, calling the given function on each valid one.
RCLCPP_PUBLIC rclcpp::Context::SharedPtr get_context() override
Return the context of the node.
RCLCPP_PUBLIC bool callback_group_in_node(rclcpp::CallbackGroup::SharedPtr group) override
Return true if the given callback group is associated with this node.
RCLCPP_PUBLIC std::atomic_bool & get_associated_with_executor_atomic() override
Return the atomic bool which is used to ensure only one executor is used.
RCLCPP_PUBLIC const char * get_fully_qualified_name() const override
Return the fully qualified name of the node.
RCL_PUBLIC RCL_WARN_UNUSED rcl_node_t rcl_get_zero_initialized_node(void)
Return a rcl_node_t struct with members initialized to NULL.
RCL_PUBLIC RCL_WARN_UNUSED const char * rcl_node_get_name(const rcl_node_t *node)
Return the name of the node.
RCL_PUBLIC RCL_WARN_UNUSED const char * rcl_node_get_namespace(const rcl_node_t *node)
Return the namespace of the node.
struct rcl_node_s rcl_node_t
Structure which encapsulates a ROS Node.
RCL_PUBLIC RCL_WARN_UNUSED const char * rcl_node_get_fully_qualified_name(const rcl_node_t *node)
Return the fully qualified name of the node.
RCL_PUBLIC RCL_WARN_UNUSED rcl_ret_t rcl_node_init(rcl_node_t *node, const char *name, const char *namespace_, rcl_context_t *context, const rcl_node_options_t *options)
Initialize a ROS node.
RCL_PUBLIC RCL_WARN_UNUSED rcl_ret_t rcl_node_resolve_name(const rcl_node_t *node, const char *input_name, rcl_allocator_t allocator, bool is_service, bool only_expand, char **output_name)
Expand a given name into a fully-qualified topic name and apply remapping rules.
Structure which encapsulates the options for creating a rcl_node_t.
Structure which encapsulates a ROS Node.
#define RCL_RET_NODE_INVALID_NAMESPACE
Invalid node namespace return code.
#define RCL_RET_OK
Success return code.
#define RCL_RET_INVALID_ARGUMENT
Invalid argument return code.
#define RCL_RET_ERROR
Unspecified error return code.
#define RCL_RET_NODE_INVALID_NAME
Invalid node name return code.
rmw_ret_t rcl_ret_t
The type that holds an rcl return code.