AutoAPMS
Streamlining behaviors in ROS 2
Loading...
Searching...
No Matches
ros_node_base.hpp
1// Copyright 2024 Robin Müller
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#pragma once
16
17#include <functional>
18#include <memory>
19#include <mutex>
20#include <string>
21#include <unordered_map>
22
23#include "auto_apms_behavior_tree_core/node/ros_node_context.hpp"
24#include "behaviortree_cpp/tree_node.h"
25#include "rclcpp/logger.hpp"
26
28{
29
45class RosNodeBase
46{
47public:
48 using Config = BT::NodeConfig;
49 using Context = RosNodeContext;
50
51protected:
52 RosNodeBase(const std::string & instance_name, Context context);
53
54 ~RosNodeBase() = default;
55
64 void applyPortAliasing(const BT::TreeNode * node) const;
65
83 template <typename InstanceT>
84 std::shared_ptr<InstanceT> getSharedEntity(
85 const std::string & entity_name, const std::function<std::shared_ptr<InstanceT>()> & factory);
86
87 const Context context_;
88 const rclcpp::Logger logger_;
89};
90
91template <typename InstanceT>
92std::shared_ptr<InstanceT> RosNodeBase::getSharedEntity(
93 const std::string & entity_name, const std::function<std::shared_ptr<InstanceT>()> & factory)
94{
95 // A separate registry (and guarding mutex) is instantiated for each InstanceT. Being function-local statics of a
96 // template, they have vague linkage and are therefore merged into a single instance process-wide across all
97 // translation units.
98 static std::mutex mutex;
99 static std::unordered_map<std::string, std::weak_ptr<InstanceT>> registry;
100
101 // Key by the owning ROS 2 node so that entities belonging to different nodes never collide.
102 const std::string key = context_.getFullyQualifiedRosNodeName() + "/" + entity_name;
103
104 std::unique_lock lock(mutex);
105 if (const auto it = registry.find(key); it != registry.end()) {
106 if (const std::shared_ptr<InstanceT> existing = it->second.lock()) return existing;
107 }
108 const std::shared_ptr<InstanceT> instance = factory();
109 registry[key] = instance;
110 return instance;
111}
112
113} // namespace auto_apms_behavior_tree::core
void applyPortAliasing(const BT::TreeNode *node) const
Support the node manifest 'port_alias' feature: copy the aliased port values onto the original ports ...
std::shared_ptr< InstanceT > getSharedEntity(const std::string &entity_name, const std::function< std::shared_ptr< InstanceT >()> &factory)
Retrieve a process-wide shared ROS 2 entity, creating it via factory on first use.
Additional parameters specific to ROS 2 determined at runtime by TreeBuilder.
Core API for AutoAPMS's behavior tree implementation.
Definition behavior.hpp:32