Introduce rclcpp_components to implement composition (#665)
* Introduce rclcpp_components package Signed-off-by: Michael Carroll <michael@openrobotics.org> * Keep pointer to NodeWrapper vs NodeInterface. Signed-off-by: Michael Carroll <michael@openrobotics.org> * Remove component registration from rclcpp Signed-off-by: Michael Carroll <michael@openrobotics.org> * Make topics names private-prefix. Signed-off-by: Michael Carroll <michael@openrobotics.org> * Handle name and namespace with remap rules. Signed-off-by: Michael Carroll <michael@openrobotics.org> * Linting. Signed-off-by: Michael Carroll <michael@openrobotics.org> * Address reviewer feedback. Signed-off-by: Michael Carroll <michael@openrobotics.org> * Change to smart pointers for managing memory. Signed-off-by: Michael Carroll <michael@openrobotics.org> * Update to use rcpputils filesystem/split. Signed-off-by: Michael Carroll <michael@openrobotics.org> * Address reviewer feedback and add docs. Signed-off-by: Michael Carroll <michael@openrobotics.org> * Add tests around ComponentManager. Signed-off-by: Michael Carroll <michael@openrobotics.org> * Lint. Signed-off-by: Michael Carroll <michael@openrobotics.org> * Address reviewer feedback and add overflow check. Signed-off-by: Michael Carroll <michael@openrobotics.org> * Fix CI. Signed-off-by: Michael Carroll <michael@openrobotics.org>
This commit is contained in:
parent
d11a10a583
commit
0f25f714fe
18 changed files with 1243 additions and 56 deletions
46
rclcpp_components/include/rclcpp_components/node_factory.hpp
Normal file
46
rclcpp_components/include/rclcpp_components/node_factory.hpp
Normal file
|
@ -0,0 +1,46 @@
|
|||
// Copyright 2019 Open Source Robotics Foundation, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef RCLCPP_COMPONENTS__NODE_FACTORY_HPP__
|
||||
#define RCLCPP_COMPONENTS__NODE_FACTORY_HPP__
|
||||
|
||||
#include "rclcpp_components/node_instance_wrapper.hpp"
|
||||
|
||||
namespace rclcpp_components
|
||||
{
|
||||
|
||||
/// The NodeFactory interface is used by the class loader to instantiate components.
|
||||
/**
|
||||
* The NodeFactory interface serves two purposes:
|
||||
* * It allows for classes not derived from `rclcpp::Node` to be used as components.
|
||||
* * It allows derived constructors to be called when components are loaded.
|
||||
*/
|
||||
class NodeFactory
|
||||
{
|
||||
public:
|
||||
NodeFactory() = default;
|
||||
|
||||
virtual ~NodeFactory() = default;
|
||||
|
||||
/// Create an instance of a component
|
||||
/**
|
||||
* \param[in] options Additional options used in the construction of the component.
|
||||
*/
|
||||
virtual
|
||||
NodeInstanceWrapper
|
||||
create_node_instance(const rclcpp::NodeOptions & options) = 0;
|
||||
};
|
||||
} // namespace rclcpp_components
|
||||
|
||||
#endif // RCLCPP_COMPONENTS__NODE_FACTORY_HPP__
|
|
@ -0,0 +1,53 @@
|
|||
// Copyright 2019 Open Source Robotics Foundation, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef RCLCPP_COMPONENTS__NODE_FACTORY_TEMPLATE_HPP__
|
||||
#define RCLCPP_COMPONENTS__NODE_FACTORY_TEMPLATE_HPP__
|
||||
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
|
||||
#include "rclcpp_components/node_factory.hpp"
|
||||
|
||||
namespace rclcpp_components
|
||||
{
|
||||
|
||||
/// NodeFactoryTemplate is a convenience class for instantiating components.
|
||||
/**
|
||||
* The NodeFactoryTemplate class can be used to provide the NodeFactory interface for
|
||||
* components that implement a single-argument constructor and `get_node_base_interface`.
|
||||
*/
|
||||
template<typename NodeT>
|
||||
class NodeFactoryTemplate : public NodeFactory
|
||||
{
|
||||
public:
|
||||
NodeFactoryTemplate() = default;
|
||||
virtual ~NodeFactoryTemplate() = default;
|
||||
|
||||
/// Create an instance of a component
|
||||
/**
|
||||
* \param[in] options Additional options used in the construction of the component.
|
||||
*/
|
||||
NodeInstanceWrapper
|
||||
create_node_instance(const rclcpp::NodeOptions & options) override
|
||||
{
|
||||
auto node = std::make_shared<NodeT>(options);
|
||||
|
||||
return NodeInstanceWrapper(
|
||||
node, std::bind(&NodeT::get_node_base_interface, node));
|
||||
}
|
||||
};
|
||||
} // namespace rclcpp_components
|
||||
|
||||
#endif // RCLCPP_COMPONENTS__NODE_FACTORY_TEMPLATE_HPP__
|
|
@ -0,0 +1,71 @@
|
|||
// Copyright 2019 Open Source Robotics Foundation, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef RCLCPP_COMPONENTS__NODE_INSTANCE_WRAPPER_HPP__
|
||||
#define RCLCPP_COMPONENTS__NODE_INSTANCE_WRAPPER_HPP__
|
||||
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
|
||||
#include "rclcpp/node_interfaces/node_base_interface.hpp"
|
||||
|
||||
namespace rclcpp_components
|
||||
{
|
||||
/// The NodeInstanceWrapper encapsulates the node instance.
|
||||
class NodeInstanceWrapper
|
||||
{
|
||||
public:
|
||||
using NodeBaseInterfaceGetter = std::function<
|
||||
rclcpp::node_interfaces::NodeBaseInterface::SharedPtr(const std::shared_ptr<void> &)>;
|
||||
|
||||
NodeInstanceWrapper()
|
||||
: node_instance_(nullptr)
|
||||
{}
|
||||
|
||||
NodeInstanceWrapper(
|
||||
std::shared_ptr<void> node_instance,
|
||||
NodeBaseInterfaceGetter node_base_interface_getter)
|
||||
: node_instance_(node_instance), node_base_interface_getter_(node_base_interface_getter)
|
||||
{}
|
||||
|
||||
/// Get a type-erased pointer to the original Node instance
|
||||
/**
|
||||
* This is only for debugging and special cases.
|
||||
* For most cases `get_node_base_interface` will be sufficient.
|
||||
*
|
||||
* \return Shared pointer to the encapsulated Node instance.
|
||||
*/
|
||||
const std::shared_ptr<void>
|
||||
get_node_instance() const
|
||||
{
|
||||
return node_instance_;
|
||||
}
|
||||
|
||||
/// Get NodeBaseInterface pointer for the encapsulated Node Instance.
|
||||
/**
|
||||
* \return Shared NodeBaseInterface pointer of the encapsulated Node instance.
|
||||
*/
|
||||
rclcpp::node_interfaces::NodeBaseInterface::SharedPtr
|
||||
get_node_base_interface()
|
||||
{
|
||||
return node_base_interface_getter_(node_instance_);
|
||||
}
|
||||
|
||||
private:
|
||||
std::shared_ptr<void> node_instance_;
|
||||
NodeBaseInterfaceGetter node_base_interface_getter_;
|
||||
};
|
||||
} // namespace rclcpp_components
|
||||
|
||||
#endif // RCLCPP_COMPONENTS__NODE_INSTANCE_WRAPPER_HPP__
|
|
@ -0,0 +1,37 @@
|
|||
// Copyright 2019 Open Source Robotics Foundation, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef RCLCPP_COMPONENTS__REGISTER_NODE_MACRO_HPP__
|
||||
#define RCLCPP_COMPONENTS__REGISTER_NODE_MACRO_HPP__
|
||||
|
||||
#include "class_loader/class_loader.hpp"
|
||||
#include "rclcpp_components/node_factory_template.hpp"
|
||||
|
||||
/// Register a component that can be dynamically loaded at runtime.
|
||||
/**
|
||||
* The registration macro should appear once per component per library.
|
||||
* The macro should appear in a single translation unit.
|
||||
*
|
||||
* Valid arguments for NodeClass shall:
|
||||
* * Have a constructor that takes a single argument that is a `rclcpp::NodeOptions` instance.
|
||||
* * Have a method of of the signature:
|
||||
* `rclcpp::node_interfaces::NodeBaseInterface::SharedPtr get_node_base_interface`
|
||||
*
|
||||
* Note: NodeClass does not need to inherit from `rclcpp::Node`, but it is the easiest way.
|
||||
*/
|
||||
#define RCLCPP_COMPONENTS_REGISTER_NODE(NodeClass) \
|
||||
CLASS_LOADER_REGISTER_CLASS(rclcpp_components::NodeFactoryTemplate<NodeClass>, \
|
||||
rclcpp_components::NodeFactory)
|
||||
|
||||
#endif // RCLCPP_COMPONENTS__REGISTER_NODE_MACRO_HPP__
|
Loading…
Add table
Add a link
Reference in a new issue