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:
Michael Carroll 2019-04-04 11:16:32 -05:00 committed by GitHub
parent d11a10a583
commit 0f25f714fe
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
18 changed files with 1243 additions and 56 deletions

View 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__

View file

@ -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__

View file

@ -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__

View file

@ -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__